mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-08-06 13:38:49 +08:00
add node view to task item
This commit is contained in:
parent
cf8956bca1
commit
b28a322d8b
@ -39,8 +39,8 @@ export default {
|
||||
],
|
||||
content: `
|
||||
<ul data-type="task_list">
|
||||
<li>A list item</li>
|
||||
<li>And another one</li>
|
||||
<li data-type="task_item" data-checked="true">A list item</li>
|
||||
<li data-type="task_item" data-checked="false">And another one</li>
|
||||
</ul>
|
||||
`,
|
||||
})
|
||||
|
@ -8,6 +8,8 @@ import { Extensions, NodeViewRenderer } from './types'
|
||||
import getSchema from './utils/getSchema'
|
||||
import getSchemaTypeByName from './utils/getSchemaTypeByName'
|
||||
import splitExtensions from './utils/splitExtensions'
|
||||
import getAttributesFromExtensions from './utils/getAttributesFromExtensions'
|
||||
import getRenderedAttributes from './utils/getRenderedAttributes'
|
||||
|
||||
export default class ExtensionManager {
|
||||
|
||||
@ -97,14 +99,17 @@ export default class ExtensionManager {
|
||||
}
|
||||
|
||||
get nodeViews() {
|
||||
const { editor } = this
|
||||
const { nodeExtensions } = splitExtensions(this.extensions)
|
||||
const allAttributes = getAttributesFromExtensions(this.extensions)
|
||||
|
||||
return Object.fromEntries(nodeExtensions
|
||||
.filter(extension => !!extension.addNodeView)
|
||||
.map(extension => {
|
||||
const extensionAttributes = allAttributes.filter(attribute => attribute.type === extension.name)
|
||||
const context = {
|
||||
options: extension.options,
|
||||
editor: this.editor,
|
||||
editor,
|
||||
type: getSchemaTypeByName(extension.name, this.schema),
|
||||
}
|
||||
|
||||
@ -115,12 +120,17 @@ export default class ExtensionManager {
|
||||
view: EditorView,
|
||||
getPos: (() => number) | boolean,
|
||||
decorations: Decoration[],
|
||||
) => renderer({
|
||||
editor: this.editor,
|
||||
node,
|
||||
getPos,
|
||||
decorations,
|
||||
})
|
||||
) => {
|
||||
const attributes = getRenderedAttributes(node, extensionAttributes)
|
||||
|
||||
return renderer({
|
||||
editor,
|
||||
node,
|
||||
getPos,
|
||||
decorations,
|
||||
attributes,
|
||||
})
|
||||
}
|
||||
|
||||
return [extension.name, nodeview]
|
||||
}))
|
||||
|
@ -8,7 +8,7 @@ import getNodeType from '../utils/getNodeType'
|
||||
function isList(node: Node, schema: Schema) {
|
||||
return (node.type === schema.nodes.bullet_list
|
||||
|| node.type === schema.nodes.ordered_list
|
||||
|| node.type === schema.nodes.todo_list)
|
||||
|| node.type === schema.nodes.task_list)
|
||||
}
|
||||
|
||||
export const ToggleList = createExtension({
|
||||
|
@ -48,7 +48,8 @@ export type NodeViewRendererProps = {
|
||||
editor: Editor,
|
||||
node: Node,
|
||||
getPos: (() => number) | boolean,
|
||||
decorations: Decoration[]
|
||||
decorations: Decoration[],
|
||||
attributes: AnyObject,
|
||||
}
|
||||
|
||||
export type NodeViewRenderer = (props: NodeViewRendererProps) => NodeView
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Node, Mark } from 'prosemirror-model'
|
||||
import { ExtensionAttribute } from '../types'
|
||||
import { ExtensionAttribute, AnyObject } from '../types'
|
||||
import mergeAttributes from './mergeAttributes'
|
||||
|
||||
export default function getRenderedAttributes(nodeOrMark: Node | Mark, extensionAttributes: ExtensionAttribute[]): { [key: string]: any } {
|
||||
export default function getRenderedAttributes(nodeOrMark: Node | Mark, extensionAttributes: ExtensionAttribute[]): AnyObject {
|
||||
return extensionAttributes
|
||||
.filter(item => item.attribute.rendered)
|
||||
.map(item => {
|
||||
|
@ -22,8 +22,14 @@ const TaskItem = createNode({
|
||||
|
||||
addAttributes() {
|
||||
return {
|
||||
done: {
|
||||
checked: {
|
||||
default: false,
|
||||
parseHTML: element => ({
|
||||
checked: element.getAttribute('data-checked') === 'true',
|
||||
}),
|
||||
renderHTML: attributes => ({
|
||||
'data-checked': attributes.checked,
|
||||
}),
|
||||
},
|
||||
}
|
||||
},
|
||||
@ -42,12 +48,55 @@ const TaskItem = createNode({
|
||||
},
|
||||
|
||||
addKeyboardShortcuts() {
|
||||
return {
|
||||
const shortcuts = {
|
||||
Enter: () => this.editor.splitListItem('task_item'),
|
||||
}
|
||||
|
||||
if (!this.options.nested) {
|
||||
return shortcuts
|
||||
}
|
||||
|
||||
return {
|
||||
...shortcuts,
|
||||
Tab: () => this.editor.sinkListItem('task_item'),
|
||||
'Shift-Tab': () => this.editor.liftListItem('task_item'),
|
||||
}
|
||||
},
|
||||
|
||||
addNodeView() {
|
||||
return ({ attributes, getPos, editor }) => {
|
||||
const { view } = editor
|
||||
const listItem = document.createElement('li')
|
||||
const checkbox = document.createElement('input')
|
||||
const content = document.createElement('div')
|
||||
|
||||
checkbox.type = 'checkbox'
|
||||
checkbox.addEventListener('change', event => {
|
||||
const { checked } = event.target as any
|
||||
|
||||
if (typeof getPos === 'function') {
|
||||
view.dispatch(view.state.tr.setNodeMarkup(getPos(), undefined, {
|
||||
checked,
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
if (attributes['data-checked'] === true) {
|
||||
checkbox.setAttribute('checked', 'checked')
|
||||
}
|
||||
|
||||
listItem.append(checkbox, content)
|
||||
|
||||
Object.entries(attributes).forEach(([key, value]) => {
|
||||
listItem.setAttribute(key, value)
|
||||
})
|
||||
|
||||
return {
|
||||
dom: listItem,
|
||||
contentDOM: content,
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
export default TaskItem
|
||||
|
Loading…
Reference in New Issue
Block a user