186 lines
6.2 KiB
TypeScript
186 lines
6.2 KiB
TypeScript
import React from 'react';
|
|
import { RowIcon } from '../../icons/ComponentIcons';
|
|
import type { ComponentDefinition } from '../types';
|
|
|
|
export const rowDefinition: ComponentDefinition = {
|
|
type: 'row',
|
|
label: 'Row',
|
|
icon: RowIcon,
|
|
category: 'container',
|
|
canHaveChildren: true,
|
|
|
|
defaultStyles: {
|
|
width: 'auto',
|
|
display: 'flex',
|
|
flexDirection: 'row',
|
|
gap: '8px',
|
|
},
|
|
|
|
defaultProps: {},
|
|
|
|
propertySchema: [],
|
|
|
|
styleSchema: [
|
|
// Layout
|
|
{ key: 'width', label: 'Width', type: 'dimension', category: 'layout' },
|
|
{ key: 'height', label: 'Height', type: 'dimension', category: 'layout' },
|
|
{ key: 'minWidth', label: 'Min Width', type: 'dimension', category: 'layout' },
|
|
{ key: 'maxWidth', label: 'Max Width', type: 'dimension', category: 'layout' },
|
|
{ key: 'minHeight', label: 'Min Height', type: 'dimension', category: 'layout' },
|
|
{ key: 'maxHeight', label: 'Max Height', type: 'dimension', category: 'layout' },
|
|
{
|
|
key: 'justifyContent',
|
|
label: 'Horizontal Align',
|
|
type: 'select',
|
|
category: 'layout',
|
|
options: [
|
|
{ value: 'flex-start', label: 'Start' },
|
|
{ value: 'center', label: 'Center' },
|
|
{ value: 'flex-end', label: 'End' },
|
|
{ value: 'space-between', label: 'Space Between' },
|
|
{ value: 'space-around', label: 'Space Around' },
|
|
{ value: 'space-evenly', label: 'Space Evenly' },
|
|
],
|
|
},
|
|
{
|
|
key: 'alignItems',
|
|
label: 'Vertical Align',
|
|
type: 'select',
|
|
category: 'layout',
|
|
options: [
|
|
{ value: 'flex-start', label: 'Start' },
|
|
{ value: 'center', label: 'Center' },
|
|
{ value: 'flex-end', label: 'End' },
|
|
{ value: 'stretch', label: 'Stretch' },
|
|
{ value: 'baseline', label: 'Baseline' },
|
|
],
|
|
},
|
|
{
|
|
key: 'flexWrap',
|
|
label: 'Flex Wrap',
|
|
type: 'select',
|
|
category: 'layout',
|
|
options: [
|
|
{ value: 'nowrap', label: 'No Wrap' },
|
|
{ value: 'wrap', label: 'Wrap' },
|
|
{ value: 'wrap-reverse', label: 'Wrap Reverse' },
|
|
],
|
|
},
|
|
{
|
|
key: 'overflow',
|
|
label: 'Overflow',
|
|
type: 'select',
|
|
category: 'layout',
|
|
options: [
|
|
{ value: 'visible', label: 'Visible' },
|
|
{ value: 'hidden', label: 'Hidden' },
|
|
{ value: 'scroll', label: 'Scroll' },
|
|
{ value: 'auto', label: 'Auto' },
|
|
],
|
|
},
|
|
// Positioning
|
|
{
|
|
key: 'position',
|
|
label: 'Position',
|
|
type: 'select',
|
|
category: 'layout',
|
|
options: [
|
|
{ value: 'static', label: 'Static' },
|
|
{ value: 'relative', label: 'Relative' },
|
|
{ value: 'absolute', label: 'Absolute' },
|
|
{ value: 'fixed', label: 'Fixed' },
|
|
{ value: 'sticky', label: 'Sticky' },
|
|
],
|
|
},
|
|
{ key: 'top', label: 'Top', type: 'dimension', category: 'layout' },
|
|
{ key: 'right', label: 'Right', type: 'dimension', category: 'layout' },
|
|
{ key: 'bottom', label: 'Bottom', type: 'dimension', category: 'layout' },
|
|
{ key: 'left', label: 'Left', type: 'dimension', category: 'layout' },
|
|
{ key: 'zIndex', label: 'Z-Index', type: 'number', category: 'layout' },
|
|
// Spacing
|
|
{ key: 'gap', label: 'Gap', type: 'dimension', category: 'spacing' },
|
|
{ key: 'padding', label: 'Padding', type: 'dimension', category: 'spacing' },
|
|
{ key: 'margin', label: 'Margin', type: 'dimension', category: 'spacing' },
|
|
// Appearance
|
|
{ key: 'backgroundColor', label: 'Background', type: 'color', category: 'appearance' },
|
|
{ key: 'opacity', label: 'Opacity', type: 'range', category: 'appearance' },
|
|
// Border
|
|
{ key: 'borderWidth', label: 'Border Width', type: 'dimension', category: 'appearance' },
|
|
{
|
|
key: 'borderStyle',
|
|
label: 'Border Style',
|
|
type: 'select',
|
|
category: 'appearance',
|
|
options: [
|
|
{ value: 'none', label: 'None' },
|
|
{ value: 'solid', label: 'Solid' },
|
|
{ value: 'dashed', label: 'Dashed' },
|
|
{ value: 'dotted', label: 'Dotted' },
|
|
{ value: 'double', label: 'Double' },
|
|
],
|
|
},
|
|
{ key: 'borderColor', label: 'Border Color', type: 'color', category: 'appearance' },
|
|
{ key: 'borderRadius', label: 'Border Radius', type: 'dimension', category: 'appearance' },
|
|
{ key: 'boxShadow', label: 'Box Shadow', type: 'boxShadow', category: 'appearance' },
|
|
// Grid Item (when inside grid container)
|
|
{ key: 'gridColumn', label: 'Grid Column', type: 'text', category: 'grid-item' },
|
|
{ key: 'gridRow', label: 'Grid Row', type: 'text', category: 'grid-item' },
|
|
{ key: 'gridColumnStart', label: 'Column Start', type: 'text', category: 'grid-item' },
|
|
{ key: 'gridColumnEnd', label: 'Column End', type: 'text', category: 'grid-item' },
|
|
{ key: 'gridRowStart', label: 'Row Start', type: 'text', category: 'grid-item' },
|
|
{ key: 'gridRowEnd', label: 'Row End', type: 'text', category: 'grid-item' },
|
|
{
|
|
key: 'justifySelf',
|
|
label: 'Justify Self',
|
|
type: 'select',
|
|
category: 'grid-item',
|
|
options: [
|
|
{ value: 'start', label: 'Start' },
|
|
{ value: 'end', label: 'End' },
|
|
{ value: 'center', label: 'Center' },
|
|
{ value: 'stretch', label: 'Stretch' },
|
|
],
|
|
},
|
|
],
|
|
|
|
render: ({ component, isSelected, onSelect, previewMode, children }) => {
|
|
const isEmpty = !component.children || component.children.length === 0;
|
|
|
|
return React.createElement(
|
|
'div',
|
|
{
|
|
style: {
|
|
...component.styles,
|
|
outline: isSelected && !previewMode ? '2px solid rgb(255, 89, 47)' : 'none',
|
|
minHeight: isEmpty && !previewMode ? '60px' : 'auto',
|
|
position: 'relative' as const,
|
|
},
|
|
onClick: previewMode
|
|
? undefined
|
|
: (e: React.MouseEvent) => {
|
|
e.stopPropagation();
|
|
onSelect(component.id);
|
|
},
|
|
},
|
|
children,
|
|
isEmpty && !previewMode
|
|
? React.createElement(
|
|
'div',
|
|
{
|
|
style: {
|
|
position: 'absolute' as const,
|
|
top: '50%',
|
|
left: '50%',
|
|
transform: 'translate(-50%, -50%)',
|
|
color: '#999',
|
|
fontSize: '14px',
|
|
pointerEvents: 'none' as const,
|
|
},
|
|
},
|
|
'Drop components here'
|
|
)
|
|
: null
|
|
);
|
|
},
|
|
};
|