{"version":3,"sources":["../../src/task-item/index.ts","../../src/task-item/task-item.ts"],"sourcesContent":["export * from './task-item.js'\n","import type { KeyboardShortcutCommand } from '@tiptap/core'\nimport { mergeAttributes, Node, renderNestedMarkdownContent, wrappingInputRule } from '@tiptap/core'\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model'\n\nexport interface TaskItemOptions {\n  /**\n   * A callback function that is called when the checkbox is clicked while the editor is in readonly mode.\n   * @param node The prosemirror node of the task item\n   * @param checked The new checked state\n   * @returns boolean\n   */\n  onReadOnlyChecked?: (node: ProseMirrorNode, checked: boolean) => boolean\n\n  /**\n   * Controls whether the task items can be nested or not.\n   * @default false\n   * @example true\n   */\n  nested: boolean\n\n  /**\n   * HTML attributes to add to the task item element.\n   * @default {}\n   * @example { class: 'foo' }\n   */\n  HTMLAttributes: Record<string, any>\n\n  /**\n   * The node type for taskList nodes\n   * @default 'taskList'\n   * @example 'myCustomTaskList'\n   */\n  taskListTypeName: string\n\n  /**\n   * Accessibility options for the task item.\n   * @default {}\n   * @example\n   * ```js\n   * {\n   *   checkboxLabel: (node) => `Task item: ${node.textContent || 'empty task item'}`\n   * }\n   */\n  a11y?: {\n    checkboxLabel?: (node: ProseMirrorNode, checked: boolean) => string\n  }\n}\n\n/**\n * Matches a task item to a - [ ] on input.\n */\nexport const inputRegex = /^\\s*(\\[([( |x])?\\])\\s$/\n\n/**\n * This extension allows you to create task items.\n * @see https://www.tiptap.dev/api/nodes/task-item\n */\nexport const TaskItem = Node.create<TaskItemOptions>({\n  name: 'taskItem',\n\n  addOptions() {\n    return {\n      nested: false,\n      HTMLAttributes: {},\n      taskListTypeName: 'taskList',\n      a11y: undefined,\n    }\n  },\n\n  content() {\n    return this.options.nested ? 'paragraph block*' : 'paragraph+'\n  },\n\n  defining: true,\n\n  addAttributes() {\n    return {\n      checked: {\n        default: false,\n        keepOnSplit: false,\n        parseHTML: element => {\n          const dataChecked = element.getAttribute('data-checked')\n\n          return dataChecked === '' || dataChecked === 'true'\n        },\n        renderHTML: attributes => ({\n          'data-checked': attributes.checked,\n        }),\n      },\n    }\n  },\n\n  parseHTML() {\n    return [\n      {\n        tag: `li[data-type=\"${this.name}\"]`,\n        priority: 51,\n      },\n    ]\n  },\n\n  renderHTML({ node, HTMLAttributes }) {\n    return [\n      'li',\n      mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n        'data-type': this.name,\n      }),\n      [\n        'label',\n        [\n          'input',\n          {\n            type: 'checkbox',\n            checked: node.attrs.checked ? 'checked' : null,\n          },\n        ],\n        ['span'],\n      ],\n      ['div', 0],\n    ]\n  },\n\n  parseMarkdown: (token, h) => {\n    // Parse the task item's text content into paragraph content\n    const content = []\n\n    // First, add the main paragraph content\n    if (token.tokens && token.tokens.length > 0) {\n      // If we have tokens, create a paragraph with the inline content\n      content.push(h.createNode('paragraph', {}, h.parseInline(token.tokens)))\n    } else if (token.text) {\n      // If we have raw text, create a paragraph with text node\n      content.push(h.createNode('paragraph', {}, [h.createNode('text', { text: token.text })]))\n    } else {\n      // Fallback: empty paragraph\n      content.push(h.createNode('paragraph', {}, []))\n    }\n\n    // Then, add any nested content (like nested task lists)\n    if (token.nestedTokens && token.nestedTokens.length > 0) {\n      const nestedContent = h.parseChildren(token.nestedTokens)\n      content.push(...nestedContent)\n    }\n\n    return h.createNode('taskItem', { checked: token.checked || false }, content)\n  },\n\n  renderMarkdown: (node, h) => {\n    const checkedChar = node.attrs?.checked ? 'x' : ' '\n    const prefix = `- [${checkedChar}] `\n\n    return renderNestedMarkdownContent(node, h, prefix)\n  },\n\n  addKeyboardShortcuts() {\n    const shortcuts: {\n      [key: string]: KeyboardShortcutCommand\n    } = {\n      Enter: () => this.editor.commands.splitListItem(this.name),\n      'Shift-Tab': () => this.editor.commands.liftListItem(this.name),\n    }\n\n    if (!this.options.nested) {\n      return shortcuts\n    }\n\n    return {\n      ...shortcuts,\n      Tab: () => this.editor.commands.sinkListItem(this.name),\n    }\n  },\n\n  addNodeView() {\n    return ({ node, HTMLAttributes, getPos, editor }) => {\n      const listItem = document.createElement('li')\n      const checkboxWrapper = document.createElement('label')\n      const checkboxStyler = document.createElement('span')\n      const checkbox = document.createElement('input')\n      const content = document.createElement('div')\n\n      const updateA11Y = (currentNode: ProseMirrorNode) => {\n        checkbox.ariaLabel =\n          this.options.a11y?.checkboxLabel?.(currentNode, checkbox.checked) ||\n          `Task item checkbox for ${currentNode.textContent || 'empty task item'}`\n      }\n\n      updateA11Y(node)\n\n      checkboxWrapper.contentEditable = 'false'\n      checkbox.type = 'checkbox'\n      checkbox.addEventListener('mousedown', event => event.preventDefault())\n      checkbox.addEventListener('change', event => {\n        // if the editor isn’t editable and we don't have a handler for\n        // readonly checks we have to undo the latest change\n        if (!editor.isEditable && !this.options.onReadOnlyChecked) {\n          checkbox.checked = !checkbox.checked\n\n          return\n        }\n\n        const { checked } = event.target as any\n\n        if (editor.isEditable && typeof getPos === 'function') {\n          editor\n            .chain()\n            .focus(undefined, { scrollIntoView: false })\n            .command(({ tr }) => {\n              const position = getPos()\n\n              if (typeof position !== 'number') {\n                return false\n              }\n              const currentNode = tr.doc.nodeAt(position)\n\n              tr.setNodeMarkup(position, undefined, {\n                ...currentNode?.attrs,\n                checked,\n              })\n\n              return true\n            })\n            .run()\n        }\n        if (!editor.isEditable && this.options.onReadOnlyChecked) {\n          // Reset state if onReadOnlyChecked returns false\n          if (!this.options.onReadOnlyChecked(node, checked)) {\n            checkbox.checked = !checkbox.checked\n          }\n        }\n      })\n\n      Object.entries(this.options.HTMLAttributes).forEach(([key, value]) => {\n        listItem.setAttribute(key, value)\n      })\n\n      listItem.dataset.checked = node.attrs.checked\n      checkbox.checked = node.attrs.checked\n\n      checkboxWrapper.append(checkbox, checkboxStyler)\n      listItem.append(checkboxWrapper, content)\n\n      Object.entries(HTMLAttributes).forEach(([key, value]) => {\n        listItem.setAttribute(key, value)\n      })\n\n      return {\n        dom: listItem,\n        contentDOM: content,\n        update: updatedNode => {\n          if (updatedNode.type !== this.type) {\n            return false\n          }\n\n          listItem.dataset.checked = updatedNode.attrs.checked\n          checkbox.checked = updatedNode.attrs.checked\n          updateA11Y(updatedNode)\n\n          return true\n        },\n      }\n    }\n  },\n\n  addInputRules() {\n    return [\n      wrappingInputRule({\n        find: inputRegex,\n        type: this.type,\n        getAttributes: match => ({\n          checked: match[match.length - 1] === 'x',\n        }),\n      }),\n    ]\n  },\n})\n"],"mappings":"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","names":[]}