npm package: @galaxy-dev/metadsl-adapter-antd
Description: Ant Design 5 adapter for MetaDSL
Latest version: 0.10.9

# @galaxy-dev/metadsl-adapter-antd

Ant Design 5 adapter for MetaDSL - provides Ant Design component implementations for the MetaDSL runtime.

## Features

- 🎨 Full Ant Design 5 component support
- 🌍 Built-in i18n support
- 📱 Responsive design with breakpoint support
- 🎯 Expression evaluation for dynamic behavior
- 🔧 TypeScript support with full type definitions
- 🚀 Auto-registration on import

## Installation

```bash
pnpm add @galaxy-dev/metadsl-adapter-antd antd dayjs
```

## Usage

### Basic Setup

```tsx
import { DSLPageProvider, FormRegistryProvider } from '@galaxy-dev/metadsl-runtime';
import { ConfigProvider } from 'antd';
import '@galaxy-dev/metadsl-adapter-antd';
import type { PageDSL } from '@galaxy-dev/metadsl-core';

const pageDSL: PageDSL = {
  type: 'page',
  children: [
    {
      type: 'form',
      name: 'userForm',
      title: 'User Registration',
      description: 'Please fill in your information',
      children: [
        {
          type: 'field',
          fieldType: 'text',
          name: 'username',
          label: 'Username',
          placeholder: 'Enter username',
        },
        {
          type: 'field',
          fieldType: 'select',
          name: 'role',
          label: 'Role',
          options: [
            { value: 'admin', label: 'Administrator' },
            { value: 'user', label: 'User' },
          ],
        },
      ],
    },
  ],
};

function App() {
  return (
    <ConfigProvider theme={{ token: { colorPrimary: '#1890ff' } }}>
      <FormRegistryProvider>
        <DSLPageProvider page={pageDSL} locale="en-US" />
      </FormRegistryProvider>
    </ConfigProvider>
  );
}
```

### Manual Registration

By default, components and fields are auto-registered on import. For manual control:

```tsx
import { registerComponents, registerFields } from '@galaxy-dev/metadsl-adapter-antd';

// Register manually
registerComponents();
registerFields();
```

## Supported Components

### Fields

All fields support DSL props including validation, disabled state, visibility, and i18n.

- **TextField** - Text input with variants (`type: 'text'`, `'email'`, `'password'`)
  - Supports prefix, suffix, addons, and clear button
  - Auto string conversion and validation

- **TextareaField** - Multi-line text input (`type: 'textarea'`)
  - Configurable rows, auto-size, character count

- **SelectField** - Dropdown select (`type: 'select'`)
  - Single/multiple selection modes
  - Search support, loading state

- **CheckboxField** - Checkbox (`type: 'checkbox'`)
  - Label support

- **RadioField** - Radio button group (`type: 'radio'`)
  - Horizontal/vertical layout
  - Button style support

- **SwitchField** - Toggle switch (`type: 'switch'`)
  - Custom checked/unchecked children
  - Loading state

### Layout Components

- **Stack** - Flex-based layout (`type: 'stack'`)
  - Vertical/horizontal direction
  - Responsive spacing
  - Alignment control

### Content Components

- **Button** - Action button (`type: 'button'`)
  - Variants: contained (primary), outlined (default), text
  - Colors: primary, secondary, error
  - Loading and disabled states
  - Expression-based onClick handlers

### Form Components

- **Form** - Form container (`type: 'form'`)
  - Title and description support
  - Action buttons with expression evaluation
  - Integrates with FormRenderer for state management

## Component Naming Convention

All Ant Design imports use the `Antd` prefix for clarity:

```tsx
import { Button as AntdButton, Space as AntdSpace, Typography as AntdTypography } from 'antd';
```

## Architecture

This adapter follows MetaDSL's adapter pattern:

1. **DSL Props** → Adapter-specific props mapping
2. **Expression Evaluation** → Dynamic behavior support
3. **i18n Integration** → Automatic text translation
4. **Registry Pattern** → Auto-registration of components and fields

### 🚨 IMPORTANT: Adapter Component Design Principles

#### 1. DSL is Library-Agnostic

**DSL definitions are unified and contain NO library-specific properties.**

The DSL schema (ButtonDSL, FieldDSL, etc.) only defines common, universal properties that work across ALL adapters:

- ✅ `label`, `placeholder`, `helperText` - universal text fields
- ✅ `disabled`, `visible`, `readOnly` - universal states
- ✅ `variant: 'contained' | 'outlined' | 'text'` - universal button styles
- ❌ NO MUI-specific props (like `sx`, `color: 'inherit'`)
- ❌ NO Ant Design-specific props (like `danger`, `ghost`)

If you need library-specific customization, use the `props` field:

```json
{
  "type": "button",
  "label": "Submit",
  "variant": "contained",
  "props": {
    "danger": true, // Ant Design specific
    "icon": "<CheckOutlined />" // Ant Design specific
  }
}
```

#### 2. Adapters Should NOT Process i18n or Expressions

**Adapter components should NEVER process i18n or expressions themselves.**

All i18n translation and expression evaluation are handled by the runtime layer:

- **ComponentRenderer** - processes component props (label, text, title, etc.)
- **FieldRenderer** - processes field props (label, placeholder, helperText, defaultValue, etc.)

Adapter components receive **already processed props** (translated strings, evaluated booleans/numbers):

```tsx
// ❌ WRONG: Do NOT do this in adapter components
export interface ButtonProps extends ButtonDSL {
  // This would include I18nValue types which are NOT valid as ReactNode
}

export function Button({ label }: ButtonProps) {
  const { i18n } = useDSLContext();
  const translatedLabel = i18n.translate(label); // ❌ Don't translate here!
  return <AntdButton>{translatedLabel}</AntdButton>;
}

// ✅ CORRECT: Adapter components receive processed props
export interface ButtonProps {
  label?: string; // Already translated by ComponentRenderer
  loading?: boolean; // Already evaluated by ComponentRenderer
  disabled?: boolean; // Already evaluated by ComponentRenderer
  // ...
}

export function Button({ label, loading, disabled }: ButtonProps) {
  // Use props directly - they are already processed
  return (
    <AntdButton loading={loading} disabled={disabled}>
      {label}
    </AntdButton>
  );
}
```

**Why this matters:**

1. **Type Safety** - I18nValue (Record<string, string>) is not assignable to ReactNode
2. **Separation of Concerns** - Runtime handles logic, adapters handle presentation
3. **Performance** - Avoid duplicate processing
4. **Consistency** - Same processing logic for all adapters

**Exception:** Components that are NOT rendered through ComponentRenderer/FieldRenderer (like `Form` which wraps `FormRenderer`) need to process their own props using `usePropsProcessor`.

## TypeScript Support

Full TypeScript support with comprehensive type definitions:

```tsx
import type { ButtonProps, StackProps, FormProps } from '@galaxy-dev/metadsl-adapter-antd';
```

## Comparison with MUI Adapter

| Feature           | adapter-mui      | adapter-antd     |
| ----------------- | ---------------- | ---------------- |
| UI Library        | Material-UI 5    | Ant Design 5     |
| Component Count   | 20+              | 9 (growing)      |
| Design System     | Material Design  | Ant Design       |
| Form Handling     | React Final Form | React Final Form |
| i18n              | ✅               | ✅               |
| Expression Engine | ✅               | ✅               |
| Responsive        | ✅               | ✅               |

## License

MIT