import { CommandFunction , ProsemirrorNode } from '@remirror/pm' ; import { Fragment , NodeRange , ResolvedPos , Slice } from '@remirror/pm/model' ; import { Transaction } from '@remirror/pm/state' ; import { liftTarget , ReplaceAroundStep } from '@remirror/pm/transform' ; import { calculateItemRange , maybeJoinList , wrapSelectedItems } from './list-commands' ; import { isListItemNode , isListNode } from './list-utils' ; function findParentItem ( $from , range ) { const parentItem = $from . node ( range . depth - 1 ) ; const parentList = $from . node ( range . depth - 2 ) ; if ( ! isListItemNode ( parentItem ) || ! isListNode ( parentList ) ) { return false ; } return { parentItem , parentList } ; } function indentSiblingsOfItems ( tr , range ) { const selectedList = range . parent ; const lastSelectedItem = range . parent . child ( range . endIndex - 1 ) ; const endOfRange = range . end ; const endOfSelectedList = range . $to . end ( range . depth ) ; if ( endOfRange < endOfSelectedList ) { tr . step ( new ReplaceAroundStep ( endOfRange - 1 , endOfSelectedList , endOfRange , endOfSelectedList , new Slice ( Fragment . from ( lastSelectedItem . type . create ( null , selectedList . copy ( ) ) ) , 1 , 0 ) , 1 , true ) ) ; return new NodeRange ( tr . doc . resolve ( range . $from . pos ) , tr . doc . resolve ( endOfSelectedList ) , range . depth ) ; } return range ; } function indentSiblingsOfList ( tr , range ) { const selectedList = range . parent ; const lastSelectedItem = range . parent . child ( range . endIndex - 1 ) ; const endOfSelectedList = range . end ; const endOfParentListItem = range . $to . end ( range . depth - 1 ) ; if ( endOfSelectedList + 1 < endOfParentListItem ) { tr . step ( new ReplaceAroundStep ( endOfSelectedList - 1 , endOfParentListItem , endOfSelectedList + 1 , endOfParentListItem , new Slice ( Fragment . from ( selectedList . type . create ( null , lastSelectedItem . type . create ( null ) ) ) , 2 , 0 ) , 0 , true ) ) ; return new NodeRange ( tr . selection . $from , tr . selection . $to , range . depth ) ; } return range ; } function changeItemsType ( tr , range , parentList , parentItem ) { const wrapped = wrapSelectedItems ( { listType : parentList . type , itemType : parentItem . type , tr , } ) ; if ( wrapped ) { return new NodeRange ( tr . selection . $from , tr . selection . $to , range . depth ) ; } return range ; } beta export function dedentList ( tr ) { let range = calculateItemRange ( tr . selection ) ; if ( ! range ) { return false ; } const findParentItemResult = findParentItem ( tr . selection . $from , range ) ; if ( ! findParentItemResult ) { return false ; } const { parentItem , parentList } = findParentItemResult ; range = indentSiblingsOfItems ( tr , range ) ; range = indentSiblingsOfList ( tr , range ) ; range = changeItemsType ( tr , range , parentList , parentItem ) ; const target = liftTarget ( range ) ; if ( typeof target !== 'number' ) { return true ; } tr . lift ( range , target ) ; range = calculateItemRange ( tr . selection ) ; if ( range ) { maybeJoinList ( tr , tr . doc . resolve ( range . end - 2 ) ) ; } return true ; } internal export const dedentListCommand = ( { tr , dispatch } ) => { if ( dedentList ( tr ) ) { dispatch ?. ( tr . scrollIntoView ( ) ) ; } return true ; } ;