diff --git a/packages/editor/package.json b/packages/editor/package.json index 817a2ae8c..fc6600992 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -91,6 +91,7 @@ "@portabletext/patches": "workspace:^", "@portabletext/schema": "workspace:^", "@portabletext/to-html": "^5.0.2", + "@sanity/json-match": "^1.0.5", "@xstate/react": "^6.1.0", "debug": "^4.4.3", "scroll-into-view-if-needed": "^3.1.0", diff --git a/packages/editor/src/behaviors/behavior.abstract.insert.ts b/packages/editor/src/behaviors/behavior.abstract.insert.ts index c38a06cf2..840c86826 100644 --- a/packages/editor/src/behaviors/behavior.abstract.insert.ts +++ b/packages/editor/src/behaviors/behavior.abstract.insert.ts @@ -1,4 +1,5 @@ import {isTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorSelector} from '../editor/editor-selector' import {isSelectionExpanded} from '../selectors' import {getFocusInlineObject} from '../selectors/selector.get-focus-inline-object' @@ -21,7 +22,7 @@ function getUniqueBlockKey( return snapshot.context.keyGenerator() } - if (snapshot.blockIndexMap.has(blockKey)) { + if (getIndexForKey(snapshot.context.value, blockKey) !== undefined) { return snapshot.context.keyGenerator() } diff --git a/packages/editor/src/editor/Editable.tsx b/packages/editor/src/editor/Editable.tsx index d2fa74b8f..7065c979b 100644 --- a/packages/editor/src/editor/Editable.tsx +++ b/packages/editor/src/editor/Editable.tsx @@ -247,7 +247,6 @@ export const PortableTextEditable = forwardRef< value: slateEditor.children as Array, selection: normalizedSelection, }, - blockIndexMap: slateEditor.blockIndexMap, }) if (slateRange) { slateEditor.select(slateRange) diff --git a/packages/editor/src/editor/create-editable-api.ts b/packages/editor/src/editor/create-editable-api.ts index ded6ae1c0..47a70c017 100644 --- a/packages/editor/src/editor/create-editable-api.ts +++ b/packages/editor/src/editor/create-editable-api.ts @@ -4,6 +4,7 @@ import { type PortableTextChild, type PortableTextObject, } from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import { isListItemActive, isStyleActive, @@ -249,7 +250,7 @@ export function createEditableAPI( return [undefined, undefined] } - const blockIndex = editor.blockIndexMap.get(blockKey) + const blockIndex = getIndexForKey(editor.children as Array, blockKey) if (blockIndex === undefined) { return [undefined, undefined] @@ -502,7 +503,6 @@ export function createEditableAPI( value: editor.children as Array, selection: selectionA, }, - blockIndexMap: editor.blockIndexMap, }) const rangeB = toSlateRange({ context: { @@ -510,7 +510,6 @@ export function createEditableAPI( value: editor.children as Array, selection: selectionB, }, - blockIndexMap: editor.blockIndexMap, }) // Make sure the ranges are valid diff --git a/packages/editor/src/editor/editor-selector.ts b/packages/editor/src/editor/editor-selector.ts index 277f1abee..4dd866f2c 100644 --- a/packages/editor/src/editor/editor-selector.ts +++ b/packages/editor/src/editor/editor-selector.ts @@ -76,7 +76,6 @@ export function getEditorSnapshot({ : null return { - blockIndexMap: slateEditorInstance.blockIndexMap, context: { converters: [...editorActorSnapshot.context.converters], keyGenerator: editorActorSnapshot.context.keyGenerator, diff --git a/packages/editor/src/editor/editor-snapshot.ts b/packages/editor/src/editor/editor-snapshot.ts index d00f53157..8c2dc3fc5 100644 --- a/packages/editor/src/editor/editor-snapshot.ts +++ b/packages/editor/src/editor/editor-snapshot.ts @@ -22,7 +22,6 @@ export type EditorContext = { */ export type EditorSnapshot = { context: EditorContext - blockIndexMap: Map /** * @beta * Subject to change @@ -61,7 +60,6 @@ export function createEditorSnapshot({ } satisfies EditorContext return { - blockIndexMap: editor.blockIndexMap, context, decoratorState: editor.decoratorState, } satisfies EditorSnapshot diff --git a/packages/editor/src/editor/range-decorations-machine.ts b/packages/editor/src/editor/range-decorations-machine.ts index ce836e538..10965d8e1 100644 --- a/packages/editor/src/editor/range-decorations-machine.ts +++ b/packages/editor/src/editor/range-decorations-machine.ts @@ -100,7 +100,6 @@ export const rangeDecorationsMachine = setup({ value: context.slateEditor.children as Array, selection: rangeDecoration.selection, }, - blockIndexMap: context.slateEditor.blockIndexMap, }) if (!Range.isRange(slateRange)) { @@ -134,7 +133,6 @@ export const rangeDecorationsMachine = setup({ value: context.slateEditor.children as Array, selection: rangeDecoration.selection, }, - blockIndexMap: context.slateEditor.blockIndexMap, }) if (!Range.isRange(slateRange)) { @@ -169,7 +167,6 @@ export const rangeDecorationsMachine = setup({ value: context.slateEditor.children as Array, selection: decoratedRange.rangeDecoration.selection, }, - blockIndexMap: context.slateEditor.blockIndexMap, }) if (!Range.isRange(slateRange)) { diff --git a/packages/editor/src/editor/render.element.tsx b/packages/editor/src/editor/render.element.tsx index 5ff802350..7df089d83 100644 --- a/packages/editor/src/editor/render.element.tsx +++ b/packages/editor/src/editor/render.element.tsx @@ -1,5 +1,6 @@ import type {PortableTextBlock} from '@portabletext/schema' import {isTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import {useSelector} from '@xstate/react' import {useContext, type ReactElement} from 'react' import type {DropPosition} from '../behaviors/behavior.core.drop-position' @@ -48,7 +49,7 @@ export function RenderElement(props: { ) } - const blockIndex = slateStatic.blockIndexMap.get(props.element._key) + const blockIndex = getIndexForKey(slateStatic.children as Array, props.element._key) const block = blockIndex !== undefined ? (slateStatic.children as Array).at(blockIndex) diff --git a/packages/editor/src/editor/selection-state-context.tsx b/packages/editor/src/editor/selection-state-context.tsx index 976acc616..7ff9d7b99 100644 --- a/packages/editor/src/editor/selection-state-context.tsx +++ b/packages/editor/src/editor/selection-state-context.tsx @@ -1,3 +1,4 @@ +import {getIndexForKey} from '@sanity/json-match' import {useSelector} from '@xstate/react' import {createContext, useContext} from 'react' import {getFocusChild} from '../selectors' @@ -111,17 +112,18 @@ export function SelectionStateProvider({ let selectedBlockKeys: Set = emptySet if (startBlockKey && endBlockKey) { - const startBlockIndex = snapshot.blockIndexMap.get(startBlockKey) - const endBlockIndex = snapshot.blockIndexMap.get(endBlockKey) + const startBlockIndex = getIndexForKey(snapshot.context.value, startBlockKey) + const endBlockIndex = getIndexForKey(snapshot.context.value, endBlockKey) if (startBlockIndex !== undefined && endBlockIndex !== undefined) { const minIndex = Math.min(startBlockIndex, endBlockIndex) const maxIndex = Math.max(startBlockIndex, endBlockIndex) selectedBlockKeys = new Set() - for (const [key, index] of snapshot.blockIndexMap) { - if (index >= minIndex && index <= maxIndex) { - selectedBlockKeys.add(key) + for (const block of snapshot.context.value) { + const index = getIndexForKey(snapshot.context.value, block._key) + if (index !== undefined && index >= minIndex && index <= maxIndex) { + selectedBlockKeys.add(block._key) } } } diff --git a/packages/editor/src/internal-utils/create-test-snapshot.ts b/packages/editor/src/internal-utils/create-test-snapshot.ts index a5192ac78..bacfe0c60 100644 --- a/packages/editor/src/internal-utils/create-test-snapshot.ts +++ b/packages/editor/src/internal-utils/create-test-snapshot.ts @@ -14,14 +14,8 @@ export function createTestSnapshot(snapshot: { value: snapshot.context?.value ?? [], selection: snapshot.context?.selection ?? null, } - const blockIndexMap = new Map() - - snapshot.context?.value?.forEach((block, index) => { - blockIndexMap.set(block._key, index) - }) return { - blockIndexMap, context, decoratorState: snapshot?.decoratorState ?? {}, } diff --git a/packages/editor/src/internal-utils/to-slate-range.test.ts b/packages/editor/src/internal-utils/to-slate-range.test.ts index 317ff8e10..66d3bbecc 100644 --- a/packages/editor/src/internal-utils/to-slate-range.test.ts +++ b/packages/editor/src/internal-utils/to-slate-range.test.ts @@ -55,7 +55,6 @@ describe(toSlateRange.name, () => { }, }, }, - blockIndexMap: new Map([[blockKey, 0]]), }) expect(range).toEqual({ @@ -104,7 +103,6 @@ describe(toSlateRange.name, () => { }, }, }, - blockIndexMap: new Map([[blockKey, 0]]), }) expect(range).toEqual({ @@ -137,7 +135,6 @@ describe(toSlateRange.name, () => { }, }, }, - blockIndexMap: new Map([[blockObjectKey, 0]]), }) expect(range).toEqual({ @@ -179,7 +176,6 @@ describe(toSlateRange.name, () => { }, }, }, - blockIndexMap: new Map([[blockKey, 0]]), }) expect(range).toEqual({ @@ -220,7 +216,6 @@ describe(toSlateRange.name, () => { }, }, }, - blockIndexMap: new Map([[blockKey, 0]]), }) expect(range).toEqual({ @@ -267,7 +262,6 @@ describe(toSlateRange.name, () => { }, }, }, - blockIndexMap: new Map([[blockKey, 0]]), }) expect(range).toEqual({ diff --git a/packages/editor/src/internal-utils/to-slate-range.ts b/packages/editor/src/internal-utils/to-slate-range.ts index 766a23157..56a10bb7a 100644 --- a/packages/editor/src/internal-utils/to-slate-range.ts +++ b/packages/editor/src/internal-utils/to-slate-range.ts @@ -4,7 +4,8 @@ import { type PortableTextObject, type PortableTextSpan, } from '@portabletext/schema' -import type {EditorContext, EditorSnapshot} from '../editor/editor-snapshot' +import {getIndexForKey} from '@sanity/json-match' +import type {EditorContext} from '../editor/editor-snapshot' import type {Path, Range} from '../slate' import type {EditorSelectionPoint} from '../types/editor' import {blockOffsetToSpanSelectionPoint} from '../utils/util.block-offset' @@ -14,11 +15,9 @@ import { getChildKeyFromSelectionPoint, } from '../utils/util.selection-point' -export function toSlateRange( - snapshot: { - context: Pick - } & Pick, -): Range | null { +export function toSlateRange(snapshot: { + context: Pick +}): Range | null { if (!snapshot.context.selection) { return null } @@ -69,7 +68,7 @@ export function toSlateRange( export function toSlateSelectionPoint( snapshot: { context: Pick - } & Pick, + }, selectionPoint: EditorSelectionPoint, direction: 'forward' | 'backward', ): @@ -84,7 +83,7 @@ export function toSlateSelectionPoint( return undefined } - const blockIndex = snapshot.blockIndexMap.get(blockKey) + const blockIndex = getIndexForKey(snapshot.context.value, blockKey) if (blockIndex === undefined) { return undefined diff --git a/packages/editor/src/operations/operation.annotation.add.ts b/packages/editor/src/operations/operation.annotation.add.ts index 3d8955e0a..996f24dda 100644 --- a/packages/editor/src/operations/operation.annotation.add.ts +++ b/packages/editor/src/operations/operation.annotation.add.ts @@ -35,7 +35,6 @@ export const addAnnotationOperationImplementation: OperationImplementation< value: operation.editor.children as Array, selection: operation.at, }, - blockIndexMap: operation.editor.blockIndexMap, }) : null diff --git a/packages/editor/src/operations/operation.annotation.remove.ts b/packages/editor/src/operations/operation.annotation.remove.ts index 9e8e6b02e..8f402ac0e 100644 --- a/packages/editor/src/operations/operation.annotation.remove.ts +++ b/packages/editor/src/operations/operation.annotation.remove.ts @@ -18,7 +18,6 @@ export const removeAnnotationOperationImplementation: OperationImplementation< value: operation.editor.children as Array, selection: operation.at, }, - blockIndexMap: operation.editor.blockIndexMap, }) : null diff --git a/packages/editor/src/operations/operation.block.set.ts b/packages/editor/src/operations/operation.block.set.ts index 1d7b8359a..58431dcbd 100644 --- a/packages/editor/src/operations/operation.block.set.ts +++ b/packages/editor/src/operations/operation.block.set.ts @@ -1,5 +1,6 @@ import {applyAll, set} from '@portabletext/patches' -import {isTextBlock} from '@portabletext/schema' +import {isTextBlock, type PortableTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import {applySetNode} from '../internal-utils/apply-set-node' import {parseMarkDefs} from '../utils/parse-blocks' import type {OperationImplementation} from './operation.types' @@ -7,7 +8,7 @@ import type {OperationImplementation} from './operation.types' export const blockSetOperationImplementation: OperationImplementation< 'block.set' > = ({context, operation}) => { - const blockIndex = operation.editor.blockIndexMap.get(operation.at[0]._key) + const blockIndex = getIndexForKey(operation.editor.children as Array, operation.at[0]._key) if (blockIndex === undefined) { throw new Error( diff --git a/packages/editor/src/operations/operation.block.unset.ts b/packages/editor/src/operations/operation.block.unset.ts index 437e591bd..97fd2ac10 100644 --- a/packages/editor/src/operations/operation.block.unset.ts +++ b/packages/editor/src/operations/operation.block.unset.ts @@ -1,4 +1,5 @@ -import {isTextBlock} from '@portabletext/schema' +import {isTextBlock, type PortableTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import {applySetNode} from '../internal-utils/apply-set-node' import type {OperationImplementation} from './operation.types' @@ -6,7 +7,7 @@ export const blockUnsetOperationImplementation: OperationImplementation< 'block.unset' > = ({context, operation}) => { const blockKey = operation.at[0]._key - const blockIndex = operation.editor.blockIndexMap.get(blockKey) + const blockIndex = getIndexForKey(operation.editor.children as Array, blockKey) if (blockIndex === undefined) { throw new Error(`Unable to find block index for block key ${blockKey}`) diff --git a/packages/editor/src/operations/operation.child.set.ts b/packages/editor/src/operations/operation.child.set.ts index 4536dea4e..17fb97d3a 100644 --- a/packages/editor/src/operations/operation.child.set.ts +++ b/packages/editor/src/operations/operation.child.set.ts @@ -16,7 +16,6 @@ export const childSetOperationImplementation: OperationImplementation< focus: {path: operation.at, offset: 0}, }, }, - blockIndexMap: operation.editor.blockIndexMap, }) if (!location) { diff --git a/packages/editor/src/operations/operation.child.unset.ts b/packages/editor/src/operations/operation.child.unset.ts index bbd7e3c4e..671739484 100644 --- a/packages/editor/src/operations/operation.child.unset.ts +++ b/packages/editor/src/operations/operation.child.unset.ts @@ -1,5 +1,6 @@ import type {PortableTextBlock} from '@portabletext/schema' import {isTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import {applySetNode} from '../internal-utils/apply-set-node' import {Editor} from '../slate' import type {OperationImplementation} from './operation.types' @@ -8,7 +9,7 @@ export const childUnsetOperationImplementation: OperationImplementation< 'child.unset' > = ({context, operation}) => { const blockKey = operation.at[0]._key - const blockIndex = operation.editor.blockIndexMap.get(blockKey) + const blockIndex = getIndexForKey(operation.editor.children as Array, blockKey) if (blockIndex === undefined) { throw new Error(`Unable to find block index for block key ${blockKey}`) diff --git a/packages/editor/src/operations/operation.decorator.add.ts b/packages/editor/src/operations/operation.decorator.add.ts index 43f54f004..7f0e670fc 100644 --- a/packages/editor/src/operations/operation.decorator.add.ts +++ b/packages/editor/src/operations/operation.decorator.add.ts @@ -19,7 +19,6 @@ export const decoratorAddOperationImplementation: OperationImplementation< value: operation.editor.children as Array, selection: operation.at, }, - blockIndexMap: operation.editor.blockIndexMap, }) : operation.editor.selection diff --git a/packages/editor/src/operations/operation.decorator.remove.ts b/packages/editor/src/operations/operation.decorator.remove.ts index db4af3b2e..93d62c3f9 100644 --- a/packages/editor/src/operations/operation.decorator.remove.ts +++ b/packages/editor/src/operations/operation.decorator.remove.ts @@ -17,7 +17,6 @@ export const decoratorRemoveOperationImplementation: OperationImplementation< value: operation.editor.children as Array, selection: operation.at, }, - blockIndexMap: operation.editor.blockIndexMap, }) : editor.selection diff --git a/packages/editor/src/operations/operation.delete.ts b/packages/editor/src/operations/operation.delete.ts index d2d06df08..922c1bd70 100644 --- a/packages/editor/src/operations/operation.delete.ts +++ b/packages/editor/src/operations/operation.delete.ts @@ -26,7 +26,6 @@ export const deleteOperationImplementation: OperationImplementation< value: operation.editor.children as Array, selection: operation.at, }, - blockIndexMap: operation.editor.blockIndexMap, }) : operation.editor.selection diff --git a/packages/editor/src/operations/operation.insert.block.ts b/packages/editor/src/operations/operation.insert.block.ts index b560d6179..1663868b0 100644 --- a/packages/editor/src/operations/operation.insert.block.ts +++ b/packages/editor/src/operations/operation.insert.block.ts @@ -68,7 +68,6 @@ export function insertBlock(options: { value: editor.children as Array, selection: options.at, }, - blockIndexMap: editor.blockIndexMap, }) : editor.selection diff --git a/packages/editor/src/operations/operation.move.block.ts b/packages/editor/src/operations/operation.move.block.ts index 468d291b2..0e1187264 100644 --- a/packages/editor/src/operations/operation.move.block.ts +++ b/packages/editor/src/operations/operation.move.block.ts @@ -1,3 +1,5 @@ +import type {PortableTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import {applyMoveNode} from '../internal-utils/apply-move-node' import {getBlockKeyFromSelectionPoint} from '../utils/util.selection-point' import type {OperationImplementation} from './operation.types' @@ -14,7 +16,7 @@ export const moveBlockOperationImplementation: OperationImplementation< throw new Error('Failed to get block key from selection point') } - const originBlockIndex = operation.editor.blockIndexMap.get(originKey) + const originBlockIndex = getIndexForKey(operation.editor.children as Array, originKey) if (originBlockIndex === undefined) { throw new Error('Failed to get block index from block key') @@ -29,8 +31,10 @@ export const moveBlockOperationImplementation: OperationImplementation< throw new Error('Failed to get block key from selection point') } - const destinationBlockIndex = - operation.editor.blockIndexMap.get(destinationKey) + const destinationBlockIndex = getIndexForKey( + operation.editor.children as Array, + destinationKey, + ) if (destinationBlockIndex === undefined) { throw new Error('Failed to get block index from block key') diff --git a/packages/editor/src/operations/operation.select.ts b/packages/editor/src/operations/operation.select.ts index 3bb3d5799..6c299f373 100644 --- a/packages/editor/src/operations/operation.select.ts +++ b/packages/editor/src/operations/operation.select.ts @@ -12,7 +12,6 @@ export const selectOperationImplementation: OperationImplementation< value: operation.editor.children as Array, selection: operation.at, }, - blockIndexMap: operation.editor.blockIndexMap, }) if (newSelection) { diff --git a/packages/editor/src/selectors/selector.get-anchor-block.ts b/packages/editor/src/selectors/selector.get-anchor-block.ts index 7bd699c4f..09a67eba9 100644 --- a/packages/editor/src/selectors/selector.get-anchor-block.ts +++ b/packages/editor/src/selectors/selector.get-anchor-block.ts @@ -1,4 +1,5 @@ import type {PortableTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorSelector} from '../editor/editor-selector' import type {BlockPath} from '../types/paths' import {getBlockKeyFromSelectionPoint} from '../utils/util.selection-point' @@ -14,7 +15,7 @@ export const getAnchorBlock: EditorSelector< } const key = getBlockKeyFromSelectionPoint(snapshot.context.selection.anchor) - const index = key ? snapshot.blockIndexMap.get(key) : undefined + const index = key ? getIndexForKey(snapshot.context.value, key) : undefined const node = index !== undefined ? snapshot.context.value.at(index) : undefined diff --git a/packages/editor/src/selectors/selector.get-focus-block.ts b/packages/editor/src/selectors/selector.get-focus-block.ts index 3889ecfbe..6f83cf2a9 100644 --- a/packages/editor/src/selectors/selector.get-focus-block.ts +++ b/packages/editor/src/selectors/selector.get-focus-block.ts @@ -1,4 +1,5 @@ import type {PortableTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorSelector} from '../editor/editor-selector' import type {BlockPath} from '../types/paths' import {getBlockKeyFromSelectionPoint} from '../utils/util.selection-point' @@ -14,7 +15,7 @@ export const getFocusBlock: EditorSelector< } const key = getBlockKeyFromSelectionPoint(snapshot.context.selection.focus) - const index = key ? snapshot.blockIndexMap.get(key) : undefined + const index = key ? getIndexForKey(snapshot.context.value, key) : undefined const node = index !== undefined ? snapshot.context.value.at(index) : undefined diff --git a/packages/editor/src/selectors/selector.get-next-block.ts b/packages/editor/src/selectors/selector.get-next-block.ts index 86fc2d795..84761c468 100644 --- a/packages/editor/src/selectors/selector.get-next-block.ts +++ b/packages/editor/src/selectors/selector.get-next-block.ts @@ -1,4 +1,5 @@ import type {PortableTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorSelector} from '../editor/editor-selector' import type {BlockPath} from '../types/paths' import {getSelectionEndBlock} from './selector.get-selection-end-block' @@ -15,9 +16,12 @@ export const getNextBlock: EditorSelector< return undefined } - const index = snapshot.blockIndexMap.get(selectionEndBlock.node._key) + const index = getIndexForKey( + snapshot.context.value, + selectionEndBlock.node._key, + ) - if (index === undefined || index === snapshot.context.value.length - 1) { + if (index === undefined) { return undefined } diff --git a/packages/editor/src/selectors/selector.get-previous-block.ts b/packages/editor/src/selectors/selector.get-previous-block.ts index 895a332b9..44cd9b593 100644 --- a/packages/editor/src/selectors/selector.get-previous-block.ts +++ b/packages/editor/src/selectors/selector.get-previous-block.ts @@ -1,4 +1,5 @@ import type {PortableTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorSelector} from '../editor/editor-selector' import type {BlockPath} from '../types/paths' import {getSelectionStartBlock} from './selector.get-selection-start-block' @@ -15,7 +16,10 @@ export const getPreviousBlock: EditorSelector< return undefined } - const index = snapshot.blockIndexMap.get(selectionStartBlock.node._key) + const index = getIndexForKey( + snapshot.context.value, + selectionStartBlock.node._key, + ) if (index === undefined || index === 0) { return undefined diff --git a/packages/editor/src/selectors/selector.get-selected-blocks.ts b/packages/editor/src/selectors/selector.get-selected-blocks.ts index 46de71730..0150f22d6 100644 --- a/packages/editor/src/selectors/selector.get-selected-blocks.ts +++ b/packages/editor/src/selectors/selector.get-selected-blocks.ts @@ -1,4 +1,5 @@ import type {PortableTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorSelector} from '../editor/editor-selector' import type {BlockPath} from '../types/paths' import {getSelectionEndPoint} from '../utils/util.get-selection-end-point' @@ -25,8 +26,8 @@ export const getSelectedBlocks: EditorSelector< return selectedBlocks } - const startBlockIndex = snapshot.blockIndexMap.get(startKey) - const endBlockIndex = snapshot.blockIndexMap.get(endKey) + const startBlockIndex = getIndexForKey(snapshot.context.value, startKey) + const endBlockIndex = getIndexForKey(snapshot.context.value, endKey) if (startBlockIndex === undefined || endBlockIndex === undefined) { return selectedBlocks diff --git a/packages/editor/src/selectors/selector.get-selected-children.ts b/packages/editor/src/selectors/selector.get-selected-children.ts index 5ce2e023c..118a07af3 100644 --- a/packages/editor/src/selectors/selector.get-selected-children.ts +++ b/packages/editor/src/selectors/selector.get-selected-children.ts @@ -1,5 +1,6 @@ import {isSpan, isTextBlock} from '@portabletext/schema' import type {PortableTextChild} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorSelector} from '../editor/editor-selector' import type {ChildPath} from '../types/paths' import { @@ -44,8 +45,8 @@ export function getSelectedChildren< return [] } - const startBlockIndex = snapshot.blockIndexMap.get(startBlockKey) - const endBlockIndex = snapshot.blockIndexMap.get(endBlockKey) + const startBlockIndex = getIndexForKey(snapshot.context.value, startBlockKey) + const endBlockIndex = getIndexForKey(snapshot.context.value, endBlockKey) if (startBlockIndex === undefined || endBlockIndex === undefined) { return [] diff --git a/packages/editor/src/selectors/selector.get-selected-text-blocks.ts b/packages/editor/src/selectors/selector.get-selected-text-blocks.ts index aefc55720..7202c8ebc 100644 --- a/packages/editor/src/selectors/selector.get-selected-text-blocks.ts +++ b/packages/editor/src/selectors/selector.get-selected-text-blocks.ts @@ -1,4 +1,5 @@ import {isTextBlock, type PortableTextTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorSelector} from '../editor/editor-selector' import type {BlockPath} from '../types/paths' import {getSelectionEndPoint} from '../utils/util.get-selection-end-point' @@ -29,8 +30,8 @@ export const getSelectedTextBlocks: EditorSelector< return selectedTextBlocks } - const startBlockIndex = snapshot.blockIndexMap.get(startBlockKey) - const endBlockIndex = snapshot.blockIndexMap.get(endBlockKey) + const startBlockIndex = getIndexForKey(snapshot.context.value, startBlockKey) + const endBlockIndex = getIndexForKey(snapshot.context.value, endBlockKey) if (startBlockIndex === undefined || endBlockIndex === undefined) { return selectedTextBlocks diff --git a/packages/editor/src/selectors/selector.get-selected-value.ts b/packages/editor/src/selectors/selector.get-selected-value.ts index 7c3e950cb..94731b424 100644 --- a/packages/editor/src/selectors/selector.get-selected-value.ts +++ b/packages/editor/src/selectors/selector.get-selected-value.ts @@ -1,4 +1,5 @@ import type {PortableTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorSelector} from '../editor/editor-selector' import {getSelectionEndPoint} from '../utils/util.get-selection-end-point' import {getSelectionStartPoint} from '../utils/util.get-selection-start-point' @@ -26,8 +27,8 @@ export const getSelectedValue: EditorSelector> = ( return [] } - const startBlockIndex = snapshot.blockIndexMap.get(startBlockKey) - const endBlockIndex = snapshot.blockIndexMap.get(endBlockKey) + const startBlockIndex = getIndexForKey(snapshot.context.value, startBlockKey) + const endBlockIndex = getIndexForKey(snapshot.context.value, endBlockKey) if (startBlockIndex === undefined || endBlockIndex === undefined) { return [] diff --git a/packages/editor/src/selectors/selector.is-overlapping-selection.ts b/packages/editor/src/selectors/selector.is-overlapping-selection.ts index 23a53ea34..f4975c046 100644 --- a/packages/editor/src/selectors/selector.is-overlapping-selection.ts +++ b/packages/editor/src/selectors/selector.is-overlapping-selection.ts @@ -1,3 +1,4 @@ +import {getIndexForKey} from '@sanity/json-match' import type {EditorSelection, EditorSelectionPoint} from '../types/editor' import { getSelectionEndPoint, @@ -43,15 +44,20 @@ export function isOverlappingSelection( return false } - const selectionStartBlockIndex = snapshot.blockIndexMap.get( + const selectionStartBlockIndex = getIndexForKey( + snapshot.context.value, selectionStartBlockKey, ) - const selectionEndBlockIndex = - snapshot.blockIndexMap.get(selectionEndBlockKey) - const editorSelectionStartBlockIndex = snapshot.blockIndexMap.get( + const selectionEndBlockIndex = getIndexForKey( + snapshot.context.value, + selectionEndBlockKey, + ) + const editorSelectionStartBlockIndex = getIndexForKey( + snapshot.context.value, editorSelectionStartBlockKey, ) - const editorSelectionEndBlockIndex = snapshot.blockIndexMap.get( + const editorSelectionEndBlockIndex = getIndexForKey( + snapshot.context.value, editorSelectionEndBlockKey, ) diff --git a/packages/editor/src/slate-plugins/slate-plugin.unique-keys.ts b/packages/editor/src/slate-plugins/slate-plugin.unique-keys.ts index 6fd8f53dd..392ec921f 100644 --- a/packages/editor/src/slate-plugins/slate-plugin.unique-keys.ts +++ b/packages/editor/src/slate-plugins/slate-plugin.unique-keys.ts @@ -1,7 +1,8 @@ import type {PortableTextBlock} from '@portabletext/schema' import {isTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorActor} from '../editor/editor-machine' -import type {EditorContext, EditorSnapshot} from '../editor/editor-snapshot' +import type {EditorContext} from '../editor/editor-snapshot' import {applySetNode} from '../internal-utils/apply-set-node' import {Editor, Element, Node, type Path} from '../slate' import type {PortableTextSlateEditor} from '../types/slate-editor' @@ -47,7 +48,6 @@ export function createUniqueKeysPlugin(editorActor: EditorActor) { operation.node._key && keyExistsAtPath( { - blockIndexMap: editor.blockIndexMap, context: { schema: context.schema, value: editor.children as Array, @@ -178,14 +178,14 @@ export function createUniqueKeysPlugin(editorActor: EditorActor) { } function keyExistsAtPath( - snapshot: Pick & { + snapshot: { context: Pick }, path: Path, key: string, ): boolean { if (path.length === 1) { - return snapshot.blockIndexMap.has(key) + return getIndexForKey(snapshot.context.value, key) !== undefined } if (path.length > 2) { diff --git a/packages/editor/src/utils/util.compare-points.ts b/packages/editor/src/utils/util.compare-points.ts index 574477981..de8912b74 100644 --- a/packages/editor/src/utils/util.compare-points.ts +++ b/packages/editor/src/utils/util.compare-points.ts @@ -1,4 +1,5 @@ import {isTextBlock} from '@portabletext/schema' +import {getIndexForKey} from '@sanity/json-match' import type {EditorSnapshot} from '../editor/editor-snapshot' import type {EditorSelectionPoint} from '../types/editor' import { @@ -29,8 +30,8 @@ export function comparePoints( throw new Error(`Cannot compare points: no block key found for ${pointB}`) } - const blockIndexA = snapshot.blockIndexMap.get(blockKeyA) - const blockIndexB = snapshot.blockIndexMap.get(blockKeyB) + const blockIndexA = getIndexForKey(snapshot.context.value, blockKeyA) + const blockIndexB = getIndexForKey(snapshot.context.value, blockKeyB) if (blockIndexA === undefined) { throw new Error(`Cannot compare points: block "${blockKeyA}" not found`) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 16d589b3d..612dd851f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -438,6 +438,9 @@ importers: '@portabletext/to-html': specifier: ^5.0.2 version: 5.0.2 + '@sanity/json-match': + specifier: ^1.0.5 + version: 1.0.5 '@xstate/react': specifier: ^6.1.0 version: 6.1.0(@types/react@19.2.14)(react@19.2.3)(xstate@5.28.0)