@portabletext/editor 1.32.0 → 1.33.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 (69) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +4 -4
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/behavior.markdown.cjs +19 -11
  4. package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
  5. package/lib/_chunks-cjs/plugin.event-listener.cjs +127 -88
  6. package/lib/_chunks-cjs/plugin.event-listener.cjs.map +1 -1
  7. package/lib/_chunks-cjs/selector.get-trimmed-selection.cjs +97 -0
  8. package/lib/_chunks-cjs/selector.get-trimmed-selection.cjs.map +1 -0
  9. package/lib/_chunks-cjs/{parse-blocks.cjs → util.block-offsets-to-selection.cjs} +21 -2
  10. package/lib/_chunks-cjs/util.block-offsets-to-selection.cjs.map +1 -0
  11. package/lib/_chunks-cjs/util.reverse-selection.cjs +11 -0
  12. package/lib/_chunks-cjs/util.reverse-selection.cjs.map +1 -1
  13. package/lib/_chunks-es/behavior.core.js +1 -1
  14. package/lib/_chunks-es/behavior.core.js.map +1 -1
  15. package/lib/_chunks-es/behavior.markdown.js +18 -11
  16. package/lib/_chunks-es/behavior.markdown.js.map +1 -1
  17. package/lib/_chunks-es/plugin.event-listener.js +127 -87
  18. package/lib/_chunks-es/plugin.event-listener.js.map +1 -1
  19. package/lib/_chunks-es/selector.get-trimmed-selection.js +100 -0
  20. package/lib/_chunks-es/selector.get-trimmed-selection.js.map +1 -0
  21. package/lib/_chunks-es/{parse-blocks.js → util.block-offsets-to-selection.js} +21 -1
  22. package/lib/_chunks-es/util.block-offsets-to-selection.js.map +1 -0
  23. package/lib/_chunks-es/util.reverse-selection.js +11 -0
  24. package/lib/_chunks-es/util.reverse-selection.js.map +1 -1
  25. package/lib/behaviors/index.d.cts +1 -0
  26. package/lib/behaviors/index.d.ts +1 -0
  27. package/lib/index.d.cts +60 -0
  28. package/lib/index.d.ts +60 -0
  29. package/lib/plugins/index.cjs +295 -3
  30. package/lib/plugins/index.cjs.map +1 -1
  31. package/lib/plugins/index.d.cts +74 -1
  32. package/lib/plugins/index.d.ts +74 -1
  33. package/lib/plugins/index.js +300 -4
  34. package/lib/plugins/index.js.map +1 -1
  35. package/lib/selectors/index.cjs +51 -1
  36. package/lib/selectors/index.cjs.map +1 -1
  37. package/lib/selectors/index.d.cts +67 -0
  38. package/lib/selectors/index.d.ts +67 -0
  39. package/lib/selectors/index.js +53 -2
  40. package/lib/selectors/index.js.map +1 -1
  41. package/lib/utils/index.cjs +5 -4
  42. package/lib/utils/index.cjs.map +1 -1
  43. package/lib/utils/index.d.cts +16 -0
  44. package/lib/utils/index.d.ts +16 -0
  45. package/lib/utils/index.js +4 -3
  46. package/package.json +2 -2
  47. package/src/behavior-actions/behavior.action.decorator.add.ts +161 -0
  48. package/src/behavior-actions/behavior.action.delete.text.ts +54 -0
  49. package/src/behavior-actions/behavior.actions.ts +5 -43
  50. package/src/behaviors/behavior.markdown-emphasis.ts +395 -0
  51. package/src/behaviors/behavior.markdown.ts +11 -4
  52. package/src/behaviors/behavior.types.ts +1 -0
  53. package/src/editor/plugins/createWithPortableTextMarkModel.ts +2 -97
  54. package/src/plugins/plugin.markdown.tsx +11 -1
  55. package/src/selectors/index.ts +5 -0
  56. package/src/selectors/selector.get-anchor-block.ts +22 -0
  57. package/src/selectors/selector.get-anchor-child.ts +36 -0
  58. package/src/selectors/selector.get-anchor-span.ts +18 -0
  59. package/src/selectors/selector.get-anchor-text-block.ts +20 -0
  60. package/src/selectors/selector.get-trimmed-selection.test.ts +658 -0
  61. package/src/selectors/selector.get-trimmed-selection.ts +175 -0
  62. package/src/utils/index.ts +1 -0
  63. package/src/utils/util.block-offsets-to-selection.ts +36 -0
  64. package/lib/_chunks-cjs/parse-blocks.cjs.map +0 -1
  65. package/lib/_chunks-cjs/util.is-empty-text-block.cjs +0 -14
  66. package/lib/_chunks-cjs/util.is-empty-text-block.cjs.map +0 -1
  67. package/lib/_chunks-es/parse-blocks.js.map +0 -1
  68. package/lib/_chunks-es/util.is-empty-text-block.js +0 -15
  69. package/lib/_chunks-es/util.is-empty-text-block.js.map +0 -1
