UNPKG

@portabletext/editor

Version:

Portable Text Editor made in React

244 lines (222 loc) 5.43 kB
import {isSpan, isTextBlock} from '@portabletext/schema' import * as selectors from '../selectors' import * as utils from '../utils' import {raise} from './behavior.types.action' import {defineBehavior} from './behavior.types.behavior' export const abstractDeleteBehaviors = [ defineBehavior({ on: 'delete.backward', guard: ({snapshot}) => { if (!snapshot.context.selection) { return false } return {selection: snapshot.context.selection} }, actions: [ ({event}, {selection}) => [ raise({ type: 'delete', direction: 'backward', unit: event.unit, at: selection, }), ], ], }), defineBehavior({ on: 'delete', guard: ({snapshot, event}) => { if (event.direction !== 'backward') { return false } const previousBlock = selectors.getPreviousBlock(snapshot) const focusTextBlock = selectors.getFocusTextBlock(snapshot) if (!previousBlock || !focusTextBlock) { return false } if (!selectors.isAtTheStartOfBlock(focusTextBlock)(snapshot)) { return false } const previousBlockEndPoint = utils.getBlockEndPoint({ context: snapshot.context, block: previousBlock, }) if (!isTextBlock(snapshot.context, previousBlock.node)) { return false } return {previousBlockEndPoint, focusTextBlock} }, actions: [ (_, {previousBlockEndPoint, focusTextBlock}) => [ raise({ type: 'delete.block', at: focusTextBlock.path, }), raise({ type: 'select', at: { anchor: previousBlockEndPoint, focus: previousBlockEndPoint, }, }), raise({ type: 'insert.block', block: focusTextBlock.node, placement: 'auto', select: 'start', }), ], ], }), defineBehavior({ on: 'delete.forward', guard: ({snapshot}) => { if (!snapshot.context.selection) { return false } return {selection: snapshot.context.selection} }, actions: [ ({event}, {selection}) => [ raise({ type: 'delete', direction: 'forward', unit: event.unit, at: selection, }), ], ], }), defineBehavior({ on: 'delete', guard: ({snapshot, event}) => { if (event.direction !== 'forward') { return false } const nextBlock = selectors.getNextBlock(snapshot) const focusTextBlock = selectors.getFocusTextBlock(snapshot) if (!nextBlock || !focusTextBlock) { return false } if (!selectors.isAtTheEndOfBlock(focusTextBlock)(snapshot)) { return false } if (!isTextBlock(snapshot.context, nextBlock.node)) { return false } return {nextBlock} }, actions: [ (_, {nextBlock}) => [ raise({ type: 'delete.block', at: nextBlock.path, }), raise({ type: 'insert.block', block: nextBlock.node, placement: 'auto', select: 'none', }), ], ], }), defineBehavior({ on: 'delete.block', actions: [ ({event}) => [ raise({ type: 'delete', at: { anchor: { path: event.at, offset: 0, }, focus: { path: event.at, offset: 0, }, }, }), ], ], }), defineBehavior({ on: 'delete.child', guard: ({snapshot, event}) => { const focusChild = selectors.getFocusChild({ ...snapshot, context: { ...snapshot.context, selection: { anchor: { path: event.at, offset: 0, }, focus: { path: event.at, offset: 0, }, }, }, }) if (!focusChild) { return false } if (isSpan(snapshot.context, focusChild.node)) { return { selection: { anchor: { path: event.at, offset: 0, }, focus: { path: event.at, offset: focusChild.node.text.length, }, }, } } return { selection: { anchor: { path: event.at, offset: 0, }, focus: { path: event.at, offset: 0, }, }, } }, actions: [(_, {selection}) => [raise({type: 'delete', at: selection})]], }), defineBehavior({ on: 'delete.text', guard: ({snapshot, event}) => { const selection = utils.blockOffsetsToSelection({ context: snapshot.context, offsets: event.at, }) if (!selection) { return false } const trimmedSelection = selectors.getTrimmedSelection({ ...snapshot, context: { ...snapshot.context, value: snapshot.context.value, selection, }, }) if (!trimmedSelection) { return false } return { selection: trimmedSelection, } }, actions: [(_, {selection}) => [raise({type: 'delete', at: selection})]], }), ]