import React, { CSSProperties } from 'react'; import { useNode, Element, UserComponent } from '@craftjs/core'; import { Container } from './Container'; import { cssPropsToString } from '../../utils/style-helpers'; import { escapeAttr, scopeId, cssValue } from '../../utils/escape'; type SplitOption = | '100' | '50-50' | '30-70' | '70-30' | '40-60' | '60-40' | '33-33-33' | '25-50-25' | '25-25-25-25' | '20-20-20-20-20' | '16-16-16-16-16-16' | 'equal'; interface ColumnLayoutProps { columns?: number; split?: SplitOption; gap?: string; style?: CSSProperties; children?: React.ReactNode; anchorId?: string; } const splitToWidths: Record = { '100': ['100%'], '50-50': ['50%', '50%'], '30-70': ['30%', '70%'], '70-30': ['70%', '30%'], '40-60': ['40%', '60%'], '60-40': ['60%', '40%'], '33-33-33': ['33.333%', '33.333%', '33.333%'], '25-50-25': ['25%', '50%', '25%'], '25-25-25-25': ['25%', '25%', '25%', '25%'], '20-20-20-20-20': ['20%', '20%', '20%', '20%', '20%'], '16-16-16-16-16-16': ['16.666%', '16.666%', '16.666%', '16.666%', '16.666%', '16.666%'], }; function getWidths(split: SplitOption, columns: number): string[] { // Check predefined splits first if (split !== 'equal') { const defined = splitToWidths[split]; if (defined && defined.length === columns) return defined; } // Try parsing custom split string (e.g., "35-65" or "25-50-25") if (split && split !== 'equal' && split.includes('-')) { const parts = split.split('-').map(Number); if (parts.length === columns && parts.every(n => !isNaN(n) && n > 0)) { return parts.map(n => `${n}%`); } } // Fallback: equal widths const w = `${(100 / columns).toFixed(3)}%`; return Array.from({ length: columns }, () => w); } export const ColumnLayout: UserComponent = ({ columns = 2, split = '50-50', gap = '16px', style = {}, anchorId, }) => { const { connectors: { connect, drag } } = useNode(); const widths = getWidths(split, columns); return (
{ if (ref) connect(drag(ref)); }} id={anchorId || undefined} style={{ display: 'flex', flexWrap: 'wrap', gap, width: '100%', minHeight: '60px', ...style, }} > {widths.map((w, i) => ( ))}
); }; /* ---------- Craft config ---------- */ ColumnLayout.craft = { displayName: 'Columns', props: { columns: 2, split: '50-50', gap: '16px', style: {}, anchorId: '', }, rules: { canDrag: () => true, canMoveIn: () => false, canMoveOut: () => true, }, }; /* ---------- HTML export ---------- */ (ColumnLayout as any).toHtml = (props: ColumnLayoutProps, childrenHtml: string, nodeId?: string) => { const columns = props.columns || 2; const split = props.split || '50-50'; // Sanitized once here so BOTH the raw // breakout -> arbitrary