Custom fields

    It's possible to create custom fields. A field needs a constructor function that users call to create instances of it in their configuration.

    Range field example

    Let's create a custom field to demonstrate.

    fields/Range.ts
    import {Field} from 'alinea'
    
    export type RangeField = Field.Create<number, {
      min?: number
      max?: number
    }>
    
    // The constructor function is used to create fields in our schema
    // later on. It is usually passed a label and options.
    export function range(label: string, options: Field.Options<RangeField> = {}): RangeField {
      return Field.create({
        label,
        options,
        // Point this
        view: '@/fields/RangeField.view'
      })
    }
    fields/Range.view.tsx
    import {InputLabel, useField} from 'alinea/dashboard'
    import {RangeField} from './Range'
    
    interface RangeViewProps {
      field: RangeField
    }
    
    // To view our field we can create a React component. 
    // This component can call the useField hook to receive the
    // current value and a method to update it.
    export default function RangeView({field}: RangeViewProps) {
      const {value, mutator, options} = useField(field)
      const {min = 0, max = 10} = options
      return (
        <InputLabel {...options}>
          <input 
            type="range" 
            min={min} max={max} 
            value={value} 
            onChange={e => mutator(Number(e.target.value))} 
          />
        </InputLabel>
      )
    }

    To use the field in your types later call the constructor function:

    import {Config} from 'alinea'
    import {range} from './RangeField'
    
    Config.type('My type', {
      fields: {
        // ...
        myRangeField: range('A range field', {
          min: 0, 
          max: 20
        })
      }
    })