@portabletext/editor 1.30.6 → 1.31.1

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 (65) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +35 -2
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/behavior.markdown.cjs +4 -4
  4. package/lib/_chunks-cjs/plugin.event-listener.cjs +139 -177
  5. package/lib/_chunks-cjs/plugin.event-listener.cjs.map +1 -1
  6. package/lib/_chunks-cjs/selector.get-text-before.cjs +5 -41
  7. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  8. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs +174 -6
  9. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs.map +1 -1
  10. package/lib/_chunks-cjs/util.is-empty-text-block.cjs +1 -58
  11. package/lib/_chunks-cjs/util.is-empty-text-block.cjs.map +1 -1
  12. package/lib/_chunks-cjs/util.reverse-selection.cjs +105 -0
  13. package/lib/_chunks-cjs/util.reverse-selection.cjs.map +1 -1
  14. package/lib/_chunks-es/behavior.core.js +36 -3
  15. package/lib/_chunks-es/behavior.core.js.map +1 -1
  16. package/lib/_chunks-es/behavior.markdown.js +2 -1
  17. package/lib/_chunks-es/behavior.markdown.js.map +1 -1
  18. package/lib/_chunks-es/plugin.event-listener.js +139 -177
  19. package/lib/_chunks-es/plugin.event-listener.js.map +1 -1
  20. package/lib/_chunks-es/selector.get-text-before.js +4 -41
  21. package/lib/_chunks-es/selector.get-text-before.js.map +1 -1
  22. package/lib/_chunks-es/selector.is-at-the-start-of-block.js +170 -2
  23. package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -1
  24. package/lib/_chunks-es/util.is-empty-text-block.js +1 -59
  25. package/lib/_chunks-es/util.is-empty-text-block.js.map +1 -1
  26. package/lib/_chunks-es/util.reverse-selection.js +106 -1
  27. package/lib/_chunks-es/util.reverse-selection.js.map +1 -1
  28. package/lib/index.d.cts +0 -4
  29. package/lib/index.d.ts +0 -4
  30. package/lib/plugins/index.cjs +8 -8
  31. package/lib/plugins/index.cjs.map +1 -1
  32. package/lib/plugins/index.d.cts +0 -4
  33. package/lib/plugins/index.d.ts +0 -4
  34. package/lib/plugins/index.js +2 -3
  35. package/lib/plugins/index.js.map +1 -1
  36. package/lib/selectors/index.cjs +33 -6
  37. package/lib/selectors/index.cjs.map +1 -1
  38. package/lib/selectors/index.d.cts +209 -0
  39. package/lib/selectors/index.d.ts +209 -0
  40. package/lib/selectors/index.js +31 -5
  41. package/lib/selectors/index.js.map +1 -1
  42. package/lib/utils/index.cjs +10 -13
  43. package/lib/utils/index.cjs.map +1 -1
  44. package/lib/utils/index.js +3 -6
  45. package/lib/utils/index.js.map +1 -1
  46. package/package.json +2 -2
  47. package/src/behaviors/behavior.core.annotations.ts +32 -0
  48. package/src/behaviors/behavior.core.ts +1 -0
  49. package/src/editor/plugins/createWithEditableAPI.ts +85 -94
  50. package/src/editor/plugins/createWithUtils.ts +1 -52
  51. package/src/selectors/index.ts +4 -0
  52. package/src/selectors/selector.get-block-offsets.ts +33 -0
  53. package/src/selectors/selector.get-caret-word-selection.test.ts +288 -0
  54. package/src/selectors/selector.get-caret-word-selection.ts +116 -0
  55. package/src/selectors/selector.get-next-inline-object.ts +56 -0
  56. package/src/selectors/selector.get-previous-inline-object.ts +53 -0
  57. package/src/types/editor.ts +0 -5
  58. package/lib/_chunks-cjs/selector.get-selection-start-point.cjs +0 -15
  59. package/lib/_chunks-cjs/selector.get-selection-start-point.cjs.map +0 -1
  60. package/lib/_chunks-cjs/util.is-equal-selection-points.cjs +0 -46
  61. package/lib/_chunks-cjs/util.is-equal-selection-points.cjs.map +0 -1
  62. package/lib/_chunks-es/selector.get-selection-start-point.js +0 -16
  63. package/lib/_chunks-es/selector.get-selection-start-point.js.map +0 -1
  64. package/lib/_chunks-es/util.is-equal-selection-points.js +0 -47
  65. package/lib/_chunks-es/util.is-equal-selection-points.js.map +0 -1
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: !0 });
3
- var util_isEmptyTextBlock = require("../_chunks-cjs/util.is-empty-text-block.cjs"), util_isEqualSelectionPoints = require("../_chunks-cjs/util.is-equal-selection-points.cjs"), parseBlocks = require("../_chunks-cjs/parse-blocks.cjs"), util_reverseSelection = require("../_chunks-cjs/util.reverse-selection.cjs"), util_sliceBlocks = require("../_chunks-cjs/util.slice-blocks.cjs");
4
- function isSpan(context, child) {
5
- return child._type === context.schema.span.name;
6
- }
3
+ var util_reverseSelection = require("../_chunks-cjs/util.reverse-selection.cjs"), util_isEmptyTextBlock = require("../_chunks-cjs/util.is-empty-text-block.cjs"), parseBlocks = require("../_chunks-cjs/parse-blocks.cjs"), util_sliceBlocks = require("../_chunks-cjs/util.slice-blocks.cjs");
7
4
  function isTextBlock(context, block) {
8
5
  return block._type === context.schema.block.name;
9
6
  }
@@ -56,7 +53,7 @@ function splitTextBlock({
56
53
  }, "children", {
57
54
  _key: lastChild._key
58
55
  }],
59
- offset: isSpan(context, lastChild) ? lastChild.text.length : 0
56
+ offset: util_reverseSelection.isSpan(context, lastChild) ? lastChild.text.length : 0
60
57
  }
61
58
  }
62
59
  }).at(0);
@@ -66,17 +63,17 @@ function splitTextBlock({
66
63
  after
67
64
  };
68
65
  }
