It's possible to create custom fields. A field needs a constructor function that users call to create instances of it in their configuration.
Let's create a custom field to demonstrate.
import {alinea} from 'alinea'
import {Field, Hint, Label, Shape} from 'alinea/core'
import {InputLabel, InputState, useInput} from 'alinea/editor'
export interface RangeFieldOptions {
min?: number
max?: number
}
export interface RangeField extends Field.Scalar<number> {
label: Label
options?: 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: Label, options?: RangeFieldOptions): RangeField {
return {
shape: new ScalarShape(label),
label,
options,
view: RangeInput,
hint: Hint.Number()
}
}
interface RangeInputProps {
state: InputState<InputState.Scalar<number>>
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({state, field}: RangeInputProps) {
const [value = 5, setValue] = useInput(state)
const {min = 0, max = 10} = field.options || {}
return (
<InputLabel label={field.label}>
<input
type="range"
min={min} max={max}
value={value}
onChange={e => setValue(Number(e.target.value))}
/>
</InputLabel>
)
}
To use the field in your types later just call the constructor function:
alinea.type('My type', {
...fields,
range: range('A range field', {min: 0, max: 20})
})
To structure the underlying data we use shapes. Alinea ships with four kinds of shape primitives that can be nested inside each other. Under the covers these are created via Yjs allowing them to be fully collaborative.
Scalar values hold a single value that is overwritten anytime it is changed.
A record value store an object with data. The object values can take any shape.
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 is an xml like structure that can hold wysiwyg data.