@wordpress/core-data
Version:
Access to and manipulation of core WordPress entities.
116 lines (115 loc) • 3.63 kB
JavaScript
// packages/core-data/src/utils/crdt-selection.ts
import { dispatch, select } from "@wordpress/data";
import { store as blockEditorStore } from "@wordpress/block-editor";
import { isUnmodifiedBlock } from "@wordpress/blocks";
import { Y } from "@wordpress/sync";
import {
createBlockSelectionHistory,
YSelectionType
} from "./block-selection-history.mjs";
import { findBlockByClientIdInDoc } from "./crdt-utils.mjs";
var selectionHistoryMap = /* @__PURE__ */ new WeakMap();
function getBlockSelectionHistory(ydoc) {
let history = selectionHistoryMap.get(ydoc);
if (!history) {
history = createBlockSelectionHistory(ydoc);
selectionHistoryMap.set(ydoc, history);
}
return history;
}
function getSelectionHistory(ydoc) {
return getBlockSelectionHistory(ydoc).getSelectionHistory();
}
function updateSelectionHistory(ydoc, wpSelection) {
return getBlockSelectionHistory(ydoc).updateSelection(wpSelection);
}
function convertYSelectionToBlockSelection(ySelection, ydoc) {
if (ySelection.type === YSelectionType.RelativeSelection) {
const { relativePosition, attributeKey, clientId } = ySelection;
const absolutePosition = Y.createAbsolutePositionFromRelativePosition(
relativePosition,
ydoc
);
if (absolutePosition) {
return {
clientId,
attributeKey,
offset: absolutePosition.index
};
}
} else if (ySelection.type === YSelectionType.BlockSelection) {
return {
clientId: ySelection.clientId,
attributeKey: void 0,
offset: void 0
};
}
return null;
}
function findSelectionFromHistory(ydoc, selectionHistory) {
for (const positionToTry of selectionHistory) {
const { start, end } = positionToTry;
const startBlock = findBlockByClientIdInDoc(start.clientId, ydoc);
const endBlock = findBlockByClientIdInDoc(end.clientId, ydoc);
if (!startBlock || !endBlock) {
continue;
}
const startBlockSelection = convertYSelectionToBlockSelection(
start,
ydoc
);
const endBlockSelection = convertYSelectionToBlockSelection(
end,
ydoc
);
if (startBlockSelection === null || endBlockSelection === null) {
continue;
}
return {
selectionStart: startBlockSelection,
selectionEnd: endBlockSelection
};
}
return null;
}
function restoreSelection(selectionHistory, ydoc) {
const selectionToRestore = findSelectionFromHistory(
ydoc,
selectionHistory
);
if (selectionToRestore === null) {
return;
}
const { getBlock } = select(blockEditorStore);
const { resetSelection } = dispatch(blockEditorStore);
const { selectionStart, selectionEnd } = selectionToRestore;
const isSelectionInSameBlock = selectionStart.clientId === selectionEnd.clientId;
if (isSelectionInSameBlock) {
const block = getBlock(selectionStart.clientId);
const isBlockEmpty = block && isUnmodifiedBlock(block);
const isBeginningOfEmptyBlock = 0 === selectionStart.offset && 0 === selectionEnd.offset && isBlockEmpty;
if (isBeginningOfEmptyBlock) {
const selectionStartWithoutOffset = {
clientId: selectionStart.clientId
};
const selectionEndWithoutOffset = {
clientId: selectionEnd.clientId
};
resetSelection(
selectionStartWithoutOffset,
selectionEndWithoutOffset,
0
);
} else {
resetSelection(selectionStart, selectionEnd, 0);
}
} else {
resetSelection(selectionEnd, selectionEnd, 0);
}
}
export {
getSelectionHistory,
restoreSelection,
updateSelectionHistory
};
//# sourceMappingURL=crdt-selection.mjs.map