/**
* @file Type definitions for panel and grid-based layout system
*/
import * as React from "react";
/**
* Panel position - either a named column position or floating coordinates
* - 'left': Dock to left side
* - 'right': Dock to right side
* - { x, y }: Float at specific coordinates
*/
export type PanelPosition = "left" | "right" | { x: number; y: number };
/**
* Configuration for a single panel
*/
export type PanelDefinition = {
/** Panel component/content */
component: React.ReactNode;
/** Panel position - column ('left'/'right') or floating coordinates */
position: PanelPosition;
/** Whether the panel is initially visible */
visible?: boolean;
// Column layout options (when position is 'left' or 'right')
/** Initial width in pixels (for column layout) */
initialWidth?: number;
/** Minimum width in pixels (for column layout) */
minWidth?: number;
/** Maximum width in pixels (for column layout) */
maxWidth?: number;
/** Whether the panel can be resized (for column layout) */
resizable?: boolean;
/** Callback when panel width changes (column mode) */
onWidthChange?: (width: number) => void;
// Floating layout options (when position is { x, y })
/** Size for floating layout */
size?: { width: number; height: number };
/** Whether the panel can be dragged (floating mode) */
draggable?: boolean;
/** Z-index for stacking order (floating mode) */
zIndex?: number;
/** Callback when panel position changes (floating mode) */
onPositionChange?: (position: { x: number; y: number }) => void;
/** Callback when panel size changes (floating mode) */
onSizeChange?: (size: { width: number; height: number }) => void;
// Common options
/** Custom CSS class name */
className?: string;
/** Custom inline styles */
style?: React.CSSProperties;
};
/**
* Configuration for editor panels - dictionary of labeled panels
* Each key is a unique label for the panel, value is the panel definition
*
* @example
* ```tsx
* panels={{
* inspector: {
* component: ,
* position: 'right',
* initialWidth: 320,
* },
* library: {
* component: ,
* position: { x: 20, y: 80 },
* size: { width: 280, height: 500 },
* }
* }}
* ```
*/
export type EditorPanelsConfig = Record;
// ==================== NEW GRID-BASED LAYOUT SYSTEM ====================
/**
* Grid track definition with optional resize capability
*/
export type GridTrack = {
/** Track size (e.g., "1fr", "300px", "auto") */
size: string;
/** Whether this track can be resized */
resizable?: boolean;
/** Minimum size in pixels (only applies if resizable) */
minSize?: number;
/** Maximum size in pixels (only applies if resizable) */
maxSize?: number;
};
/**
* Grid-based layout configuration for the editor
*/
export type GridLayoutConfig = {
/** Grid template areas as 2D array. Example: [["canvas", "inspector"], ["statusbar", "statusbar"]] */
areas: string[][];
/** Row track definitions */
rows: GridTrack[];
/** Column track definitions */
columns: GridTrack[];
/** CSS gap between grid cells */
gap?: string;
/** Custom CSS class name */
className?: string;
/** Custom inline styles */
style?: React.CSSProperties;
};
/**
* Layer positioning mode
* - 'grid': Use CSS Grid positioning (gridArea, gridRow, gridColumn)
* - 'absolute': Position absolutely within parent
* - 'relative': Position relative to normal flow
* - 'fixed': Position fixed to viewport
*/
export type LayerPositionMode = "grid" | "absolute" | "relative" | "fixed";
/**
* Drawer behavior configuration
* Controls how a layer behaves as a mobile-friendly drawer
*/
export type DrawerBehavior = {
/** Drawer placement direction */
placement: "top" | "right" | "bottom" | "left";
/** Initial state (open/closed) */
defaultOpen?: boolean;
/** Controlled open state (when provided, drawer becomes controlled) */
open?: boolean;
/** Whether drawer can be dismissed by clicking outside */
dismissible?: boolean;
/** Whether to show a backdrop/overlay */
showBackdrop?: boolean;
/** Backdrop opacity (0-1) */
backdropOpacity?: number;
/** Size when open (pixels or percentage) */
size?: string | number;
/** Callback when drawer state changes */
onStateChange?: (open: boolean) => void;
/** Header configuration for drawer */
header?: {
/** Header title text */
title?: string;
/** Whether to show close button in header (default: true if header is provided) */
showCloseButton?: boolean;
};
};
/**
* Layer definition for grid-based layout system
* Combines background layers, overlay layers, UI layers, and main canvas into unified system
*/
export type LayerDefinition = {
/** Unique identifier for the layer */
id: string;
/** Layer content/component */
component: React.ReactNode;
/** Whether the layer is visible */
visible?: boolean;
// Grid positioning (when positionMode is 'grid')
/** CSS grid-area name */
gridArea?: string;
/** CSS grid-row value */
gridRow?: string;
/** CSS grid-column value */
gridColumn?: string;
// Absolute/Fixed/Relative positioning
/** Positioning mode */
positionMode?: LayerPositionMode;
/**
* Position coordinates (for absolute/fixed/relative modes)
* - Numbers are converted to px (e.g., `100` → `100px`)
* - Strings are used as-is, supporting %, calc(), vw, vh, etc.
*
* @example
* ```tsx
* // Pixel positioning
* position: { top: 20, left: 100 }
*
* // Percentage positioning
* position: { left: "50%", top: "25%" }
*
* // Centered with transform
* position: { left: "50%", top: "50%" }
* // Note: Use layer.style for transform: { transform: "translate(-50%, -50%)" }
*
* // Mixed units
* position: { top: "10vh", right: 20 }
*
* // CSS calc()
* position: { left: "calc(50% - 160px)", top: 0 }
* ```
*/
position?: {
top?: number | string;
right?: number | string;
bottom?: number | string;
left?: number | string;
};
// Stacking and dimensions
/** Z-index for stacking order */
zIndex?: number;
/** Width (CSS value or pixels) */
width?: string | number;
/** Height (CSS value or pixels) */
height?: string | number;
// Interactivity
/** Whether the layer blocks pointer events (default: true for absolute/fixed, false for grid) */
pointerEvents?: boolean | "auto" | "none";
/** Whether the layer can be dragged (for floating layers) */
draggable?: boolean;
/** Callback when layer position changes (for draggable layers) */
onPositionChange?: (position: { x: number; y: number }) => void;
/** Drawer behavior for mobile-friendly slide-in panels */
drawer?: DrawerBehavior;
// Styling
/** Custom CSS class name */
className?: string;
/** Custom inline styles */
style?: React.CSSProperties;
};
/**
* Configuration for grid-based editor layout
* Replaces overlayLayers, backgroundLayers, uiOverlayLayers, and main canvas with unified layer system
*
* @example
* ```tsx
* gridLayout={{
* config: {
* areas: `
* "toolbar toolbar toolbar"
* "sidebar canvas inspector"
* "statusbar statusbar statusbar"
* `,
* rows: "auto 1fr auto",
* columns: "250px 1fr 320px",
* gap: "0",
* },
* layers: [
* {
* id: "canvas",
* component: ,
* gridArea: "canvas",
* zIndex: 0,
* },
* {
* id: "toolbar",
* component: ,
* gridArea: "toolbar",
* zIndex: 1,
* },
* {
* id: "background-grid",
* component: ,
* gridArea: "canvas",
* zIndex: -1,
* pointerEvents: false,
* },
* ]
* }}
* ```
*/
export type EditorGridLayout = {
/** Grid layout configuration */
config: GridLayoutConfig;
/** Layers to render in the grid */
layers: LayerDefinition[];
};