import { SourceCode } from '@theme';
import { BasicStory, FallbackRendererStory, CustomStrategyStory } from 'components/form-materials/components/constant-inputs';

# ConstantInput

ConstantInput is a constant input component that automatically selects the appropriate input type renderer based on the provided JSON Schema.

The component supports custom rendering strategies and fallback renderers, capable of handling constant inputs for various data types.

## Examples

### Basic Usage

<BasicStory />

```tsx pure title="form-meta.tsx"
const formMeta = {
  render: () => (
    <>
      <FormHeader />
      <Field<string> name="constant_string" defaultValue="Hello World">
        {({ field }) => (
          <ConstantInput
            value={field.value}
            onChange={(value) => field.onChange(value)}
            schema={{ type: 'string' }}
          />
        )}
      </Field>
      <Field<string> name="constant_enum" defaultValue="morning">
        {({ field }) => (
          <ConstantInput
            value={field.value}
            onChange={(value) => field.onChange(value)}
            schema={{ type: 'string', enum: ['morning', 'afternoon'] }}
          />
        )}
      </Field>
    </>
  ),
}
```

:::tip{title="Register Constant Input for New Types"}

Refer to [Type Management](../common/json-schema-preset) to configure constant inputs when registering types

:::

### Fallback Renderer

When the component cannot find a suitable renderer, it will use the fallback renderer:

<FallbackRendererStory />

```tsx pure title="form-meta.tsx"
const formMeta = {
  render: () => (
    <>
      <FormHeader />
      <Field<any> name="constant_fallback" defaultValue={{ custom: 'data' }}>
        {({ field }) => (
          <ConstantInput
            value={field.value}
            onChange={(value) => field.onChange(value)}
            schema={{ type: 'custom-unsupported-type' }}
            fallbackRenderer={({ value, onChange, readonly }) => (
              <div style={{ padding: '8px', background: '#f0f0f0', border: '1px dashed #ccc' }}>
                <p>Fallback renderer for unsupported type</p>
              </div>
            )}
          />
        )}
      </Field>
    </>
  ),
}
```

### Custom Strategy

Use custom rendering strategies to override default behavior:

<CustomStrategyStory />

```tsx pure title="form-meta.tsx"
const formMeta = {
  render: () => (
    <>
      <FormHeader />
      <Field<string> name="constant_custom" defaultValue="Custom Value">
        {({ field }) => (
          <ConstantInput
            value={field.value}
            onChange={(value) => field.onChange(value)}
            schema={{ type: 'object' }}
            strategies={[
              {
                hit: (schema) => schema.type === 'object',
                Renderer: ({ value, onChange, readonly }) => (
                  <p>Object is not supported now</p>
                ),
              },
            ]}
          />
        )}
      </Field>
    </>
  ),
}
```

## API Reference

### ConstantInput Props

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `value` | `any` | - | Input value |
| `onChange` | `(value: any) => void` | - | Callback function when value changes |
| `schema` | `IJsonSchema` | - | JSON Schema used to determine the renderer |
| `strategies` | `Strategy[]` | - | Array of custom rendering strategies |
| `fallbackRenderer` | `React.FC<ConstantRendererProps>` | - | Fallback renderer used when no suitable renderer is found |
| `readonly` | `boolean` | `false` | Whether it is read-only mode |

### Strategy Interface

```typescript
interface Strategy<Value = any> {
  hit: (schema: IJsonSchema) => boolean;
  Renderer: React.FC<ConstantRendererProps<Value>>;
}
```

## Source Code Guide

<SourceCode
  href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/constant-input"
/>

Use CLI command to copy source code locally:

```bash
npx @flowgram.ai/cli@latest materials components/constant-input
```

### Directory Structure

```
constant-input/
├── index.tsx    # Main component implementation, contains ConstantInput core logic
└── types.ts     # Type definitions, including Strategy interface and PropsType
```

### Core Implementation

#### Renderer Selection Logic

The component selects the appropriate renderer through the following steps:

1. **Strategy Matching**: First checks if there are any strategies in the `strategies` array that match the current schema
2. **Type Manager**: If no matching strategy is found, uses the type manager (`useTypeManager`) to get the renderer corresponding to the schema
3. **Fallback Rendering**: If all above fail, uses the provided `fallbackRenderer` or the default disabled input box

#### Type System Integration

ConstantInput is deeply integrated with [**Material Type Management**](../common/json-schema-preset):

- Gets the type manager through the `useTypeManager` Hook
- Uses `typeManager.getTypeBySchema(schema)` to get the renderer for the corresponding type
- Supports all JSON Schema standard types (string, number, boolean, object, array, etc.)

### Dependencies

#### flowgram API

[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable/json-schema)
- [`IJsonSchema`](https://flowgram.ai/auto-docs/json-schema/interfaces/IJsonSchema): JSON Schema type definition
- [`useTypeManager`](https://flowgram.ai/auto-docs/json-schema/functions/useTypeManager): Type manager Hook

#### Third-party Libraries

[**Semi UI**](https://semi.design/en-US)
- Basic input component library, provides default input controls
