@udecode/plate-list
Advanced tools
Comparing version 3.1.2 to 3.1.3
# @udecode/plate-list | ||
## 3.1.3 | ||
### Patch Changes | ||
- [`d73b22d0`](https://github.com/udecode/plate/commit/d73b22d03a0fc270265cbd1bdecfcc4adc70b9d8) Thanks [@zbeyens](https://github.com/zbeyens)! - Fix list delete forward | ||
- Updated dependencies [[`f6c58134`](https://github.com/udecode/plate/commit/f6c581347cc5877b7afa0774ef1ad78ad227564e)]: | ||
- @udecode/plate-common@3.1.3 | ||
- @udecode/plate-reset-node@3.1.3 | ||
## 3.1.2 | ||
@@ -4,0 +14,0 @@ |
import { getPlatePluginOptions, getPlatePluginType, getPlatePluginTypes, mapPlatePluginKeysToOptions, isElement, getRenderElement, getSlateClass } from '@udecode/plate-core'; | ||
import { getElementDeserializer, findNode, getParent, match, wrapNodes, findDescendant, getLastChildPath, moveChildren, setNodes, ELEMENT_DEFAULT, unwrapNodes, getAbove, isLastChild, insertNodes, getNode, getNodes, isBlockTextEmptyAfterSelection, isFirstChild, isExpanded, getPreviousPath, deleteFragment, someNode, getChildren, insertEmptyElement, isCollapsed, isSelectionAtBlockStart, isRangeAcrossBlocks, isBlockAboveEmpty, getNodeDeserializer, getToggleElementOnKeyDown } from '@udecode/plate-common'; | ||
import { getElementDeserializer, findNode, getParent, match, wrapNodes, findDescendant, getLastChildPath, moveChildren, setNodes, ELEMENT_DEFAULT, unwrapNodes, getAbove, isLastChild, insertNodes, getNode, getNodes, isBlockTextEmptyAfterSelection, isFirstChild, isExpanded, getPreviousPath, deleteFragment, someNode, isCollapsed, isSelectionAtBlockStart, isRangeAcrossBlocks, isSelectionAtBlockEnd, getChildren, isBlockAboveEmpty, insertEmptyElement, getNodeDeserializer, getToggleElementOnKeyDown } from '@udecode/plate-common'; | ||
import { Path, Editor, Transforms, Range, Node } from 'slate'; | ||
@@ -646,6 +646,13 @@ import { getResetNodeOnKeyDown, SIMULATE_BACKSPACE } from '@udecode/plate-reset-node'; | ||
const moveListItems = (editor, increase = true) => { | ||
const moveListItems = (editor, { | ||
increase = true, | ||
at = (() => { | ||
var _editor$selection; | ||
return (_editor$selection = editor.selection) !== null && _editor$selection !== void 0 ? _editor$selection : undefined; | ||
})() | ||
} = {}) => { | ||
// Get the selected lic | ||
const [...lics] = getNodes(editor, { | ||
at: editor.selection, | ||
at, | ||
match: { | ||
@@ -695,3 +702,5 @@ type: getPlatePluginType(editor, ELEMENT_LIC) | ||
const indentListItems = editor => { | ||
moveListItems(editor, true); | ||
moveListItems(editor, { | ||
increase: true | ||
}); | ||
}; | ||
@@ -913,3 +922,4 @@ | ||
list, | ||
listItem | ||
listItem, | ||
reverse = true | ||
}) => { | ||
@@ -957,3 +967,3 @@ const [liNode, liPath] = listItem; // Stop if the list item has no sublist | ||
deleteFragment(editor, { | ||
reverse: true | ||
reverse | ||
}); | ||
@@ -1024,5 +1034,5 @@ tempLiPath = tempLiPathRef.unref(); // 4 | ||
const unindentListItems = editor => { | ||
moveListItems(editor, false); | ||
}; | ||
const unindentListItems = (editor, options = {}) => moveListItems(editor, { ...options, | ||
increase: false | ||
}); | ||
@@ -1042,3 +1052,5 @@ const getListOnKeyDown = pluginKeys => editor => e => { | ||
e.preventDefault(); | ||
moveListItems(editor, !e.shiftKey); | ||
moveListItems(editor, { | ||
increase: !e.shiftKey | ||
}); | ||
return; | ||
@@ -1068,166 +1080,2 @@ } | ||
/** | ||
* Recursively get all the: | ||
* - block children | ||
* - inline children except those at excludeDepth | ||
*/ | ||
const getDeepInlineChildren = (editor, { | ||
children | ||
}) => { | ||
const inlineChildren = []; | ||
for (const child of children) { | ||
if (Editor.isBlock(editor, child[0])) { | ||
inlineChildren.push(...getDeepInlineChildren(editor, { | ||
children: getChildren(child) | ||
})); | ||
} else { | ||
inlineChildren.push(child); | ||
} | ||
} | ||
return inlineChildren; | ||
}; | ||
/** | ||
* If the list item has no child: insert an empty list item container. | ||
* Else: move the children that are not valid to the list item container. | ||
*/ | ||
const normalizeListItem = (editor, { | ||
listItem, | ||
validLiChildrenTypes = [] | ||
}) => { | ||
let changed = false; | ||
const allValidLiChildrenTypes = [getPlatePluginType(editor, ELEMENT_UL), getPlatePluginType(editor, ELEMENT_OL), getPlatePluginType(editor, ELEMENT_LIC), ...validLiChildrenTypes]; | ||
const [, liPath] = listItem; | ||
const liChildren = getChildren(listItem); // Get invalid (type) li children path refs to be moved | ||
const invalidLiChildrenPathRefs = liChildren.filter(([child]) => !allValidLiChildrenTypes.includes(child.type)).map(([, childPath]) => Editor.pathRef(editor, childPath)); | ||
const firstLiChild = liChildren[0]; | ||
const [firstLiChildNode, firstLiChildPath] = firstLiChild !== null && firstLiChild !== void 0 ? firstLiChild : []; // If li has no child or inline child, insert lic | ||
if (!firstLiChild || !Editor.isBlock(editor, firstLiChildNode)) { | ||
insertEmptyElement(editor, getPlatePluginType(editor, ELEMENT_LIC), { | ||
at: liPath.concat([0]) | ||
}); | ||
return true; | ||
} // If first li child is a block but not lic, set it to lic | ||
if (Editor.isBlock(editor, firstLiChildNode) && !match(firstLiChildNode, { | ||
type: getPlatePluginType(editor, ELEMENT_LIC) | ||
})) { | ||
setNodes(editor, { | ||
type: getPlatePluginType(editor, ELEMENT_LIC) | ||
}); | ||
changed = true; | ||
} | ||
const licChildren = getChildren(firstLiChild); | ||
if (licChildren.length) { | ||
Editor.withoutNormalizing(editor, () => { | ||
var _licChildren; | ||
const blockPathRefs = []; | ||
const inlineChildren = []; // Check that lic has no block children | ||
for (const licChild of licChildren) { | ||
if (!Editor.isBlock(editor, licChild[0])) { | ||
break; | ||
} | ||
blockPathRefs.push(Editor.pathRef(editor, licChild[1])); | ||
inlineChildren.push(...getDeepInlineChildren(editor, { | ||
children: getChildren(licChild) | ||
})); | ||
} | ||
const to = Path.next((_licChildren = licChildren[licChildren.length - 1]) === null || _licChildren === void 0 ? void 0 : _licChildren[1]); // Move lic nested inline children to its children | ||
inlineChildren.reverse().forEach(([, path]) => { | ||
Transforms.moveNodes(editor, { | ||
at: path, | ||
to | ||
}); | ||
}); // Remove lic block children | ||
blockPathRefs.forEach(pathRef => { | ||
const path = pathRef.unref(); | ||
path && Transforms.removeNodes(editor, { | ||
at: path | ||
}); | ||
}); | ||
if (blockPathRefs.length) { | ||
changed = true; | ||
} | ||
}); | ||
} | ||
if (changed) return true; // Ensure that any text nodes under the list are inside the list item container | ||
invalidLiChildrenPathRefs.reverse().forEach(ref => { | ||
const path = ref.unref(); | ||
path && Transforms.moveNodes(editor, { | ||
at: path, | ||
to: firstLiChildPath.concat([0]) | ||
}); | ||
}); | ||
return !!invalidLiChildrenPathRefs.length; | ||
}; | ||
/** | ||
* Normalize list node to force the ul>li>p+ul structure. | ||
*/ | ||
const getListNormalizer = (editor, { | ||
validLiChildrenTypes | ||
}) => { | ||
const { | ||
normalizeNode | ||
} = editor; | ||
const liType = getPlatePluginType(editor, ELEMENT_LI); | ||
const licType = getPlatePluginType(editor, ELEMENT_LIC); | ||
const defaultType = getPlatePluginType(editor, ELEMENT_DEFAULT); | ||
return ([node, path]) => { | ||
if (!isElement(node)) return; | ||
if (match(node, { | ||
type: getListTypes(editor) | ||
})) { | ||
if (!node.children.length || !node.children.find(item => item.type === liType)) { | ||
return Transforms.removeNodes(editor, { | ||
at: path | ||
}); | ||
} | ||
} | ||
if (node.type === getPlatePluginType(editor, ELEMENT_LI)) { | ||
if (normalizeListItem(editor, { | ||
listItem: [node, path], | ||
validLiChildrenTypes | ||
})) { | ||
return; | ||
} | ||
} // LIC should have LI parent. If not, set LIC to DEFAULT type. | ||
if (node.type === licType && licType !== defaultType) { | ||
var _getParent; | ||
if (((_getParent = getParent(editor, path)) === null || _getParent === void 0 ? void 0 : _getParent[0].type) !== liType) { | ||
setNodes(editor, { | ||
type: defaultType | ||
}, { | ||
at: path | ||
}); | ||
return; | ||
} | ||
} | ||
normalizeNode([node, path]); | ||
}; | ||
}; | ||
/** | ||
* If at (default = selection) is in ul>li>p, return li and ul node entries. | ||
@@ -1366,2 +1214,23 @@ */ | ||
/** | ||
* Searches upward for the root list element | ||
*/ | ||
const getListRoot = (editor, at = editor.selection) => { | ||
if (!at) return; | ||
const parentList = getAbove(editor, { | ||
at, | ||
match: { | ||
type: [getPlatePluginType(editor, ELEMENT_UL), getPlatePluginType(editor, ELEMENT_OL)] | ||
} | ||
}); | ||
if (parentList) { | ||
var _getListRoot; | ||
const [, parentListPath] = parentList; | ||
return (_getListRoot = getListRoot(editor, parentListPath)) !== null && _getListRoot !== void 0 ? _getListRoot : parentList; | ||
} | ||
}; | ||
/** | ||
* Is selection across blocks with list items | ||
@@ -1388,2 +1257,65 @@ */ | ||
const pathToEntry = (editor, path) => Editor.node(editor, path); | ||
const getListDeleteForward = editor => { | ||
const res = getListItemEntry(editor, {}); | ||
let moved = false; | ||
if (!isSelectionAtBlockEnd(editor) || !res) { | ||
return moved; | ||
} | ||
Editor.withoutNormalizing(editor, () => { | ||
const { | ||
listItem | ||
} = res; | ||
if (!hasListChild(editor, listItem[0])) { | ||
const li = getPlatePluginOptions(editor, ELEMENT_LI); | ||
const liWithSiblings = Array.from(Editor.nodes(editor, { | ||
at: listItem[1], | ||
mode: 'lowest', | ||
match: (node, path) => { | ||
var _getNode; | ||
if (path.length === 0) { | ||
return false; | ||
} | ||
const isNodeLi = node.type === li.type; | ||
const isSiblingOfNodeLi = ((_getNode = getNode(editor, Path.next(path))) === null || _getNode === void 0 ? void 0 : _getNode.type) === li.type; | ||
return isNodeLi && isSiblingOfNodeLi; | ||
} | ||
}), entry => entry[1])[0]; | ||
if (!liWithSiblings) { | ||
return; | ||
} | ||
const siblingListItem = pathToEntry(editor, Path.next(liWithSiblings)); | ||
const siblingList = Editor.parent(editor, siblingListItem[1]); | ||
moved = removeListItem(editor, { | ||
list: siblingList, | ||
listItem: siblingListItem, | ||
reverse: false | ||
}); | ||
if (moved) return; | ||
return; | ||
} | ||
const nestedList = pathToEntry(editor, Path.next([...listItem[1], 0])); | ||
const nestedListItem = getChildren(nestedList)[0]; | ||
moved = removeFirstListItem(editor, { | ||
list: nestedList, | ||
listItem: nestedListItem | ||
}); | ||
if (moved) return; | ||
moved = removeListItem(editor, { | ||
list: nestedList, | ||
listItem: nestedListItem | ||
}); | ||
}); | ||
return moved; | ||
}; | ||
const getListDeleteFragment = editor => { | ||
@@ -1543,2 +1475,166 @@ let deleted = false; | ||
/** | ||
* Recursively get all the: | ||
* - block children | ||
* - inline children except those at excludeDepth | ||
*/ | ||
const getDeepInlineChildren = (editor, { | ||
children | ||
}) => { | ||
const inlineChildren = []; | ||
for (const child of children) { | ||
if (Editor.isBlock(editor, child[0])) { | ||
inlineChildren.push(...getDeepInlineChildren(editor, { | ||
children: getChildren(child) | ||
})); | ||
} else { | ||
inlineChildren.push(child); | ||
} | ||
} | ||
return inlineChildren; | ||
}; | ||
/** | ||
* If the list item has no child: insert an empty list item container. | ||
* Else: move the children that are not valid to the list item container. | ||
*/ | ||
const normalizeListItem = (editor, { | ||
listItem, | ||
validLiChildrenTypes = [] | ||
}) => { | ||
let changed = false; | ||
const allValidLiChildrenTypes = [getPlatePluginType(editor, ELEMENT_UL), getPlatePluginType(editor, ELEMENT_OL), getPlatePluginType(editor, ELEMENT_LIC), ...validLiChildrenTypes]; | ||
const [, liPath] = listItem; | ||
const liChildren = getChildren(listItem); // Get invalid (type) li children path refs to be moved | ||
const invalidLiChildrenPathRefs = liChildren.filter(([child]) => !allValidLiChildrenTypes.includes(child.type)).map(([, childPath]) => Editor.pathRef(editor, childPath)); | ||
const firstLiChild = liChildren[0]; | ||
const [firstLiChildNode, firstLiChildPath] = firstLiChild !== null && firstLiChild !== void 0 ? firstLiChild : []; // If li has no child or inline child, insert lic | ||
if (!firstLiChild || !Editor.isBlock(editor, firstLiChildNode)) { | ||
insertEmptyElement(editor, getPlatePluginType(editor, ELEMENT_LIC), { | ||
at: liPath.concat([0]) | ||
}); | ||
return true; | ||
} // If first li child is a block but not lic, set it to lic | ||
if (Editor.isBlock(editor, firstLiChildNode) && !match(firstLiChildNode, { | ||
type: getPlatePluginType(editor, ELEMENT_LIC) | ||
})) { | ||
setNodes(editor, { | ||
type: getPlatePluginType(editor, ELEMENT_LIC) | ||
}); | ||
changed = true; | ||
} | ||
const licChildren = getChildren(firstLiChild); | ||
if (licChildren.length) { | ||
Editor.withoutNormalizing(editor, () => { | ||
var _licChildren; | ||
const blockPathRefs = []; | ||
const inlineChildren = []; // Check that lic has no block children | ||
for (const licChild of licChildren) { | ||
if (!Editor.isBlock(editor, licChild[0])) { | ||
break; | ||
} | ||
blockPathRefs.push(Editor.pathRef(editor, licChild[1])); | ||
inlineChildren.push(...getDeepInlineChildren(editor, { | ||
children: getChildren(licChild) | ||
})); | ||
} | ||
const to = Path.next((_licChildren = licChildren[licChildren.length - 1]) === null || _licChildren === void 0 ? void 0 : _licChildren[1]); // Move lic nested inline children to its children | ||
inlineChildren.reverse().forEach(([, path]) => { | ||
Transforms.moveNodes(editor, { | ||
at: path, | ||
to | ||
}); | ||
}); // Remove lic block children | ||
blockPathRefs.forEach(pathRef => { | ||
const path = pathRef.unref(); | ||
path && Transforms.removeNodes(editor, { | ||
at: path | ||
}); | ||
}); | ||
if (blockPathRefs.length) { | ||
changed = true; | ||
} | ||
}); | ||
} | ||
if (changed) return true; // Ensure that any text nodes under the list are inside the list item container | ||
invalidLiChildrenPathRefs.reverse().forEach(ref => { | ||
const path = ref.unref(); | ||
path && Transforms.moveNodes(editor, { | ||
at: path, | ||
to: firstLiChildPath.concat([0]) | ||
}); | ||
}); | ||
return !!invalidLiChildrenPathRefs.length; | ||
}; | ||
/** | ||
* Normalize list node to force the ul>li>p+ul structure. | ||
*/ | ||
const getListNormalizer = (editor, { | ||
validLiChildrenTypes | ||
}) => { | ||
const { | ||
normalizeNode | ||
} = editor; | ||
const liType = getPlatePluginType(editor, ELEMENT_LI); | ||
const licType = getPlatePluginType(editor, ELEMENT_LIC); | ||
const defaultType = getPlatePluginType(editor, ELEMENT_DEFAULT); | ||
return ([node, path]) => { | ||
if (!isElement(node)) return; | ||
if (match(node, { | ||
type: getListTypes(editor) | ||
})) { | ||
if (!node.children.length || !node.children.find(item => item.type === liType)) { | ||
return Transforms.removeNodes(editor, { | ||
at: path | ||
}); | ||
} | ||
} | ||
if (node.type === getPlatePluginType(editor, ELEMENT_LI)) { | ||
if (normalizeListItem(editor, { | ||
listItem: [node, path], | ||
validLiChildrenTypes | ||
})) { | ||
return; | ||
} | ||
} // LIC should have LI parent. If not, set LIC to DEFAULT type. | ||
if (node.type === licType && licType !== defaultType) { | ||
var _getParent; | ||
if (((_getParent = getParent(editor, path)) === null || _getParent === void 0 ? void 0 : _getParent[0].type) !== liType) { | ||
setNodes(editor, { | ||
type: defaultType | ||
}, { | ||
at: path | ||
}); | ||
return; | ||
} | ||
} | ||
normalizeNode([node, path]); | ||
}; | ||
}; | ||
const withList = ({ | ||
@@ -1550,2 +1646,3 @@ validLiChildrenTypes | ||
deleteBackward, | ||
deleteForward, | ||
deleteFragment | ||
@@ -1564,2 +1661,7 @@ } = editor; | ||
editor.deleteForward = unit => { | ||
if (getListDeleteForward(editor)) return; | ||
deleteForward(unit); | ||
}; | ||
editor.deleteFragment = () => { | ||
@@ -1589,23 +1691,2 @@ if (getListDeleteFragment(editor)) return; | ||
/** | ||
* Searches upward for the root list element | ||
*/ | ||
const getListRoot = (editor, at = editor.selection) => { | ||
if (!at) return; | ||
const parentList = getAbove(editor, { | ||
at, | ||
match: { | ||
type: [getPlatePluginType(editor, ELEMENT_UL), getPlatePluginType(editor, ELEMENT_OL)] | ||
} | ||
}); | ||
if (parentList) { | ||
var _getListRoot; | ||
const [, parentListPath] = parentList; | ||
return (_getListRoot = getListRoot(editor, parentListPath)) !== null && _getListRoot !== void 0 ? _getListRoot : parentList; | ||
} | ||
}; | ||
const CLASS_TODO_LIST_CHECKED = 'slate-TodoListElement-rootChecked'; | ||
@@ -1612,0 +1693,0 @@ |
@@ -650,6 +650,13 @@ 'use strict'; | ||
const moveListItems = (editor, increase = true) => { | ||
const moveListItems = (editor, { | ||
increase = true, | ||
at = (() => { | ||
var _editor$selection; | ||
return (_editor$selection = editor.selection) !== null && _editor$selection !== void 0 ? _editor$selection : undefined; | ||
})() | ||
} = {}) => { | ||
// Get the selected lic | ||
const [...lics] = plateCommon.getNodes(editor, { | ||
at: editor.selection, | ||
at, | ||
match: { | ||
@@ -699,3 +706,5 @@ type: plateCore.getPlatePluginType(editor, ELEMENT_LIC) | ||
const indentListItems = editor => { | ||
moveListItems(editor, true); | ||
moveListItems(editor, { | ||
increase: true | ||
}); | ||
}; | ||
@@ -917,3 +926,4 @@ | ||
list, | ||
listItem | ||
listItem, | ||
reverse = true | ||
}) => { | ||
@@ -961,3 +971,3 @@ const [liNode, liPath] = listItem; // Stop if the list item has no sublist | ||
plateCommon.deleteFragment(editor, { | ||
reverse: true | ||
reverse | ||
}); | ||
@@ -1028,5 +1038,5 @@ tempLiPath = tempLiPathRef.unref(); // 4 | ||
const unindentListItems = editor => { | ||
moveListItems(editor, false); | ||
}; | ||
const unindentListItems = (editor, options = {}) => moveListItems(editor, { ...options, | ||
increase: false | ||
}); | ||
@@ -1046,3 +1056,5 @@ const getListOnKeyDown = pluginKeys => editor => e => { | ||
e.preventDefault(); | ||
moveListItems(editor, !e.shiftKey); | ||
moveListItems(editor, { | ||
increase: !e.shiftKey | ||
}); | ||
return; | ||
@@ -1072,166 +1084,2 @@ } | ||
/** | ||
* Recursively get all the: | ||
* - block children | ||
* - inline children except those at excludeDepth | ||
*/ | ||
const getDeepInlineChildren = (editor, { | ||
children | ||
}) => { | ||
const inlineChildren = []; | ||
for (const child of children) { | ||
if (slate.Editor.isBlock(editor, child[0])) { | ||
inlineChildren.push(...getDeepInlineChildren(editor, { | ||
children: plateCommon.getChildren(child) | ||
})); | ||
} else { | ||
inlineChildren.push(child); | ||
} | ||
} | ||
return inlineChildren; | ||
}; | ||
/** | ||
* If the list item has no child: insert an empty list item container. | ||
* Else: move the children that are not valid to the list item container. | ||
*/ | ||
const normalizeListItem = (editor, { | ||
listItem, | ||
validLiChildrenTypes = [] | ||
}) => { | ||
let changed = false; | ||
const allValidLiChildrenTypes = [plateCore.getPlatePluginType(editor, ELEMENT_UL), plateCore.getPlatePluginType(editor, ELEMENT_OL), plateCore.getPlatePluginType(editor, ELEMENT_LIC), ...validLiChildrenTypes]; | ||
const [, liPath] = listItem; | ||
const liChildren = plateCommon.getChildren(listItem); // Get invalid (type) li children path refs to be moved | ||
const invalidLiChildrenPathRefs = liChildren.filter(([child]) => !allValidLiChildrenTypes.includes(child.type)).map(([, childPath]) => slate.Editor.pathRef(editor, childPath)); | ||
const firstLiChild = liChildren[0]; | ||
const [firstLiChildNode, firstLiChildPath] = firstLiChild !== null && firstLiChild !== void 0 ? firstLiChild : []; // If li has no child or inline child, insert lic | ||
if (!firstLiChild || !slate.Editor.isBlock(editor, firstLiChildNode)) { | ||
plateCommon.insertEmptyElement(editor, plateCore.getPlatePluginType(editor, ELEMENT_LIC), { | ||
at: liPath.concat([0]) | ||
}); | ||
return true; | ||
} // If first li child is a block but not lic, set it to lic | ||
if (slate.Editor.isBlock(editor, firstLiChildNode) && !plateCommon.match(firstLiChildNode, { | ||
type: plateCore.getPlatePluginType(editor, ELEMENT_LIC) | ||
})) { | ||
plateCommon.setNodes(editor, { | ||
type: plateCore.getPlatePluginType(editor, ELEMENT_LIC) | ||
}); | ||
changed = true; | ||
} | ||
const licChildren = plateCommon.getChildren(firstLiChild); | ||
if (licChildren.length) { | ||
slate.Editor.withoutNormalizing(editor, () => { | ||
var _licChildren; | ||
const blockPathRefs = []; | ||
const inlineChildren = []; // Check that lic has no block children | ||
for (const licChild of licChildren) { | ||
if (!slate.Editor.isBlock(editor, licChild[0])) { | ||
break; | ||
} | ||
blockPathRefs.push(slate.Editor.pathRef(editor, licChild[1])); | ||
inlineChildren.push(...getDeepInlineChildren(editor, { | ||
children: plateCommon.getChildren(licChild) | ||
})); | ||
} | ||
const to = slate.Path.next((_licChildren = licChildren[licChildren.length - 1]) === null || _licChildren === void 0 ? void 0 : _licChildren[1]); // Move lic nested inline children to its children | ||
inlineChildren.reverse().forEach(([, path]) => { | ||
slate.Transforms.moveNodes(editor, { | ||
at: path, | ||
to | ||
}); | ||
}); // Remove lic block children | ||
blockPathRefs.forEach(pathRef => { | ||
const path = pathRef.unref(); | ||
path && slate.Transforms.removeNodes(editor, { | ||
at: path | ||
}); | ||
}); | ||
if (blockPathRefs.length) { | ||
changed = true; | ||
} | ||
}); | ||
} | ||
if (changed) return true; // Ensure that any text nodes under the list are inside the list item container | ||
invalidLiChildrenPathRefs.reverse().forEach(ref => { | ||
const path = ref.unref(); | ||
path && slate.Transforms.moveNodes(editor, { | ||
at: path, | ||
to: firstLiChildPath.concat([0]) | ||
}); | ||
}); | ||
return !!invalidLiChildrenPathRefs.length; | ||
}; | ||
/** | ||
* Normalize list node to force the ul>li>p+ul structure. | ||
*/ | ||
const getListNormalizer = (editor, { | ||
validLiChildrenTypes | ||
}) => { | ||
const { | ||
normalizeNode | ||
} = editor; | ||
const liType = plateCore.getPlatePluginType(editor, ELEMENT_LI); | ||
const licType = plateCore.getPlatePluginType(editor, ELEMENT_LIC); | ||
const defaultType = plateCore.getPlatePluginType(editor, plateCommon.ELEMENT_DEFAULT); | ||
return ([node, path]) => { | ||
if (!plateCore.isElement(node)) return; | ||
if (plateCommon.match(node, { | ||
type: getListTypes(editor) | ||
})) { | ||
if (!node.children.length || !node.children.find(item => item.type === liType)) { | ||
return slate.Transforms.removeNodes(editor, { | ||
at: path | ||
}); | ||
} | ||
} | ||
if (node.type === plateCore.getPlatePluginType(editor, ELEMENT_LI)) { | ||
if (normalizeListItem(editor, { | ||
listItem: [node, path], | ||
validLiChildrenTypes | ||
})) { | ||
return; | ||
} | ||
} // LIC should have LI parent. If not, set LIC to DEFAULT type. | ||
if (node.type === licType && licType !== defaultType) { | ||
var _getParent; | ||
if (((_getParent = plateCommon.getParent(editor, path)) === null || _getParent === void 0 ? void 0 : _getParent[0].type) !== liType) { | ||
plateCommon.setNodes(editor, { | ||
type: defaultType | ||
}, { | ||
at: path | ||
}); | ||
return; | ||
} | ||
} | ||
normalizeNode([node, path]); | ||
}; | ||
}; | ||
/** | ||
* If at (default = selection) is in ul>li>p, return li and ul node entries. | ||
@@ -1370,2 +1218,23 @@ */ | ||
/** | ||
* Searches upward for the root list element | ||
*/ | ||
const getListRoot = (editor, at = editor.selection) => { | ||
if (!at) return; | ||
const parentList = plateCommon.getAbove(editor, { | ||
at, | ||
match: { | ||
type: [plateCore.getPlatePluginType(editor, ELEMENT_UL), plateCore.getPlatePluginType(editor, ELEMENT_OL)] | ||
} | ||
}); | ||
if (parentList) { | ||
var _getListRoot; | ||
const [, parentListPath] = parentList; | ||
return (_getListRoot = getListRoot(editor, parentListPath)) !== null && _getListRoot !== void 0 ? _getListRoot : parentList; | ||
} | ||
}; | ||
/** | ||
* Is selection across blocks with list items | ||
@@ -1392,2 +1261,65 @@ */ | ||
const pathToEntry = (editor, path) => slate.Editor.node(editor, path); | ||
const getListDeleteForward = editor => { | ||
const res = getListItemEntry(editor, {}); | ||
let moved = false; | ||
if (!plateCommon.isSelectionAtBlockEnd(editor) || !res) { | ||
return moved; | ||
} | ||
slate.Editor.withoutNormalizing(editor, () => { | ||
const { | ||
listItem | ||
} = res; | ||
if (!hasListChild(editor, listItem[0])) { | ||
const li = plateCore.getPlatePluginOptions(editor, ELEMENT_LI); | ||
const liWithSiblings = Array.from(slate.Editor.nodes(editor, { | ||
at: listItem[1], | ||
mode: 'lowest', | ||
match: (node, path) => { | ||
var _getNode; | ||
if (path.length === 0) { | ||
return false; | ||
} | ||
const isNodeLi = node.type === li.type; | ||
const isSiblingOfNodeLi = ((_getNode = plateCommon.getNode(editor, slate.Path.next(path))) === null || _getNode === void 0 ? void 0 : _getNode.type) === li.type; | ||
return isNodeLi && isSiblingOfNodeLi; | ||
} | ||
}), entry => entry[1])[0]; | ||
if (!liWithSiblings) { | ||
return; | ||
} | ||
const siblingListItem = pathToEntry(editor, slate.Path.next(liWithSiblings)); | ||
const siblingList = slate.Editor.parent(editor, siblingListItem[1]); | ||
moved = removeListItem(editor, { | ||
list: siblingList, | ||
listItem: siblingListItem, | ||
reverse: false | ||
}); | ||
if (moved) return; | ||
return; | ||
} | ||
const nestedList = pathToEntry(editor, slate.Path.next([...listItem[1], 0])); | ||
const nestedListItem = plateCommon.getChildren(nestedList)[0]; | ||
moved = removeFirstListItem(editor, { | ||
list: nestedList, | ||
listItem: nestedListItem | ||
}); | ||
if (moved) return; | ||
moved = removeListItem(editor, { | ||
list: nestedList, | ||
listItem: nestedListItem | ||
}); | ||
}); | ||
return moved; | ||
}; | ||
const getListDeleteFragment = editor => { | ||
@@ -1547,2 +1479,166 @@ let deleted = false; | ||
/** | ||
* Recursively get all the: | ||
* - block children | ||
* - inline children except those at excludeDepth | ||
*/ | ||
const getDeepInlineChildren = (editor, { | ||
children | ||
}) => { | ||
const inlineChildren = []; | ||
for (const child of children) { | ||
if (slate.Editor.isBlock(editor, child[0])) { | ||
inlineChildren.push(...getDeepInlineChildren(editor, { | ||
children: plateCommon.getChildren(child) | ||
})); | ||
} else { | ||
inlineChildren.push(child); | ||
} | ||
} | ||
return inlineChildren; | ||
}; | ||
/** | ||
* If the list item has no child: insert an empty list item container. | ||
* Else: move the children that are not valid to the list item container. | ||
*/ | ||
const normalizeListItem = (editor, { | ||
listItem, | ||
validLiChildrenTypes = [] | ||
}) => { | ||
let changed = false; | ||
const allValidLiChildrenTypes = [plateCore.getPlatePluginType(editor, ELEMENT_UL), plateCore.getPlatePluginType(editor, ELEMENT_OL), plateCore.getPlatePluginType(editor, ELEMENT_LIC), ...validLiChildrenTypes]; | ||
const [, liPath] = listItem; | ||
const liChildren = plateCommon.getChildren(listItem); // Get invalid (type) li children path refs to be moved | ||
const invalidLiChildrenPathRefs = liChildren.filter(([child]) => !allValidLiChildrenTypes.includes(child.type)).map(([, childPath]) => slate.Editor.pathRef(editor, childPath)); | ||
const firstLiChild = liChildren[0]; | ||
const [firstLiChildNode, firstLiChildPath] = firstLiChild !== null && firstLiChild !== void 0 ? firstLiChild : []; // If li has no child or inline child, insert lic | ||
if (!firstLiChild || !slate.Editor.isBlock(editor, firstLiChildNode)) { | ||
plateCommon.insertEmptyElement(editor, plateCore.getPlatePluginType(editor, ELEMENT_LIC), { | ||
at: liPath.concat([0]) | ||
}); | ||
return true; | ||
} // If first li child is a block but not lic, set it to lic | ||
if (slate.Editor.isBlock(editor, firstLiChildNode) && !plateCommon.match(firstLiChildNode, { | ||
type: plateCore.getPlatePluginType(editor, ELEMENT_LIC) | ||
})) { | ||
plateCommon.setNodes(editor, { | ||
type: plateCore.getPlatePluginType(editor, ELEMENT_LIC) | ||
}); | ||
changed = true; | ||
} | ||
const licChildren = plateCommon.getChildren(firstLiChild); | ||
if (licChildren.length) { | ||
slate.Editor.withoutNormalizing(editor, () => { | ||
var _licChildren; | ||
const blockPathRefs = []; | ||
const inlineChildren = []; // Check that lic has no block children | ||
for (const licChild of licChildren) { | ||
if (!slate.Editor.isBlock(editor, licChild[0])) { | ||
break; | ||
} | ||
blockPathRefs.push(slate.Editor.pathRef(editor, licChild[1])); | ||
inlineChildren.push(...getDeepInlineChildren(editor, { | ||
children: plateCommon.getChildren(licChild) | ||
})); | ||
} | ||
const to = slate.Path.next((_licChildren = licChildren[licChildren.length - 1]) === null || _licChildren === void 0 ? void 0 : _licChildren[1]); // Move lic nested inline children to its children | ||
inlineChildren.reverse().forEach(([, path]) => { | ||
slate.Transforms.moveNodes(editor, { | ||
at: path, | ||
to | ||
}); | ||
}); // Remove lic block children | ||
blockPathRefs.forEach(pathRef => { | ||
const path = pathRef.unref(); | ||
path && slate.Transforms.removeNodes(editor, { | ||
at: path | ||
}); | ||
}); | ||
if (blockPathRefs.length) { | ||
changed = true; | ||
} | ||
}); | ||
} | ||
if (changed) return true; // Ensure that any text nodes under the list are inside the list item container | ||
invalidLiChildrenPathRefs.reverse().forEach(ref => { | ||
const path = ref.unref(); | ||
path && slate.Transforms.moveNodes(editor, { | ||
at: path, | ||
to: firstLiChildPath.concat([0]) | ||
}); | ||
}); | ||
return !!invalidLiChildrenPathRefs.length; | ||
}; | ||
/** | ||
* Normalize list node to force the ul>li>p+ul structure. | ||
*/ | ||
const getListNormalizer = (editor, { | ||
validLiChildrenTypes | ||
}) => { | ||
const { | ||
normalizeNode | ||
} = editor; | ||
const liType = plateCore.getPlatePluginType(editor, ELEMENT_LI); | ||
const licType = plateCore.getPlatePluginType(editor, ELEMENT_LIC); | ||
const defaultType = plateCore.getPlatePluginType(editor, plateCommon.ELEMENT_DEFAULT); | ||
return ([node, path]) => { | ||
if (!plateCore.isElement(node)) return; | ||
if (plateCommon.match(node, { | ||
type: getListTypes(editor) | ||
})) { | ||
if (!node.children.length || !node.children.find(item => item.type === liType)) { | ||
return slate.Transforms.removeNodes(editor, { | ||
at: path | ||
}); | ||
} | ||
} | ||
if (node.type === plateCore.getPlatePluginType(editor, ELEMENT_LI)) { | ||
if (normalizeListItem(editor, { | ||
listItem: [node, path], | ||
validLiChildrenTypes | ||
})) { | ||
return; | ||
} | ||
} // LIC should have LI parent. If not, set LIC to DEFAULT type. | ||
if (node.type === licType && licType !== defaultType) { | ||
var _getParent; | ||
if (((_getParent = plateCommon.getParent(editor, path)) === null || _getParent === void 0 ? void 0 : _getParent[0].type) !== liType) { | ||
plateCommon.setNodes(editor, { | ||
type: defaultType | ||
}, { | ||
at: path | ||
}); | ||
return; | ||
} | ||
} | ||
normalizeNode([node, path]); | ||
}; | ||
}; | ||
const withList = ({ | ||
@@ -1554,2 +1650,3 @@ validLiChildrenTypes | ||
deleteBackward, | ||
deleteForward, | ||
deleteFragment | ||
@@ -1568,2 +1665,7 @@ } = editor; | ||
editor.deleteForward = unit => { | ||
if (getListDeleteForward(editor)) return; | ||
deleteForward(unit); | ||
}; | ||
editor.deleteFragment = () => { | ||
@@ -1593,23 +1695,2 @@ if (getListDeleteFragment(editor)) return; | ||
/** | ||
* Searches upward for the root list element | ||
*/ | ||
const getListRoot = (editor, at = editor.selection) => { | ||
if (!at) return; | ||
const parentList = plateCommon.getAbove(editor, { | ||
at, | ||
match: { | ||
type: [plateCore.getPlatePluginType(editor, ELEMENT_UL), plateCore.getPlatePluginType(editor, ELEMENT_OL)] | ||
} | ||
}); | ||
if (parentList) { | ||
var _getListRoot; | ||
const [, parentListPath] = parentList; | ||
return (_getListRoot = getListRoot(editor, parentListPath)) !== null && _getListRoot !== void 0 ? _getListRoot : parentList; | ||
} | ||
}; | ||
const CLASS_TODO_LIST_CHECKED = 'slate-TodoListElement-rootChecked'; | ||
@@ -1616,0 +1697,0 @@ |
@@ -0,3 +1,8 @@ | ||
import { EditorNodesOptions } from '@udecode/plate-common/src'; | ||
import { SPEditor } from '@udecode/plate-core'; | ||
export declare const moveListItems: (editor: SPEditor, increase?: boolean) => void; | ||
export declare type MoveListItemsOptions = { | ||
increase?: boolean; | ||
at?: EditorNodesOptions['at']; | ||
}; | ||
export declare const moveListItems: (editor: SPEditor, { increase, at, }?: MoveListItemsOptions) => void; | ||
//# sourceMappingURL=moveListItems.d.ts.map |
@@ -6,2 +6,3 @@ import { SPEditor, TElement } from '@udecode/plate-core'; | ||
listItem: NodeEntry<TElement>; | ||
reverse?: boolean; | ||
} | ||
@@ -11,3 +12,3 @@ /** | ||
*/ | ||
export declare const removeListItem: (editor: SPEditor, { list, listItem }: RemoveListItemOptions) => boolean | undefined; | ||
export declare const removeListItem: (editor: SPEditor, { list, listItem, reverse }: RemoveListItemOptions) => boolean | undefined; | ||
//# sourceMappingURL=removeListItem.d.ts.map |
import { SPEditor } from '@udecode/plate-core'; | ||
export declare const unindentListItems: (editor: SPEditor) => void; | ||
import { MoveListItemsOptions } from './moveListItems'; | ||
export declare type UnindentListItemsOptions = Omit<MoveListItemsOptions, 'increase'>; | ||
export declare const unindentListItems: (editor: SPEditor, options?: UnindentListItemsOptions) => void; | ||
//# sourceMappingURL=unindentListItems.d.ts.map |
{ | ||
"name": "@udecode/plate-list", | ||
"version": "3.1.2", | ||
"version": "3.1.3", | ||
"description": "List plugin for Plate", | ||
@@ -35,5 +35,5 @@ "keywords": [ | ||
"dependencies": { | ||
"@udecode/plate-common": "2.0.0", | ||
"@udecode/plate-common": "3.1.3", | ||
"@udecode/plate-core": "1.0.0", | ||
"@udecode/plate-reset-node": "2.0.0" | ||
"@udecode/plate-reset-node": "3.1.3" | ||
}, | ||
@@ -40,0 +40,0 @@ "peerDependencies": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
337155
93
3294
+ Added@udecode/plate-common@3.1.3(transitive)
+ Added@udecode/plate-reset-node@3.1.3(transitive)
- Removed@udecode/plate-common@2.0.0(transitive)
- Removed@udecode/plate-reset-node@2.0.0(transitive)
Updated@udecode/plate-common@3.1.3