Skip to content

Commit

Permalink
Fix list delete forward
Browse files Browse the repository at this point in the history
  • Loading branch information
nemanja-tosic committed Sep 11, 2021
1 parent d5e874c commit c404823
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 12 deletions.
4 changes: 2 additions & 2 deletions packages/common/src/queries/isSelectionAtBlockEnd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { isEnd } from './isEnd';
/**
* Is the selection focus at the end of its parent block.
*/
export const isSelectionAtBlockEnd = (editor: TEditor) => {
export const isSelectionAtBlockEnd = (editor: TEditor): boolean => {
const path = getBlockAbove(editor)?.[1];

return path && isEnd(editor, editor.selection?.focus, path);
return !!path && isEnd(editor, editor.selection?.focus, path);
};
100 changes: 100 additions & 0 deletions packages/elements/list/src/getListDeleteForward.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import {
deleteFragment,
getAbove,
getChildren,
getNode,
isLastChild,
isSelectionAtBlockEnd,
} from '@udecode/plate-common';
import {
getPlatePluginOptions,
SPEditor,
TDescendant,
} from '@udecode/plate-core';
import { Editor, Node, Path } from 'slate';
import { getListItemEntry } from './queries';
import {moveListItemsToList, removeFirstListItem, removeListItem} from './transforms';
import { ELEMENT_LI, ELEMENT_UL } from './defaults';
import { getLastChild } from '../../../common/src';

export const getListDeleteForward = (
editor: SPEditor,
unit: 'character' | 'word' | 'line' | 'block'
) => {
// at next child
const res = getListItemEntry(editor, {});
// next lic

let moved: boolean | undefined = false;
if (!isSelectionAtBlockEnd(editor) || !res) {
return moved;
}

Editor.withoutNormalizing(editor, () => {
let { list, listItem } = res;

const nestedListPath = Path.next([...listItem[1], 0]);
const nestedList = getNode<TDescendant>(editor, nestedListPath);
if (nestedList) {
list = [nestedList, nestedListPath];
listItem = getChildren([nestedList, nestedListPath])[0];
} else if (getLastChild(list)?.[1] === listItem[1]) {
return;
}

moved = removeFirstListItem(editor, {
list: list,
listItem: listItem,
});
if (moved) return;

moved = removeListItem(editor, {
list: list,
listItem: listItem,
});
if (moved) return;

deleteFragment(editor, { unit });

const li = getPlatePluginOptions(editor, ELEMENT_LI);
const lisWithSiblings = Array.from(
Editor.nodes(editor, {
at: listItem[1],
mode: 'lowest',
match: (node: TDescendant, path) => {
if (path.length === 0) {
return false;
}

const isNodeLi = node.type === li.type;
const isSiblingOfNodeLi =
(getNode(editor, Path.next(path)) as TDescendant)?.type === li.type;

return isNodeLi && isSiblingOfNodeLi;
},
})
);

const nextListItemPath = Path.next(lisWithSiblings[0][1]);
const nextListItem = getNode(editor, nextListItemPath) as TDescendant;
const nextList = getAbove<TDescendant>(editor, {
mode: 'lowest',
at: nextListItemPath,
match: {
type: getPlatePluginOptions(editor, ELEMENT_UL).type,
},
})!;

// If it's the first li, move the sublist to the parent list
moved = !!moveListItemsToList(editor, {
fromListItem: [nextListItem, nextListItemPath],
toList: list,
toListIndex: 1,
});
if (moved) return;

moved = true;
});

return moved;
};
2 changes: 1 addition & 1 deletion packages/elements/list/src/getListOnKeyDown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const getListOnKeyDown = (

if (listSelected) {
e.preventDefault();
moveListItems(editor, !e.shiftKey);
moveListItems(editor, { increase: !e.shiftKey });
return;
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/elements/list/src/transforms/indentListItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import { SPEditor } from '@udecode/plate-core';
import { moveListItems } from './moveListItems';

export const indentListItems = (editor: SPEditor) => {
moveListItems(editor, true);
moveListItems(editor, { increase: true });
};
16 changes: 14 additions & 2 deletions packages/elements/list/src/transforms/moveListItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@ import { ELEMENT_LIC } from '../defaults';
import { isListNested } from '../queries/isListNested';
import { moveListItemDown } from './moveListItemDown';
import { moveListItemUp } from './moveListItemUp';
import { EditorNodesOptions } from '@udecode/plate-common/src';

export const moveListItems = (editor: SPEditor, increase = true) => {
export type MoveListItemsOptions = {
increase?: boolean;
at?: EditorNodesOptions['at'];
};

export const moveListItems = (
editor: SPEditor,
{
increase = true,
at = editor.selection ?? undefined,
}: MoveListItemsOptions = {}
) => {
// Get the selected lic
const [...lics] = getNodes(editor, {
at: editor.selection!,
at,
match: {
type: getPlatePluginType(editor, ELEMENT_LIC),
},
Expand Down
11 changes: 7 additions & 4 deletions packages/elements/list/src/transforms/unindentListItems.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { SPEditor } from '@udecode/plate-core';
import { moveListItems } from './moveListItems';
import { moveListItems, MoveListItemsOptions } from './moveListItems';

export const unindentListItems = (editor: SPEditor) => {
moveListItems(editor, false);
};
export type UnindentListItemsOptions = Omit<MoveListItemsOptions, 'increase'>;

export const unindentListItems = (
editor: SPEditor,
options: UnindentListItemsOptions = {}
): void => moveListItems(editor, { ...options, increase: false });
189 changes: 189 additions & 0 deletions packages/elements/list/src/withList.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ const testDeleteBackward = (input: any, expected: any) => {
expect(editor.children).toEqual(expected.children);
};

const testDeleteForward = (input: any, expected: any) => {
const editor = createEditorPlugins({
editor: input,
plugins: [createParagraphPlugin(), createListPlugin()],
});

editor.deleteForward('character');

expect(editor.children).toEqual(expected.children);
};

describe('withList', () => {
describe('normalizeList', () => {
describe('when there is no lic in li', () => {
Expand Down Expand Up @@ -303,4 +314,182 @@ describe('withList', () => {
});
});
});

describe('when deleteForward at block end', () => {
it('should merge the next element when last child', () => {
const input = ((
<editor>
<hul>
<hli>
<hlic>
level 1<cursor />
</hlic>
</hli>
</hul>
<hul>
<hli>
<hlic>level 2</hlic>
</hli>
</hul>
</editor>
) as any) as Editor;

const expected = ((
<editor>
<hul>
<hli>
<hlic>
level 1
<cursor />
level 2
</hlic>
</hli>
</hul>
</editor>
) as any) as Editor;

testDeleteForward(input, expected);
});

it('should merge next sibling li', () => {
const input = ((
<editor>
<hul>
<hli>
<hlic>
level 1<cursor />
</hlic>
</hli>
<hli>
<hlic>level 2</hlic>
</hli>
</hul>
</editor>
) as any) as Editor;

const expected = ((
<editor>
<hul>
<hli>
<hlic>
level 1
<cursor />
level 2
</hlic>
</hli>
</hul>
</editor>
) as any) as Editor;

testDeleteForward(input, expected);
});

it('should merge next li and shift one level up', () => {
const input = ((
<editor>
<hul>
<hli>
<hlic>level 1</hlic>
<hul>
<hli>
<hlic>
level 2<cursor />
</hlic>
</hli>
</hul>
</hli>
<hli>
<hlic>level 3</hlic>
<hul>
<hli>
<hlic>level 4</hlic>
</hli>
</hul>
</hli>
</hul>
</editor>
) as any) as Editor;

const expected = ((
<editor>
<hul>
<hli>
<hlic>level 1</hlic>
<hul>
<hli>
<hlic>level 2level 3</hlic>
</hli>
</hul>
</hli>
<hli>
<hlic>level 4</hlic>
</hli>
</hul>
</editor>
) as any) as Editor;

testDeleteForward(input, expected);
});

it('should shift all nested lists one level up', () => {
const input = ((
<editor>
<hul>
<hli>
<hlic>
level 1<cursor />
</hlic>
<hul>
<hli>
<hlic>level 2</hlic>
<hul>
<hli>
<hlic>level 3</hlic>
<hul>
<hli>
<hlic>level 4</hlic>
</hli>
</hul>
</hli>
<hli>
<hlic>level 5</hlic>
</hli>
</hul>
</hli>
</hul>
</hli>
</hul>
</editor>
) as any) as Editor;

const expected = ((
<editor>
<hul>
<hli>
<hlic>
level 1
<cursor />
level 2
</hlic>
<hul>
<hli>
<hlic>level 3</hlic>
<hul>
<hli>
<hlic>level 4</hlic>
</hli>
</hul>
</hli>
<hli>
<hlic>level 5</hlic>
</hli>
</hul>
</hli>
</hul>
</editor>
) as any) as Editor;

testDeleteForward(input, expected);
});
});
});
Loading

0 comments on commit c404823

Please sign in to comment.