import { createExtension } from "../../../editor/BlockNoteExtension.js"; import { createBlockConfig, createBlockSpec } from "../../../schema/index.js"; import { addDefaultPropsExternalHTML, defaultProps, parseDefaultProps, } from "../../defaultProps.js"; import { handleEnter } from "../../utils/listItemEnterHandler.js"; import { getListItemContent } from "../getListItemContent.js"; export type CheckListItemBlockConfig = ReturnType< typeof createCheckListItemConfig >; export const createCheckListItemConfig = createBlockConfig( () => ({ type: "checkListItem" as const, propSchema: { ...defaultProps, checked: { default: false, type: "boolean" }, }, content: "inline", }) as const, ); export const createCheckListItemBlockSpec = createBlockSpec( createCheckListItemConfig, { meta: { isolating: false, }, parse(element) { if (element.tagName === "input") { // Ignore if we already parsed an ancestor list item to avoid double-parsing. if (element.closest("[data-content-type]") || element.closest("li")) { return undefined; } if ((element as HTMLInputElement).type === "checkbox") { return { checked: (element as HTMLInputElement).checked }; } return undefined; } if (element.tagName !== "LI") { return undefined; } const parent = element.parentElement; if (parent === null) { return undefined; } if ( parent.tagName === "UL" || (parent.tagName === "DIV" && parent.parentElement?.tagName === "UL") ) { const checkbox = (element.querySelector("input[type=checkbox]") as HTMLInputElement) || null; if (checkbox === null) { return undefined; } return { ...parseDefaultProps(element), checked: checkbox.checked }; } return; }, // As `li` elements can contain multiple paragraphs, we need to merge their contents // into a single one so that ProseMirror can parse everything correctly. parseContent: ({ el, schema }) => getListItemContent(el, schema, "checkListItem"), render(block, editor) { const dom = document.createDocumentFragment(); const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.checked = block.props.checked; if (block.props.checked) { checkbox.setAttribute("checked", ""); } checkbox.disabled = !editor.isEditable; checkbox.addEventListener("change", () => { if (!editor.isEditable) { return; } editor.updateBlock(block, { props: { checked: !block.props.checked } }); }); // We use a
tag, because for
tag, because for