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.

    import {FieldOptions, ScalarField, Hint, WithoutLabel} from 'alinea/core'
    import {InputLabel, useField} from 'alinea/dashboard'
    
    interface RangeFieldOptions extends FieldOptions<number> {
      min?: number
      max?: number
    }
    
    class RangeField extends ScalarField<number, RangeFieldOptions> {
    }
    
    // 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: WithoutLabel<RangeFieldOptions> = {}): RangeField {
      return new RangeField({
        hint: Hint.Number(),
        options: {label, ...options},
        view: RangeInput
      })
    }
    
    interface RangeInputProps {
      field: RangeField
    }
    
    // To view our field we can create a React component. 
    // This component can call the useInput hook to receive the
    // current value and a method to update it.
    function RangeInput({field}: RangeInputProps) {
      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'
    
    Config.type('My type', {
      fields: {
        // ...
        myRangeField: range('A range field', {
          min: 0, 
          max: 20
        })
      }
    })

    Field types

    Alinea ships with four kinds of field primitives that can be nested inside each other. Under the covers these are created via Y.js allowing them to be fully collaborative.

    Scalar fields

    Scalar values hold a single value that is overwritten anytime it is changed.

    Record fields

    A record value stores an object with data. The object values can take any shape.

    List fields

    A list holds an array of values, which must be record shapes. Every item in a list has a type, an automatically generated id and an index for sorting added on.

    Rich text fields

    Rich text is an XML like structure for WYSIWYG data.