# 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.
