colonel-kurtz
Version:
140 lines (107 loc) • 4.61 kB
Markdown
# Block Types
1. [Overview](#overview)
2. [Properties](#properties)
3. [Creating Block Types](#creating-block-types)
4. [Advanced Block Types](#advanced-block-types)
5. [Updating content](#updating-content)
## Overview
As it pertains to Colonel Kurtz, a block type is a unique entry that
describes the editing experience for a block. When a block is created,
it will be assigned a `type` equal to the id of a Block Type.
## Properties
| Property | Description |
| ----------- | -------------------------------------------------------------------------------------------------------------- |
| id | A unique identifier. Assigned to a block when it is created. |
| label | A display name given to the block type in the interface. |
| component | A React component used to edit a block of a given type. |
| types | An array of other BlockType ids that may be created as children. |
| maxChildren | An integer specifying the maximum allowed children that may be created. |
| root | Configures the BlockType to display in the menu unless specifically asked for using `types`. Defaults to true. |
| group | When set, groups BlockTypes of the provided string name within the block menu selector. |
## Creating Block Types
Block Types require a unique identifier and a React component
definition. They are added to Colonel Kurtz by passing in a
`blockTypes` property when making an instance:
```javascript
let blockTypes = [
{
id: 'image',
label: 'Image',
component: require('../addons/image')
}
]
```
The `id` value must be unique (the `label` property _should_ be,
however it isn't formally validated). The `component` value requires a
bit more configuration.
Being a React Component, components only mandate a `render`
method. You can update the content for a block with the `onChange`
property that is sent down from the editor:
```javascript
class TextBook extends React.Component {
render() {
return <textarea onBlur={this._onBlur.bind(this)} />
}
_onBlur(e) {
// Alternatively,
// this.props.onChange('text', e.currentTarget.textContent)
this.props.onChange({
text: e.currentTarget.textContent
})
}
}
```
Now that the `Textbox` component has been created, we can send it into
the available block types passed into a `ColonelKurtz` instance.
```javascript
let blockTypes = [
{
id: 'text',
label: 'Textbox',
component: Textbox
}
]
let editor = new ColonelKurtz({
el: document.getElementById('app'),
blockTypes: blockTypes
})
```
## Advanced Block Types
Block types can be as sophisticated as you wish. There technically
isn't anything to stop you from building a React app and assigning it
as a component definition. For an example of this, see [the ArsArsenal
photo gallery](https://github.com/vigetlabs/ars-arsenal).
ArsArsenal can operate as a stand-alone gallery, however it exposes a
"component" key that is useable by Colonel Kurtz:
```javascript
import { Component as ArsArsenal } from 'ars-arsenal'
let blockTypes = [
{
id: 'image',
label: 'Image',
component: ArsArsenal
}
]
```
## Updating content
Each block type is passed an `onChange` property. You can use this property to signal changes to the `content` field for a given block.
There are two ways to update content: provide an object, or a key path and value.
### Updating content with an object
Passing an object into the `onChange` prop will merge the fields provided into the existing content block:
```javascript
changeText(text) {
this.props.onChange({ text })
}
```
### Updating content with a key path and value
By providing a key path and value, Colonel Kurtz update a specific key within the shape of your content. This is particularly useful for updating nested keys.
This behaves similarly to [Lodash's set function](https://lodash.com/docs#set):
```javascript
changeText(text) {
this.props.onChange('text', text)
// { text: text }
this.props.onChange('deeply.nested.key', true)
// { deeply: { nested: { key: true } } }
}
```
By providing a string of `dot` separated values, CK will drill down into content properties on your behalf. This aims to greatly improve the ergonomics of updating nested keys.