import { Node } from 'tiptap'
import { sinkListItem, splitToDefaultListItem, liftListItem } from 'tiptap-commands'
export default class TodoItem extends Node {
get name() {
return 'todo_item'
}
get defaultOptions() {
return {
nested: false,
}
}
get view() {
return {
props: ['node', 'updateAttrs', 'view'],
methods: {
onChange() {
this.updateAttrs({
done: !this.node.attrs.done,
})
},
},
template: `
`,
/*
The render function enables TodoItem to work in `runtimeonly` builds,
which is required for frameworks requiring strict CSP policies. For
example, doing this is required in Chrome Extensions. Having both
the template and the render function ensures there are no issues
converting the node to JSON and rendering the component.
*/
render(h) {
return h('li', {
attrs: {
'data-type': this.node.type.name,
'data-done': this.node.attrs.done.toString(),
'data-drag-handle': '',
},
}, [
h('span', {
class: 'todo-checkbox',
attrs: {
contenteditable: false,
},
on: {
click: this.onChange,
},
}),
h('div', {
class: 'todo-content',
attrs: {
contenteditable: this.view.editable.toString(),
},
ref: 'content',
}),
])
},
}
}
get schema() {
return {
attrs: {
done: {
default: false,
},
},
draggable: true,
content: this.options.nested ? '(paragraph|todo_list)+' : 'paragraph+',
toDOM: node => {
const { done } = node.attrs
return [
'li',
{
'data-type': this.name,
'data-done': done.toString(),
},
['span', { class: 'todo-checkbox', contenteditable: 'false' }],
['div', { class: 'todo-content' }, 0],
]
},
parseDOM: [{
priority: 51,
tag: `[data-type="${this.name}"]`,
getAttrs: dom => ({
done: dom.getAttribute('data-done') === 'true',
}),
}],
}
}
keys({ type }) {
return {
Enter: splitToDefaultListItem(type),
Tab: this.options.nested ? sinkListItem(type) : () => {},
'Shift-Tab': liftListItem(type),
}
}
}