69
- exports.blockOffsetToSpanSelectionPoint = util_isEmptyTextBlock.blockOffsetToSpanSelectionPoint;
66
+ exports.blockOffsetToSpanSelectionPoint = util_reverseSelection.blockOffsetToSpanSelectionPoint;
67
+ exports.getBlockEndPoint = util_reverseSelection.getBlockEndPoint;
68
+ exports.getBlockStartPoint = util_reverseSelection.getBlockStartPoint;
69
+ exports.isEqualSelectionPoints = util_reverseSelection.isEqualSelectionPoints;
70
+ exports.isKeyedSegment = util_reverseSelection.isKeyedSegment;
71
+ exports.isSpan = util_reverseSelection.isSpan;
72
+ exports.reverseSelection = util_reverseSelection.reverseSelection;
73
+ exports.spanSelectionPointToBlockOffset = util_reverseSelection.spanSelectionPointToBlockOffset;
70
74
  exports.getTextBlockText = util_isEmptyTextBlock.getTextBlockText;
71
75
  exports.isEmptyTextBlock = util_isEmptyTextBlock.isEmptyTextBlock;
72
- exports.spanSelectionPointToBlockOffset = util_isEmptyTextBlock.spanSelectionPointToBlockOffset;
73
- exports.getBlockEndPoint = util_isEqualSelectionPoints.getBlockEndPoint;
74
- exports.getBlockStartPoint = util_isEqualSelectionPoints.getBlockStartPoint;
75
- exports.isEqualSelectionPoints = util_isEqualSelectionPoints.isEqualSelectionPoints;
76
- exports.isKeyedSegment = util_isEqualSelectionPoints.isKeyedSegment;
77
- exports.reverseSelection = util_reverseSelection.reverseSelection;
78
76
  exports.sliceBlocks = util_sliceBlocks.sliceBlocks;
79
- exports.isSpan = isSpan;
80
77
  exports.isTextBlock = isTextBlock;
81
78
  exports.mergeTextBlocks = mergeTextBlocks;