@@ -0,0 +1,100 @@
1
+ import { isPortableTextTextBlock, isPortableTextSpan } from "@sanity/types";
2
+ import { isEmptyTextBlock, isKeyedSegment } from "./util.reverse-selection.js";
3
+ import { isSelectionCollapsed, getFocusTextBlock, getSelectionStartPoint, getSelectionEndPoint } from "./selector.is-at-the-start-of-block.js";
4
+ const getTrimmedSelection = ({
5
+ context
6
+ }) => {
7
+ if (!context.selection)
8
+ return context.selection;
9
+ const startPoint = getSelectionStartPoint({
10
+ context
11
+ }), endPoint = getSelectionEndPoint({
12
+ context
13
+ });
14
+ if (!startPoint || !endPoint)
15
+ return context.selection;
16
+ const startBlockKey = isKeyedSegment(startPoint.path[0]) ? startPoint.path[0]._key : null, startChildKey = isKeyedSegment(startPoint.path[2]) ? startPoint.path[2]._key : null, endBlockKey = isKeyedSegment(endPoint.path[0]) ? endPoint.path[0]._key : null, endChildKey = isKeyedSegment(endPoint.path[2]) ? endPoint.path[2]._key : null;
17
+ if (!startBlockKey || !endBlockKey)
18
+ return context.selection;
19
+ let startBlockFound = !1, adjustedStartPoint, trimStartPoint = !1, adjustedEndPoint, trimEndPoint = !1, previousPotentialEndpoint;
20
+ for (const block of context.value)
21
+ if (!(block._key === startBlockKey && (startBlockFound = !0, isPortableTextTextBlock(block) && isEmptyTextBlock(block))) && startBlockFound && isPortableTextTextBlock(block)) {
22
+ if (block._key === endBlockKey && isEmptyTextBlock(block))
23
+ break;
24
+ for (const child of block.children) {
25
+ if (child._key === endChildKey && (!isPortableTextSpan(child) || endPoint.offset === 0)) {
26
+ adjustedEndPoint = previousPotentialEndpoint ? {
27
+ path: [{
28
+ _key: previousPotentialEndpoint.blockKey
29
+ }, "children", {
30
+ _key: previousPotentialEndpoint.span._key
31
+ }],
32
+ offset: previousPotentialEndpoint.span.text.length
33
+ } : void 0, trimEndPoint = !0;
34
+ break;
35
+ }
36
+ if (trimStartPoint) {
37
+ const lonelySpan = isPortableTextSpan(child) && block.children.length === 1;
38
+ (isPortableTextSpan(child) && child.text.length > 0 || lonelySpan) && (adjustedStartPoint = {
39
+ path: [{
40
+ _key: block._key
41
+ }, "children", {
42
+ _key: child._key
43
+ }],
44
+ offset: 0
45
+ }, previousPotentialEndpoint = {
46
+ blockKey: block._key,
47
+ span: child
48
+ }, trimStartPoint = !1);
49
+ continue;
50
+ }
51
+ if (child._key === startChildKey) {
52
+ if (!isPortableTextSpan(child)) {
53
+ trimStartPoint = !0;
54
+ continue;
55
+ }
56
+ if (startPoint.offset === child.text.length) {
57
+ trimStartPoint = !0, previousPotentialEndpoint = child.text.length > 0 ? {
58
+ blockKey: block._key,
59
+ span: child
60
+ } : previousPotentialEndpoint;
61
+ continue;
62
+ }
63
+ }
64
+ previousPotentialEndpoint = isPortableTextSpan(child) && child.text.length > 0 ? {
65
+ blockKey: block._key,
66
+ span: child
67
+ } : previousPotentialEndpoint;
68
+ }
69
+ if (block._key === endBlockKey)
70
+ break;
71
+ }
72
+ const trimmedSelection = context.selection.backward ? {
73
+ anchor: trimEndPoint && adjustedEndPoint ? adjustedEndPoint : endPoint,
74
+ focus: adjustedStartPoint ?? startPoint,
75
+ backward: !0
76
+ } : {
77
+ anchor: adjustedStartPoint ?? startPoint,
78
+ focus: trimEndPoint && adjustedEndPoint ? adjustedEndPoint : endPoint
79
+ };
80
+ if (isSelectionCollapsed({
81
+ context: {
82
+ ...context,
83
+ selection: trimmedSelection
84
+ }
85
+ })) {
86
+ const focusTextBlock = getFocusTextBlock({
87
+ context: {
88
+ ...context,
89
+ selection: trimmedSelection
90
+ }
91
+ });
92
+ if (focusTextBlock && !isEmptyTextBlock(focusTextBlock.node))
93
+ return null;
94
+ }
95
+ return trimmedSelection;
96
+ };
97
+ export {
98
+ getTrimmedSelection
99
+ };
100
+ //# sourceMappingURL=selector.get-trimmed-selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.get-trimmed-selection.js","sources":["../../src/selectors/selector.get-trimmed-selection.ts"],"sourcesContent":["import {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type PortableTextSpan,\n} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport type {EditorSelection, EditorSelectionPoint} from '../types/editor'\nimport {isEmptyTextBlock, isKeyedSegment} from '../utils'\nimport {getSelectionEndPoint} from './selector.get-selection-end-point'\nimport {getSelectionStartPoint} from './selector.get-selection-start-point'\nimport {isSelectionCollapsed} from './selector.is-selection-collapsed'\nimport {getFocusTextBlock} from './selectors'\n\n/**\n * @public\n */\nexport const getTrimmedSelection: EditorSelector<EditorSelection> = ({\n context,\n}) => {\n if (!context.selection) {\n return context.selection\n }\n\n const startPoint = getSelectionStartPoint({context})\n const endPoint = getSelectionEndPoint({context})\n\n if (!startPoint || !endPoint) {\n return context.selection\n }\n\n const startBlockKey = isKeyedSegment(startPoint.path[0])\n ? startPoint.path[0]._key\n : null\n const startChildKey = isKeyedSegment(startPoint.path[2])\n ? startPoint.path[2]._key\n : null\n const endBlockKey = isKeyedSegment(endPoint.path[0])\n ? endPoint.path[0]._key\n : null\n const endChildKey = isKeyedSegment(endPoint.path[2])\n ? endPoint.path[2]._key\n : null\n\n if (!startBlockKey || !endBlockKey) {\n return context.selection\n }\n\n let startBlockFound = false\n let adjustedStartPoint: EditorSelectionPoint | undefined\n let trimStartPoint = false\n let adjustedEndPoint: EditorSelectionPoint | undefined\n let trimEndPoint = false\n let previousPotentialEndpoint:\n | {blockKey: string; span: PortableTextSpan}\n | undefined\n\n for (const block of context.value) {\n if (block._key === startBlockKey) {\n startBlockFound = true\n\n if (isPortableTextTextBlock(block) && isEmptyTextBlock(block)) {\n continue\n }\n }\n\n if (!startBlockFound) {\n continue\n }\n\n if (!isPortableTextTextBlock(block)) {\n continue\n }\n\n if (block._key === endBlockKey && isEmptyTextBlock(block)) {\n break\n }\n\n for (const child of block.children) {\n if (child._key === endChildKey) {\n if (!isPortableTextSpan(child) || endPoint.offset === 0) {\n adjustedEndPoint = previousPotentialEndpoint\n ? {\n path: [\n {_key: previousPotentialEndpoint.blockKey},\n 'children',\n {_key: previousPotentialEndpoint.span._key},\n ],\n offset: previousPotentialEndpoint.span.text.length,\n }\n : undefined\n\n trimEndPoint = true\n break\n }\n }\n\n if (trimStartPoint) {\n const lonelySpan =\n isPortableTextSpan(child) && block.children.length === 1\n\n if (\n (isPortableTextSpan(child) && child.text.length > 0) ||\n lonelySpan\n ) {\n adjustedStartPoint = {\n path: [{_key: block._key}, 'children', {_key: child._key}],\n offset: 0,\n }\n previousPotentialEndpoint = {blockKey: block._key, span: child}\n trimStartPoint = false\n }\n\n continue\n }\n\n if (child._key === startChildKey) {\n if (!isPortableTextSpan(child)) {\n trimStartPoint = true\n continue\n }\n\n if (startPoint.offset === child.text.length) {\n trimStartPoint = true\n previousPotentialEndpoint =\n child.text.length > 0\n ? {blockKey: block._key, span: child}\n : previousPotentialEndpoint\n continue\n }\n }\n\n previousPotentialEndpoint =\n isPortableTextSpan(child) && child.text.length > 0\n ? {blockKey: block._key, span: child}\n : previousPotentialEndpoint\n }\n\n if (block._key === endBlockKey) {\n break\n }\n }\n\n const trimmedSelection = context.selection.backward\n ? {\n anchor: trimEndPoint && adjustedEndPoint ? adjustedEndPoint : endPoint,\n focus: adjustedStartPoint ?? startPoint,\n backward: true,\n }\n : {\n anchor: adjustedStartPoint ?? startPoint,\n focus: trimEndPoint && adjustedEndPoint ? adjustedEndPoint : endPoint,\n }\n\n if (\n isSelectionCollapsed({\n context: {\n ...context,\n selection: trimmedSelection,\n },\n })\n ) {\n const focusTextBlock = getFocusTextBlock({\n context: {\n ...context,\n selection: trimmedSelection,\n },\n })\n\n if (focusTextBlock && !isEmptyTextBlock(focusTextBlock.node)) {\n return null\n }\n }\n\n return trimmedSelection\n}\n"],"names":["getTrimmedSelection","context","selection","startPoint","getSelectionStartPoint","endPoint","getSelectionEndPoint","startBlockKey","isKeyedSegment","path","_key","startChildKey","endBlockKey","endChildKey","startBlockFound","adjustedStartPoint","trimStartPoint","adjustedEndPoint","trimEndPoint","previousPotentialEndpoint","block","value","isPortableTextTextBlock","isEmptyTextBlock","child","children","isPortableTextSpan","offset","blockKey","span","text","length","undefined","lonelySpan","trimmedSelection","backward","anchor","focus","isSelectionCollapsed","focusTextBlock","getFocusTextBlock","node"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { isPortableTextTextBlock, isPortableTextSpan } from "@sanity/types";
2
+ import { blockOffsetToSpanSelectionPoint } from "./util.reverse-selection.js";
2
3
  function isTypedObject(object) {
3
4
  return isRecord(object) && typeof object._type == "string";
4
5
  }
