# ACoreX Layout Builder System

The **Layout Builder** is a powerful, fluent API system for creating dynamic layouts, pages, forms, and dialogs in the ACoreX Platform. It replaces the older Dynamic Form Builder with a more flexible, type-safe, and comprehensive solution.

## Table of Contents

- [Overview](#overview)
- [Key Features](#key-features)
- [Architecture](#architecture)
- [Getting Started](#getting-started)
- [Core Concepts](#core-concepts)
- [Container Types](#container-types)
- [Form Fields](#form-fields)
- [Widget Types](#widget-types)
- [Dialog Builder](#dialog-builder)
- [Layout Inheritance](#layout-inheritance)
- [Complete Examples](#complete-examples)
- [Migration Guide](#migration-guide)
- [Best Practices](#best-practices)
- [API Reference](#api-reference)

---

## Overview

The Layout Builder provides a fluent, delegate-based API for creating complex layouts without manually constructing configuration objects. It supports:

- **🎨 Multiple Container Types**: Flex, Grid, Panel, Page, Tabset, Fieldset
- **📝 Rich Form Capabilities**: Form fields with automatic path generation
- **🔄 Property Inheritance**: Automatic propagation of mode, readonly, disabled, and visibility
- **💬 Dialog Support**: Built-in dialog builder with action management
- **✅ Type Safety**: Full TypeScript support with IntelliSense
- **🎯 Fluent API**: Readable, chainable method calls with delegate pattern
- **🔧 Widget Support**: 15+ built-in widgets plus custom widget support

### Comparison: Layout Builder vs Dynamic Form Builder

| Feature                          | Dynamic Form Builder | Layout Builder |
|----------------------------------|----------------------|----------------|
| **Purpose**                      | Forms only           | Full layouts + forms |
| **Container Types**              | Groups only          | Flex, Grid, Panel, Page, Tabset, Fieldset |
| **Nesting**                      | Limited              | Unlimited nesting |
| **Layout Control**               | Basic                | Advanced (Flexbox, Grid) |
| **Property Inheritance**         | No                   | Yes (mode, readonly, disabled) |
| **Dialog Support**               | Separate service     | Built-in |
| **Widget Path Management**       | Manual               | Automatic |
| **Custom Widgets**               | Limited              | Full support |

---

## Key Features

### 1. Fluent API with Delegate Pattern

```typescript
builder.flex(flexContainer => {
  flexContainer
    .setDirection('column')
    .setGap('16px')
    .formField('First Name', field => {
      field.path('firstName');
      field.textBox({ placeholder: 'Enter name' });
    });
});
```

### 2. Automatic Property Inheritance

```typescript
// Parent container sets mode to 'view'
builder.flex(flexContainer => {
  flexContainer.mode('view');  // All children inherit 'view' mode
  
  flexContainer.formField('Name', field => {
    field.textBox();  // Automatically in 'view' mode
  });
});
```

### 3. Automatic Path Generation

```typescript
// Path is automatically generated from field name
flexContainer.formField('First Name', field => {
  field.textBox();  // path = 'first_name' (auto-generated)
});

// Or explicitly set path
flexContainer.formField('First Name', field => {
  field.path('user.firstName');
  field.textBox();
});
```

### 4. Nested Containers

```typescript
builder.flex(mainContainer => {
  mainContainer
    .setDirection('column')
    .panel(panel => {
      panel
        .setCaption('Personal Info')
        .flex(innerFlex => {
          innerFlex.setDirection('row');
          // Add widgets...
        });
    });
});
```

---

## Architecture

### Service Structure

```
AXPLayoutBuilderService
  └── create() → ILayoutBuilder
       ├── flex()
       ├── grid()
       ├── panel()
       ├── page()
       ├── tabset()
       ├── fieldset()
       ├── dialog()
       └── build() → AXPWidgetNode
```

### Builder Hierarchy

```
BaseContainerBuilder (Abstract)
  ├── LayoutContainerMixin
  │    ├── ChildContainerMixin
  │    │    └── WidgetContainerMixin
  │    │         ├── FlexContainerBuilder
  │    │         ├── GridContainerBuilder
  │    │         ├── PanelContainerBuilder
  │    │         ├── PageContainerBuilder
  │    │         ├── TabsetContainerBuilder
  │    │         └── ListWidgetBuilder
  │    └── FieldsetContainerBuilder
  │         └── FormFieldBuilder
  └── DialogContainerBuilder
```

---

## Getting Started

### Installation

The Layout Builder is part of the `@acorex/platform/layout/builder` package:

```typescript
import { AXPLayoutBuilderService, AXPLayoutRendererComponent } from '@acorex/platform/layout/builder';
```

### Basic Setup

**Component:**

```typescript
import { Component, OnInit, inject, signal } from '@angular/core';
import { AXPLayoutBuilderService, AXPLayoutRendererComponent } from '@acorex/platform/layout/builder';
import { AXPWidgetNode } from '@acorex/platform/layout/widget-core';

@Component({
  selector: 'app-my-page',
  standalone: true,
  imports: [AXPLayoutRendererComponent],
  template: `
    <axp-layout-renderer 
      [layout]="layoutDefinition()" 
      [(context)]="formContext">
    </axp-layout-renderer>
  `
})
export class MyPageComponent implements OnInit {
  private readonly layoutBuilder = inject(AXPLayoutBuilderService);
  
  layoutDefinition = signal<AXPWidgetNode | undefined>(undefined);
  formContext = signal<any>({ 
    firstName: '', 
    lastName: '', 
    email: '' 
  });

  ngOnInit() {
    this.buildLayout();
  }

  buildLayout() {
    const builder = this.layoutBuilder.create();
    
    builder.flex(flexContainer => {
      flexContainer
        .setDirection('column')
        .setGap('16px')
        .formField('First Name', field => {
          field.path('firstName');
          field.textBox({ placeholder: 'Enter first name' });
        })
        .formField('Last Name', field => {
          field.path('lastName');
          field.textBox({ placeholder: 'Enter last name' });
        });
    });
    
    this.layoutDefinition.set(builder.build());
  }
}
```

---

## Core Concepts

### 1. Containers

Containers hold other containers or widgets. They provide layout structure.

**Available Containers:**
- **Flex**: Flexbox layout (row/column)
- **Grid**: CSS Grid layout
- **Panel**: Card-like container with header
- **Page**: Full page layout
- **Tabset**: Tabbed container
- **Fieldset**: Form section with title/description

### 2. Form Fields

Form fields are special containers that wrap a single widget and provide a label.

```typescript
.formField('Label', field => {
  field.path('fieldPath');     // Data binding path
  field.textBox({ ... });      // Widget type
});
```

### 3. Widgets

Widgets are the actual input/display components. They are always contained within form fields or containers.

### 4. Inheritance Context

Properties like `mode`, `readonly`, `disabled`, and `visible` are automatically inherited from parent containers.

```typescript
builder.flex(flexContainer => {
  flexContainer.mode('view');        // Set parent mode
  flexContainer.readonly(true);      // All children readonly
  
  flexContainer.formField('Name', field => {
    field.textBox();  // Automatically: mode='view', readonly=true
  });
});
```

---

## Container Types

### 1. Flex Container

**Purpose**: Flexbox layout for responsive row/column arrangements.

```typescript
builder.flex(flexContainer => {
  flexContainer
    .setDirection('column')          // row | column | row-reverse | column-reverse
    .setJustifyContent('center')     // flex-start | flex-end | center | space-between | space-around
    .setAlignItems('stretch')        // flex-start | flex-end | center | baseline | stretch
    .setGap('16px')                  // Gap between items
    .setWrap('wrap')                 // nowrap | wrap | wrap-reverse
    .setPadding('20px')
    .setMargin('10px')
    .setBackgroundColor('#f5f5f5');
});
```

### 2. Grid Container

**Purpose**: CSS Grid layout for complex 2D layouts.

```typescript
builder.grid(gridContainer => {
  gridContainer
    .setColumns(3)                   // Number of columns
    .setRows(2)                      // Number of rows
    .setGap('16px')                  // Gap between cells
    .setJustifyItems('center')       // start | end | center | stretch
    .setAlignItems('center')         // start | end | center | stretch
    .setAutoFlow('row')              // row | column | row dense | column dense
    .setPadding('20px')
    .setBackgroundColor('#ffffff');
});
```

### 3. Panel Container

**Purpose**: Card-like container with optional header, icon, and styling.

```typescript
builder.panel(panel => {
  panel
    .setCaption('User Information')  // Header text
    .setIcon('fa-user')              // Header icon
    .setLook('outline')              // solid | fill | outline | flat | none
    .setShowHeader(true)             // Show/hide header
    .setCollapsed(false)             // Collapsed state
    .formField('Name', field => {
      field.textBox();
    });
});
```

### 4. Page Container

**Purpose**: Full page layout with theme support.

```typescript
builder.page(page => {
  page
    .setBackgroundColor('#f9f9f9')
    .setTheme({ id: 'light-theme' })
    .setHasHeader(true)
    .setHasFooter(true)
    .setDirection('ltr')
    .flex(content => {
      // Page content
    });
});
```

### 5. Tabset Container

**Purpose**: Tabbed interface for organizing content.

```typescript
builder.tabset(tabset => {
  tabset
    .setLook('with-line')            // with-line | with-line-color | pills | pills-color
    .setOrientation('horizontal')    // vertical | horizontal
    .setActiveIndex(0)               // Initial active tab
    .panel(tab1 => {
      tab1.setCaption('Tab 1');
      // Tab 1 content
    })
    .panel(tab2 => {
      tab2.setCaption('Tab 2');
      // Tab 2 content
    });
});
```

### 6. Fieldset Container

**Purpose**: Form section with title, description, and multi-column support.

```typescript
builder.fieldset(fieldset => {
  fieldset
    .setTitle('Personal Information')
    .setDescription('Please provide your personal details')
    .setIcon('fa-user')
    .setCols(2)                      // Number of columns for fields
    .setCollapsible(true)
    .setIsOpen(true)
    .setLook('fieldset')             // fieldset | card | group
    .setShowHeader(true)
    .formField('First Name', field => {
      field.textBox();
    })
    .formField('Last Name', field => {
      field.textBox();
    });
});
```

---

## Form Fields

Form fields wrap widgets and provide labels, descriptions, and path management.

### Basic Form Field

```typescript
.formField('Field Label', field => {
  field.path('dataPath');
  field.textBox({ placeholder: 'Enter value' });
});
```

### Form Field Methods

```typescript
.formField('Email', field => {
  field.path('user.email');              // Data binding path
  field.setLabel('Email Address');        // Custom label
  field.setShowLabel(true);              // Show/hide label
  field.mode('edit');                    // edit | view
  field.visible(true);                   // boolean | expression string
  field.readonly(false);                 // boolean | expression string
  field.disabled(false);                 // boolean | expression string
  field.textBox({ 
    placeholder: 'email@example.com',
    prefix: '📧'
  });
});
```

### Auto-Generated Paths

```typescript
// Path from field name
.formField('First Name', field => {
  field.textBox();  // path = 'first_name'
});

// Path from explicit name
.formField('Full Name', field => {
  field.name('fullName');
  field.textBox();  // path = 'fullName'
});

// Path from explicit path
.formField('Name', field => {
  field.path('user.profile.fullName');
  field.textBox();  // path = 'user.profile.fullName'
});
```

---

## Widget Types

### Text Input Widgets

#### 1. Text Box

```typescript
field.textBox({
  placeholder: 'Enter text',
  maxLength: 100,
  minLength: 3,
  prefix: '🔍',
  suffix: '.com',
  clearButton: true
});
```

#### 2. Large Text Box

```typescript
field.largeTextBox({
  placeholder: 'Enter description',
  rows: 4,
  maxLength: 1000,
  resizable: true
});
```

#### 3. Rich Text Editor

```typescript
field.richText({
  placeholder: 'Enter formatted text',
  toolbar: ['bold', 'italic', 'underline', 'link']
});
```

#### 4. Password Box

```typescript
field.passwordBox({
  placeholder: 'Enter password',
  revealToggle: true,
  maxLength: 50
});
```

### Selection Widgets

#### 5. Select Box

```typescript
field.selectBox({
  dataSource: ['Option 1', 'Option 2', 'Option 3'],
  placeholder: 'Select option',
  multiple: false,
  searchable: true,
  clearButton: true
});

// With objects
field.selectBox({
  dataSource: [
    { id: 1, name: 'Option 1' },
    { id: 2, name: 'Option 2' }
  ],
  valueField: 'id',
  textField: 'name',
  placeholder: 'Select option'
});
```

#### 6. Lookup Box

```typescript
field.lookupBox({
  entity: 'human-capital-management.employee',
  multiple: true,
  expose: [
    { source: 'id', target: 'employeeIds.{id}' },
    { source: 'title', target: 'employeeNames.{title}' }
  ],
  searchable: true,
  allowClear: true
});
```

#### 7. Selection List

```typescript
field.selectionList({
  dataSource: ['Option A', 'Option B', 'Option C'],
  multiple: true,
  searchable: false
});
```

### Numeric Widgets

#### 8. Number Box

```typescript
field.numberBox({
  min: 0,
  max: 100,
  step: 1,
  format: '#,##0.00',
  placeholder: 'Enter number'
});
```

### Date/Time Widgets

#### 9. Date Time Box

```typescript
field.dateTimeBox({
  type: 'date',              // date | time | datetime
  format: 'YYYY-MM-DD',
  min: '2024-01-01',
  max: '2024-12-31',
  clearButton: true,
  placeholder: 'Select date'
});
```

### Boolean Widgets

#### 10. Toggle Switch

```typescript
field.toggleSwitch({
  label: 'Enable notifications',
  trueText: 'On',
  falseText: 'Off'
});
```

### Color Widgets

#### 11. Color Box

```typescript
field.colorBox({
  format: 'hex',              // hex | rgb | hsl
  showAlpha: true,
  showPalette: true
});
```

### Custom Widgets

```typescript
field.customWidget('signature-pad', {
  width: 400,
  height: 200,
  backgroundColor: '#ffffff'
});
```

---

## Dialog Builder

The Layout Builder includes built-in dialog support with automatic form rendering and action management.

### Basic Dialog

```typescript
async showDialog() {
  const dialogRef = await this.layoutBuilder
    .create()
    .dialog(dialog => {
      dialog
        .setTitle('User Information')
        .setSize('md')                    // sm | md | lg | xl
        .setCloseButton(false)
        .setContext({ firstName: '', lastName: '' })
        .content(layoutBuilder => {
          layoutBuilder.flex(flex => {
            flex
              .setDirection('column')
              .setGap('16px')
              .formField('First Name', field => {
                field.path('firstName');
                field.textBox({ placeholder: 'Enter first name' });
              })
              .formField('Last Name', field => {
                field.path('lastName');
                field.textBox({ placeholder: 'Enter last name' });
              });
          });
        })
        .setActions(actions => {
          actions
            .cancel('@general:actions.cancel.title')
            .submit('@general:actions.submit.title');
        });
    })
    .show();

  // Wait for user interaction
  const formData = dialogRef.context();
  const action = dialogRef.action();

  if (action === 'submit') {
    console.log('Form data:', formData);
  }

  dialogRef.close();
}
```

### Dialog with Custom Actions

```typescript
.setActions(actions => {
  actions
    .cancel('@general:actions.cancel.title')
    .submit('@general:actions.save.title')
    .custom({
      title: 'Save Draft',
      icon: 'fa-save',
      color: 'secondary',
      command: { name: 'save-draft' }
    });
})
```

### Dialog with Nested Containers

```typescript
.content(layoutBuilder => {
  layoutBuilder.flex(mainFlex => {
    mainFlex
      .setDirection('column')
      .setGap('20px')
      .fieldset(fieldset => {
        fieldset
          .setTitle('Personal Info')
          .setCols(2)
          .formField('First Name', field => {
            field.textBox();
          })
          .formField('Last Name', field => {
            field.textBox();
          });
      })
      .panel(panel => {
        panel
          .setCaption('Additional Info')
          .formField('Phone', field => {
            field.textBox();
          });
      });
  });
})
```

---

## Layout Inheritance

Properties are automatically inherited from parent containers to children.

### Inherited Properties

- **mode**: `edit` | `view`
- **readonly**: `boolean | expression string`
- **disabled**: `boolean | expression string`
- **visible**: `boolean | expression string`
- **direction**: `rtl` | `ltr`

### Example: Parent Sets Mode

```typescript
builder.flex(mainContainer => {
  mainContainer.mode('view');  // All children inherit 'view' mode
  
  mainContainer.formField('Name', field => {
    field.textBox();  // mode = 'view'
  });
  
  mainContainer.formField('Email', field => {
    field.mode('edit');  // Override: mode = 'edit'
    field.textBox();
  });
});
```

### Example: Readonly Inheritance

```typescript
builder.fieldset(fieldset => {
  fieldset.readonly(true);  // All fields readonly
  
  fieldset.formField('First Name', field => {
    field.textBox();  // readonly = true
  });
  
  fieldset.formField('Last Name', field => {
    field.readonly(false);  // Override: readonly = false
    field.textBox();
  });
});
```

### Example: Conditional Visibility

```typescript
builder.flex(container => {
  container.visible("context.eval('user.role') === 'admin'");
  
  container.formField('Admin Settings', field => {
    field.textBox();  // Only visible when user.role === 'admin'
  });
});
```

---

## Complete Examples

### Example 1: Registration Form

```typescript
buildLayout() {
  const builder = this.layoutBuilder.create();
  
  builder.flex(mainContainer => {
    mainContainer
      .mode('edit')
      .setDirection('column')
      .setGap('20px');
    
    // Personal Information
    mainContainer.fieldset(personalFieldset => {
      personalFieldset
        .setTitle('Personal Information')
        .setDescription('Please provide your basic personal details')
        .setIcon('fa-light fa-user')
        .setCols(2)
        .formField('First Name', field => {
          field.path('firstName');
          field.textBox({ 
            placeholder: 'Enter your first name',
            validations: [{ rule: 'required', message: 'First name is required' }]
          });
        })
        .formField('Last Name', field => {
          field.path('lastName');
          field.textBox({ placeholder: 'Enter your last name' });
        })
        .formField('Email Address', field => {
          field.path('email');
          field.textBox({ 
            placeholder: 'Enter your email address',
            prefix: '📧'
          });
        })
        .formField('Phone Number', field => {
          field.path('phone');
          field.textBox({ 
            placeholder: 'Enter your phone number',
            prefix: '📱'
          });
        })
        .formField('Date of Birth', field => {
          field.path('birthDate');
          field.dateTimeBox({ 
            type: 'date',
            placeholder: 'Select your birth date'
          });
        })
        .formField('Gender', field => {
          field.path('gender');
          field.selectBox({
            placeholder: 'Select your gender',
            dataSource: ['Male', 'Female', 'Other', 'Prefer not to say']
          });
        });
    });
    
    // Address Information
    mainContainer.fieldset(addressFieldset => {
      addressFieldset
        .setTitle('Address Information')
        .setDescription('Your current residential address')
        .setIcon('fa-light fa-home')
        .setCols(2)
        .formField('Street Address', field => {
          field.path('address.street');
          field.textBox({ placeholder: 'Enter your street address' });
        })
        .formField('City', field => {
          field.path('address.city');
          field.textBox({ placeholder: 'Enter your city' });
        })
        .formField('State/Province', field => {
          field.path('address.state');
          field.selectBox({
            placeholder: 'Select your state/province',
            dataSource: ['California', 'New York', 'Texas', 'Florida']
          });
        })
        .formField('ZIP/Postal Code', field => {
          field.path('address.zip');
          field.textBox({ placeholder: 'Enter ZIP/postal code' });
        });
    });
    
    // Account Security
    mainContainer.fieldset(securityFieldset => {
      securityFieldset
        .setTitle('Account Security')
        .setDescription('Set up your account credentials')
        .setIcon('fa-light fa-lock')
        .setCols(2)
        .formField('Password', field => {
          field.path('password');
          field.passwordBox({
            placeholder: 'Enter password (min 8 characters)',
            revealToggle: true
          });
        })
        .formField('Confirm Password', field => {
          field.path('confirmPassword');
          field.passwordBox({
            placeholder: 'Confirm your password',
            revealToggle: true
          });
        })
        .formField('Two-Factor Authentication', field => {
          field.path('twoFactorEnabled');
          field.toggleSwitch({
            label: 'Enable Two-Factor Authentication'
          });
        });
    });
  });
  
  return builder.build();
}
```

### Example 2: Dashboard with Tabs

```typescript
buildDashboard() {
  const builder = this.layoutBuilder.create();
  
  builder.page(page => {
    page
      .setBackgroundColor('#f5f5f5')
      .setHasHeader(true)
      .tabset(tabset => {
        tabset
          .setLook('pills')
          .setOrientation('horizontal')
          
          // Overview Tab
          .panel(overviewTab => {
            overviewTab
              .setCaption('Overview')
              .setIcon('fa-chart-line')
              .flex(content => {
                content
                  .setDirection('row')
                  .setGap('20px')
                  .panel(statsPanel => {
                    statsPanel.setCaption('Statistics');
                    // Add stats widgets
                  });
              });
          })
          
          // Settings Tab
          .panel(settingsTab => {
            settingsTab
              .setCaption('Settings')
              .setIcon('fa-cog')
              .fieldset(fieldset => {
                fieldset
                  .setTitle('User Preferences')
                  .setCols(2)
                  .formField('Language', field => {
                    field.selectBox({
                      dataSource: ['English', 'Spanish', 'French']
                    });
                  })
                  .formField('Theme', field => {
                    field.selectBox({
                      dataSource: ['Light', 'Dark', 'Auto']
                    });
                  });
              });
          });
      });
  });
  
  return builder.build();
}
```

### Example 3: Dialog with Nested Panels

```typescript
async showComplexDialog() {
  const dialogRef = await this.layoutBuilder
    .create()
    .dialog(dialog => {
      dialog
        .setTitle('Project Configuration')
        .setSize('xl')
        .setContext({ 
          projectName: '', 
          category: '',
          members: [],
          startDate: null
        })
        .content(layoutBuilder => {
          layoutBuilder.flex(mainFlex => {
            mainFlex
              .setDirection('column')
              .setGap('20px')
              
              // Project Details Panel
              .panel(detailsPanel => {
                detailsPanel
                  .setCaption('Project Details')
                  .setIcon('fa-folder')
                  .fieldset(fieldset => {
                    fieldset
                      .setCols(2)
                      .formField('Project Name', field => {
                        field.path('projectName');
                        field.textBox({ 
                          placeholder: 'Enter project name',
                          validations: [{ rule: 'required' }]
                        });
                      })
                      .formField('Category', field => {
                        field.path('category');
                        field.lookupBox({
                          entity: 'project-management.category',
                          multiple: false
                        });
                      });
                  });
              })
              
              // Team Panel
              .panel(teamPanel => {
                teamPanel
                  .setCaption('Team Members')
                  .setIcon('fa-users')
                  .formField('Members', field => {
                    field.path('members');
                    field.lookupBox({
                      entity: 'human-capital-management.employee',
                      multiple: true,
                      expose: [
                        { source: 'id', target: 'memberIds.{id}' },
                        { source: 'title', target: 'memberNames.{title}' }
                      ]
                    });
                  });
              })
              
              // Timeline Panel
              .panel(timelinePanel => {
                timelinePanel
                  .setCaption('Timeline')
                  .setIcon('fa-calendar')
                  .fieldset(fieldset => {
                    fieldset
                      .setCols(2)
                      .formField('Start Date', field => {
                        field.path('startDate');
                        field.dateTimeBox({
                          type: 'date',
                          format: 'YYYY-MM-DD'
                        });
                      })
                      .formField('End Date', field => {
                        field.path('endDate');
                        field.dateTimeBox({
                          type: 'date',
                          format: 'YYYY-MM-DD'
                        });
                      });
                  });
              });
          });
        })
        .setActions(actions => {
          actions
            .cancel('@general:actions.cancel.title')
            .submit('@general:actions.create.title');
        });
    })
    .show();
  
  const formData = dialogRef.context();
  const action = dialogRef.action();
  
  if (action === 'submit') {
    console.log('Project data:', formData);
  }
  
  dialogRef.close();
}
```

---

## Migration Guide

### From Dynamic Form Builder to Layout Builder

#### Before (Dynamic Form Builder)

```typescript
import { AXPDynamicFormBuilderService } from '@acorex/platform/layout/components';

async showDialog() {
  const dialog = this.formBuilder.dialog();
  const dialogRef = await dialog
    .title('@user:edit.title')
    .size('lg')
    .group('basic-info', group => {
      group
        .field('firstName', field => {
          field.title('@user:firstName');
          field.textBox({ required: true, maxLength: 50 });
        })
        .field('lastName', field => {
          field.title('@user:lastName');
          field.textBox({ required: true, maxLength: 50 });
        });
    })
    .context(user)
    .actions(actions => {
      actions
        .cancel('@general:actions.cancel.title')
        .submit('@general:actions.save.title');
    })
    .show();
  
  const formData = dialogRef.context();
  const action = dialogRef.action();
}
```

#### After (Layout Builder)

```typescript
import { AXPLayoutBuilderService } from '@acorex/platform/layout/builder';

async showDialog() {
  const dialogRef = await this.layoutBuilder
    .create()
    .dialog(dialog => {
      dialog
        .setTitle('@user:edit.title')
        .setSize('lg')
        .setContext(user)
        .content(layoutBuilder => {
          layoutBuilder.flex(flex => {
            flex
              .setDirection('column')
              .setGap('16px')
              .formField('@user:firstName', field => {
                field.path('firstName');
                field.textBox({ 
                  placeholder: 'Enter first name',
                  validations: [{ rule: 'required' }, { rule: 'maxLength', options: { value: 50 } }]
                });
              })
              .formField('@user:lastName', field => {
                field.path('lastName');
                field.textBox({ 
                  placeholder: 'Enter last name',
                  validations: [{ rule: 'required' }, { rule: 'maxLength', options: { value: 50 } }]
                });
              });
          });
        })
        .setActions(actions => {
          actions
            .cancel('@general:actions.cancel.title')
            .submit('@general:actions.save.title');
        });
    })
    .show();
  
  const formData = dialogRef.context();
  const action = dialogRef.action();
}
```

### Key Migration Changes

| Dynamic Form Builder              | Layout Builder |
|-----------------------------------|----------------|
| `.group(name, delegate)`          | `.flex(delegate)` or `.fieldset(delegate)` |
| `.field(path, delegate)`          | `.formField(label, delegate)` + `field.path(path)` |
| `.title(text)`                    | `.setTitle(text)` or `.setCaption(text)` |
| `.mode(mode)`                     | `.mode(mode)` (same, but inherited) |
| Direct widget methods             | Same widget methods |
| `.actions(delegate)`              | `.setActions(delegate)` |
| `.show()`                         | `.show()` (same) |

### Component Migration Example

**Before:**

```typescript
export class SignatureComponent {
  private readonly formBuilder = inject(AXPDynamicFormBuilderService);
  
  async showPopup() {
    const ref = await this.formBuilder
      .dialog()
      .title('Signature')
      .size('lg')
      .group('signature', group => {
        group
          .mode('view')
          .field('preview', field => {
            field
              .options({ readonly: true })
              .widget('image', { src: url, width: '100%' });
          });
      })
      .actions(a => a.cancel('@general:actions.cancel.title'))
      .show();
    ref.close();
  }
}
```

**After:**

```typescript
export class SignatureComponent {
  private readonly layoutBuilder = inject(AXPLayoutBuilderService);
  
  async showPopup() {
    const ref = await this.layoutBuilder
      .create()
      .dialog(dialog => {
        dialog
          .setTitle('Signature')
          .setSize('lg')
          .content(layoutBuilder => {
            layoutBuilder.flex(flex => {
              flex
                .mode('view')
                .formField('Preview', field => {
                  field
                    .readonly(true)
                    .customWidget('image', { 
                      src: url, 
                      width: '100%', 
                      height: 'auto',
                      objectFit: 'contain'
                    });
                });
            });
          })
          .setActions(actions => {
            actions.cancel('@general:actions.cancel.title');
          });
      })
      .show();
    ref.close();
  }
}
```

---

## Best Practices

### 1. Use Descriptive Names

```typescript
// ✅ Good
.formField('User Email Address', field => {
  field.path('user.email');
});

// ❌ Bad
.formField('Email', field => {
  field.path('e');
});
```

### 2. Group Related Fields

```typescript
// ✅ Good
.fieldset(fieldset => {
  fieldset
    .setTitle('Contact Information')
    .setCols(2)
    .formField('Email', field => { ... })
    .formField('Phone', field => { ... });
});

// ❌ Bad - scattered fields
.formField('Email', field => { ... })
.formField('Name', field => { ... })
.formField('Phone', field => { ... })
.formField('Address', field => { ... });
```

### 3. Use Property Inheritance

```typescript
// ✅ Good
.fieldset(fieldset => {
  fieldset.mode('view');  // All fields inherit view mode
  fieldset.formField('Name', field => field.textBox());
  fieldset.formField('Email', field => field.textBox());
});

// ❌ Bad - repetitive
.fieldset(fieldset => {
  fieldset.formField('Name', field => {
    field.mode('view');
    field.textBox();
  });
  fieldset.formField('Email', field => {
    field.mode('view');
    field.textBox();
  });
});
```

### 4. Provide Clear Placeholders

```typescript
// ✅ Good
.formField('Email', field => {
  field.textBox({ 
    placeholder: 'Enter your email address (e.g., user@example.com)'
  });
});

// ❌ Bad
.formField('Email', field => {
  field.textBox();
});
```

### 5. Use Appropriate Container Types

```typescript
// ✅ Good - Use flex for simple vertical/horizontal layouts
.flex(container => {
  container.setDirection('column');
});

// ✅ Good - Use grid for complex 2D layouts
.grid(container => {
  container.setColumns(3).setRows(2);
});

// ❌ Bad - Using grid for simple vertical layout
.grid(container => {
  container.setColumns(1);  // Just use flex!
});
```

### 6. Set Validation Rules

```typescript
// ✅ Good
.formField('Email', field => {
  field.textBox({
    validations: [
      { rule: 'required', message: 'Email is required' },
      { rule: 'email', message: 'Invalid email format' }
    ]
  });
});

// ❌ Bad - No validation
.formField('Email', field => {
  field.textBox();
});
```

### 7. Use Translation Keys

```typescript
// ✅ Good
.setTitle('@module:section.title')
.formField('@module:field.label', field => { ... })

// ❌ Bad - Hardcoded text
.setTitle('User Information')
.formField('Name', field => { ... })
```

### 8. Proper Dialog Context Management

```typescript
// ✅ Good
async showDialog(user: User) {
  const dialogRef = await this.layoutBuilder
    .create()
    .dialog(dialog => {
      dialog.setContext({ ...user });  // Clone the object
      // ... rest of dialog setup
    })
    .show();
  
  const formData = dialogRef.context();
  const action = dialogRef.action();
  
  if (action === 'submit') {
    await this.saveUser(formData);
  }
  
  dialogRef.close();
}

// ❌ Bad - Mutating original object
async showDialog(user: User) {
  const dialogRef = await this.layoutBuilder
    .create()
    .dialog(dialog => {
      dialog.setContext(user);  // Direct reference!
    })
    .show();
}
```

### 9. Organize Complex Forms with Fieldsets

```typescript
// ✅ Good
.flex(mainContainer => {
  mainContainer
    .fieldset(personalInfo => {
      personalInfo.setTitle('Personal Information');
      // Personal fields
    })
    .fieldset(contactInfo => {
      contactInfo.setTitle('Contact Information');
      // Contact fields
    })
    .fieldset(preferences => {
      preferences.setTitle('Preferences');
      // Preference fields
    });
});
```

### 10. Handle Dialog Actions Properly

```typescript
// ✅ Good
const dialogRef = await dialog.show();
const formData = dialogRef.context();
const action = dialogRef.action();

if (action === 'cancel') {
  return { cancelled: true };
}

if (action === 'submit') {
  const isValid = await this.validate(formData);
  if (isValid) {
    await this.save(formData);
    return { cancelled: false, data: formData };
  }
}

dialogRef.close();

// ❌ Bad - No action handling
const dialogRef = await dialog.show();
await this.save(dialogRef.context());
dialogRef.close();
```

---

## API Reference

### AXPLayoutBuilderService

```typescript
class AXPLayoutBuilderService {
  create(): ILayoutBuilder;
}
```

### ILayoutBuilder

```typescript
interface ILayoutBuilder {
  flex(delegate: (container: IFlexContainerBuilder) => void): ILayoutBuilder;
  grid(delegate: (container: IGridContainerBuilder) => void): ILayoutBuilder;
  panel(delegate: (container: IPanelContainerBuilder) => void): ILayoutBuilder;
  page(delegate: (container: IPageContainerBuilder) => void): ILayoutBuilder;
  tabset(delegate: (container: ITabsetContainerBuilder) => void): ILayoutBuilder;
  fieldset(delegate: (container: IFieldsetContainerBuilder) => void): ILayoutBuilder;
  dialog(delegate: (container: IDialogBuilder) => void): IDialogBuilder;
  formField(label: string, delegate?: (field: IFormFieldBuilder) => void): ILayoutBuilder;
  build(): AXPWidgetNode;
}
```

### Container Builders

All container builders extend the base interface:

```typescript
interface IBaseContainerBuilder<TContainer> {
  name(name: string): TContainer;
  path(path: string): TContainer;
  mode(mode: 'edit' | 'view'): TContainer;
  visible(condition: boolean | string): TContainer;
  disabled(condition: boolean | string): TContainer;
  readonly(condition: boolean | string): TContainer;
  direction(direction: 'rtl' | 'ltr'): TContainer;
  build(): AXPWidgetNode;
}
```

### Form Field Builder

```typescript
interface IFormFieldBuilder extends IBaseContainerBuilder<IFormFieldBuilder> {
  setLabel(label: string): IFormFieldBuilder;
  setShowLabel(showLabel: boolean): IFormFieldBuilder;
  
  // Widget methods
  textBox(options?: TextBoxOptions): IFormFieldBuilder;
  largeTextBox(options?: LargeTextBoxOptions): IFormFieldBuilder;
  richText(options?: RichTextOptions): IFormFieldBuilder;
  passwordBox(options?: PasswordBoxOptions): IFormFieldBuilder;
  numberBox(options?: NumberBoxOptions): IFormFieldBuilder;
  selectBox(options: SelectBoxOptions): IFormFieldBuilder;
  lookupBox(options: LookupBoxOptions): IFormFieldBuilder;
  selectionList(options: SelectionListOptions): IFormFieldBuilder;
  dateTimeBox(options?: DateTimeBoxOptions): IFormFieldBuilder;
  toggleSwitch(options?: ToggleSwitchOptions): IFormFieldBuilder;
  colorBox(options?: ColorBoxOptions): IFormFieldBuilder;
  customWidget<T>(type: string, options?: T): IFormFieldBuilder;
}
```

### Dialog Builder

```typescript
interface IDialogBuilder {
  setTitle(title: string): IDialogBuilder;
  setMessage(message?: string): IDialogBuilder;
  setSize(size: 'sm' | 'md' | 'lg' | 'xl'): IDialogBuilder;
  setCloseButton(closeButton: boolean): IDialogBuilder;
  setContext(context: any): IDialogBuilder;
  content(delegate: (layoutBuilder: IFlexContainerBuilder) => void): IDialogBuilder;
  setActions(delegate?: (actions: IActionBuilder) => void): IDialogBuilder;
  show(): Promise<AXPDialogRef>;
}
```

### Action Builder

```typescript
interface IActionBuilder {
  cancel(text?: string): IActionBuilder;
  submit(text?: string): IActionBuilder;
  custom(action: AXPActionMenuItem): IActionBuilder;
}
```

### Dialog Reference

```typescript
interface AXPDialogRef {
  context(): any;
  action(): string;
  setLoading(loading: boolean): void;
  close(): void;
}
```

### Layout Renderer Component

```typescript
@Component({
  selector: 'axp-layout-renderer'
})
class AXPLayoutRendererComponent {
  @Input() layout: AXPWidgetNode | AXPDynamicFormDefinition;
  @Input() context: any;
  @Input() look: 'fieldset' | 'card' | 'group';
  @Input() mode: 'edit' | 'view';
  
  @Output() contextInitiated: EventEmitter<any>;
  @Output() validityChange: EventEmitter<boolean>;
  
  getContext(): any;
  updateContext(context: any): void;
  getWidgetTree(): AXPWidgetNode | null;
  validate(): Promise<AXValidationSummary>;
  clear(): void;
  reset(): void;
}
```

---

## Summary

The **ACoreX Layout Builder** is a comprehensive solution for building dynamic, type-safe layouts in the ACoreX Platform. It provides:

✅ **Fluent API** with delegate pattern for readable code  
✅ **Multiple container types** for flexible layouts  
✅ **Automatic property inheritance** for consistent behavior  
✅ **Built-in dialog support** with action management  
✅ **15+ widgets** with custom widget support  
✅ **Type safety** with full TypeScript support  
✅ **Automatic path generation** for form fields  

For more examples and advanced usage, refer to the [examples directory](./examples/) or contact the platform team.

---

**Last Updated**: October 2025  
**Version**: 1.0.0  
**Maintainer**: ACoreX Platform Team
