diff --git a/resources/js/wysiwyg/lexical/list/LexicalListItemNode.ts b/resources/js/wysiwyg/lexical/list/LexicalListItemNode.ts index c20329e4b..33b021298 100644 --- a/resources/js/wysiwyg/lexical/list/LexicalListItemNode.ts +++ b/resources/js/wysiwyg/lexical/list/LexicalListItemNode.ts @@ -13,7 +13,6 @@ import type { DOMConversionOutput, DOMExportOutput, EditorConfig, - EditorThemeClasses, LexicalNode, NodeKey, ParagraphNode, @@ -22,10 +21,6 @@ import type { Spread, } from 'lexical'; -import { - addClassNamesToElement, - removeClassNamesFromElement, -} from '@lexical/utils'; import { $applyNodeReplacement, $createParagraphNode, @@ -36,11 +31,11 @@ import { LexicalEditor, } from 'lexical'; import invariant from 'lexical/shared/invariant'; -import normalizeClassNames from 'lexical/shared/normalizeClassNames'; import {$createListNode, $isListNode} from './'; -import {$handleIndent, $handleOutdent, mergeLists} from './formatList'; +import {mergeLists} from './formatList'; import {isNestedListNode} from './utils'; +import {el} from "../../utils/dom"; export type SerializedListItemNode = Spread< { @@ -74,11 +69,17 @@ export class ListItemNode extends ElementNode { createDOM(config: EditorConfig): HTMLElement { const element = document.createElement('li'); const parent = this.getParent(); + if ($isListNode(parent) && parent.getListType() === 'check') { - updateListItemChecked(element, this, null, parent); + updateListItemChecked(element, this); } + element.value = this.__value; - $setListItemThemeClassNames(element, config.theme, this); + + if ($hasNestedListWithoutLabel(this)) { + element.style.listStyle = 'none'; + } + return element; } @@ -89,11 +90,12 @@ export class ListItemNode extends ElementNode { ): boolean { const parent = this.getParent(); if ($isListNode(parent) && parent.getListType() === 'check') { - updateListItemChecked(dom, this, prevNode, parent); + updateListItemChecked(dom, this); } + + dom.style.listStyle = $hasNestedListWithoutLabel(this) ? 'none' : ''; // @ts-expect-error - this is always HTMLListItemElement dom.value = this.__value; - $setListItemThemeClassNames(dom, config.theme, this); return false; } @@ -132,6 +134,20 @@ export class ListItemNode extends ElementNode { exportDOM(editor: LexicalEditor): DOMExportOutput { const element = this.createDOM(editor._config); + + if (element.classList.contains('task-list-item')) { + const input = el('input', { + type: 'checkbox', + disabled: 'disabled', + }); + if (element.hasAttribute('checked')) { + input.setAttribute('checked', 'checked'); + element.removeAttribute('checked'); + } + + element.prepend(input); + } + return { element, }; @@ -390,89 +406,33 @@ export class ListItemNode extends ElementNode { } } -function $setListItemThemeClassNames( - dom: HTMLElement, - editorThemeClasses: EditorThemeClasses, - node: ListItemNode, -): void { - const classesToAdd = []; - const classesToRemove = []; - const listTheme = editorThemeClasses.list; - const listItemClassName = listTheme ? listTheme.listitem : undefined; - let nestedListItemClassName; +function $hasNestedListWithoutLabel(node: ListItemNode): boolean { + const children = node.getChildren(); + let hasLabel = false; + let hasNestedList = false; - if (listTheme && listTheme.nested) { - nestedListItemClassName = listTheme.nested.listitem; - } - - if (listItemClassName !== undefined) { - classesToAdd.push(...normalizeClassNames(listItemClassName)); - } - - if (listTheme) { - const parentNode = node.getParent(); - const isCheckList = - $isListNode(parentNode) && parentNode.getListType() === 'check'; - const checked = node.getChecked(); - - if (!isCheckList || checked) { - classesToRemove.push(listTheme.listitemUnchecked); - } - - if (!isCheckList || !checked) { - classesToRemove.push(listTheme.listitemChecked); - } - - if (isCheckList) { - classesToAdd.push( - checked ? listTheme.listitemChecked : listTheme.listitemUnchecked, - ); + for (const child of children) { + if ($isListNode(child)) { + hasNestedList = true; + } else if (child.getTextContent().trim().length > 0) { + hasLabel = true; } } - if (nestedListItemClassName !== undefined) { - const nestedListItemClasses = normalizeClassNames(nestedListItemClassName); - - if (node.getChildren().some((child) => $isListNode(child))) { - classesToAdd.push(...nestedListItemClasses); - } else { - classesToRemove.push(...nestedListItemClasses); - } - } - - if (classesToRemove.length > 0) { - removeClassNamesFromElement(dom, ...classesToRemove); - } - - if (classesToAdd.length > 0) { - addClassNamesToElement(dom, ...classesToAdd); - } + return hasNestedList && !hasLabel; } function updateListItemChecked( dom: HTMLElement, listItemNode: ListItemNode, - prevListItemNode: ListItemNode | null, - listNode: ListNode, ): void { - // Only add attributes for leaf list items - if ($isListNode(listItemNode.getFirstChild())) { - dom.removeAttribute('role'); - dom.removeAttribute('tabIndex'); - dom.removeAttribute('aria-checked'); + // Only set task list attrs for leaf list items + const shouldBeTaskItem = !$isListNode(listItemNode.getFirstChild()); + dom.classList.toggle('task-list-item', shouldBeTaskItem); + if (listItemNode.__checked) { + dom.setAttribute('checked', 'checked'); } else { - dom.setAttribute('role', 'checkbox'); - dom.setAttribute('tabIndex', '-1'); - - if ( - !prevListItemNode || - listItemNode.__checked !== prevListItemNode.__checked - ) { - dom.setAttribute( - 'aria-checked', - listItemNode.getChecked() ? 'true' : 'false', - ); - } + dom.removeAttribute('checked'); } } diff --git a/resources/js/wysiwyg/lexical/list/LexicalListNode.ts b/resources/js/wysiwyg/lexical/list/LexicalListNode.ts index e22fbf771..138c895e6 100644 --- a/resources/js/wysiwyg/lexical/list/LexicalListNode.ts +++ b/resources/js/wysiwyg/lexical/list/LexicalListNode.ts @@ -36,9 +36,11 @@ import { updateChildrenListItemValue, } from './formatList'; import {$getListDepth, $wrapInListItem} from './utils'; +import {extractDirectionFromElement} from "../../nodes/_common"; export type SerializedListNode = Spread< { + id: string; listType: ListType; start: number; tag: ListNodeTagType; @@ -58,15 +60,18 @@ export class ListNode extends ElementNode { __start: number; /** @internal */ __listType: ListType; + /** @internal */ + __id: string = ''; static getType(): string { return 'list'; } static clone(node: ListNode): ListNode { - const listType = node.__listType || TAG_TO_LIST_TYPE[node.__tag]; - - return new ListNode(listType, node.__start, node.__key); + const newNode = new ListNode(node.__listType, node.__start, node.__key); + newNode.__id = node.__id; + newNode.__dir = node.__dir; + return newNode; } constructor(listType: ListType, start: number, key?: NodeKey) { @@ -81,6 +86,16 @@ export class ListNode extends ElementNode { return this.__tag; } + setId(id: string) { + const self = this.getWritable(); + self.__id = id; + } + + getId(): string { + const self = this.getLatest(); + return self.__id; + } + setListType(type: ListType): void { const writable = this.getWritable(); writable.__listType = type; @@ -108,6 +123,14 @@ export class ListNode extends ElementNode { dom.__lexicalListType = this.__listType; $setListThemeClassNames(dom, config.theme, this); + if (this.__id) { + dom.setAttribute('id', this.__id); + } + + if (this.__dir) { + dom.setAttribute('dir', this.__dir); + } + return dom; } @@ -116,7 +139,11 @@ export class ListNode extends ElementNode { dom: HTMLElement, config: EditorConfig, ): boolean { - if (prevNode.__tag !== this.__tag) { + if ( + prevNode.__tag !== this.__tag + || prevNode.__dir !== this.__dir + || prevNode.__id !== this.__id + ) { return true; } @@ -148,8 +175,7 @@ export class ListNode extends ElementNode { static importJSON(serializedNode: SerializedListNode): ListNode { const node = $createListNode(serializedNode.listType, serializedNode.start); - node.setFormat(serializedNode.format); - node.setIndent(serializedNode.indent); + node.setId(serializedNode.id); node.setDirection(serializedNode.direction); return node; } @@ -177,6 +203,7 @@ export class ListNode extends ElementNode { tag: this.getTag(), type: 'list', version: 1, + id: this.__id, }; } @@ -277,28 +304,21 @@ function $setListThemeClassNames( } /* - * This function normalizes the children of a ListNode after the conversion from HTML, - * ensuring that they are all ListItemNodes and contain either a single nested ListNode - * or some other inline content. + * This function is a custom normalization function to allow nested lists within list item elements. + * Original taken from https://github.com/facebook/lexical/blob/6e10210fd1e113ccfafdc999b1d896733c5c5bea/packages/lexical-list/src/LexicalListNode.ts#L284-L303 + * With modifications made. */ function $normalizeChildren(nodes: Array): Array { const normalizedListItems: Array = []; - for (let i = 0; i < nodes.length; i++) { - const node = nodes[i]; + + for (const node of nodes) { if ($isListItemNode(node)) { normalizedListItems.push(node); - const children = node.getChildren(); - if (children.length > 1) { - children.forEach((child) => { - if ($isListNode(child)) { - normalizedListItems.push($wrapInListItem(child)); - } - }); - } } else { normalizedListItems.push($wrapInListItem(node)); } } + return normalizedListItems; } @@ -334,6 +354,14 @@ function $convertListNode(domNode: HTMLElement): DOMConversionOutput { } } + if (domNode.id && node) { + node.setId(domNode.id); + } + + if (domNode.dir && node) { + node.setDirection(extractDirectionFromElement(domNode)); + } + return { after: $normalizeChildren, node, diff --git a/resources/js/wysiwyg/lexical/list/__tests__/unit/LexicalListItemNode.test.ts b/resources/js/wysiwyg/lexical/list/__tests__/unit/LexicalListItemNode.test.ts index 581db0294..523c7eb12 100644 --- a/resources/js/wysiwyg/lexical/list/__tests__/unit/LexicalListItemNode.test.ts +++ b/resources/js/wysiwyg/lexical/list/__tests__/unit/LexicalListItemNode.test.ts @@ -1265,99 +1265,5 @@ describe('LexicalListItemNode tests', () => { expect($isListItemNode(listItemNode)).toBe(true); }); }); - - describe('ListItemNode.setIndent()', () => { - let listNode: ListNode; - let listItemNode1: ListItemNode; - let listItemNode2: ListItemNode; - - beforeEach(async () => { - const {editor} = testEnv; - - await editor.update(() => { - const root = $getRoot(); - listNode = new ListNode('bullet', 1); - listItemNode1 = new ListItemNode(); - - listItemNode2 = new ListItemNode(); - - root.append(listNode); - listNode.append(listItemNode1, listItemNode2); - listItemNode1.append(new TextNode('one')); - listItemNode2.append(new TextNode('two')); - }); - }); - it('indents and outdents list item', async () => { - const {editor} = testEnv; - - await editor.update(() => { - listItemNode1.setIndent(3); - }); - - await editor.update(() => { - expect(listItemNode1.getIndent()).toBe(3); - }); - - expectHtmlToBeEqual( - editor.getRootElement()!.innerHTML, - html` -
    -
  • -
      -
    • -
        -
      • -
          -
        • - one -
        • -
        -
      • -
      -
    • -
    -
  • -
  • - two -
  • -
- `, - ); - - await editor.update(() => { - listItemNode1.setIndent(0); - }); - - await editor.update(() => { - expect(listItemNode1.getIndent()).toBe(0); - }); - - expectHtmlToBeEqual( - editor.getRootElement()!.innerHTML, - html` -
    -
  • - one -
  • -
  • - two -
  • -
- `, - ); - }); - - it('handles fractional indent values', async () => { - const {editor} = testEnv; - - await editor.update(() => { - listItemNode1.setIndent(0.5); - }); - - await editor.update(() => { - expect(listItemNode1.getIndent()).toBe(0); - }); - }); - }); }); }); diff --git a/resources/js/wysiwyg/nodes/custom-list-item.ts b/resources/js/wysiwyg/nodes/custom-list-item.ts deleted file mode 100644 index 11887b436..000000000 --- a/resources/js/wysiwyg/nodes/custom-list-item.ts +++ /dev/null @@ -1,120 +0,0 @@ -import {$isListNode, ListItemNode, SerializedListItemNode} from "@lexical/list"; -import {EditorConfig} from "lexical/LexicalEditor"; -import {DOMExportOutput, LexicalEditor, LexicalNode} from "lexical"; - -import {el} from "../utils/dom"; -import {$isCustomListNode} from "./custom-list"; - -function updateListItemChecked( - dom: HTMLElement, - listItemNode: ListItemNode, -): void { - // Only set task list attrs for leaf list items - const shouldBeTaskItem = !$isListNode(listItemNode.getFirstChild()); - dom.classList.toggle('task-list-item', shouldBeTaskItem); - if (listItemNode.__checked) { - dom.setAttribute('checked', 'checked'); - } else { - dom.removeAttribute('checked'); - } -} - - -export class CustomListItemNode extends ListItemNode { - static getType(): string { - return 'custom-list-item'; - } - - static clone(node: CustomListItemNode): CustomListItemNode { - return new CustomListItemNode(node.__value, node.__checked, node.__key); - } - - createDOM(config: EditorConfig): HTMLElement { - const element = document.createElement('li'); - const parent = this.getParent(); - - if ($isListNode(parent) && parent.getListType() === 'check') { - updateListItemChecked(element, this); - } - - element.value = this.__value; - - if ($hasNestedListWithoutLabel(this)) { - element.style.listStyle = 'none'; - } - - return element; - } - - updateDOM( - prevNode: ListItemNode, - dom: HTMLElement, - config: EditorConfig, - ): boolean { - const parent = this.getParent(); - if ($isListNode(parent) && parent.getListType() === 'check') { - updateListItemChecked(dom, this); - } - - dom.style.listStyle = $hasNestedListWithoutLabel(this) ? 'none' : ''; - // @ts-expect-error - this is always HTMLListItemElement - dom.value = this.__value; - - return false; - } - - exportDOM(editor: LexicalEditor): DOMExportOutput { - const element = this.createDOM(editor._config); - element.style.textAlign = this.getFormatType(); - - if (element.classList.contains('task-list-item')) { - const input = el('input', { - type: 'checkbox', - disabled: 'disabled', - }); - if (element.hasAttribute('checked')) { - input.setAttribute('checked', 'checked'); - element.removeAttribute('checked'); - } - - element.prepend(input); - } - - return { - element, - }; - } - - exportJSON(): SerializedListItemNode { - return { - ...super.exportJSON(), - type: 'custom-list-item', - }; - } -} - -function $hasNestedListWithoutLabel(node: CustomListItemNode): boolean { - const children = node.getChildren(); - let hasLabel = false; - let hasNestedList = false; - - for (const child of children) { - if ($isCustomListNode(child)) { - hasNestedList = true; - } else if (child.getTextContent().trim().length > 0) { - hasLabel = true; - } - } - - return hasNestedList && !hasLabel; -} - -export function $isCustomListItemNode( - node: LexicalNode | null | undefined, -): node is CustomListItemNode { - return node instanceof CustomListItemNode; -} - -export function $createCustomListItemNode(): CustomListItemNode { - return new CustomListItemNode(); -} \ No newline at end of file diff --git a/resources/js/wysiwyg/nodes/custom-list.ts b/resources/js/wysiwyg/nodes/custom-list.ts deleted file mode 100644 index 4b05fa62e..000000000 --- a/resources/js/wysiwyg/nodes/custom-list.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { - DOMConversionFn, - DOMConversionMap, EditorConfig, - LexicalNode, - Spread -} from "lexical"; -import {$isListItemNode, ListItemNode, ListNode, ListType, SerializedListNode} from "@lexical/list"; -import {$createCustomListItemNode} from "./custom-list-item"; -import {extractDirectionFromElement} from "./_common"; - - -export type SerializedCustomListNode = Spread<{ - id: string; -}, SerializedListNode> - -export class CustomListNode extends ListNode { - __id: string = ''; - - static getType() { - return 'custom-list'; - } - - setId(id: string) { - const self = this.getWritable(); - self.__id = id; - } - - getId(): string { - const self = this.getLatest(); - return self.__id; - } - - static clone(node: CustomListNode) { - const newNode = new CustomListNode(node.__listType, node.__start, node.__key); - newNode.__id = node.__id; - newNode.__dir = node.__dir; - return newNode; - } - - createDOM(config: EditorConfig): HTMLElement { - const dom = super.createDOM(config); - if (this.__id) { - dom.setAttribute('id', this.__id); - } - - if (this.__dir) { - dom.setAttribute('dir', this.__dir); - } - - return dom; - } - - updateDOM(prevNode: ListNode, dom: HTMLElement, config: EditorConfig): boolean { - return super.updateDOM(prevNode, dom, config) || - prevNode.__dir !== this.__dir; - } - - exportJSON(): SerializedCustomListNode { - return { - ...super.exportJSON(), - type: 'custom-list', - version: 1, - id: this.__id, - }; - } - - static importJSON(serializedNode: SerializedCustomListNode): CustomListNode { - const node = $createCustomListNode(serializedNode.listType); - node.setId(serializedNode.id); - node.setDirection(serializedNode.direction); - return node; - } - - static importDOM(): DOMConversionMap | null { - // @ts-ignore - const converter = super.importDOM().ol().conversion as DOMConversionFn; - const customConvertFunction = (element: HTMLElement) => { - const baseResult = converter(element); - if (element.id && baseResult?.node) { - (baseResult.node as CustomListNode).setId(element.id); - } - - if (element.dir && baseResult?.node) { - (baseResult.node as CustomListNode).setDirection(extractDirectionFromElement(element)); - } - - if (baseResult) { - baseResult.after = $normalizeChildren; - } - - return baseResult; - }; - - return { - ol: () => ({ - conversion: customConvertFunction, - priority: 0, - }), - ul: () => ({ - conversion: customConvertFunction, - priority: 0, - }), - }; - } -} - -/* - * This function is a custom normalization function to allow nested lists within list item elements. - * Original taken from https://github.com/facebook/lexical/blob/6e10210fd1e113ccfafdc999b1d896733c5c5bea/packages/lexical-list/src/LexicalListNode.ts#L284-L303 - * With modifications made. - * Copyright (c) Meta Platforms, Inc. and affiliates. - * MIT license - */ -function $normalizeChildren(nodes: Array): Array { - const normalizedListItems: Array = []; - - for (const node of nodes) { - if ($isListItemNode(node)) { - normalizedListItems.push(node); - } else { - normalizedListItems.push($wrapInListItem(node)); - } - } - - return normalizedListItems; -} - -function $wrapInListItem(node: LexicalNode): ListItemNode { - const listItemWrapper = $createCustomListItemNode(); - return listItemWrapper.append(node); -} - -export function $createCustomListNode(type: ListType): CustomListNode { - return new CustomListNode(type, 1); -} - -export function $isCustomListNode(node: LexicalNode | null | undefined): node is CustomListNode { - return node instanceof CustomListNode; -} \ No newline at end of file diff --git a/resources/js/wysiwyg/nodes/index.ts b/resources/js/wysiwyg/nodes/index.ts index 7b274eba1..7e0ce9daf 100644 --- a/resources/js/wysiwyg/nodes/index.ts +++ b/resources/js/wysiwyg/nodes/index.ts @@ -17,10 +17,8 @@ import {CodeBlockNode} from "./code-block"; import {DiagramNode} from "./diagram"; import {EditorUiContext} from "../ui/framework/core"; import {MediaNode} from "./media"; -import {CustomListItemNode} from "./custom-list-item"; import {CustomTableCellNode} from "./custom-table-cell"; import {CustomTableRowNode} from "./custom-table-row"; -import {CustomListNode} from "./custom-list"; import {HeadingNode} from "@lexical/rich-text/LexicalHeadingNode"; import {QuoteNode} from "@lexical/rich-text/LexicalQuoteNode"; @@ -32,8 +30,8 @@ export function getNodesForPageEditor(): (KlassConstructor | CalloutNode, HeadingNode, QuoteNode, - CustomListNode, - CustomListItemNode, // TODO - Alignment? + ListNode, + ListItemNode, CustomTableNode, CustomTableRowNode, CustomTableCellNode, @@ -45,18 +43,6 @@ export function getNodesForPageEditor(): (KlassConstructor | MediaNode, // TODO - Alignment ParagraphNode, LinkNode, - { - replace: ListNode, - with: (node: ListNode) => { - return new CustomListNode(node.getListType(), node.getStart()); - } - }, - { - replace: ListItemNode, - with: (node: ListItemNode) => { - return new CustomListItemNode(node.__value, node.__checked); - } - }, { replace: TableNode, with(node: TableNode) { diff --git a/resources/js/wysiwyg/services/keyboard-handling.ts b/resources/js/wysiwyg/services/keyboard-handling.ts index 3f0b0c495..5f7f41ef0 100644 --- a/resources/js/wysiwyg/services/keyboard-handling.ts +++ b/resources/js/wysiwyg/services/keyboard-handling.ts @@ -14,8 +14,8 @@ import {$isImageNode} from "../nodes/image"; import {$isMediaNode} from "../nodes/media"; import {getLastSelection} from "../utils/selection"; import {$getNearestNodeBlockParent} from "../utils/nodes"; -import {$isCustomListItemNode} from "../nodes/custom-list-item"; import {$setInsetForSelection} from "../utils/lists"; +import {$isListItemNode} from "@lexical/list"; function isSingleSelectedNode(nodes: LexicalNode[]): boolean { if (nodes.length === 1) { @@ -62,7 +62,7 @@ function handleInsetOnTab(editor: LexicalEditor, event: KeyboardEvent|null): boo const change = event?.shiftKey ? -40 : 40; const selection = $getSelection(); const nodes = selection?.getNodes() || []; - if (nodes.length > 1 || (nodes.length === 1 && $isCustomListItemNode(nodes[0].getParent()))) { + if (nodes.length > 1 || (nodes.length === 1 && $isListItemNode(nodes[0].getParent()))) { editor.update(() => { $setInsetForSelection(editor, change); }); diff --git a/resources/js/wysiwyg/ui/framework/helpers/task-list-handler.ts b/resources/js/wysiwyg/ui/framework/helpers/task-list-handler.ts index da8c0eae3..62a784d83 100644 --- a/resources/js/wysiwyg/ui/framework/helpers/task-list-handler.ts +++ b/resources/js/wysiwyg/ui/framework/helpers/task-list-handler.ts @@ -1,5 +1,5 @@ import {$getNearestNodeFromDOMNode, LexicalEditor} from "lexical"; -import {$isCustomListItemNode} from "../../../nodes/custom-list-item"; +import {$isListItemNode} from "@lexical/list"; class TaskListHandler { protected editorContainer: HTMLElement; @@ -38,7 +38,7 @@ class TaskListHandler { this.editor.update(() => { const node = $getNearestNodeFromDOMNode(listItem); - if ($isCustomListItemNode(node)) { + if ($isListItemNode(node)) { node.setChecked(!node.getChecked()); } }); diff --git a/resources/js/wysiwyg/utils/formats.ts b/resources/js/wysiwyg/utils/formats.ts index d724730e3..1be802ebf 100644 --- a/resources/js/wysiwyg/utils/formats.ts +++ b/resources/js/wysiwyg/utils/formats.ts @@ -16,8 +16,7 @@ import { } from "./selection"; import {$createCodeBlockNode, $isCodeBlockNode, $openCodeEditorForNode, CodeBlockNode} from "../nodes/code-block"; import {$createCalloutNode, $isCalloutNode, CalloutCategory} from "../nodes/callout"; -import {insertList, ListNode, ListType, removeList} from "@lexical/list"; -import {$isCustomListNode} from "../nodes/custom-list"; +import {$isListNode, insertList, ListNode, ListType, removeList} from "@lexical/list"; import {$createLinkNode, $isLinkNode} from "@lexical/link"; import {$createHeadingNode, $isHeadingNode, HeadingTagType} from "@lexical/rich-text/LexicalHeadingNode"; import {$createQuoteNode, $isQuoteNode} from "@lexical/rich-text/LexicalQuoteNode"; @@ -51,7 +50,7 @@ export function toggleSelectionAsList(editor: LexicalEditor, type: ListType) { editor.getEditorState().read(() => { const selection = $getSelection(); const listSelected = $selectionContainsNodeType(selection, (node: LexicalNode | null | undefined): boolean => { - return $isCustomListNode(node) && (node as ListNode).getListType() === type; + return $isListNode(node) && (node as ListNode).getListType() === type; }); if (listSelected) { diff --git a/resources/js/wysiwyg/utils/lists.ts b/resources/js/wysiwyg/utils/lists.ts index 30a97cbc1..646f341c2 100644 --- a/resources/js/wysiwyg/utils/lists.ts +++ b/resources/js/wysiwyg/utils/lists.ts @@ -1,22 +1,21 @@ -import {$createCustomListItemNode, $isCustomListItemNode, CustomListItemNode} from "../nodes/custom-list-item"; -import {$createCustomListNode, $isCustomListNode} from "../nodes/custom-list"; import {$getSelection, BaseSelection, LexicalEditor} from "lexical"; import {$getBlockElementNodesInSelection, $selectNodes, $toggleSelection} from "./selection"; import {nodeHasInset} from "./nodes"; +import {$createListItemNode, $createListNode, $isListItemNode, $isListNode, ListItemNode} from "@lexical/list"; -export function $nestListItem(node: CustomListItemNode): CustomListItemNode { +export function $nestListItem(node: ListItemNode): ListItemNode { const list = node.getParent(); - if (!$isCustomListNode(list)) { + if (!$isListNode(list)) { return node; } - const listItems = list.getChildren() as CustomListItemNode[]; + const listItems = list.getChildren() as ListItemNode[]; const nodeIndex = listItems.findIndex((n) => n.getKey() === node.getKey()); const isFirst = nodeIndex === 0; - const newListItem = $createCustomListItemNode(); - const newList = $createCustomListNode(list.getListType()); + const newListItem = $createListItemNode(); + const newList = $createListNode(list.getListType()); newList.append(newListItem); newListItem.append(...node.getChildren()); @@ -31,11 +30,11 @@ export function $nestListItem(node: CustomListItemNode): CustomListItemNode { return newListItem; } -export function $unnestListItem(node: CustomListItemNode): CustomListItemNode { +export function $unnestListItem(node: ListItemNode): ListItemNode { const list = node.getParent(); const parentListItem = list?.getParent(); const outerList = parentListItem?.getParent(); - if (!$isCustomListNode(list) || !$isCustomListNode(outerList) || !$isCustomListItemNode(parentListItem)) { + if (!$isListNode(list) || !$isListNode(outerList) || !$isListItemNode(parentListItem)) { return node; } @@ -51,19 +50,19 @@ export function $unnestListItem(node: CustomListItemNode): CustomListItemNode { return node; } -function getListItemsForSelection(selection: BaseSelection|null): (CustomListItemNode|null)[] { +function getListItemsForSelection(selection: BaseSelection|null): (ListItemNode|null)[] { const nodes = selection?.getNodes() || []; const listItemNodes = []; outer: for (const node of nodes) { - if ($isCustomListItemNode(node)) { + if ($isListItemNode(node)) { listItemNodes.push(node); continue; } const parents = node.getParents(); for (const parent of parents) { - if ($isCustomListItemNode(parent)) { + if ($isListItemNode(parent)) { listItemNodes.push(parent); continue outer; } @@ -75,8 +74,8 @@ function getListItemsForSelection(selection: BaseSelection|null): (CustomListIte return listItemNodes; } -function $reduceDedupeListItems(listItems: (CustomListItemNode|null)[]): CustomListItemNode[] { - const listItemMap: Record = {}; +function $reduceDedupeListItems(listItems: (ListItemNode|null)[]): ListItemNode[] { + const listItemMap: Record = {}; for (const item of listItems) { if (item === null) {