From 48af095058bcf122f0460493072a1f9c18441cf6 Mon Sep 17 00:00:00 2001 From: Zaki Date: Wed, 29 Jun 2022 17:35:22 -0700 Subject: [PATCH 1/4] Add ability to indent/un-indent multiple list items --- packages/nodes/list/src/onKeyDownList.ts | 1 - .../nodes/list/src/onkeyDownList.spec.tsx | 168 ++++++++++++++++++ 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 packages/nodes/list/src/onkeyDownList.spec.tsx diff --git a/packages/nodes/list/src/onKeyDownList.ts b/packages/nodes/list/src/onKeyDownList.ts index d4e8bed8ab..ab3a72b4af 100644 --- a/packages/nodes/list/src/onKeyDownList.ts +++ b/packages/nodes/list/src/onKeyDownList.ts @@ -23,7 +23,6 @@ export const onKeyDownList = < if (editor.selection && (isTab || isUntab)) { const listSelected = getAboveNode(editor, { at: editor.selection, - match: { type }, }); if (listSelected) { diff --git a/packages/nodes/list/src/onkeyDownList.spec.tsx b/packages/nodes/list/src/onkeyDownList.spec.tsx new file mode 100644 index 0000000000..15f8da671b --- /dev/null +++ b/packages/nodes/list/src/onkeyDownList.spec.tsx @@ -0,0 +1,168 @@ +/** @jsx jsx */ + +import { getPlugin, HotkeyPlugin, Hotkeys } from '@udecode/plate-core'; +import { createListPlugin } from '@udecode/plate-list'; +import { jsx } from '@udecode/plate-test-utils'; +import { createPlateUIEditor } from '@udecode/plate-ui/src/utils/createPlateUIEditor'; +import * as isHotkey from 'is-hotkey'; +import { onKeyDownList } from './onKeyDownList'; + +jsx; + +it('should indent single list item', () => { + const input = ( + + + + some text + + + + + some text + + + + + ) as any; + + const output = ( + + + + some text + + + + + some text + + + + + + + ) as any; + + const event = new KeyboardEvent('keydown', { key: 'Tab' }) as any; + const editor = createPlateUIEditor({ + editor: input, + plugins: [createListPlugin()], + }); + + onKeyDownList(editor, getPlugin(editor, 'ul'))(event as any); + expect(editor.children).toEqual(output.children); +}); + +it('should indent multiple list items', () => { + const input = ( + + + + first element + + + + + second element + + + + + third element + + + + + ) as any; + + const output = ( + + + + first element + + + + + second element + + + + + third element + + + + + + + ) as any; + + const event = new KeyboardEvent('keydown', { key: 'Tab' }) as any; + const editor = createPlateUIEditor({ + editor: input, + plugins: [createListPlugin()], + }); + + onKeyDownList(editor, getPlugin(editor, 'ul'))(event as any); + expect(editor.children).toEqual(output.children); +}); + +it('should un-indent multiple list items', () => { + const input = ( + + + + first element + + + + + second element + + + + + third element + + + + + + + ) as any; + + const output = ( + + + + first element + + + + + second element + + + + + third element + + + + + ) as any; + + const event = new KeyboardEvent('keydown', { + shiftKey: true, + key: 'Tab', + }) as any; + const editor = createPlateUIEditor({ + editor: input, + plugins: [createListPlugin()], + }); + + onKeyDownList(editor, getPlugin(editor, 'ul'))(event as any); + expect(editor.children).toEqual(output.children); +}); From 4b43c4b1c97719092c41574df77e086b6acff643 Mon Sep 17 00:00:00 2001 From: Zaki Date: Thu, 30 Jun 2022 11:01:48 -0700 Subject: [PATCH 2/4] some improvement --- .../nodes/list/src/onkeyDownList.spec.tsx | 198 ++++++++++++++++-- 1 file changed, 178 insertions(+), 20 deletions(-) diff --git a/packages/nodes/list/src/onkeyDownList.spec.tsx b/packages/nodes/list/src/onkeyDownList.spec.tsx index 15f8da671b..02792e29f8 100644 --- a/packages/nodes/list/src/onkeyDownList.spec.tsx +++ b/packages/nodes/list/src/onkeyDownList.spec.tsx @@ -8,18 +8,26 @@ import * as isHotkey from 'is-hotkey'; import { onKeyDownList } from './onKeyDownList'; jsx; +/* +input: +1. E1 +2. |E2 -it('should indent single list item', () => { +output: +1. E1 + 1. |E2 +*/ +it('should indent single list item (start of item)', () => { const input = ( - some text + E1 - some text + E2 @@ -30,12 +38,12 @@ it('should indent single list item', () => { - some text + E1 - some text + E2 @@ -54,22 +62,88 @@ it('should indent single list item', () => { expect(editor.children).toEqual(output.children); }); -it('should indent multiple list items', () => { +/* +input: +1. E1 +2. E2| + +output: +1. E1 + 1. E2| +*/ +it('should indent single list item (end of item)', () => { + const input = ( + + + + E1 + + + + E2 + + + + + + ) as any; + + const output = ( + + + + E1 + + + + E2 + + + + + + + + ) as any; + + const event = new KeyboardEvent('keydown', { key: 'Tab' }) as any; + const editor = createPlateUIEditor({ + editor: input, + plugins: [createListPlugin()], + }); + + onKeyDownList(editor, getPlugin(editor, 'ul'))(event as any); + expect(editor.children).toEqual(output.children); +}); + +/* +input: +1. E1 +2. |E2 +3. E3| + +output: +1. E1 + 1. |E2 + 2. E3| +*/ +it('should indent multiple list items (start/end)', () => { const input = ( - first element + E1 - second element + E2 - third element + E3 + @@ -80,17 +154,17 @@ it('should indent multiple list items', () => { - first element + E1 - second element + E2 - third element + E3 @@ -109,22 +183,34 @@ it('should indent multiple list items', () => { expect(editor.children).toEqual(output.children); }); -it('should un-indent multiple list items', () => { +/* +input: +1. E1 + 1. |E2 + 2. E3| + +output: +1. E1 +2. |E2 +3. E3| +*/ +it('should un-indent multiple list items (start/end)', () => { const input = ( - first element + E1 - second element + E2 - third element + E3 + @@ -137,17 +223,18 @@ it('should un-indent multiple list items', () => { - first element + E1 - second element + E2 - third element + E3 + @@ -163,6 +250,77 @@ it('should un-indent multiple list items', () => { plugins: [createListPlugin()], }); - onKeyDownList(editor, getPlugin(editor, 'ul'))(event as any); + onKeyDownList(editor, getPlugin(editor, 'list'))(event as any); expect(editor.children).toEqual(output.children); }); + +/* +input: +1. E1 + 1. |E2 + 2. E3 +| + +output: +1. E1 +2. |E2 +3. E3 +| +*/ +it('should un-indent multiple list items (start/out)', () => { + const input = ( + + + + E1 + + + + + E2 + + + + E3 + + + + + + + ) as any; + + const output = ( + + + + E1 + + + + + E2 + + + + + E3 + + + + + + ) as any; + + const event = new KeyboardEvent('keydown', { + shiftKey: true, + key: 'Tab', + }) as any; + const editor = createPlateUIEditor({ + editor: input, + plugins: [createListPlugin()], + }); + + onKeyDownList(editor, getPlugin(editor, 'list'))(event as any); + expect(editor.children).toEqual(output.children); +}); \ No newline at end of file From 1c1236954eb08a4401aba763f18c7c0592ba32f3 Mon Sep 17 00:00:00 2001 From: Zaki Date: Thu, 30 Jun 2022 17:39:04 -0700 Subject: [PATCH 3/4] fix using unhang; add more test cases --- packages/nodes/list/src/onKeyDownList.ts | 32 +++++++- .../nodes/list/src/onkeyDownList.spec.tsx | 76 ++++++++++++++++++- 2 files changed, 101 insertions(+), 7 deletions(-) diff --git a/packages/nodes/list/src/onKeyDownList.ts b/packages/nodes/list/src/onKeyDownList.ts index ab3a72b4af..6affa8f184 100644 --- a/packages/nodes/list/src/onKeyDownList.ts +++ b/packages/nodes/list/src/onKeyDownList.ts @@ -2,13 +2,17 @@ import { getAboveNode, HotkeyPlugin, Hotkeys, + isCollapsed, KeyboardHandlerReturnType, PlateEditor, + select, + unhangRange, Value, WithPlatePlugin, } from '@udecode/plate-core'; import isHotkey from 'is-hotkey'; import { castArray } from 'lodash'; +import { Range } from 'slate'; import { moveListItems, toggleList } from './transforms'; export const onKeyDownList = < @@ -20,15 +24,37 @@ export const onKeyDownList = < ): KeyboardHandlerReturnType => (e) => { const isTab = Hotkeys.isTab(editor, e); const isUntab = Hotkeys.isUntab(editor, e); + + let workRange = editor.selection; + if (editor.selection && (isTab || isUntab)) { + const { selection } = editor; + + // Unhang the expanded selection + if (!isCollapsed(editor.selection)) { + const { anchor, focus } = Range.isBackward(selection) + ? { anchor: selection.focus, focus: selection.anchor } + : { anchor: selection.anchor, focus: selection.focus }; + + // This is a workaround for a Slate bug + // See: https://github.com/ianstormtaylor/slate/pull/5039 + anchor.offset = 0; + const unHungRange = unhangRange(editor, { anchor, focus }); + if (unHungRange) { + workRange = unHungRange; + select(editor, unHungRange); + } + } + + // check if we're in a list context. const listSelected = getAboveNode(editor, { at: editor.selection, }); - if (listSelected) { + if (workRange && listSelected) { e.preventDefault(); - moveListItems(editor, { increase: isTab }); - return; + moveListItems(editor, { at: workRange, increase: isTab }); + return true; } } diff --git a/packages/nodes/list/src/onkeyDownList.spec.tsx b/packages/nodes/list/src/onkeyDownList.spec.tsx index 02792e29f8..0440e4f9ca 100644 --- a/packages/nodes/list/src/onkeyDownList.spec.tsx +++ b/packages/nodes/list/src/onkeyDownList.spec.tsx @@ -164,7 +164,8 @@ it('should indent multiple list items (start/end)', () => { - E3 + E3 + @@ -281,9 +282,11 @@ it('should un-indent multiple list items (start/out)', () => { - E3 + + E3 + + - @@ -323,4 +326,69 @@ it('should un-indent multiple list items (start/out)', () => { onKeyDownList(editor, getPlugin(editor, 'list'))(event as any); expect(editor.children).toEqual(output.children); -}); \ No newline at end of file +}); + +it('should unhang before indentation', () => { + const input = ( + + + + E1 + + + + + E2 + + + + E3 + + + + + + paragraph + + + + ) as any; + + const output = ( + + + + E1 + + + + + E2 + + + + E3 + + + + + + + + paragraph + + + + ) as any; + + const event = new KeyboardEvent('keydown', { + key: 'Tab', + }) as any; + const editor = createPlateUIEditor({ + editor: input, + plugins: [createListPlugin()], + }); + + onKeyDownList(editor, getPlugin(editor, 'list'))(event as any); + expect(editor.children).toEqual(output.children); +}); From 94cd1a45da9f71c7f61a53c97e5945e3229c99e5 Mon Sep 17 00:00:00 2001 From: Zaki Date: Thu, 30 Jun 2022 19:57:21 -0700 Subject: [PATCH 4/4] Adding changset for list indentation fix --- .changeset/lemon-queens-pretend.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lemon-queens-pretend.md diff --git a/.changeset/lemon-queens-pretend.md b/.changeset/lemon-queens-pretend.md new file mode 100644 index 0000000000..fab90d90af --- /dev/null +++ b/.changeset/lemon-queens-pretend.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-list': minor +--- + +Improved list item indentation when selection spans across different elements