82
79
  exports.splitTextBlock = splitTextBlock;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/utils/util.is-span.ts","../../src/utils/util.is-text-block.ts","../../src/utils/util.merge-text-blocks.ts","../../src/utils/util.split-text-block.ts"],"sourcesContent":["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 {PortableTextBlock, PortableTextTextBlock} from '@sanity/types'\nimport type {EditorContext} from '../selectors'\n\n/**\n * @public\n */\nexport function isTextBlock(\n context: Pick<EditorContext, 'schema'>,\n block: PortableTextBlock,\n): block is PortableTextTextBlock {\n return block._type === context.schema.block.name\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport {parseBlock} from '../internal-utils/parse-blocks'\nimport type {EditorContext} from '../selectors'\nimport {isTextBlock} from './util.is-text-block'\n\n/**\n * @beta\n */\nexport function mergeTextBlocks({\n context,\n targetBlock,\n incomingBlock,\n}: {\n context: Pick<EditorContext, 'keyGenerator' | 'schema'>\n targetBlock: PortableTextTextBlock\n incomingBlock: PortableTextTextBlock\n}) {\n const parsedIncomingBlock = parseBlock({\n context,\n block: incomingBlock,\n options: {refreshKeys: true},\n })\n\n if (!parsedIncomingBlock || !isTextBlock(context, parsedIncomingBlock)) {\n return targetBlock\n }\n\n return {\n ...targetBlock,\n children: [...targetBlock.children, ...parsedIncomingBlock.children],\n markDefs: [\n ...(targetBlock.markDefs ?? []),\n ...(parsedIncomingBlock.markDefs ?? []),\n ],\n }\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport {isTextBlock, sliceBlocks, type EditorSelectionPoint} from '.'\nimport type {EditorContext} from '../selectors'\nimport {isSpan} from './util.is-span'\n\n/**\n * @beta\n */\nexport function splitTextBlock({\n context,\n block,\n point,\n}: {\n context: Pick<EditorContext, 'schema'>\n block: PortableTextTextBlock\n point: EditorSelectionPoint\n}): {before: PortableTextTextBlock; after: PortableTextTextBlock} | undefined {\n const firstChild = block.children.at(0)\n const lastChild = block.children.at(block.children.length - 1)\n\n if (!firstChild || !lastChild) {\n return undefined\n }\n\n const before = sliceBlocks({\n blocks: [block],\n selection: {\n anchor: {\n path: [{_key: block._key}, 'children', {_key: firstChild._key}],\n offset: 0,\n },\n focus: point,\n },\n }).at(0)\n const after = sliceBlocks({\n blocks: [block],\n selection: {\n anchor: point,\n focus: {\n path: [{_key: block._key}, 'children', {_key: lastChild._key}],\n offset: isSpan(context, lastChild) ? lastChild.text.length : 0,\n },\n },\n }).at(0)\n\n if (!before || !after) {\n return undefined\n }\n\n if (!isTextBlock(context, before) || !isTextBlock(context, after)) {\n return undefined\n }\n\n return {before, after}\n}\n"],"names":["isSpan","context","child","_type","schema","span","name","isTextBlock","block","mergeTextBlocks","targetBlock","incomingBlock","parsedIncomingBlock","parseBlock","options","refreshKeys","children","markDefs","splitTextBlock","point","firstChild","at","lastChild","length","before","sliceBlocks","blocks","selection","anchor","path","_key","offset","focus","after","text"],"mappings":";;;AAMgBA,SAAAA,OACdC,SACAC,OAC2B;AAC3B,SAAOA,MAAMC,UAAUF,QAAQG,OAAOC,KAAKC;AAC7C;ACLgBC,SAAAA,YACdN,SACAO,OACgC;AAChC,SAAOA,MAAML,UAAUF,QAAQG,OAAOI,MAAMF;AAC9C;ACHO,SAASG,gBAAgB;AAAA,EAC9BR;AAAAA,EACAS;AAAAA,EACAC;AAKF,GAAG;AACD,QAAMC,sBAAsBC,YAAAA,WAAW;AAAA,IACrCZ;AAAAA,IACAO,OAAOG;AAAAA,IACPG,SAAS;AAAA,MAACC,aAAa;AAAA,IAAA;AAAA,EAAI,CAC5B;AAED,SAAI,CAACH,uBAAuB,CAACL,YAAYN,SAASW,mBAAmB,IAC5DF,cAGF;AAAA,IACL,GAAGA;AAAAA,IACHM,UAAU,CAAC,GAAGN,YAAYM,UAAU,GAAGJ,oBAAoBI,QAAQ;AAAA,IACnEC,UAAU,CACR,GAAIP,YAAYO,YAAY,CAAA,GAC5B,GAAIL,oBAAoBK,YAAY,CAAG,CAAA;AAAA,EAE3C;AACF;AC3BO,SAASC,eAAe;AAAA,EAC7BjB;AAAAA,EACAO;AAAAA,EACAW;AAKF,GAA8E;AAC5E,QAAMC,aAAaZ,MAAMQ,SAASK,GAAG,CAAC,GAChCC,YAAYd,MAAMQ,SAASK,GAAGb,MAAMQ,SAASO,SAAS,CAAC;AAEzD,MAAA,CAACH,cAAc,CAACE;AAClB;AAGF,QAAME,SAASC,iBAAAA,YAAY;AAAA,IACzBC,QAAQ,CAAClB,KAAK;AAAA,IACdmB,WAAW;AAAA,MACTC,QAAQ;AAAA,QACNC,MAAM,CAAC;AAAA,UAACC,MAAMtB,MAAMsB;AAAAA,WAAO,YAAY;AAAA,UAACA,MAAMV,WAAWU;AAAAA,QAAAA,CAAK;AAAA,QAC9DC,QAAQ;AAAA,MACV;AAAA,MACAC,OAAOb;AAAAA,IAAAA;AAAAA,EAEV,CAAA,EAAEE,GAAG,CAAC,GACDY,QAAQR,iBAAAA,YAAY;AAAA,IACxBC,QAAQ,CAAClB,KAAK;AAAA,IACdmB,WAAW;AAAA,MACTC,QAAQT;AAAAA,MACRa,OAAO;AAAA,QACLH,MAAM,CAAC;AAAA,UAACC,MAAMtB,MAAMsB;AAAAA,WAAO,YAAY;AAAA,UAACA,MAAMR,UAAUQ;AAAAA,QAAAA,CAAK;AAAA,QAC7DC,QAAQ/B,OAAOC,SAASqB,SAAS,IAAIA,UAAUY,KAAKX,SAAS;AAAA,MAAA;AAAA,IAC/D;AAAA,EACF,CACD,EAAEF,GAAG,CAAC;AAEP,MAAI,EAACG,CAAAA,UAAU,CAACS,UAIZ,EAAC1B,CAAAA,YAAYN,SAASuB,MAAM,KAAK,CAACjB,YAAYN,SAASgC,KAAK;AAIzD,WAAA;AAAA,MAACT;AAAAA,MAAQS;AAAAA,IAAK;AACvB;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/utils/util.is-text-block.ts","../../src/utils/util.merge-text-blocks.ts","../../src/utils/util.split-text-block.ts"],"sourcesContent":["import type {PortableTextBlock, PortableTextTextBlock} from '@sanity/types'\nimport type {EditorContext} from '../selectors'\n\n/**\n * @public\n */\nexport function isTextBlock(\n context: Pick<EditorContext, 'schema'>,\n block: PortableTextBlock,\n): block is PortableTextTextBlock {\n return block._type === context.schema.block.name\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport {parseBlock} from '../internal-utils/parse-blocks'\nimport type {EditorContext} from '../selectors'\nimport {isTextBlock} from './util.is-text-block'\n\n/**\n * @beta\n */\nexport function mergeTextBlocks({\n context,\n targetBlock,\n incomingBlock,\n}: {\n context: Pick<EditorContext, 'keyGenerator' | 'schema'>\n targetBlock: PortableTextTextBlock\n incomingBlock: PortableTextTextBlock\n}) {\n const parsedIncomingBlock = parseBlock({\n context,\n block: incomingBlock,\n options: {refreshKeys: true},\n })\n\n if (!parsedIncomingBlock || !isTextBlock(context, parsedIncomingBlock)) {\n return targetBlock\n }\n\n return {\n ...targetBlock,\n children: [...targetBlock.children, ...parsedIncomingBlock.children],\n markDefs: [\n ...(targetBlock.markDefs ?? []),\n ...(parsedIncomingBlock.markDefs ?? []),\n ],\n }\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport {isTextBlock, sliceBlocks, type EditorSelectionPoint} from '.'\nimport type {EditorContext} from '../selectors'\nimport {isSpan} from './util.is-span'\n\n/**\n * @beta\n */\nexport function splitTextBlock({\n context,\n block,\n point,\n}: {\n context: Pick<EditorContext, 'schema'>\n block: PortableTextTextBlock\n point: EditorSelectionPoint\n}): {before: PortableTextTextBlock; after: PortableTextTextBlock} | undefined {\n const firstChild = block.children.at(0)\n const lastChild = block.children.at(block.children.length - 1)\n\n if (!firstChild || !lastChild) {\n return undefined\n }\n\n const before = sliceBlocks({\n blocks: [block],\n selection: {\n anchor: {\n path: [{_key: block._key}, 'children', {_key: firstChild._key}],\n offset: 0,\n },\n focus: point,\n },\n }).at(0)\n const after = sliceBlocks({\n blocks: [block],\n selection: {\n anchor: point,\n focus: {\n path: [{_key: block._key}, 'children', {_key: lastChild._key}],\n offset: isSpan(context, lastChild) ? lastChild.text.length : 0,\n },\n },\n }).at(0)\n\n if (!before || !after) {\n return undefined\n }\n\n if (!isTextBlock(context, before) || !isTextBlock(context, after)) {\n return undefined\n }\n\n return {before, after}\n}\n"],"names":["isTextBlock","context","block","_type","schema","name","mergeTextBlocks","targetBlock","incomingBlock","parsedIncomingBlock","parseBlock","options","refreshKeys","children","markDefs","splitTextBlock","point","firstChild","at","lastChild","length","before","sliceBlocks","blocks","selection","anchor","path","_key","offset","focus","after","isSpan","text"],"mappings":";;;AAMgBA,SAAAA,YACdC,SACAC,OACgC;AAChC,SAAOA,MAAMC,UAAUF,QAAQG,OAAOF,MAAMG;AAC9C;ACHO,SAASC,gBAAgB;AAAA,EAC9BL;AAAAA,EACAM;AAAAA,EACAC;AAKF,GAAG;AACD,QAAMC,sBAAsBC,YAAAA,WAAW;AAAA,IACrCT;AAAAA,IACAC,OAAOM;AAAAA,IACPG,SAAS;AAAA,MAACC,aAAa;AAAA,IAAA;AAAA,EAAI,CAC5B;AAED,SAAI,CAACH,uBAAuB,CAACT,YAAYC,SAASQ,mBAAmB,IAC5DF,cAGF;AAAA,IACL,GAAGA;AAAAA,IACHM,UAAU,CAAC,GAAGN,YAAYM,UAAU,GAAGJ,oBAAoBI,QAAQ;AAAA,IACnEC,UAAU,CACR,GAAIP,YAAYO,YAAY,CAAA,GAC5B,GAAIL,oBAAoBK,YAAY,CAAG,CAAA;AAAA,EAE3C;AACF;AC3BO,SAASC,eAAe;AAAA,EAC7Bd;AAAAA,EACAC;AAAAA,EACAc;AAKF,GAA8E;AAC5E,QAAMC,aAAaf,MAAMW,SAASK,GAAG,CAAC,GAChCC,YAAYjB,MAAMW,SAASK,GAAGhB,MAAMW,SAASO,SAAS,CAAC;AAEzD,MAAA,CAACH,cAAc,CAACE;AAClB;AAGF,QAAME,SAASC,iBAAAA,YAAY;AAAA,IACzBC,QAAQ,CAACrB,KAAK;AAAA,IACdsB,WAAW;AAAA,MACTC,QAAQ;AAAA,QACNC,MAAM,CAAC;AAAA,UAACC,MAAMzB,MAAMyB;AAAAA,WAAO,YAAY;AAAA,UAACA,MAAMV,WAAWU;AAAAA,QAAAA,CAAK;AAAA,QAC9DC,QAAQ;AAAA,MACV;AAAA,MACAC,OAAOb;AAAAA,IAAAA;AAAAA,EAEV,CAAA,EAAEE,GAAG,CAAC,GACDY,QAAQR,iBAAAA,YAAY;AAAA,IACxBC,QAAQ,CAACrB,KAAK;AAAA,IACdsB,WAAW;AAAA,MACTC,QAAQT;AAAAA,MACRa,OAAO;AAAA,QACLH,MAAM,CAAC;AAAA,UAACC,MAAMzB,MAAMyB;AAAAA,WAAO,YAAY;AAAA,UAACA,MAAMR,UAAUQ;AAAAA,QAAAA,CAAK;AAAA,QAC7DC,QAAQG,sBAAO9B,OAAAA,SAASkB,SAAS,IAAIA,UAAUa,KAAKZ,SAAS;AAAA,MAAA;AAAA,IAC/D;AAAA,EACF,CACD,EAAEF,GAAG,CAAC;AAEP,MAAI,EAACG,CAAAA,UAAU,CAACS,UAIZ,EAAC9B,CAAAA,YAAYC,SAASoB,MAAM,KAAK,CAACrB,YAAYC,SAAS6B,KAAK;AAIzD,WAAA;AAAA,MAACT;AAAAA,MAAQS;AAAAA,IAAK;AACvB;;;;;;;;;;;;;;;"}
@@ -1,11 +1,8 @@
1
- import { blockOffsetToSpanSelectionPoint, getTextBlockText, isEmptyTextBlock, spanSelectionPointToBlockOffset } from "../_chunks-es/util.is-empty-text-block.js";
2
- import { getBlockEndPoint, getBlockStartPoint, isEqualSelectionPoints, isKeyedSegment } from "../_chunks-es/util.is-equal-selection-points.js";
1
+ import { isSpan } from "../_chunks-es/util.reverse-selection.js";
2
+ import { blockOffsetToSpanSelectionPoint, getBlockEndPoint, getBlockStartPoint, isEqualSelectionPoints, isKeyedSegment, reverseSelection, spanSelectionPointToBlockOffset } from "../_chunks-es/util.reverse-selection.js";
3
+ import { getTextBlockText, isEmptyTextBlock } from "../_chunks-es/util.is-empty-text-block.js";
3
4
  import { parseBlock } from "../_chunks-es/parse-blocks.js";
4
- import { reverseSelection } from "../_chunks-es/util.reverse-selection.js";
5
5
  import { sliceBlocks } from "../_chunks-es/util.slice-blocks.js";
6
- function isSpan(context, child) {
7
- return child._type === context.schema.span.name;
8
- }
9
6
  function isTextBlock(context, block) {
10
7
  return block._type === context.schema.block.name;
11
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/utils/util.is-span.ts","../../src/utils/util.is-text-block.ts","../../src/utils/util.merge-text-blocks.ts","../../src/utils/util.split-text-block.ts"],"sourcesContent":["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 {PortableTextBlock, PortableTextTextBlock} from '@sanity/types'\nimport type {EditorContext} from '../selectors'\n\n/**\n * @public\n */\nexport function isTextBlock(\n context: Pick<EditorContext, 'schema'>,\n block: PortableTextBlock,\n): block is PortableTextTextBlock {\n return block._type === context.schema.block.name\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport {parseBlock} from '../internal-utils/parse-blocks'\nimport type {EditorContext} from '../selectors'\nimport {isTextBlock} from './util.is-text-block'\n\n/**\n * @beta\n */\nexport function mergeTextBlocks({\n context,\n targetBlock,\n incomingBlock,\n}: {\n context: Pick<EditorContext, 'keyGenerator' | 'schema'>\n targetBlock: PortableTextTextBlock\n incomingBlock: PortableTextTextBlock\n}) {\n const parsedIncomingBlock = parseBlock({\n context,\n block: incomingBlock,\n options: {refreshKeys: true},\n })\n\n if (!parsedIncomingBlock || !isTextBlock(context, parsedIncomingBlock)) {\n return targetBlock\n }\n\n return {\n ...targetBlock,\n children: [...targetBlock.children, ...parsedIncomingBlock.children],\n markDefs: [\n ...(targetBlock.markDefs ?? []),\n ...(parsedIncomingBlock.markDefs ?? []),\n ],\n }\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport {isTextBlock, sliceBlocks, type EditorSelectionPoint} from '.'\nimport type {EditorContext} from '../selectors'\nimport {isSpan} from './util.is-span'\n\n/**\n * @beta\n */\nexport function splitTextBlock({\n context,\n block,\n point,\n}: {\n context: Pick<EditorContext, 'schema'>\n block: PortableTextTextBlock\n point: EditorSelectionPoint\n}): {before: PortableTextTextBlock; after: PortableTextTextBlock} | undefined {\n const firstChild = block.children.at(0)\n const lastChild = block.children.at(block.children.length - 1)\n\n if (!firstChild || !lastChild) {\n return undefined\n }\n\n const before = sliceBlocks({\n blocks: [block],\n selection: {\n anchor: {\n path: [{_key: block._key}, 'children', {_key: firstChild._key}],\n offset: 0,\n },\n focus: point,\n },\n }).at(0)\n const after = sliceBlocks({\n blocks: [block],\n selection: {\n anchor: point,\n focus: {\n path: [{_key: block._key}, 'children', {_key: lastChild._key}],\n offset: isSpan(context, lastChild) ? lastChild.text.length : 0,\n },\n },\n }).at(0)\n\n if (!before || !after) {\n return undefined\n }\n\n if (!isTextBlock(context, before) || !isTextBlock(context, after)) {\n return undefined\n }\n\n return {before, after}\n}\n"],"names":["isSpan","context","child","_type","schema","span","name","isTextBlock","block","mergeTextBlocks","targetBlock","incomingBlock","parsedIncomingBlock","parseBlock","options","refreshKeys","children","markDefs","splitTextBlock","point","firstChild","at","lastChild","length","before","sliceBlocks","blocks","selection","anchor","path","_key","offset","focus","after","text"],"mappings":";;;;;AAMgBA,SAAAA,OACdC,SACAC,OAC2B;AAC3B,SAAOA,MAAMC,UAAUF,QAAQG,OAAOC,KAAKC;AAC7C;ACLgBC,SAAAA,YACdN,SACAO,OACgC;AAChC,SAAOA,MAAML,UAAUF,QAAQG,OAAOI,MAAMF;AAC9C;ACHO,SAASG,gBAAgB;AAAA,EAC9BR;AAAAA,EACAS;AAAAA,EACAC;AAKF,GAAG;AACD,QAAMC,sBAAsBC,WAAW;AAAA,IACrCZ;AAAAA,IACAO,OAAOG;AAAAA,IACPG,SAAS;AAAA,MAACC,aAAa;AAAA,IAAA;AAAA,EAAI,CAC5B;AAED,SAAI,CAACH,uBAAuB,CAACL,YAAYN,SAASW,mBAAmB,IAC5DF,cAGF;AAAA,IACL,GAAGA;AAAAA,IACHM,UAAU,CAAC,GAAGN,YAAYM,UAAU,GAAGJ,oBAAoBI,QAAQ;AAAA,IACnEC,UAAU,CACR,GAAIP,YAAYO,YAAY,CAAA,GAC5B,GAAIL,oBAAoBK,YAAY,CAAG,CAAA;AAAA,EAE3C;AACF;AC3BO,SAASC,eAAe;AAAA,EAC7BjB;AAAAA,EACAO;AAAAA,EACAW;AAKF,GAA8E;AAC5E,QAAMC,aAAaZ,MAAMQ,SAASK,GAAG,CAAC,GAChCC,YAAYd,MAAMQ,SAASK,GAAGb,MAAMQ,SAASO,SAAS,CAAC;AAEzD,MAAA,CAACH,cAAc,CAACE;AAClB;AAGF,QAAME,SAASC,YAAY;AAAA,IACzBC,QAAQ,CAAClB,KAAK;AAAA,IACdmB,WAAW;AAAA,MACTC,QAAQ;AAAA,QACNC,MAAM,CAAC;AAAA,UAACC,MAAMtB,MAAMsB;AAAAA,WAAO,YAAY;AAAA,UAACA,MAAMV,WAAWU;AAAAA,QAAAA,CAAK;AAAA,QAC9DC,QAAQ;AAAA,MACV;AAAA,MACAC,OAAOb;AAAAA,IAAAA;AAAAA,EAEV,CAAA,EAAEE,GAAG,CAAC,GACDY,QAAQR,YAAY;AAAA,IACxBC,QAAQ,CAAClB,KAAK;AAAA,IACdmB,WAAW;AAAA,MACTC,QAAQT;AAAAA,MACRa,OAAO;AAAA,QACLH,MAAM,CAAC;AAAA,UAACC,MAAMtB,MAAMsB;AAAAA,WAAO,YAAY;AAAA,UAACA,MAAMR,UAAUQ;AAAAA,QAAAA,CAAK;AAAA,QAC7DC,QAAQ/B,OAAOC,SAASqB,SAAS,IAAIA,UAAUY,KAAKX,SAAS;AAAA,MAAA;AAAA,IAC/D;AAAA,EACF,CACD,EAAEF,GAAG,CAAC;AAEP,MAAI,EAACG,CAAAA,UAAU,CAACS,UAIZ,EAAC1B,CAAAA,YAAYN,SAASuB,MAAM,KAAK,CAACjB,YAAYN,SAASgC,KAAK;AAIzD,WAAA;AAAA,MAACT;AAAAA,MAAQS;AAAAA,IAAK;AACvB;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/utils/util.is-text-block.ts","../../src/utils/util.merge-text-blocks.ts","../../src/utils/util.split-text-block.ts"],"sourcesContent":["import type {PortableTextBlock, PortableTextTextBlock} from '@sanity/types'\nimport type {EditorContext} from '../selectors'\n\n/**\n * @public\n */\nexport function isTextBlock(\n context: Pick<EditorContext, 'schema'>,\n block: PortableTextBlock,\n): block is PortableTextTextBlock {\n return block._type === context.schema.block.name\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport {parseBlock} from '../internal-utils/parse-blocks'\nimport type {EditorContext} from '../selectors'\nimport {isTextBlock} from './util.is-text-block'\n\n/**\n * @beta\n */\nexport function mergeTextBlocks({\n context,\n targetBlock,\n incomingBlock,\n}: {\n context: Pick<EditorContext, 'keyGenerator' | 'schema'>\n targetBlock: PortableTextTextBlock\n incomingBlock: PortableTextTextBlock\n}) {\n const parsedIncomingBlock = parseBlock({\n context,\n block: incomingBlock,\n options: {refreshKeys: true},\n })\n\n if (!parsedIncomingBlock || !isTextBlock(context, parsedIncomingBlock)) {\n return targetBlock\n }\n\n return {\n ...targetBlock,\n children: [...targetBlock.children, ...parsedIncomingBlock.children],\n markDefs: [\n ...(targetBlock.markDefs ?? []),\n ...(parsedIncomingBlock.markDefs ?? []),\n ],\n }\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport {isTextBlock, sliceBlocks, type EditorSelectionPoint} from '.'\nimport type {EditorContext} from '../selectors'\nimport {isSpan} from './util.is-span'\n\n/**\n * @beta\n */\nexport function splitTextBlock({\n context,\n block,\n point,\n}: {\n context: Pick<EditorContext, 'schema'>\n block: PortableTextTextBlock\n point: EditorSelectionPoint\n}): {before: PortableTextTextBlock; after: PortableTextTextBlock} | undefined {\n const firstChild = block.children.at(0)\n const lastChild = block.children.at(block.children.length - 1)\n\n if (!firstChild || !lastChild) {\n return undefined\n }\n\n const before = sliceBlocks({\n blocks: [block],\n selection: {\n anchor: {\n path: [{_key: block._key}, 'children', {_key: firstChild._key}],\n offset: 0,\n },\n focus: point,\n },\n }).at(0)\n const after = sliceBlocks({\n blocks: [block],\n selection: {\n anchor: point,\n focus: {\n path: [{_key: block._key}, 'children', {_key: lastChild._key}],\n offset: isSpan(context, lastChild) ? lastChild.text.length : 0,\n },\n },\n }).at(0)\n\n if (!before || !after) {\n return undefined\n }\n\n if (!isTextBlock(context, before) || !isTextBlock(context, after)) {\n return undefined\n }\n\n return {before, after}\n}\n"],"names":["isTextBlock","context","block","_type","schema","name","mergeTextBlocks","targetBlock","incomingBlock","parsedIncomingBlock","parseBlock","options","refreshKeys","children","markDefs","splitTextBlock","point","firstChild","at","lastChild","length","before","sliceBlocks","blocks","selection","anchor","path","_key","offset","focus","after","isSpan","text"],"mappings":";;;;;AAMgBA,SAAAA,YACdC,SACAC,OACgC;AAChC,SAAOA,MAAMC,UAAUF,QAAQG,OAAOF,MAAMG;AAC9C;ACHO,SAASC,gBAAgB;AAAA,EAC9BL;AAAAA,EACAM;AAAAA,EACAC;AAKF,GAAG;AACD,QAAMC,sBAAsBC,WAAW;AAAA,IACrCT;AAAAA,IACAC,OAAOM;AAAAA,IACPG,SAAS;AAAA,MAACC,aAAa;AAAA,IAAA;AAAA,EAAI,CAC5B;AAED,SAAI,CAACH,uBAAuB,CAACT,YAAYC,SAASQ,mBAAmB,IAC5DF,cAGF;AAAA,IACL,GAAGA;AAAAA,IACHM,UAAU,CAAC,GAAGN,YAAYM,UAAU,GAAGJ,oBAAoBI,QAAQ;AAAA,IACnEC,UAAU,CACR,GAAIP,YAAYO,YAAY,CAAA,GAC5B,GAAIL,oBAAoBK,YAAY,CAAG,CAAA;AAAA,EAE3C;AACF;AC3BO,SAASC,eAAe;AAAA,EAC7Bd;AAAAA,EACAC;AAAAA,EACAc;AAKF,GAA8E;AAC5E,QAAMC,aAAaf,MAAMW,SAASK,GAAG,CAAC,GAChCC,YAAYjB,MAAMW,SAASK,GAAGhB,MAAMW,SAASO,SAAS,CAAC;AAEzD,MAAA,CAACH,cAAc,CAACE;AAClB;AAGF,QAAME,SAASC,YAAY;AAAA,IACzBC,QAAQ,CAACrB,KAAK;AAAA,IACdsB,WAAW;AAAA,MACTC,QAAQ;AAAA,QACNC,MAAM,CAAC;AAAA,UAACC,MAAMzB,MAAMyB;AAAAA,WAAO,YAAY;AAAA,UAACA,MAAMV,WAAWU;AAAAA,QAAAA,CAAK;AAAA,QAC9DC,QAAQ;AAAA,MACV;AAAA,MACAC,OAAOb;AAAAA,IAAAA;AAAAA,EAEV,CAAA,EAAEE,GAAG,CAAC,GACDY,QAAQR,YAAY;AAAA,IACxBC,QAAQ,CAACrB,KAAK;AAAA,IACdsB,WAAW;AAAA,MACTC,QAAQT;AAAAA,MACRa,OAAO;AAAA,QACLH,MAAM,CAAC;AAAA,UAACC,MAAMzB,MAAMyB;AAAAA,WAAO,YAAY;AAAA,UAACA,MAAMR,UAAUQ;AAAAA,QAAAA,CAAK;AAAA,QAC7DC,QAAQG,OAAO9B,SAASkB,SAAS,IAAIA,UAAUa,KAAKZ,SAAS;AAAA,MAAA;AAAA,IAC/D;AAAA,EACF,CACD,EAAEF,GAAG,CAAC;AAEP,MAAI,EAACG,CAAAA,UAAU,CAACS,UAIZ,EAAC9B,CAAAA,YAAYC,SAASoB,MAAM,KAAK,CAACrB,YAAYC,SAAS6B,KAAK;AAIzD,WAAA;AAAA,MAACT;AAAAA,MAAQS;AAAAA,IAAK;AACvB;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.30.6",
3
+ "version": "1.31.1",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -112,7 +112,7 @@
112
112
  "vite": "^6.0.11",
113
113
  "vitest": "^3.0.5",
114
114
  "vitest-browser-react": "^0.0.4",
115
- "racejar": "1.1.3"
115
+ "racejar": "1.2.0"
116
116
  },
117
117
  "peerDependencies": {
118
118
  "@sanity/schema": "^3.74.1",
@@ -23,7 +23,39 @@ const toggleAnnotationOn = defineBehavior({
23
23
  ],
24
24
  })
25
25
 
26
+ const addAnnotationOnCollapsedSelection = defineBehavior({
27
+ on: 'annotation.add',
28
+ guard: ({context}) => {
29
+ if (!selectors.isSelectionCollapsed({context})) {
30
+ return false
31
+ }
32
+
33
+ const caretWordSelection = selectors.getCaretWordSelection({context})
34
+
35
+ if (
36
+ !caretWordSelection ||
37
+ !selectors.isSelectionExpanded({
38
+ context: {
39
+ ...context,
40
+ selection: caretWordSelection,
41
+ },
42
+ })
43
+ ) {
44
+ return false
45
+ }
46
+
47
+ return {caretWordSelection}
48
+ },
49
+ actions: [
50
+ ({event}, {caretWordSelection}) => [
51
+ raise({type: 'select', selection: caretWordSelection}),
52
+ raise({type: 'annotation.add', annotation: event.annotation}),
53
+ ],
54
+ ],
55
+ })
56
+
26
57
  export const coreAnnotationBehaviors = {
27
58
  toggleAnnotationOff,
28
59
  toggleAnnotationOn,
60
+ addAnnotationOnCollapsedSelection,
29
61
  }
@@ -13,6 +13,7 @@ import {coreStyleBehaviors} from './behavior.core.style'
13
13
  export const coreBehaviors = [
14
14
  coreAnnotationBehaviors.toggleAnnotationOff,
15
15
  coreAnnotationBehaviors.toggleAnnotationOn,
16
+ coreAnnotationBehaviors.addAnnotationOnCollapsedSelection,
16
17
  coreDecoratorBehaviors.toggleDecoratorOff,
17
18
  coreDecoratorBehaviors.toggleDecoratorOn,
18
19
  coreDecoratorBehaviors.strongShortcut,
@@ -629,119 +629,110 @@ export const addAnnotationActionImplementation: BehaviorActionImplementation<
629
629
  AddedAnnotationPaths | undefined
630
630
  > = ({context, action}) => {
631
631
  const editor = action.editor
632
- const {selection: originalSelection} = editor
633
- let paths: AddedAnnotationPaths | undefined = undefined
634
-
635
- if (originalSelection) {
636
- if (Range.isCollapsed(originalSelection)) {
637
- editor.pteExpandToWord()
638
- editor.onChange()
639
- }
640
-
641
- // If we still have a selection, add the annotation to the selected text
642
- if (editor.selection) {
643
- let spanPath: Path | undefined
644
- let markDefPath: Path | undefined
645
- const markDefPaths: Path[] = []
646
632
 
647
- if (!editor.selection) {
648
- return
649
- }
633
+ if (!editor.selection || Range.isCollapsed(editor.selection)) {
634
+ return
635
+ }
650
636
 
651
- const selectedBlocks = Editor.nodes(editor, {
652
- at: editor.selection,
653
- match: (node) => editor.isTextBlock(node),
654
- reverse: Range.isBackward(editor.selection),
655
- })
637
+ let paths: AddedAnnotationPaths | undefined = undefined
638
+ let spanPath: Path | undefined
639
+ let markDefPath: Path | undefined
640
+ const markDefPaths: Path[] = []
641
+
642
+ const selectedBlocks = Editor.nodes(editor, {
643
+ at: editor.selection,
644
+ match: (node) => editor.isTextBlock(node),
645
+ reverse: Range.isBackward(editor.selection),
646
+ })
656
647
 
657
- for (const [block, blockPath] of selectedBlocks) {
658
- if (block.children.length === 0) {
659
- continue
660
- }
648
+ for (const [block, blockPath] of selectedBlocks) {
649
+ if (block.children.length === 0) {
650
+ continue
651
+ }
661
652
 
662
- if (block.children.length === 1 && block.children[0].text === '') {
663
- continue
664
- }
653
+ if (block.children.length === 1 && block.children[0].text === '') {
654
+ continue
655
+ }
665
656
 
666
- const annotationKey = context.keyGenerator()
667
- const markDefs = block.markDefs ?? []
668
- const existingMarkDef = markDefs.find(
669
- (markDef) =>
670
- markDef._type === action.annotation.name &&
671
- markDef._key === annotationKey,
672
- )
657
+ const annotationKey = context.keyGenerator()
658
+ const markDefs = block.markDefs ?? []
659
+ const existingMarkDef = markDefs.find(
660
+ (markDef) =>
661
+ markDef._type === action.annotation.name &&
662
+ markDef._key === annotationKey,
663
+ )
673
664
 
674
- if (existingMarkDef === undefined) {
675
- Transforms.setNodes(
676
- editor,
665
+ if (existingMarkDef === undefined) {
666
+ Transforms.setNodes(
667
+ editor,
668
+ {
669
+ markDefs: [
670
+ ...markDefs,
677
671
  {
678
- markDefs: [
679
- ...markDefs,
680
- {
681
- _type: action.annotation.name,
682
- _key: annotationKey,
683
- ...action.annotation.value,
684
- },
685
- ],
672
+ _type: action.annotation.name,
673
+ _key: annotationKey,
674
+ ...action.annotation.value,
686
675
  },
687
- {at: blockPath},
688
- )
676
+ ],
677
+ },
678
+ {at: blockPath},
679
+ )
689
680
 
690
- markDefPath = [{_key: block._key}, 'markDefs', {_key: annotationKey}]
691
- if (Range.isBackward(editor.selection)) {
692
- markDefPaths.unshift(markDefPath)
693
- } else {
694
- markDefPaths.push(markDefPath)
695
- }
696
- }
681
+ markDefPath = [{_key: block._key}, 'markDefs', {_key: annotationKey}]
697
682
 
698
- Transforms.setNodes(editor, {}, {match: Text.isText, split: true})
683
+ if (Range.isBackward(editor.selection)) {
684
+ markDefPaths.unshift(markDefPath)
685
+ } else {
686
+ markDefPaths.push(markDefPath)
687
+ }
688
+ }
699
689
 
700
- const children = Node.children(editor, blockPath)
690
+ Transforms.setNodes(editor, {}, {match: Text.isText, split: true})
701
691
 
702
- for (const [span, path] of children) {
703
- if (!editor.isTextSpan(span)) {
704
- continue
705
- }
692
+ const children = Node.children(editor, blockPath)
706
693
 
707
- if (!Range.includes(editor.selection, path)) {
708
- continue
709
- }
694
+ for (const [span, path] of children) {
695
+ if (!editor.isTextSpan(span)) {
696
+ continue
697
+ }
710
698
 
711
- const marks = span.marks ?? []
712
- const existingSameTypeAnnotations = marks.filter((mark) =>
713
- markDefs.some(
714
- (markDef) =>
715
- markDef._key === mark &&
716
- markDef._type === action.annotation.name,
699
+ if (!Range.includes(editor.selection, path)) {
700
+ continue
701
+ }
702
+
703
+ const marks = span.marks ?? []
704
+ const existingSameTypeAnnotations = marks.filter((mark) =>
705
+ markDefs.some(
706
+ (markDef) =>
707
+ markDef._key === mark && markDef._type === action.annotation.name,
708
+ ),
709
+ )
710
+
711
+ Transforms.setNodes(
712
+ editor,
713
+ {
714
+ marks: [
715
+ ...marks.filter(
716
+ (mark) => !existingSameTypeAnnotations.includes(mark),
717
717
  ),
718
- )
718
+ annotationKey,
719
+ ],
720
+ },
721
+ {at: path},
722
+ )
719
723
 
720
- Transforms.setNodes(
721
- editor,
722
- {
723
- marks: [
724
- ...marks.filter(
725
- (mark) => !existingSameTypeAnnotations.includes(mark),
726
- ),
727
- annotationKey,
728
- ],
729
- },
730
- {at: path},
731
- )
732
- spanPath = [{_key: block._key}, 'children', {_key: span._key}]
733
- }
734
- }
724
+ spanPath = [{_key: block._key}, 'children', {_key: span._key}]
725
+ }
726
+ }
735
727
 
736
- if (markDefPath && spanPath) {
737
- paths = {
738
- markDefPath,
739
- markDefPaths,
740
- spanPath,
741
- }
742
- }
728
+ if (markDefPath && spanPath) {
729
+ paths = {
730
+ markDefPath,
731
+ markDefPaths,
732
+ spanPath,
743
733
  }
744
734
  }
735
+
745
736
  return paths
746
737
  }
747
738
 
@@ -1,5 +1,3 @@
1
- import {Editor, Range, Text, Transforms} from 'slate'
2
- import {debugWithName} from '../../internal-utils/debug'
3
1
  import {toSlateValue} from '../../internal-utils/values'
4
2
  import type {
5
3
  PortableTextMemberSchemaTypes,
@@ -7,12 +5,11 @@ import type {
7
5
  } from '../../types/editor'
8
6
  import type {EditorActor} from '../editor-machine'
9
7
 
10
- const debug = debugWithName('plugin:withUtils')
11
-
12
8
  interface Options {
13
9
  editorActor: EditorActor
14
10
  schemaTypes: PortableTextMemberSchemaTypes
15
11
  }
12
+
16
13
  /**
17
14
  * This plugin makes various util commands available in the editor
18
15
  *
@@ -21,54 +18,6 @@ export function createWithUtils({editorActor, schemaTypes}: Options) {
21
18
  return function withUtils(
22
19
  editor: PortableTextSlateEditor,
23
20
  ): PortableTextSlateEditor {
24
- // Expands the the selection to wrap around the word the focus is at
25
- editor.pteExpandToWord = () => {
26
- const {selection} = editor
27
- if (selection && !Range.isExpanded(selection)) {
28
- const [textNode] = Editor.node(editor, selection.focus, {depth: 2})
29
- if (!textNode || !Text.isText(textNode) || textNode.text.length === 0) {
30
- debug(`pteExpandToWord: Can't expand to word here`)
31
- return
32
- }
33
- const {focus} = selection
34
- const focusOffset = focus.offset
35
- const charsBefore = textNode.text.slice(0, focusOffset)
36
- const charsAfter = textNode.text.slice(focusOffset, -1)
37
- const isEmpty = (str: string) => str.match(/\s/g)
38
- const whiteSpaceBeforeIndex = charsBefore
39
- .split('')
40
- .reverse()
41
- .findIndex((str) => isEmpty(str))
42
- const newStartOffset =
43
- whiteSpaceBeforeIndex > -1
44
- ? charsBefore.length - whiteSpaceBeforeIndex
45
- : 0
46
- const whiteSpaceAfterIndex = charsAfter
47
- .split('')
48
- .findIndex((obj) => isEmpty(obj))
49
- const newEndOffset =
50
- charsBefore.length +
51
- (whiteSpaceAfterIndex > -1
52
- ? whiteSpaceAfterIndex
53
- : charsAfter.length + 1)
54
- if (
55
- !(
56
- newStartOffset === newEndOffset ||
57
- Number.isNaN(newStartOffset) ||
58
- Number.isNaN(newEndOffset)
59
- )
60
- ) {
61
- debug('pteExpandToWord: Expanding to focused word')
62
- Transforms.setSelection(editor, {
63
- anchor: {...selection.anchor, offset: newStartOffset},
64
- focus: {...selection.focus, offset: newEndOffset},
65
- })
66
- return
67
- }
68
- debug(`pteExpandToWord: Can't expand to word here`)
69
- }
70
- }
71
-
72
21
  editor.pteCreateTextBlock = (options: {
73
22
  decorators: Array<string>
74
23
  listItem?: string
@@ -9,6 +9,10 @@ export type {
9
9
  export {getActiveAnnotations} from './selector.get-active-annotations'
10
10
  export {getActiveListItem} from './selector.get-active-list-item'
11
11
  export {getActiveStyle} from './selector.get-active-style'
12
+ export {getBlockOffsets} from './selector.get-block-offsets'
13
+ export {getCaretWordSelection} from './selector.get-caret-word-selection'
14
+ export {getNextInlineObject} from './selector.get-next-inline-object'
15
+ export {getPreviousInlineObject} from './selector.get-previous-inline-object'
12
16
  export {getSelectedSlice} from './selector.get-selected-slice'
13
17
  export {getSelectedSpans} from './selector.get-selected-spans'
14
18
  export {getSelection} from './selector.get-selection'
@@ -0,0 +1,33 @@
1
+ import type {EditorSelector} from '../editor/editor-selector'
2
+ import * as utils from '../utils'
3
+ import {getSelectionEndPoint} from './selector.get-selection-end-point'
4
+ import {getSelectionStartPoint} from './selector.get-selection-start-point'
5
+
6
+ /**
7
+ * @public
8
+ */
9
+ export const getBlockOffsets: EditorSelector<
10
+ {start: utils.BlockOffset; end: utils.BlockOffset} | undefined
11
+ > = ({context}) => {
12
+ if (!context.selection) {
13
+ return undefined
14
+ }
15
+
16
+ const selectionStartPoint = getSelectionStartPoint({context})
17
+ const selectionEndPoint = getSelectionEndPoint({context})
18
+
19
+ if (!selectionStartPoint || !selectionEndPoint) {
20
+ return undefined
21
+ }
22
+
23
+ const start = utils.spanSelectionPointToBlockOffset({
24
+ value: context.value,
25
+ selectionPoint: selectionStartPoint,
26
+ })
27
+ const end = utils.spanSelectionPointToBlockOffset({
28
+ value: context.value,
29
+ selectionPoint: selectionEndPoint,
30
+ })
31
+
32
+ return start && end ? {start, end} : undefined
33
+ }