@portabletext/editor 1.36.6 → 1.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/lib/_chunks-cjs/behavior.markdown.cjs +1 -1
  2. package/lib/_chunks-cjs/editor-provider.cjs +63 -4
  3. package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
  4. package/lib/_chunks-es/behavior.markdown.js +1 -1
  5. package/lib/_chunks-es/editor-provider.js +67 -8
  6. package/lib/_chunks-es/editor-provider.js.map +1 -1
  7. package/lib/behaviors/index.d.cts +1 -0
  8. package/lib/behaviors/index.d.ts +1 -0
  9. package/lib/index.d.cts +1 -0
  10. package/lib/index.d.ts +1 -0
  11. package/lib/plugins/index.cjs +1 -1
  12. package/lib/plugins/index.d.cts +1 -0
  13. package/lib/plugins/index.d.ts +1 -0
  14. package/lib/plugins/index.js +1 -1
  15. package/lib/selectors/index.cjs +69 -14
  16. package/lib/selectors/index.cjs.map +1 -1
  17. package/lib/selectors/index.d.cts +17 -0
  18. package/lib/selectors/index.d.ts +17 -0
  19. package/lib/selectors/index.js +63 -8
  20. package/lib/selectors/index.js.map +1 -1
  21. package/lib/utils/index.d.cts +1 -0
  22. package/lib/utils/index.d.ts +1 -0
  23. package/package.json +7 -7
  24. package/src/behavior-actions/behavior.action.decorator.add.ts +1 -0
  25. package/src/behavior-actions/behavior.action.delete.text.ts +1 -0
  26. package/src/behavior-actions/behavior.action.delete.ts +1 -3
  27. package/src/behavior-actions/behavior.action.insert-blocks.ts +66 -1
  28. package/src/editor/editor-machine.ts +16 -3
  29. package/src/editor/editor-selector.ts +1 -0
  30. package/src/editor/editor-snapshot.ts +4 -0
  31. package/src/internal-utils/create-test-snapshot.ts +1 -0
  32. package/src/selectors/index.ts +2 -0
  33. package/src/selectors/selector.get-focus-inline-object.ts +21 -0
  34. package/src/selectors/selector.is-overlapping-selection.test.ts +171 -0
  35. package/src/selectors/selector.is-overlapping-selection.ts +108 -4
  36. package/src/selectors/selector.is-point-after-selection.ts +3 -1
  37. package/src/selectors/selector.is-point-before-selection.ts +3 -1
  38. package/src/selectors/selector.is-selecting-entire-blocks.ts +34 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/selectors/selector.get-active-annotations.ts","../../src/selectors/selector.get-anchor-block.ts","../../src/selectors/selector.get-anchor-text-block.ts","../../src/selectors/selector.get-anchor-child.ts","../../src/selectors/selector.get-anchor-span.ts","../../src/selectors/selector.get-block-offsets.ts","../../src/selectors/selector.get-selection.ts","../../src/selectors/selector.get-value.ts","../../src/selectors/selector.is-point-after-selection.ts","../../src/selectors/selector.is-point-before-selection.ts","../../src/selectors/selector.is-overlapping-selection.ts"],"sourcesContent":["import {isPortableTextTextBlock, type PortableTextObject} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getSelectedSpans} from './selector.get-selected-spans'\nimport {getSelectedBlocks} from './selectors'\n\n/**\n * @public\n */\nexport const getActiveAnnotations: EditorSelector<Array<PortableTextObject>> = (\n snapshot,\n) => {\n if (!snapshot.context.selection) {\n return []\n }\n\n const selectedBlocks = getSelectedBlocks(snapshot)\n const selectedSpans = getSelectedSpans(snapshot)\n\n if (selectedSpans.length === 0) {\n return []\n }\n\n const selectionMarkDefs = selectedBlocks.flatMap((block) =>\n isPortableTextTextBlock(block.node) ? (block.node.markDefs ?? []) : [],\n )\n\n return selectionMarkDefs.filter((markDef) =>\n selectedSpans.some((span) => span.node.marks?.includes(markDef._key)),\n )\n}\n","import type {KeyedSegment, PortableTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {isKeyedSegment} from '../utils'\n\n/**\n * @public\n */\nexport const getAnchorBlock: EditorSelector<\n {node: PortableTextBlock; path: [KeyedSegment]} | undefined\n> = (snapshot) => {\n const key = snapshot.context.selection\n ? isKeyedSegment(snapshot.context.selection.anchor.path[0])\n ? snapshot.context.selection.anchor.path[0]._key\n : undefined\n : undefined\n\n const node = key\n ? snapshot.context.value.find((block) => block._key === key)\n : undefined\n\n return node && key ? {node, path: [{_key: key}]} : undefined\n}\n","import {\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextTextBlock,\n} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getAnchorBlock} from './selector.get-anchor-block'\n\n/**\n * @public\n */\nexport const getAnchorTextBlock: EditorSelector<\n {node: PortableTextTextBlock; path: [KeyedSegment]} | undefined\n> = (snapshot) => {\n const anchorBlock = getAnchorBlock(snapshot)\n\n return anchorBlock && isPortableTextTextBlock(anchorBlock.node)\n ? {node: anchorBlock.node, path: anchorBlock.path}\n : undefined\n}\n","import type {KeyedSegment} from '@portabletext/patches'\nimport type {PortableTextObject, PortableTextSpan} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {isKeyedSegment} from '../utils'\nimport {getAnchorTextBlock} from './selector.get-anchor-text-block'\n\n/**\n * @public\n */\nexport const getAnchorChild: EditorSelector<\n | {\n node: PortableTextObject | PortableTextSpan\n path: [KeyedSegment, 'children', KeyedSegment]\n }\n | undefined\n> = (snapshot) => {\n const anchorBlock = getAnchorTextBlock(snapshot)\n\n if (!anchorBlock) {\n return undefined\n }\n\n const key = snapshot.context.selection\n ? isKeyedSegment(snapshot.context.selection.anchor.path[2])\n ? snapshot.context.selection.anchor.path[2]._key\n : undefined\n : undefined\n\n const node = key\n ? anchorBlock.node.children.find((span) => span._key === key)\n : undefined\n\n return node && key\n ? {node, path: [...anchorBlock.path, 'children', {_key: key}]}\n : undefined\n}\n","import type {KeyedSegment} from '@portabletext/patches'\nimport {isPortableTextSpan, type PortableTextSpan} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getAnchorChild} from './selector.get-anchor-child'\n\n/**\n * @public\n */\nexport const getAnchorSpan: EditorSelector<\n | {node: PortableTextSpan; path: [KeyedSegment, 'children', KeyedSegment]}\n | undefined\n> = (snapshot) => {\n const anchorChild = getAnchorChild(snapshot)\n\n return anchorChild && isPortableTextSpan(anchorChild.node)\n ? {node: anchorChild.node, path: anchorChild.path}\n : undefined\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport type {BlockOffset} from '../types/block-offset'\nimport * as utils from '../utils'\nimport {getSelectionEndPoint} from './selector.get-selection-end-point'\nimport {getSelectionStartPoint} from './selector.get-selection-start-point'\n\n/**\n * @public\n */\nexport const getBlockOffsets: EditorSelector<\n {start: BlockOffset; end: BlockOffset} | undefined\n> = (snapshot) => {\n if (!snapshot.context.selection) {\n return undefined\n }\n\n const selectionStartPoint = getSelectionStartPoint(snapshot)\n const selectionEndPoint = getSelectionEndPoint(snapshot)\n\n if (!selectionStartPoint || !selectionEndPoint) {\n return undefined\n }\n\n const start = utils.spanSelectionPointToBlockOffset({\n value: snapshot.context.value,\n selectionPoint: selectionStartPoint,\n })\n const end = utils.spanSelectionPointToBlockOffset({\n value: snapshot.context.value,\n selectionPoint: selectionEndPoint,\n })\n\n return start && end ? {start, end} : undefined\n}\n","import type {EditorSelection} from '..'\nimport type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const getSelection: EditorSelector<EditorSelection> = (snapshot) => {\n return snapshot.context.selection\n}\n","import type {PortableTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const getValue: EditorSelector<Array<PortableTextBlock>> = (\n snapshot,\n) => {\n return snapshot.context.value\n}\n","import {isKeySegment, isPortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport type {EditorSelectionPoint} from '../types/editor'\nimport {reverseSelection} from '../utils/util.reverse-selection'\n\n/**\n * @public\n */\nexport function isPointAfterSelection(\n point: EditorSelectionPoint,\n): EditorSelector<boolean> {\n return (snapshot) => {\n if (!snapshot.context.selection) {\n return false\n }\n\n const selection = reverseSelection(snapshot.context.selection)\n\n const pointBlockKey = isKeySegment(point.path[0])\n ? point.path[0]._key\n : undefined\n const pointChildKey = isKeySegment(point.path[2])\n ? point.path[2]._key\n : undefined\n\n const endBlockKey = isKeySegment(selection.focus.path[0])\n ? selection.focus.path[0]._key\n : undefined\n const endChildKey = isKeySegment(selection.focus.path[2])\n ? selection.focus.path[2]._key\n : undefined\n\n if (!pointBlockKey || !endBlockKey) {\n return false\n }\n\n let after = false\n\n for (const block of snapshot.context.value) {\n if (block._key === endBlockKey) {\n if (block._key !== pointBlockKey) {\n after = true\n break\n }\n\n // Both the point and the selection end in this block\n\n if (!isPortableTextTextBlock(block)) {\n break\n }\n\n if (!pointChildKey || !endChildKey) {\n break\n }\n\n for (const child of block.children) {\n if (child._key === endChildKey) {\n if (child._key !== pointChildKey) {\n after = true\n break\n }\n\n // Both the point and the selection end in this child\n\n after = point.offset > selection.focus.offset\n break\n }\n\n if (child._key === pointChildKey) {\n break\n }\n }\n }\n\n if (block._key === pointBlockKey) {\n break\n }\n }\n\n return after\n }\n}\n","import {isKeySegment, isPortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport type {EditorSelectionPoint} from '../types/editor'\nimport {reverseSelection} from '../utils/util.reverse-selection'\n\n/**\n * @public\n */\nexport function isPointBeforeSelection(\n point: EditorSelectionPoint,\n): EditorSelector<boolean> {\n return (snapshot) => {\n if (!snapshot.context.selection) {\n return false\n }\n\n const selection = reverseSelection(snapshot.context.selection)\n\n const pointBlockKey = isKeySegment(point.path[0])\n ? point.path[0]._key\n : undefined\n const pointChildKey = isKeySegment(point.path[2])\n ? point.path[2]._key\n : undefined\n\n const startBlockKey = isKeySegment(selection.anchor.path[0])\n ? selection.anchor.path[0]._key\n : undefined\n const startChildKey = isKeySegment(selection.anchor.path[2])\n ? selection.anchor.path[2]._key\n : undefined\n\n if (!pointBlockKey || !startBlockKey) {\n return false\n }\n\n let before = false\n\n for (const block of snapshot.context.value) {\n if (block._key === pointBlockKey) {\n if (block._key !== startBlockKey) {\n before = true\n break\n }\n\n // Both the point and the selection start in this block\n\n if (!isPortableTextTextBlock(block)) {\n break\n }\n\n if (!pointChildKey || !startChildKey) {\n break\n }\n\n for (const child of block.children) {\n if (child._key === pointChildKey) {\n if (child._key !== startChildKey) {\n before = true\n break\n }\n\n // Both the point and the selection start in this child\n\n before = point.offset < selection.anchor.offset\n break\n }\n\n if (child._key === startChildKey) {\n break\n }\n }\n }\n\n if (block._key === startBlockKey) {\n break\n }\n }\n\n return before\n }\n}\n","import type {EditorSelection} from '../types/editor'\nimport type {EditorSelector} from './../editor/editor-selector'\nimport {getSelectionEndPoint} from './selector.get-selection-end-point'\nimport {getSelectionStartPoint} from './selector.get-selection-start-point'\nimport {isPointAfterSelection} from './selector.is-point-after-selection'\nimport {isPointBeforeSelection} from './selector.is-point-before-selection'\n\n/**\n * @public\n */\nexport function isOverlappingSelection(\n selection: EditorSelection,\n): EditorSelector<boolean> {\n return (snapshot) => {\n if (!selection || !snapshot.context.selection) {\n return false\n }\n\n const selectionStartPoint = getSelectionStartPoint({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection,\n },\n })\n const selectionEndPoint = getSelectionEndPoint({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection,\n },\n })\n\n if (!selectionStartPoint || !selectionEndPoint) {\n return false\n }\n\n if (!isPointAfterSelection(selectionStartPoint)(snapshot)) {\n return false\n }\n\n if (!isPointBeforeSelection(selectionEndPoint)(snapshot)) {\n return false\n }\n\n return true\n }\n}\n"],"names":["getActiveAnnotations","snapshot","context","selection","selectedBlocks","getSelectedBlocks","selectedSpans","getSelectedSpans","length","flatMap","block","isPortableTextTextBlock","node","markDefs","filter","markDef","some","span","marks","includes","_key","getAnchorBlock","key","isKeyedSegment","anchor","path","undefined","value","find","getAnchorTextBlock","anchorBlock","getAnchorChild","children","getAnchorSpan","anchorChild","isPortableTextSpan","getBlockOffsets","selectionStartPoint","getSelectionStartPoint","selectionEndPoint","getSelectionEndPoint","start","utils","selectionPoint","end","getSelection","getValue","isPointAfterSelection","point","reverseSelection","pointBlockKey","isKeySegment","pointChildKey","endBlockKey","focus","endChildKey","after","child","offset","isPointBeforeSelection","startBlockKey","startChildKey","before","isOverlappingSelection"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/selectors/selector.is-selecting-entire-blocks.ts","../../src/selectors/selector.get-active-annotations.ts","../../src/selectors/selector.get-anchor-block.ts","../../src/selectors/selector.get-anchor-text-block.ts","../../src/selectors/selector.get-anchor-child.ts","../../src/selectors/selector.get-anchor-span.ts","../../src/selectors/selector.get-block-offsets.ts","../../src/selectors/selector.get-focus-inline-object.ts","../../src/selectors/selector.get-selection.ts","../../src/selectors/selector.get-value.ts","../../src/selectors/selector.is-point-after-selection.ts","../../src/selectors/selector.is-point-before-selection.ts","../../src/selectors/selector.is-overlapping-selection.ts"],"sourcesContent":["import type {EditorSelector} from '../editor/editor-selector'\nimport * as utils from '../utils'\nimport {getSelectionEndBlock, getSelectionStartBlock} from './selectors'\n\n/**\n * @public\n */\nexport const isSelectingEntireBlocks: EditorSelector<boolean> = (snapshot) => {\n if (!snapshot.context.selection) {\n return false\n }\n\n const startPoint = snapshot.context.selection.backward\n ? snapshot.context.selection.focus\n : snapshot.context.selection.anchor\n const endPoint = snapshot.context.selection.backward\n ? snapshot.context.selection.anchor\n : snapshot.context.selection.focus\n\n const startBlock = getSelectionStartBlock(snapshot)\n const endBlock = getSelectionEndBlock(snapshot)\n\n if (!startBlock || !endBlock) {\n return false\n }\n\n const startBlockStartPoint = utils.getBlockStartPoint(startBlock)\n const endBlockEndPoint = utils.getBlockEndPoint(endBlock)\n\n return (\n utils.isEqualSelectionPoints(startBlockStartPoint, startPoint) &&\n utils.isEqualSelectionPoints(endBlockEndPoint, endPoint)\n )\n}\n","import {isPortableTextTextBlock, type PortableTextObject} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getSelectedSpans} from './selector.get-selected-spans'\nimport {getSelectedBlocks} from './selectors'\n\n/**\n * @public\n */\nexport const getActiveAnnotations: EditorSelector<Array<PortableTextObject>> = (\n snapshot,\n) => {\n if (!snapshot.context.selection) {\n return []\n }\n\n const selectedBlocks = getSelectedBlocks(snapshot)\n const selectedSpans = getSelectedSpans(snapshot)\n\n if (selectedSpans.length === 0) {\n return []\n }\n\n const selectionMarkDefs = selectedBlocks.flatMap((block) =>\n isPortableTextTextBlock(block.node) ? (block.node.markDefs ?? []) : [],\n )\n\n return selectionMarkDefs.filter((markDef) =>\n selectedSpans.some((span) => span.node.marks?.includes(markDef._key)),\n )\n}\n","import type {KeyedSegment, PortableTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {isKeyedSegment} from '../utils'\n\n/**\n * @public\n */\nexport const getAnchorBlock: EditorSelector<\n {node: PortableTextBlock; path: [KeyedSegment]} | undefined\n> = (snapshot) => {\n const key = snapshot.context.selection\n ? isKeyedSegment(snapshot.context.selection.anchor.path[0])\n ? snapshot.context.selection.anchor.path[0]._key\n : undefined\n : undefined\n\n const node = key\n ? snapshot.context.value.find((block) => block._key === key)\n : undefined\n\n return node && key ? {node, path: [{_key: key}]} : undefined\n}\n","import {\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextTextBlock,\n} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getAnchorBlock} from './selector.get-anchor-block'\n\n/**\n * @public\n */\nexport const getAnchorTextBlock: EditorSelector<\n {node: PortableTextTextBlock; path: [KeyedSegment]} | undefined\n> = (snapshot) => {\n const anchorBlock = getAnchorBlock(snapshot)\n\n return anchorBlock && isPortableTextTextBlock(anchorBlock.node)\n ? {node: anchorBlock.node, path: anchorBlock.path}\n : undefined\n}\n","import type {KeyedSegment} from '@portabletext/patches'\nimport type {PortableTextObject, PortableTextSpan} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {isKeyedSegment} from '../utils'\nimport {getAnchorTextBlock} from './selector.get-anchor-text-block'\n\n/**\n * @public\n */\nexport const getAnchorChild: EditorSelector<\n | {\n node: PortableTextObject | PortableTextSpan\n path: [KeyedSegment, 'children', KeyedSegment]\n }\n | undefined\n> = (snapshot) => {\n const anchorBlock = getAnchorTextBlock(snapshot)\n\n if (!anchorBlock) {\n return undefined\n }\n\n const key = snapshot.context.selection\n ? isKeyedSegment(snapshot.context.selection.anchor.path[2])\n ? snapshot.context.selection.anchor.path[2]._key\n : undefined\n : undefined\n\n const node = key\n ? anchorBlock.node.children.find((span) => span._key === key)\n : undefined\n\n return node && key\n ? {node, path: [...anchorBlock.path, 'children', {_key: key}]}\n : undefined\n}\n","import type {KeyedSegment} from '@portabletext/patches'\nimport {isPortableTextSpan, type PortableTextSpan} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getAnchorChild} from './selector.get-anchor-child'\n\n/**\n * @public\n */\nexport const getAnchorSpan: EditorSelector<\n | {node: PortableTextSpan; path: [KeyedSegment, 'children', KeyedSegment]}\n | undefined\n> = (snapshot) => {\n const anchorChild = getAnchorChild(snapshot)\n\n return anchorChild && isPortableTextSpan(anchorChild.node)\n ? {node: anchorChild.node, path: anchorChild.path}\n : undefined\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport type {BlockOffset} from '../types/block-offset'\nimport * as utils from '../utils'\nimport {getSelectionEndPoint} from './selector.get-selection-end-point'\nimport {getSelectionStartPoint} from './selector.get-selection-start-point'\n\n/**\n * @public\n */\nexport const getBlockOffsets: EditorSelector<\n {start: BlockOffset; end: BlockOffset} | undefined\n> = (snapshot) => {\n if (!snapshot.context.selection) {\n return undefined\n }\n\n const selectionStartPoint = getSelectionStartPoint(snapshot)\n const selectionEndPoint = getSelectionEndPoint(snapshot)\n\n if (!selectionStartPoint || !selectionEndPoint) {\n return undefined\n }\n\n const start = utils.spanSelectionPointToBlockOffset({\n value: snapshot.context.value,\n selectionPoint: selectionStartPoint,\n })\n const end = utils.spanSelectionPointToBlockOffset({\n value: snapshot.context.value,\n selectionPoint: selectionEndPoint,\n })\n\n return start && end ? {start, end} : undefined\n}\n","import {\n isPortableTextSpan,\n type KeyedSegment,\n type PortableTextObject,\n} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getFocusChild} from './selectors'\n\n/**\n * @public\n */\nexport const getFocusInlineObject: EditorSelector<\n | {node: PortableTextObject; path: [KeyedSegment, 'children', KeyedSegment]}\n | undefined\n> = (snapshot) => {\n const focusChild = getFocusChild(snapshot)\n\n return focusChild && !isPortableTextSpan(focusChild.node)\n ? {node: focusChild.node, path: focusChild.path}\n : undefined\n}\n","import type {EditorSelection} from '..'\nimport type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const getSelection: EditorSelector<EditorSelection> = (snapshot) => {\n return snapshot.context.selection\n}\n","import type {PortableTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const getValue: EditorSelector<Array<PortableTextBlock>> = (\n snapshot,\n) => {\n return snapshot.context.value\n}\n","import {isKeySegment, isPortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport type {EditorSelectionPoint} from '../types/editor'\nimport {reverseSelection} from '../utils/util.reverse-selection'\n\n/**\n * @public\n */\nexport function isPointAfterSelection(\n point: EditorSelectionPoint,\n): EditorSelector<boolean> {\n return (snapshot) => {\n if (!snapshot.context.selection) {\n return false\n }\n\n const selection = snapshot.context.selection.backward\n ? reverseSelection(snapshot.context.selection)\n : snapshot.context.selection\n\n const pointBlockKey = isKeySegment(point.path[0])\n ? point.path[0]._key\n : undefined\n const pointChildKey = isKeySegment(point.path[2])\n ? point.path[2]._key\n : undefined\n\n const endBlockKey = isKeySegment(selection.focus.path[0])\n ? selection.focus.path[0]._key\n : undefined\n const endChildKey = isKeySegment(selection.focus.path[2])\n ? selection.focus.path[2]._key\n : undefined\n\n if (!pointBlockKey || !endBlockKey) {\n return false\n }\n\n let after = false\n\n for (const block of snapshot.context.value) {\n if (block._key === endBlockKey) {\n if (block._key !== pointBlockKey) {\n after = true\n break\n }\n\n // Both the point and the selection end in this block\n\n if (!isPortableTextTextBlock(block)) {\n break\n }\n\n if (!pointChildKey || !endChildKey) {\n break\n }\n\n for (const child of block.children) {\n if (child._key === endChildKey) {\n if (child._key !== pointChildKey) {\n after = true\n break\n }\n\n // Both the point and the selection end in this child\n\n after = point.offset > selection.focus.offset\n break\n }\n\n if (child._key === pointChildKey) {\n break\n }\n }\n }\n\n if (block._key === pointBlockKey) {\n break\n }\n }\n\n return after\n }\n}\n","import {isKeySegment, isPortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport type {EditorSelectionPoint} from '../types/editor'\nimport {reverseSelection} from '../utils/util.reverse-selection'\n\n/**\n * @public\n */\nexport function isPointBeforeSelection(\n point: EditorSelectionPoint,\n): EditorSelector<boolean> {\n return (snapshot) => {\n if (!snapshot.context.selection) {\n return false\n }\n\n const selection = snapshot.context.selection.backward\n ? reverseSelection(snapshot.context.selection)\n : snapshot.context.selection\n\n const pointBlockKey = isKeySegment(point.path[0])\n ? point.path[0]._key\n : undefined\n const pointChildKey = isKeySegment(point.path[2])\n ? point.path[2]._key\n : undefined\n\n const startBlockKey = isKeySegment(selection.anchor.path[0])\n ? selection.anchor.path[0]._key\n : undefined\n const startChildKey = isKeySegment(selection.anchor.path[2])\n ? selection.anchor.path[2]._key\n : undefined\n\n if (!pointBlockKey || !startBlockKey) {\n return false\n }\n\n let before = false\n\n for (const block of snapshot.context.value) {\n if (block._key === pointBlockKey) {\n if (block._key !== startBlockKey) {\n before = true\n break\n }\n\n // Both the point and the selection start in this block\n\n if (!isPortableTextTextBlock(block)) {\n break\n }\n\n if (!pointChildKey || !startChildKey) {\n break\n }\n\n for (const child of block.children) {\n if (child._key === pointChildKey) {\n if (child._key !== startChildKey) {\n before = true\n break\n }\n\n // Both the point and the selection start in this child\n\n before = point.offset < selection.anchor.offset\n break\n }\n\n if (child._key === startChildKey) {\n break\n }\n }\n }\n\n if (block._key === startBlockKey) {\n break\n }\n }\n\n return before\n }\n}\n","import type {EditorSelection} from '../types/editor'\nimport {isEqualSelectionPoints} from '../utils'\nimport type {EditorSelector} from './../editor/editor-selector'\nimport {getSelectionEndPoint} from './selector.get-selection-end-point'\nimport {getSelectionStartPoint} from './selector.get-selection-start-point'\nimport {isPointAfterSelection} from './selector.is-point-after-selection'\nimport {isPointBeforeSelection} from './selector.is-point-before-selection'\n\n/**\n * @public\n */\nexport function isOverlappingSelection(\n selection: EditorSelection,\n): EditorSelector<boolean> {\n return (snapshot) => {\n if (!selection || !snapshot.context.selection) {\n return false\n }\n\n const selectionStartPoint = getSelectionStartPoint({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection,\n },\n })\n const selectionEndPoint = getSelectionEndPoint({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection,\n },\n })\n\n const originalSelectionStartPoint = getSelectionStartPoint(snapshot)\n const originalSelectionEndPoint = getSelectionEndPoint(snapshot)\n\n if (\n !selectionStartPoint ||\n !selectionEndPoint ||\n !originalSelectionStartPoint ||\n !originalSelectionEndPoint\n ) {\n return false\n }\n\n const startPointBeforeSelection =\n isPointBeforeSelection(selectionStartPoint)(snapshot)\n const startPointAfterSelection =\n isPointAfterSelection(selectionStartPoint)(snapshot)\n const endPointBeforeSelection =\n isPointBeforeSelection(selectionEndPoint)(snapshot)\n const endPointAfterSelection =\n isPointAfterSelection(selectionEndPoint)(snapshot)\n\n const originalStartPointBeforeStartPoint = isPointBeforeSelection(\n originalSelectionStartPoint,\n )({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: {\n anchor: selectionStartPoint,\n focus: selectionStartPoint,\n },\n },\n })\n const originalStartPointAfterStartPoint = isPointAfterSelection(\n originalSelectionStartPoint,\n )({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: {\n anchor: selectionStartPoint,\n focus: selectionStartPoint,\n },\n },\n })\n\n const originalEndPointBeforeEndPoint = isPointBeforeSelection(\n originalSelectionEndPoint,\n )({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: {\n anchor: selectionEndPoint,\n focus: selectionEndPoint,\n },\n },\n })\n const originalEndPointAfterEndPoint = isPointAfterSelection(\n originalSelectionEndPoint,\n )({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: {\n anchor: selectionEndPoint,\n focus: selectionEndPoint,\n },\n },\n })\n\n const endPointEqualToOriginalStartPoint = isEqualSelectionPoints(\n selectionEndPoint,\n originalSelectionStartPoint,\n )\n const startPointEqualToOriginalEndPoint = isEqualSelectionPoints(\n selectionStartPoint,\n originalSelectionEndPoint,\n )\n\n if (endPointBeforeSelection && !endPointEqualToOriginalStartPoint) {\n return false\n }\n\n if (startPointAfterSelection && !startPointEqualToOriginalEndPoint) {\n return false\n }\n\n if (\n !originalStartPointBeforeStartPoint &&\n originalStartPointAfterStartPoint &&\n !originalEndPointBeforeEndPoint &&\n originalEndPointAfterEndPoint\n ) {\n return !endPointEqualToOriginalStartPoint\n }\n\n if (\n originalStartPointBeforeStartPoint &&\n !originalStartPointAfterStartPoint &&\n originalEndPointBeforeEndPoint &&\n !originalEndPointAfterEndPoint\n ) {\n return !startPointEqualToOriginalEndPoint\n }\n\n if (\n !startPointAfterSelection ||\n !startPointBeforeSelection ||\n !endPointAfterSelection ||\n !endPointBeforeSelection\n ) {\n return true\n }\n\n return false\n }\n}\n"],"names":["isSelectingEntireBlocks","snapshot","context","selection","startPoint","backward","focus","anchor","endPoint","startBlock","getSelectionStartBlock","endBlock","getSelectionEndBlock","startBlockStartPoint","utils","endBlockEndPoint","getActiveAnnotations","selectedBlocks","getSelectedBlocks","selectedSpans","getSelectedSpans","length","flatMap","block","isPortableTextTextBlock","node","markDefs","filter","markDef","some","span","marks","includes","_key","getAnchorBlock","key","isKeyedSegment","path","undefined","value","find","getAnchorTextBlock","anchorBlock","getAnchorChild","children","getAnchorSpan","anchorChild","isPortableTextSpan","getBlockOffsets","selectionStartPoint","getSelectionStartPoint","selectionEndPoint","getSelectionEndPoint","start","selectionPoint","end","getFocusInlineObject","focusChild","getFocusChild","getSelection","getValue","isPointAfterSelection","point","reverseSelection","pointBlockKey","isKeySegment","pointChildKey","endBlockKey","endChildKey","after","child","offset","isPointBeforeSelection","startBlockKey","startChildKey","before","isOverlappingSelection","originalSelectionStartPoint","originalSelectionEndPoint","startPointBeforeSelection","startPointAfterSelection","endPointBeforeSelection","endPointAfterSelection","originalStartPointBeforeStartPoint","originalStartPointAfterStartPoint","originalEndPointBeforeEndPoint","originalEndPointAfterEndPoint","endPointEqualToOriginalStartPoint","isEqualSelectionPoints","startPointEqualToOriginalEndPoint"],"mappings":"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"}
@@ -352,6 +352,7 @@ declare type EditorContext = {
352
352
  activeDecorators: Array<string>
353
353
  converters: Array<Converter>
354
354
  keyGenerator: () => string
355
+ readOnly: boolean
355
356
  schema: EditorSchema
356
357
  selection: EditorSelection
357
358
  value: Array<PortableTextBlock>
@@ -352,6 +352,7 @@ declare type EditorContext = {
352
352
  activeDecorators: Array<string>
353
353
  converters: Array<Converter>
354
354
  keyGenerator: () => string
355
+ readOnly: boolean
355
356
  schema: EditorSchema
356
357
  selection: EditorSelection
357
358
  value: Array<PortableTextBlock>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.36.6",
3
+ "version": "1.37.0",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -79,15 +79,15 @@
79
79
  "slate-react": "0.112.1",
80
80
  "use-effect-event": "^1.0.2",
81
81
  "xstate": "^5.19.2",
82
- "@portabletext/block-tools": "1.1.11",
83
- "@portabletext/patches": "1.1.3"
82
+ "@portabletext/patches": "1.1.3",
83
+ "@portabletext/block-tools": "1.1.12"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@portabletext/toolkit": "^2.0.17",
87
87
  "@sanity/diff-match-patch": "^3.2.0",
88
88
  "@sanity/pkg-utils": "^7.0.4",
89
- "@sanity/schema": "^3.77.2",
90
- "@sanity/types": "^3.77.2",
89
+ "@sanity/schema": "^3.78.0",
90
+ "@sanity/types": "^3.78.0",
91
91
  "@testing-library/jest-dom": "^6.6.3",
92
92
  "@testing-library/react": "^16.2.0",
93
93
  "@types/debug": "^4.1.12",
@@ -115,8 +115,8 @@
115
115
  "racejar": "1.2.1"
116
116
  },
117
117
  "peerDependencies": {
118
- "@sanity/schema": "^3.77.2",
119
- "@sanity/types": "^3.77.2",
118
+ "@sanity/schema": "^3.78.0",
119
+ "@sanity/types": "^3.78.0",
120
120
  "react": "^16.9 || ^17 || ^18 || ^19",
121
121
  "rxjs": "^7.8.2"
122
122
  },
@@ -93,6 +93,7 @@ export const decoratorAddActionImplementation: BehaviorActionImplementation<
93
93
  activeDecorators: [],
94
94
  converters: [],
95
95
  keyGenerator: context.keyGenerator,
96
+ readOnly: false,
96
97
  schema: context.schema,
97
98
  selection: newSelection,
98
99
  value: newValue,
@@ -34,6 +34,7 @@ export const deleteTextActionImplementation: BehaviorActionImplementation<
34
34
  schema: context.schema,
35
35
  keyGenerator: context.keyGenerator,
36
36
  activeDecorators: [],
37
+ readOnly: false,
37
38
  value,
38
39
  selection,
39
40
  },
@@ -1,4 +1,3 @@
1
- import {deleteFragment, select} from 'slate'
2
1
  import {toSlateRange} from '../internal-utils/ranges'
3
2
  import type {BehaviorActionImplementation} from './behavior.actions'
4
3
 
@@ -13,6 +12,5 @@ export const deleteActionImplementation: BehaviorActionImplementation<
13
12
  )
14
13
  }
15
14
 
16
- select(action.editor, range)
17
- deleteFragment(action.editor)
15
+ action.editor.delete({at: range})
18
16
  }
@@ -1,5 +1,5 @@
1
1
  import {isEqual, uniq} from 'lodash'
2
- import {Editor, Transforms} from 'slate'
2
+ import {Editor, Node, Path, Transforms} from 'slate'
3
3
  import {isEqualToEmptyEditor, toSlateValue} from '../internal-utils/values'
4
4
  import type {BehaviorActionImplementation} from './behavior.actions'
5
5
 
@@ -43,10 +43,75 @@ export const insertBlocksActionImplementation: BehaviorActionImplementation<
43
43
  if (action.placement === 'after' && focusPath) {
44
44
  const nextPath = [focusPath[0] + 1]
45
45
  Transforms.insertNodes(action.editor, fragment, {at: nextPath})
46
+
47
+ const [nextBlock, nextBlockPath] = Editor.node(
48
+ action.editor,
49
+ Path.next(focusPath),
50
+ {depth: 1},
51
+ )
52
+ const nextChild = Node.child(nextBlock, 0)
53
+ const firstChildIsInlineObject = !action.editor.isTextSpan(nextChild)
54
+
55
+ if (firstChildIsInlineObject) {
56
+ // If the first child in the next block is an inline object then we
57
+ // add an empty span right before it to a place to put the cursor.
58
+ // This is a Slate constraint that we have to adhere to.
59
+ Transforms.insertNodes(
60
+ action.editor,
61
+ {
62
+ _key: context.keyGenerator(),
63
+ _type: 'span',
64
+ text: '',
65
+ marks: [],
66
+ },
67
+ {
68
+ at: [nextBlockPath[0], 0],
69
+ },
70
+ )
71
+ }
72
+
73
+ Transforms.select(action.editor, {
74
+ anchor: {path: [nextPath[0], 0], offset: 0},
75
+ focus: {path: [nextPath[0], 0], offset: 0},
76
+ })
77
+ return
78
+ }
79
+
80
+ if (!action.editor.isTextBlock(focusBlock)) {
81
+ const nextPath = [focusPath[0] + 1]
82
+ Transforms.insertNodes(action.editor, fragment, {at: nextPath})
83
+
84
+ const [nextBlock, nextBlockPath] = Editor.node(
85
+ action.editor,
86
+ Path.next(focusPath),
87
+ {depth: 1},
88
+ )
89
+ const nextChild = Node.child(nextBlock, 0)
90
+ const firstChildIsInlineObject = !action.editor.isTextSpan(nextChild)
91
+
92
+ if (firstChildIsInlineObject) {
93
+ // If the first child in the next block is an inline object then we
94
+ // add an empty span right before it to a place to put the cursor.
95
+ // This is a Slate constraint that we have to adhere to.
96
+ Transforms.insertNodes(
97
+ action.editor,
98
+ {
99
+ _key: context.keyGenerator(),
100
+ _type: 'span',
101
+ text: '',
102
+ marks: [],
103
+ },
104
+ {
105
+ at: [nextBlockPath[0], 0],
106
+ },
107
+ )
108
+ }
109
+
46
110
  Transforms.select(action.editor, {
47
111
  anchor: {path: [nextPath[0], 0], offset: 0},
48
112
  focus: {path: [nextPath[0], 0], offset: 0},
49
113
  })
114
+
50
115
  return
51
116
  }
52
117
 
@@ -360,7 +360,10 @@ export const editorMachine = setup({
360
360
  withApplyingBehaviorActions(event.editor, () => {
361
361
  try {
362
362
  performAction({
363
- context,
363
+ context: {
364
+ keyGenerator: context.keyGenerator,
365
+ schema: context.schema,
366
+ },
364
367
  action: defaultAction,
365
368
  })
366
369
  } catch (error) {
@@ -379,6 +382,7 @@ export const editorMachine = setup({
379
382
  converters: [...context.converters],
380
383
  editor: event.editor,
381
384
  keyGenerator: context.keyGenerator,
385
+ readOnly: self.getSnapshot().matches({'edit mode': 'read only'}),
382
386
  schema: context.schema,
383
387
  hasTag: (tag) => self.getSnapshot().hasTag(tag),
384
388
  })
@@ -440,7 +444,13 @@ export const editorMachine = setup({
440
444
  }
441
445
 
442
446
  try {
443
- performAction({context, action: internalAction})
447
+ performAction({
448
+ context: {
449
+ keyGenerator: context.keyGenerator,
450
+ schema: context.schema,
451
+ },
452
+ action: internalAction,
453
+ })
444
454
  } catch (error) {
445
455
  console.error(
446
456
  new Error(
@@ -483,7 +493,10 @@ export const editorMachine = setup({
483
493
  withApplyingBehaviorActions(event.editor, () => {
484
494
  try {
485
495
  performAction({
486
- context,
496
+ context: {
497
+ keyGenerator: context.keyGenerator,
498
+ schema: context.schema,
499
+ },
487
500
  action: defaultAction,
488
501
  })
489
502
  } catch (error) {
@@ -73,6 +73,7 @@ export function getEditorSnapshot({
73
73
  slateEditorInstance,
74
74
  }),
75
75
  keyGenerator: editorActorSnapshot.context.keyGenerator,
76
+ readOnly: editorActorSnapshot.matches({'edit mode': 'read only'}),
76
77
  schema: editorActorSnapshot.context.schema,
77
78
  selection: editorActorSnapshot.context.selection,
78
79
  value: getValue({editorActorSnapshot, slateEditorInstance}),
@@ -15,6 +15,7 @@ export type EditorContext = {
15
15
  activeDecorators: Array<string>
16
16
  converters: Array<Converter>
17
17
  keyGenerator: () => string
18
+ readOnly: boolean
18
19
  schema: EditorSchema
19
20
  selection: EditorSelection
20
21
  value: Array<PortableTextBlock>
@@ -38,12 +39,14 @@ export function createEditorSnapshot({
38
39
  converters,
39
40
  editor,
40
41
  keyGenerator,
42
+ readOnly,
41
43
  schema,
42
44
  hasTag,
43
45
  }: {
44
46
  converters: Array<Converter>
45
47
  editor: PortableTextSlateEditor
46
48
  keyGenerator: () => string
49
+ readOnly: boolean
47
50
  schema: EditorSchema
48
51
  hasTag: HasTag
49
52
  }) {
@@ -61,6 +64,7 @@ export function createEditorSnapshot({
61
64
  }),
62
65
  converters,
63
66
  keyGenerator,
67
+ readOnly,
64
68
  schema,
65
69
  selection,
66
70
  value,
@@ -13,6 +13,7 @@ export function createTestSnapshot(snapshot: {
13
13
  snapshot.context?.schema ?? compileSchemaDefinition(defineSchema({})),
14
14
  keyGenerator: snapshot.context?.keyGenerator ?? createTestKeyGenerator(),
15
15
  activeDecorators: snapshot.context?.activeDecorators ?? [],
16
+ readOnly: snapshot.context?.readOnly ?? false,
16
17
  value: snapshot.context?.value ?? [],
17
18
  selection: snapshot.context?.selection ?? null,
18
19
  },
@@ -1,3 +1,4 @@
1
+ export {isSelectingEntireBlocks} from './selector.is-selecting-entire-blocks'
1
2
  export {getActiveAnnotations} from './selector.get-active-annotations'
2
3
  export {getActiveListItem} from './selector.get-active-list-item'
3
4
  export {getActiveStyle} from './selector.get-active-style'
@@ -7,6 +8,7 @@ export {getAnchorSpan} from './selector.get-anchor-span'
7
8
  export {getAnchorTextBlock} from './selector.get-anchor-text-block'
8
9
  export {getBlockOffsets} from './selector.get-block-offsets'
9
10
  export {getCaretWordSelection} from './selector.get-caret-word-selection'
11
+ export {getFocusInlineObject} from './selector.get-focus-inline-object'
10
12
  export {getNextInlineObject} from './selector.get-next-inline-object'
11
13
  export {getPreviousInlineObject} from './selector.get-previous-inline-object'
12
14
  export {getSelectedSlice} from './selector.get-selected-slice'
@@ -0,0 +1,21 @@
1
+ import {
2
+ isPortableTextSpan,
3
+ type KeyedSegment,
4
+ type PortableTextObject,
5
+ } from '@sanity/types'
6
+ import type {EditorSelector} from '../editor/editor-selector'
7
+ import {getFocusChild} from './selectors'
8
+
9
+ /**
10
+ * @public
11
+ */
12
+ export const getFocusInlineObject: EditorSelector<
13
+ | {node: PortableTextObject; path: [KeyedSegment, 'children', KeyedSegment]}
14
+ | undefined
15
+ > = (snapshot) => {
16
+ const focusChild = getFocusChild(snapshot)
17
+
18
+ return focusChild && !isPortableTextSpan(focusChild.node)
19
+ ? {node: focusChild.node, path: focusChild.path}
20
+ : undefined
21
+ }
@@ -0,0 +1,171 @@
1
+ import {describe, expect, test} from 'vitest'
2
+ import {createTestSnapshot} from '../internal-utils/create-test-snapshot'
3
+ import type {EditorSelection} from '../types/editor'
4
+ import {isOverlappingSelection} from './selector.is-overlapping-selection'
5
+
6
+ function snapshot(selection: EditorSelection) {
7
+ return createTestSnapshot({
8
+ context: {
9
+ selection,
10
+ value: [
11
+ {_type: 'image', _key: 'k0'},
12
+ {
13
+ _type: 'block',
14
+ _key: 'k1',
15
+ children: [
16
+ {_type: 'span', _key: 'k3', text: 'foo'},
17
+ {_type: 'stock-ticker', _key: 'k4'},
18
+ {_type: 'span', _key: 'k5', text: 'bar'},
19
+ ],
20
+ },
21
+ {_type: 'image', _key: 'k2'},
22
+ ],
23
+ },
24
+ })
25
+ }
26
+
27
+ describe(isOverlappingSelection.name, () => {
28
+ test('null', () => {
29
+ expect(isOverlappingSelection(null)(snapshot(null))).toBe(false)
30
+ })
31
+
32
+ test('fully selected block object', () => {
33
+ expect(
34
+ isOverlappingSelection({
35
+ anchor: {path: [{_key: 'k0'}], offset: 0},
36
+ focus: {path: [{_key: 'k0'}], offset: 0},
37
+ })(
38
+ snapshot({
39
+ anchor: {path: [{_key: 'k0'}], offset: 0},
40
+ focus: {path: [{_key: 'k0'}], offset: 0},
41
+ }),
42
+ ),
43
+ ).toBe(true)
44
+ })
45
+
46
+ test('block object inside selection', () => {
47
+ expect(
48
+ isOverlappingSelection({
49
+ anchor: {path: [{_key: 'k0'}], offset: 0},
50
+ focus: {path: [{_key: 'k0'}], offset: 0},
51
+ })(
52
+ snapshot({
53
+ anchor: {path: [{_key: 'k0'}], offset: 0},
54
+ focus: {path: [{_key: 'k2'}], offset: 0},
55
+ }),
56
+ ),
57
+ ).toBe(true)
58
+ })
59
+
60
+ test('fully selected inline object', () => {
61
+ expect(
62
+ isOverlappingSelection({
63
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
64
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
65
+ })(
66
+ snapshot({
67
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
68
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
69
+ }),
70
+ ),
71
+ ).toBe(true)
72
+ })
73
+
74
+ test('inline object inside selection', () => {
75
+ expect(
76
+ isOverlappingSelection({
77
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
78
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
79
+ })(
80
+ snapshot({
81
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
82
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
83
+ }),
84
+ ),
85
+ ).toBe(true)
86
+ })
87
+
88
+ test('selection right before', () => {
89
+ expect(
90
+ isOverlappingSelection({
91
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 0},
92
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
93
+ })(
94
+ snapshot({
95
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
96
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
97
+ }),
98
+ ),
99
+ ).toBe(false)
100
+ })
101
+
102
+ test('selection overlapping from the start', () => {
103
+ expect(
104
+ isOverlappingSelection({
105
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 0},
106
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 3},
107
+ })(
108
+ snapshot({
109
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
110
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
111
+ }),
112
+ ),
113
+ ).toBe(true)
114
+ })
115
+
116
+ test('selection right after', () => {
117
+ expect(
118
+ isOverlappingSelection({
119
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
120
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 2},
121
+ })(
122
+ snapshot({
123
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
124
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
125
+ }),
126
+ ),
127
+ ).toBe(false)
128
+ })
129
+
130
+ test('selection overlapping from the end', () => {
131
+ expect(
132
+ isOverlappingSelection({
133
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 0},
134
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 2},
135
+ })(
136
+ snapshot({
137
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
138
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
139
+ }),
140
+ ),
141
+ ).toBe(true)
142
+ })
143
+
144
+ test('before inline object', () => {
145
+ expect(
146
+ isOverlappingSelection({
147
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
148
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
149
+ })(
150
+ snapshot({
151
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
152
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
153
+ }),
154
+ ),
155
+ ).toBe(false)
156
+ })
157
+
158
+ test('after inline object', () => {
159
+ expect(
160
+ isOverlappingSelection({
161
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 2},
162
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 2},
163
+ })(
164
+ snapshot({
165
+ anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
166
+ focus: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
167
+ }),
168
+ ),
169
+ ).toBe(false)
170
+ })
171
+ })