import { wrapAction } from '../helper'; import { EditContext, EditEvent } from '../index.data'; import * as R from 'rambda'; import { getActivedCell, getCell } from '../../store/selectors'; import { selectCellAbove, selectCellBelow, selectCellLeft, selectCellRight, } from '../../store/actions'; import { GuardMeta } from 'xstate'; import { dissoc, reAppend } from 'valor-app-utils'; import { useEventBus } from 'valor-hooks'; import { EDITOR_MACHINE_EVENT_BUS, PICK_CELL } from './constants'; import { getColumnByCell } from '../../store/selectors/column'; export const guards = { // 针对外部传入事件 isRowSelected: (context: EditContext, event: EditEvent) => { return !!event.selectedRow; }, // 针对外部传入事件 isCellSelected: (context: EditContext, event: EditEvent) => { return !!event.selectedCell; }, // 针对外部传入事件 isColumnSelected: (context: EditContext, event: EditEvent) => { return !!event.selectedColumn; }, // 针对当前context isSingleCellInContext: (context: EditContext, event: EditEvent) => { return ( context.selectionType === 'cell' && context.selectedCellRange.length > 0 && context.selectedCellRange[0] === context.selectedCellRange[1] ); }, isCurrentCellSelected: (context: EditContext, event: EditEvent) => { if (context.selectionType === 'row') return false; return ( guards.isSingleCellInContext(context, event) && context.selectedCellRange[0] === event.selectedCell ); }, isActivedCellSelected: (context: EditContext, event: EditEvent, meta: any) => { return event.selectedCell === getActivedCell(context as any); }, pickingIsOff: ( context: EditContext, event: EditEvent, meta: GuardMeta, ) => { return !!meta!.state.matches('editing.picking.off'); }, pickingIsOff_and_isNotActivedCellSelected: ( context: EditContext, event: EditEvent, meta: any, ) => { return ( !guards.isActivedCellSelected(context, event, meta) && guards.pickingIsOff(context, event, meta) ); }, }; export const actions = { // 第一次选择, 此时没有一行 reSelect: wrapAction((context: EditContext, editEvent: EditEvent) => { const { selectedRow, selectedColumn, selectedCell, state } = editEvent; const result = !R.isNil(selectedRow) ? { selectionType: 'row', isActiving: false, selectedRowRange: [selectedRow, selectedRow] } : !R.isNil(selectedColumn) ? { selectionType: 'column', isActiving: false, selectedColumnRange: [selectedColumn, selectedColumn], } : { isActiving: false, selectionType: 'cell', selectedCellRange: [selectedCell, selectedCell], }; return result; }), clearSelect: wrapAction((context: EditContext, { }: EditEvent) => { return { isActiving: false, selectionType: null, }; }), // 移动过程, 此时一定选中了第一行, 并且第二行有可能是选中行, 也可能选中单元格(应转化为行) appendSelect: wrapAction( (context: EditContext, { selectedRow, selectedColumn, selectedCell, state }: EditEvent) => { if (context.selectionType === 'row') { if (selectedCell) { // 若append时选中的是单元格, 则应计算出该单元格所在的行 const rowId = getCell(state!, selectedCell)!.rowId!; return { selectedRowRange: [context.selectedRowRange[0], rowId] }; } else { return { selectedRowRange: [context.selectedRowRange[0], selectedRow] }; } } else if (context.selectionType === 'column') { if (selectedCell) { const cell = getCell(state!, selectedCell); const columnId = getColumnByCell(state!, cell!.id); return { selectedColumnRange: [context.selectedColumnRange[0], columnId] }; } else { return { selectedColumnRange: [context.selectedColumnRange[0], selectedColumn] }; } } else { // 将后续单元格转成单元格, 忽略行 if (selectedCell) { return { selectedCellRange: [context.selectedCellRange[0], selectedCell] }; } else { return {}; } } }, ), rePick: wrapAction((context: EditContext, { selectedRow, selectedCell, state }: EditEvent) => { return R.isNil(selectedCell) ? {} : { pickedCells: [selectedCell, selectedCell] }; }), appendPick: wrapAction( (context: EditContext, { selectedRow, selectedCell, state }: EditEvent) => { if (R.isNil(selectedCell)) return {}; return { pickedCells: reAppend(context.pickedCells || [], selectedCell) }; }, ), appendPickedAndNotify: wrapAction( (context: EditContext, { selectedRow, selectedCell, state }: EditEvent) => { const cells = reAppend(context.pickedCells || [], selectedCell); if (cells && cells.filter(Boolean).length > 0) { const { dispatchEvent } = useEventBus(EDITOR_MACHINE_EVENT_BUS); dispatchEvent(PICK_CELL, cells); } return { pickedCells: [] }; }, ), moveSelect: wrapAction((context: EditContext, editEvent: EditEvent) => { const { key, state } = editEvent; const f = { ArrowUp: selectCellAbove, ArrowDown: selectCellBelow, ArrowLeft: selectCellLeft, ArrowRight: selectCellRight, }[key!]; const newSelection = f({ ...state!, selectionType: 'cell', selectedCellRange: context.selectedCellRange, }); return Object.assign({}, newSelection, { isActiving: false }); }), activeCurrentCell: wrapAction((context: EditContext) => { return { isActiving: true, selectionType: 'cell', }; }), restoreSelectingFromEditing: wrapAction( (context: EditContext, { selectedCell }: EditEvent, meta) => { // 如果点击了单元格,则直接选择之 // 否则恢复active const selectedCellId = selectedCell || getActivedCell(context as any); return { isActiving: false, selectionType: 'cell', selectedCellRange: [selectedCellId, selectedCellId], }; }, ), };