@@ -74,7 +75,26 @@ function parseBlock({
74
75
  }
75
76
  return context.schema.lists.find((list) => list.value === block.listItem) || (delete parsedBlock.listItem, delete parsedBlock.level), parsedBlock;
76
77
  }
78
+ function blockOffsetsToSelection({
79
+ value,
80
+ offsets,
81
+ backward
82
+ }) {
83
+ const anchor = blockOffsetToSpanSelectionPoint({
84
+ value,
85
+ blockOffset: offsets.anchor
86
+ }), focus = blockOffsetToSpanSelectionPoint({
87
+ value,
88
+ blockOffset: offsets.focus
89
+ });
90
+ return !anchor || !focus ? null : {
91
+ anchor,
92
+ focus,
93
+ backward
94
+ };
95
+ }
77
96
  export {
97
+ blockOffsetsToSelection,
78
98
  parseBlock
79
99
  };
80
- //# sourceMappingURL=parse-blocks.js.map
100
+ //# sourceMappingURL=util.block-offsets-to-selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.block-offsets-to-selection.js","sources":["../../src/internal-utils/asserters.ts","../../src/internal-utils/parse-blocks.ts","../../src/utils/util.block-offsets-to-selection.ts"],"sourcesContent":["import type {TypedObject} from '@sanity/types'\n\nexport function isTypedObject(object: unknown): object is TypedObject {\n return isRecord(object) && typeof object._type === 'string'\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && (typeof value === 'object' || typeof value === 'function')\n}\n","import {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type PortableTextBlock,\n} from '@sanity/types'\nimport type {EditorContext} from '../editor/editor-snapshot'\nimport {isTypedObject} from './asserters'\n\nexport function parseBlock({\n context,\n block,\n options,\n}: {\n context: Pick<EditorContext, 'keyGenerator' | 'schema'>\n block: unknown\n options: {\n refreshKeys: boolean\n }\n}): PortableTextBlock | undefined {\n if (!isTypedObject(block)) {\n return undefined\n }\n\n if (\n block._type !== context.schema.block.name &&\n !context.schema.blockObjects.some(\n (blockObject) => blockObject.name === block._type,\n )\n ) {\n return undefined\n }\n\n if (block._type !== context.schema.block.name) {\n const _key = options.refreshKeys\n ? context.keyGenerator()\n : typeof block._key === 'string'\n ? block._key\n : context.keyGenerator()\n return {\n ...block,\n _key,\n }\n }\n\n if (!isPortableTextTextBlock(block)) {\n return {\n _type: context.schema.block.name,\n _key: options.refreshKeys\n ? context.keyGenerator()\n : typeof block._key === 'string'\n ? block._key\n : context.keyGenerator(),\n children: [\n {\n _key: context.keyGenerator(),\n _type: context.schema.span.name,\n text: '',\n marks: [],\n },\n ],\n markDefs: [],\n style: context.schema.styles[0].value,\n }\n }\n\n const markDefKeyMap = new Map<string, string>()\n const markDefs = (block.markDefs ?? []).flatMap((markDef) => {\n if (\n context.schema.annotations.some(\n (annotation) => annotation.name === markDef._type,\n )\n ) {\n const _key = options.refreshKeys ? context.keyGenerator() : markDef._key\n markDefKeyMap.set(markDef._key, _key)\n\n return [\n {\n ...markDef,\n _key,\n },\n ]\n }\n\n return []\n })\n\n const children = block.children.flatMap((child) => {\n if (!isTypedObject(child)) {\n return []\n }\n\n if (\n child._type !== context.schema.span.name &&\n !context.schema.inlineObjects.some(\n (inlineObject) => inlineObject.name === child._type,\n )\n ) {\n return []\n }\n\n if (!isPortableTextSpan(child)) {\n return [\n {\n ...child,\n _key: options.refreshKeys ? context.keyGenerator() : child._key,\n },\n ]\n }\n\n const marks = (child.marks ?? []).flatMap((mark) => {\n if (markDefKeyMap.has(mark)) {\n return [markDefKeyMap.get(mark)]\n }\n\n if (\n context.schema.decorators.some((decorator) => decorator.value === mark)\n ) {\n return [mark]\n }\n\n return []\n })\n\n return [\n {\n ...child,\n _key: options.refreshKeys ? context.keyGenerator() : child._key,\n marks,\n },\n ]\n })\n\n const parsedBlock = {\n ...block,\n _key: options.refreshKeys ? context.keyGenerator() : block._key,\n children:\n children.length > 0\n ? children\n : [\n {\n _key: context.keyGenerator(),\n _type: context.schema.span.name,\n text: '',\n marks: [],\n },\n ],\n markDefs,\n }\n\n if (!context.schema.styles.find((style) => style.value === block.style)) {\n const defaultStyle = context.schema.styles[0].value\n\n if (defaultStyle !== undefined) {\n parsedBlock.style = defaultStyle\n } else {\n delete parsedBlock.style\n }\n }\n\n if (!context.schema.lists.find((list) => list.value === block.listItem)) {\n delete parsedBlock.listItem\n delete parsedBlock.level\n }\n\n return parsedBlock\n}\n","import type {PortableTextBlock} from '@sanity/types'\nimport type {BlockOffset} from '../behaviors'\nimport type {EditorSelection} from '../selectors'\nimport {blockOffsetToSpanSelectionPoint} from './util.block-offset'\n\n/**\n * @public\n */\nexport function blockOffsetsToSelection({\n value,\n offsets,\n backward,\n}: {\n value: Array<PortableTextBlock>\n offsets: {anchor: BlockOffset; focus: BlockOffset}\n backward?: boolean\n}): EditorSelection {\n const anchor = blockOffsetToSpanSelectionPoint({\n value,\n blockOffset: offsets.anchor,\n })\n const focus = blockOffsetToSpanSelectionPoint({\n value,\n blockOffset: offsets.focus,\n })\n\n if (!anchor || !focus) {\n return null\n }\n\n return {\n anchor,\n focus,\n backward,\n }\n}\n"],"names":["isTypedObject","object","isRecord","_type","value","parseBlock","context","block","options","schema","name","blockObjects","some","blockObject","_key","refreshKeys","keyGenerator","isPortableTextTextBlock","children","span","text","marks","markDefs","style","styles","markDefKeyMap","Map","flatMap","markDef","annotations","annotation","set","child","inlineObjects","inlineObject","isPortableTextSpan","mark","has","get","decorators","decorator","parsedBlock","length","find","defaultStyle","undefined","lists","list","listItem","level","blockOffsetsToSelection","offsets","backward","anchor","blockOffsetToSpanSelectionPoint","blockOffset","focus"],"mappings":"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"}
@@ -90,6 +90,15 @@ function getBlockStartPoint({
90
90
  offset: 0
91
91
  };
92
92
  }
