Skip to content

Commit 9b5bf85

Browse files
committed
feat: enhance layout components with improved props handling and responsive configurations
1 parent 1fe13fe commit 9b5bf85

File tree

5 files changed

+98
-35
lines changed

5 files changed

+98
-35
lines changed

packages/components/src/renderers/complex/scroll-area.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,44 @@ import { ScrollArea, ScrollBar } from '../../ui';
1212
import { renderChildren } from '../../lib/utils';
1313

1414
ComponentRegistry.register('scroll-area',
15-
({ schema, className, ...props }: { schema: ScrollAreaSchema; className?: string; [key: string]: any }) => (
16-
<ScrollArea className={className} style={{ height: schema.height, width: schema.width }} {...props}>
17-
{renderChildren(schema.content || schema.children)}
18-
{schema.orientation === 'horizontal' && <ScrollBar orientation="horizontal" />}
15+
({ schema, className, ...props }: { schema: ScrollAreaSchema; className?: string; [key: string]: any }) => {
16+
// Extract designer-related props
17+
const {
18+
'data-obj-id': dataObjId,
19+
'data-obj-type': dataObjType,
20+
style,
21+
...scrollAreaProps
22+
} = props;
23+
24+
const orientation = schema.orientation || 'vertical';
25+
26+
return (
27+
<ScrollArea
28+
className={className}
29+
style={{ height: schema.height, width: schema.width, ...style }}
30+
{...scrollAreaProps}
31+
data-obj-id={dataObjId}
32+
data-obj-type={dataObjType}
33+
>
34+
{renderChildren(schema.children)}
35+
{(orientation === 'horizontal' || orientation === 'both') && <ScrollBar orientation="horizontal" />}
36+
{(orientation === 'vertical' || orientation === 'both') && <ScrollBar orientation="vertical" />}
1937
</ScrollArea>
20-
),
38+
)},
2139
{
2240
namespace: 'ui',
2341
label: 'Scroll Area',
2442
inputs: [
2543
{ name: 'height', type: 'string', label: 'Height (e.g. 200px)' },
2644
{ name: 'width', type: 'string', label: 'Width' },
2745
{ name: 'orientation', type: 'enum', enum: ['vertical', 'horizontal', 'both'], defaultValue: 'vertical', label: 'Orientation' },
28-
{ name: 'content', type: 'slot', label: 'Content' },
2946
{ name: 'className', type: 'string', label: 'CSS Class' }
3047
],
3148
defaultProps: {
3249
height: '200px',
3350
width: '100%',
3451
orientation: 'vertical',
35-
content: [
52+
children: [
3653
{ type: 'div', className: 'p-4', body: [{ type: 'text', content: 'Scrollable content goes here. Add more content to see scrolling behavior.' }] }
3754
],
3855
className: 'rounded-md border'

packages/components/src/renderers/layout/aspect-ratio.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ ComponentRegistry.register('aspect-ratio',
3030
{schema.image ? (
3131
<img src={schema.image} alt={schema.alt || ''} className="rounded-md object-cover w-full h-full" />
3232
) : (
33-
renderChildren(schema.body)
33+
renderChildren(schema.children || schema.body)
3434
)}
3535
</AspectRatio>
3636
);

packages/components/src/renderers/layout/card.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import { ComponentRegistry } from '@object-ui/core';
1010
import type { CardSchema } from '@object-ui/types';
11-
import { renderChildren } from '../../lib/utils';
11+
import { renderChildren, cn } from '../../lib/utils';
1212
import {
1313
Card,
1414
CardHeader,
@@ -28,11 +28,18 @@ const CardRenderer = forwardRef<HTMLDivElement, { schema: CardSchema; className?
2828
style,
2929
...cardProps
3030
} = props;
31+
32+
const isClickable = schema.clickable || !!props.onClick;
33+
const isHoverable = schema.hoverable || isClickable;
3134

3235
return (
3336
<Card
3437
ref={ref}
35-
className={className}
38+
className={cn(
39+
className,
40+
isHoverable && "transition-colors hover:bg-muted/50",
41+
isClickable && "cursor-pointer active:bg-muted"
42+
)}
3643
{...cardProps}
3744
// Apply designer props
3845
{...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}

packages/components/src/renderers/layout/grid.tsx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,27 @@ const GAPS: Record<number, string> = {
5050
ComponentRegistry.register('grid',
5151
({ schema, className, ...props }: { schema: GridSchema & { smColumns?: number, mdColumns?: number, lgColumns?: number, xlColumns?: number }; className?: string; [key: string]: any }) => {
5252
// Determine columns configuration
53-
// Supports direct number or responsive object logic if schema allows,
54-
// but here we primarily handle the flat properties supported by the designer inputs
55-
const baseCols = typeof schema.columns === 'number' ? schema.columns : 2;
56-
const smCols = schema.smColumns;
57-
const mdCols = schema.mdColumns;
58-
const lgCols = schema.lgColumns;
59-
const xlCols = schema.xlColumns;
53+
// Supports detailed object configuration from schema
54+
let baseCols = 2;
55+
let smCols, mdCols, lgCols, xlCols;
56+
57+
if (typeof schema.columns === 'number') {
58+
baseCols = schema.columns;
59+
} else if (typeof schema.columns === 'object' && schema.columns !== null) {
60+
// Handle responsive object: { xs: 1, sm: 2, md: 3, lg: 4 }
61+
// Note: 'xs' corresponds to base (mobile-first)
62+
baseCols = schema.columns.xs ?? 1;
63+
smCols = schema.columns.sm;
64+
mdCols = schema.columns.md;
65+
lgCols = schema.columns.lg;
66+
xlCols = schema.columns.xl;
67+
}
68+
69+
// Fallback to legacy flat props if provided (from designer)
70+
if (schema.smColumns) smCols = schema.smColumns;
71+
if (schema.mdColumns) mdCols = schema.mdColumns;
72+
if (schema.lgColumns) lgCols = schema.lgColumns;
73+
if (schema.xlColumns) xlCols = schema.xlColumns;
6074

6175
const gap = schema.gap ?? 4;
6276

@@ -71,7 +85,7 @@ ComponentRegistry.register('grid',
7185
lgCols && GRID_COLS_LG[lgCols],
7286
xlCols && GRID_COLS_XL[xlCols],
7387
// Gap
74-
GAPS[gap] || 'gap-4',
88+
GAPS[gap] || `gap-[${gap * 0.25}rem]`, // Fallback for arbitrary values if not in map
7589
className
7690
);
7791

packages/components/src/renderers/layout/tabs.tsx

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,63 @@ import {
1515
TabsTrigger,
1616
TabsContent
1717
} from '../../ui';
18+
import { cn } from '../../lib/utils';
19+
import React from 'react';
1820

19-
ComponentRegistry.register('tabs',
20-
({ schema, className, ...props }: { schema: TabsSchema; className?: string; [key: string]: any }) => {
21-
// Extract designer-related props
22-
const {
23-
'data-obj-id': dataObjId,
24-
'data-obj-type': dataObjType,
25-
style,
26-
...tabsProps
27-
} = props;
21+
const TabsRenderer = ({ schema, className, onChange, value, ...props }: { schema: TabsSchema; className?: string; onChange?: (val: string) => void; value?: string; [key: string]: any }) => {
22+
// Extract designer-related props
23+
const {
24+
'data-obj-id': dataObjId,
25+
'data-obj-type': dataObjType,
26+
style,
27+
...tabsProps
28+
} = props;
2829

29-
return (
30+
const handleValueChange = (val: string) => {
31+
if (onChange) {
32+
onChange(val);
33+
}
34+
};
35+
36+
const isVertical = schema.orientation === 'vertical';
37+
38+
return (
3039
<Tabs
31-
defaultValue={schema.defaultValue}
32-
className={className}
40+
defaultValue={value === undefined ? schema.defaultValue : undefined}
41+
value={value ?? schema.value}
42+
onValueChange={handleValueChange}
43+
orientation={schema.orientation || 'horizontal'}
44+
className={cn(className, isVertical && "flex gap-2")}
3345
{...tabsProps}
3446
// Apply designer props
3547
{...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
3648
>
37-
<TabsList>
49+
<TabsList className={cn(isVertical && "flex-col h-auto items-stretch bg-muted/50 p-1")}>
3850
{schema.items?.map((item) => (
39-
<TabsTrigger key={item.value} value={item.value}>{item.label}</TabsTrigger>
51+
<TabsTrigger
52+
key={item.value}
53+
value={item.value}
54+
disabled={item.disabled}
55+
className={cn(isVertical && "justify-start")}
56+
>
57+
{item.label}
58+
</TabsTrigger>
4059
))}
4160
</TabsList>
4261
{schema.items?.map((item) => (
43-
<TabsContent key={item.value} value={item.value}>
44-
{renderChildren((item as any).body)}
62+
<TabsContent
63+
key={item.value}
64+
value={item.value}
65+
className={cn("mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", isVertical && "mt-0 flex-1")}
66+
>
67+
{renderChildren(item.content || (item as any).body)}
4568
</TabsContent>
4669
))}
4770
</Tabs>
4871
);
49-
},
72+
};
73+
74+
ComponentRegistry.register('tabs', TabsRenderer,
5075
{
5176
namespace: 'ui',
5277
label: 'Tabs',

0 commit comments

Comments
 (0)