> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Inspector grammar

# MetabindUI Inspector Grammar with Zod Compatibility

## Overview

The `inspector` function defines component properties for both UI editing controls and type validation. This grammar is compatible with Zod schemas and can be used to auto-generate TypeScript types.

## Basic Structure

```ts theme={null}
const inspector = () => ({
  propertyName: {
    title: 'Human-readable title',
    type: 'string',
    description: 'Optional description of this property',
    // Additional type-specific fields
  },
  // Additional properties...
});
```

## Mapping to Zod

```ts theme={null}
import { z } from 'zod/v4';

function createZodSchema(inspectorDefinition) {
  const schemaObj = {};

  for (const [key, def] of Object.entries(inspectorDefinition)) {
    let schema;

    switch (def.type) {
      case 'string':
        schema = z.string();
        if (def.minLength !== undefined) schema = schema.min(def.minLength);
        if (def.maxLength !== undefined) schema = schema.max(def.maxLength);
        break;

      case 'number':
        schema = z.number();
        if (def.min !== undefined) schema = schema.min(def.min);
        if (def.max !== undefined) schema = schema.max(def.max);
        break;

      case 'boolean':
        schema = z.boolean();
        break;

      case 'color':
        schema = z.string().regex(/^#/, { message: 'Must be a valid color string' });
        break;

      case 'enum':
        const values = def.options.map(([v]) => v);
        schema = z.enum([...values]);
        break;

      case 'json':
        schema = z.any();
        break;

      case 'array':
        const itemSchema = createZodSchema({ item: def.itemType }).item;
        schema = z.array(itemSchema);
        if (def.minItems !== undefined) schema = schema.min(def.minItems);
        if (def.maxItems !== undefined) schema = schema.max(def.maxItems);
        break;

      case 'object':
        schema = z.object(createZodSchema(def.properties));
        break;

      default:
        schema = z.any();
    }

    if (def.default !== undefined) {
      schema = schema.default(def.default);
    } else if (!def.required) {
      schema = schema.optional();
    }

    schemaObj[key] = schema;
  }

  return schemaObj;
}

// Usage
const zodSchema = z.object(createZodSchema(inspector()));
type MyComponentProps = z.infer<typeof zodSchema>;
```

## Property Types

| Type       | UI Control     | Zod Equivalent                        |
| ---------- | -------------- | ------------------------------------- |
| string     | Text input     | `z.string()`                          |
| number     | Number input   | `z.number()`                          |
| boolean    | Toggle         | `z.boolean()`                         |
| color      | Color picker   | `z.string().regex(/^#/))`             |
| enum       | Dropdown       | `z.enum([...])`                       |
| json       | JSON editor    | `z.any()`                             |
| array      | List           | `z.array(...)`                        |
| object     | Object editor  | `z.object({...})`                     |
| asset      | Media browser  | `z.string()` or `z.array(z.string())` |
| components | Component list | `z.array(...)`                        |

### Common Fields

All property types may include:

* `title`: Human-readable name
* `description`: Description or tooltip
* `default`: Default value
* `required`: Whether the field is mandatory
* `hidden`: Hide from UI editor
* `deprecated`: Mark as deprecated with optional message
* `group`: Group for UI organization
* `condition`: Conditional display rule `{ key, eq }`

## Type-Specific Fields

### String

```ts theme={null}
{
  type: 'string',
  default: 'Default text',
  placeholder: 'Enter text here...',
  multiline: false,
  minLength: 0,
  maxLength: 100
}
```

### Number

```ts theme={null}
{
  type: 'number',
  default: 0,
  min: 0,
  max: 100,
  step: 1,
  unit: 'px',
  slider: true
}
```

### Boolean

```ts theme={null}
{
  type: 'boolean',
  default: false,
  labels: {
    true: 'Enabled',
    false: 'Disabled'
  }
}
```

### Color

```ts theme={null}
{
  type: 'color',
  default: '#ffffff',
  format: 'hex',
  alpha: true
}
```

### Enum

```ts theme={null}
{
  type: 'enum',
  options: [
    ['value1', 'Display 1'],
    ['value2', 'Display 2']
  ],
  default: 'value1'
}
```

### JSON

```ts theme={null}
{
  type: 'json',
  default: { key: 'value' }
}
```

### Array

```ts theme={null}
{
  type: 'array',
  itemType: { type: 'string' },
  default: [],
  minItems: 0,
  maxItems: 10
}
```

### Object

```ts theme={null}
{
  type: 'object',
  properties: {
    field1: { type: 'string', title: 'Field 1' },
    field2: { type: 'number', title: 'Field 2' }
  },
  default: { field1: '', field2: 0 }
}
```

## Advanced Features

### Conditional Properties

```ts theme={null}
{
  type: {
    type: 'enum',
    options: [['simple', 'Simple'], ['advanced', 'Advanced']],
    default: 'simple'
  },
  advancedSetting: {
    type: 'string',
    condition: { key: 'type', eq: 'advanced' }
  }
}
```

### Asset

```ts theme={null}
{
  type: 'asset',
  title: 'Background Image',
  assetTypes: ['image', 'video'], // Optional - defaults to ['image'] if not provided
  multiSelect: false, // Optional - defaults to false if not provided
  default: '' // Optional - ID of default asset
}

// For multi-selection
{
  type: 'asset',
  title: 'Gallery Images',
  assetTypes: ['image'],
  multiSelect: true,
  default: [] // Optional - array of asset IDs
}
```

### Custom Controls

```ts theme={null}
{
  type: 'custom',
  control: 'imagePicker',
  controlProps: {
    source: 'library'
  }
}
```

### Computed Defaults

```ts theme={null}
{
  width: {
    type: 'number',
    default: 100
  },
  height: {
    type: 'number',
    default: '@{width}'
  }
}
```

## TypeScript Type Generation

```ts theme={null}
interface MyComponentProps {
  /** Main heading text */
  title?: string;
  size?: 'small' | 'medium' | 'large';
  showIcon?: boolean;
  iconName?: string;
  colors?: {
    background?: string;
    text?: string;
  };
  padding?: {
    top?: number;
    right?: number;
    bottom?: number;
    left?: number;
  };
  items?: Array<{
    label?: string;
    value?: string;
  }>;
}
```

## Best Practices

1. Use descriptive `title` and `description`.
2. Group related properties with `group`.
3. Set sensible `default` values.
4. Use `condition` to improve UI relevance.
5. Avoid unused fields.
6. Maintain property declaration order.
7. Favor predictable, flat object shapes.
8. Avoid optional fields unless semantically needed.