93
+ function getTextBlockText(block) {
94
+ return block.children.map((child) => child.text ?? "").join("");
95
+ }
96
+ function isEmptyTextBlock(block) {
97
+ if (!isPortableTextTextBlock(block))
98
+ return !1;
99
+ const onlyText = block.children.every(isPortableTextSpan), blockText = getTextBlockText(block);
100
+ return onlyText && blockText === "";
101
+ }
93
102
  function isEqualSelectionPoints(a, b) {
94
103
  return a.offset === b.offset && JSON.stringify(a.path) === JSON.stringify(b.path);
95
104
  }
@@ -111,6 +120,8 @@ export {
111
120
  blockOffsetToSpanSelectionPoint,
112
121
  getBlockEndPoint,
113
122
  getBlockStartPoint,
123
+ getTextBlockText,
124
+ isEmptyTextBlock,
114
125
  isEqualSelectionPoints,
115
126
  isKeyedSegment,
116
127
  isSpan,
@@ -1 +1 @@
1
- {"version":3,"file":"util.reverse-selection.js","sources":["../../src/utils/util.is-keyed-segment.ts","../../src/utils/util.block-offset.ts","../../src/utils/util.get-block-end-point.ts","../../src/utils/util.get-block-start-point.ts","../../src/utils/util.is-equal-selection-points.ts","../../src/utils/util.is-span.ts","../../src/utils/util.reverse-selection.ts"],"sourcesContent":["import type {KeyedSegment, PathSegment} from '@sanity/types'\n\n/**\n * @public\n */\nexport function isKeyedSegment(segment: PathSegment): segment is KeyedSegment {\n return typeof segment === 'object' && segment !== null && '_key' in segment\n}\n","import {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextBlock,\n} from '@sanity/types'\nimport type {BlockOffset} from '../behaviors/behavior.types'\nimport type {EditorSelectionPoint} from '../types/editor'\nimport {isKeyedSegment} from './util.is-keyed-segment'\n\n/**\n * @public\n */\nexport function blockOffsetToSpanSelectionPoint({\n value,\n blockOffset,\n}: {\n value: Array<PortableTextBlock>\n blockOffset: BlockOffset\n}) {\n let offsetLeft = blockOffset.offset\n let selectionPoint:\n | {path: [KeyedSegment, 'children', KeyedSegment]; offset: number}\n | undefined\n\n for (const block of value) {\n if (block._key !== blockOffset.path[0]._key) {\n continue\n }\n\n if (!isPortableTextTextBlock(block)) {\n continue\n }\n\n for (const child of block.children) {\n if (!isPortableTextSpan(child)) {\n continue\n }\n\n if (offsetLeft === 0) {\n selectionPoint = {\n path: [...blockOffset.path, 'children', {_key: child._key}],\n offset: 0,\n }\n break\n }\n\n if (offsetLeft <= child.text.length) {\n selectionPoint = {\n path: [...blockOffset.path, 'children', {_key: child._key}],\n offset: offsetLeft,\n }\n break\n }\n\n offsetLeft -= child.text.length\n }\n }\n\n return selectionPoint\n}\n\n/**\n * @public\n */\nexport function spanSelectionPointToBlockOffset({\n value,\n selectionPoint,\n}: {\n value: Array<PortableTextBlock>\n selectionPoint: EditorSelectionPoint\n}): BlockOffset | undefined {\n let offset = 0\n\n const blockKey = isKeyedSegment(selectionPoint.path[0])\n ? selectionPoint.path[0]._key\n : undefined\n const spanKey = isKeyedSegment(selectionPoint.path[2])\n ? selectionPoint.path[2]._key\n : undefined\n\n if (!blockKey || !spanKey) {\n return undefined\n }\n\n for (const block of value) {\n if (block._key !== blockKey) {\n continue\n }\n\n if (!isPortableTextTextBlock(block)) {\n continue\n }\n\n for (const child of block.children) {\n if (!isPortableTextSpan(child)) {\n continue\n }\n\n if (child._key === spanKey) {\n return {\n path: [{_key: block._key}],\n offset: offset + selectionPoint.offset,\n }\n }\n\n offset += child.text.length\n }\n }\n}\n","import {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextBlock,\n} from '@sanity/types'\nimport type {EditorSelectionPoint} from '../types/editor'\n\n/**\n * @public\n */\nexport function getBlockEndPoint({\n node,\n path,\n}: {\n node: PortableTextBlock\n path: [KeyedSegment]\n}): EditorSelectionPoint {\n if (isPortableTextTextBlock(node)) {\n const lastChild = node.children[node.children.length - 1]\n\n if (lastChild) {\n return {\n path: [...path, 'children', {_key: lastChild._key}],\n offset: isPortableTextSpan(lastChild) ? lastChild.text.length : 0,\n }\n }\n }\n\n return {\n path,\n offset: 0,\n }\n}\n","import {\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextBlock,\n} from '@sanity/types'\nimport type {EditorSelectionPoint} from '../types/editor'\n\n/**\n * @public\n */\nexport function getBlockStartPoint({\n node,\n path,\n}: {\n node: PortableTextBlock\n path: [KeyedSegment]\n}): EditorSelectionPoint {\n if (isPortableTextTextBlock(node)) {\n return {\n path: [...path, 'children', {_key: node.children[0]._key}],\n offset: 0,\n }\n }\n\n return {\n path,\n offset: 0,\n }\n}\n","import type {EditorSelectionPoint} from '../types/editor'\n\n/**\n * @public\n */\nexport function isEqualSelectionPoints(\n a: EditorSelectionPoint,\n b: EditorSelectionPoint,\n) {\n return (\n a.offset === b.offset && JSON.stringify(a.path) === JSON.stringify(b.path)\n )\n}\n","import type {PortableTextChild, PortableTextSpan} from '@sanity/types'\nimport type {EditorContext} from '../selectors'\n\n/**\n * @public\n */\nexport function isSpan(\n context: Pick<EditorContext, 'schema'>,\n child: PortableTextChild,\n): child is PortableTextSpan {\n return child._type === context.schema.span.name\n}\n","import type {EditorSelection} from '../types/editor'\n\n/**\n * @public\n */\nexport function reverseSelection(\n selection: NonNullable<EditorSelection>,\n): NonNullable<EditorSelection> {\n if (selection.backward) {\n return {\n anchor: selection.focus,\n focus: selection.anchor,\n backward: false,\n }\n }\n\n return {\n anchor: selection.focus,\n focus: selection.anchor,\n backward: true,\n }\n}\n"],"names":["isKeyedSegment","segment","blockOffsetToSpanSelectionPoint","value","blockOffset","offsetLeft","offset","selectionPoint","block","_key","path","isPortableTextTextBlock","child","children","isPortableTextSpan","text","length","spanSelectionPointToBlockOffset","blockKey","undefined","spanKey","getBlockEndPoint","node","lastChild","getBlockStartPoint","isEqualSelectionPoints","a","b","JSON","stringify","isSpan","context","_type","schema","span","name","reverseSelection","selection","backward","anchor","focus"],"mappings":"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"}
1
+ {"version":3,"file":"util.reverse-selection.js","sources":["../../src/utils/util.is-keyed-segment.ts","../../src/utils/util.block-offset.ts","../../src/utils/util.get-block-end-point.ts","../../src/utils/util.get-block-start-point.ts","../../src/utils/util.get-text-block-text.ts","../../src/utils/util.is-empty-text-block.ts","../../src/utils/util.is-equal-selection-points.ts","../../src/utils/util.is-span.ts","../../src/utils/util.reverse-selection.ts"],"sourcesContent":["import type {KeyedSegment, PathSegment} from '@sanity/types'\n\n/**\n * @public\n */\nexport function isKeyedSegment(segment: PathSegment): segment is KeyedSegment {\n return typeof segment === 'object' && segment !== null && '_key' in segment\n}\n","import {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextBlock,\n} from '@sanity/types'\nimport type {BlockOffset} from '../behaviors/behavior.types'\nimport type {EditorSelectionPoint} from '../types/editor'\nimport {isKeyedSegment} from './util.is-keyed-segment'\n\n/**\n * @public\n */\nexport function blockOffsetToSpanSelectionPoint({\n value,\n blockOffset,\n}: {\n value: Array<PortableTextBlock>\n blockOffset: BlockOffset\n}) {\n let offsetLeft = blockOffset.offset\n let selectionPoint:\n | {path: [KeyedSegment, 'children', KeyedSegment]; offset: number}\n | undefined\n\n for (const block of value) {\n if (block._key !== blockOffset.path[0]._key) {\n continue\n }\n\n if (!isPortableTextTextBlock(block)) {\n continue\n }\n\n for (const child of block.children) {\n if (!isPortableTextSpan(child)) {\n continue\n }\n\n if (offsetLeft === 0) {\n selectionPoint = {\n path: [...blockOffset.path, 'children', {_key: child._key}],\n offset: 0,\n }\n break\n }\n\n if (offsetLeft <= child.text.length) {\n selectionPoint = {\n path: [...blockOffset.path, 'children', {_key: child._key}],\n offset: offsetLeft,\n }\n break\n }\n\n offsetLeft -= child.text.length\n }\n }\n\n return selectionPoint\n}\n\n/**\n * @public\n */\nexport function spanSelectionPointToBlockOffset({\n value,\n selectionPoint,\n}: {\n value: Array<PortableTextBlock>\n selectionPoint: EditorSelectionPoint\n}): BlockOffset | undefined {\n let offset = 0\n\n const blockKey = isKeyedSegment(selectionPoint.path[0])\n ? selectionPoint.path[0]._key\n : undefined\n const spanKey = isKeyedSegment(selectionPoint.path[2])\n ? selectionPoint.path[2]._key\n : undefined\n\n if (!blockKey || !spanKey) {\n return undefined\n }\n\n for (const block of value) {\n if (block._key !== blockKey) {\n continue\n }\n\n if (!isPortableTextTextBlock(block)) {\n continue\n }\n\n for (const child of block.children) {\n if (!isPortableTextSpan(child)) {\n continue\n }\n\n if (child._key === spanKey) {\n return {\n path: [{_key: block._key}],\n offset: offset + selectionPoint.offset,\n }\n }\n\n offset += child.text.length\n }\n }\n}\n","import {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextBlock,\n} from '@sanity/types'\nimport type {EditorSelectionPoint} from '../types/editor'\n\n/**\n * @public\n */\nexport function getBlockEndPoint({\n node,\n path,\n}: {\n node: PortableTextBlock\n path: [KeyedSegment]\n}): EditorSelectionPoint {\n if (isPortableTextTextBlock(node)) {\n const lastChild = node.children[node.children.length - 1]\n\n if (lastChild) {\n return {\n path: [...path, 'children', {_key: lastChild._key}],\n offset: isPortableTextSpan(lastChild) ? lastChild.text.length : 0,\n }\n }\n }\n\n return {\n path,\n offset: 0,\n }\n}\n","import {\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextBlock,\n} from '@sanity/types'\nimport type {EditorSelectionPoint} from '../types/editor'\n\n/**\n * @public\n */\nexport function getBlockStartPoint({\n node,\n path,\n}: {\n node: PortableTextBlock\n path: [KeyedSegment]\n}): EditorSelectionPoint {\n if (isPortableTextTextBlock(node)) {\n return {\n path: [...path, 'children', {_key: node.children[0]._key}],\n offset: 0,\n }\n }\n\n return {\n path,\n offset: 0,\n }\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\n\n/**\n * @public\n */\nexport function getTextBlockText(block: PortableTextTextBlock) {\n return block.children.map((child) => child.text ?? '').join('')\n}\n","import {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type PortableTextBlock,\n} from '@sanity/types'\nimport {getTextBlockText} from './util.get-text-block-text'\n\n/**\n * @public\n */\nexport function isEmptyTextBlock(block: PortableTextBlock) {\n if (!isPortableTextTextBlock(block)) {\n return false\n }\n\n const onlyText = block.children.every(isPortableTextSpan)\n const blockText = getTextBlockText(block)\n\n return onlyText && blockText === ''\n}\n","import type {EditorSelectionPoint} from '../types/editor'\n\n/**\n * @public\n */\nexport function isEqualSelectionPoints(\n a: EditorSelectionPoint,\n b: EditorSelectionPoint,\n) {\n return (\n a.offset === b.offset && JSON.stringify(a.path) === JSON.stringify(b.path)\n )\n}\n","import type {PortableTextChild, PortableTextSpan} from '@sanity/types'\nimport type {EditorContext} from '../selectors'\n\n/**\n * @public\n */\nexport function isSpan(\n context: Pick<EditorContext, 'schema'>,\n child: PortableTextChild,\n): child is PortableTextSpan {\n return child._type === context.schema.span.name\n}\n","import type {EditorSelection} from '../types/editor'\n\n/**\n * @public\n */\nexport function reverseSelection(\n selection: NonNullable<EditorSelection>,\n): NonNullable<EditorSelection> {\n if (selection.backward) {\n return {\n anchor: selection.focus,\n focus: selection.anchor,\n backward: false,\n }\n }\n\n return {\n anchor: selection.focus,\n focus: selection.anchor,\n backward: true,\n }\n}\n"],"names":["isKeyedSegment","segment","blockOffsetToSpanSelectionPoint","value","blockOffset","offsetLeft","offset","selectionPoint","block","_key","path","isPortableTextTextBlock","child","children","isPortableTextSpan","text","length","spanSelectionPointToBlockOffset","blockKey","undefined","spanKey","getBlockEndPoint","node","lastChild","getBlockStartPoint","getTextBlockText","map","join","isEmptyTextBlock","onlyText","every","blockText","isEqualSelectionPoints","a","b","JSON","stringify","isSpan","context","_type","schema","span","name","reverseSelection","selection","backward","anchor","focus"],"mappings":"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"}
@@ -1042,6 +1042,7 @@ export declare type SyntheticBehaviorEvent =
1042
1042
  | {
1043
1043
  type: 'decorator.add'
1044
1044
  decorator: string
1045
+ selection?: NonNullable<EditorSelection>
1045
1046
  }
1046
1047
  | {
1047
1048
  type: 'decorator.remove'
@@ -1042,6 +1042,7 @@ export declare type SyntheticBehaviorEvent =
1042
1042
  | {
1043
1043
  type: 'decorator.add'
1044
1044
  decorator: string
1045
+ selection?: NonNullable<EditorSelection>
1045
1046
  }
1046
1047
  | {
1047
1048
  type: 'decorator.remove'