@portabletext/editor 1.33.3 → 1.33.4

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 (67) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +11 -204
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/behavior.markdown.cjs +7 -7
  4. package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
  5. package/lib/_chunks-cjs/plugin.event-listener.cjs +196 -25
  6. package/lib/_chunks-cjs/plugin.event-listener.cjs.map +1 -1
  7. package/lib/_chunks-cjs/selector.get-text-before.cjs +3 -3
  8. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  9. package/lib/_chunks-cjs/selector.is-active-style.cjs +246 -0
  10. package/lib/_chunks-cjs/selector.is-active-style.cjs.map +1 -0
  11. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs +23 -198
  12. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs.map +1 -1
  13. package/lib/_chunks-cjs/util.block-offsets-to-selection.cjs +3 -3
  14. package/lib/_chunks-cjs/util.block-offsets-to-selection.cjs.map +1 -1
  15. package/lib/_chunks-cjs/util.reverse-selection.cjs +0 -135
  16. package/lib/_chunks-cjs/util.reverse-selection.cjs.map +1 -1
  17. package/lib/_chunks-cjs/util.slice-blocks.cjs +138 -1
  18. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  19. package/lib/_chunks-es/behavior.core.js +9 -202
  20. package/lib/_chunks-es/behavior.core.js.map +1 -1
  21. package/lib/_chunks-es/behavior.markdown.js +1 -1
  22. package/lib/_chunks-es/plugin.event-listener.js +193 -23
  23. package/lib/_chunks-es/plugin.event-listener.js.map +1 -1
  24. package/lib/_chunks-es/selector.get-text-before.js +2 -1
  25. package/lib/_chunks-es/selector.get-text-before.js.map +1 -1
  26. package/lib/_chunks-es/selector.is-active-style.js +249 -0
  27. package/lib/_chunks-es/selector.is-active-style.js.map +1 -0
  28. package/lib/_chunks-es/selector.is-at-the-start-of-block.js +12 -187
  29. package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -1
  30. package/lib/_chunks-es/util.block-offsets-to-selection.js +1 -1
  31. package/lib/_chunks-es/util.reverse-selection.js +1 -136
  32. package/lib/_chunks-es/util.reverse-selection.js.map +1 -1
  33. package/lib/_chunks-es/util.slice-blocks.js +140 -3
  34. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  35. package/lib/index.d.cts +1 -115
  36. package/lib/index.d.ts +1 -115
  37. package/lib/plugins/index.cjs +11 -11
  38. package/lib/plugins/index.cjs.map +1 -1
  39. package/lib/plugins/index.d.cts +1 -115
  40. package/lib/plugins/index.d.ts +1 -115
  41. package/lib/plugins/index.js +1 -1
  42. package/lib/selectors/index.cjs +16 -21
  43. package/lib/selectors/index.cjs.map +1 -1
  44. package/lib/selectors/index.js +7 -11
  45. package/lib/selectors/index.js.map +1 -1
  46. package/lib/utils/index.cjs +13 -13
  47. package/lib/utils/index.cjs.map +1 -1
  48. package/lib/utils/index.js +3 -3
  49. package/package.json +1 -1
  50. package/src/behaviors/behavior.core.annotations.ts +0 -24
  51. package/src/behaviors/behavior.core.decorators.ts +0 -19
  52. package/src/behaviors/behavior.core.insert-break.ts +4 -4
  53. package/src/behaviors/behavior.core.lists.ts +0 -30
  54. package/src/behaviors/behavior.core.ts +2 -17
  55. package/src/behaviors/behavior.default.ts +198 -0
  56. package/src/behaviors/behavior.foundational.ts +12 -12
  57. package/src/converters/converter.text-html.serialize.test.ts +1 -1
  58. package/src/editor/editor-machine.ts +8 -8
  59. package/src/selectors/selector.get-selection-text.ts +14 -89
  60. package/src/utils/util.slice-blocks.ts +12 -1
  61. package/lib/_chunks-cjs/selector.get-trimmed-selection.cjs +0 -97
  62. package/lib/_chunks-cjs/selector.get-trimmed-selection.cjs.map +0 -1
  63. package/lib/_chunks-es/selector.get-trimmed-selection.js +0 -100
  64. package/lib/_chunks-es/selector.get-trimmed-selection.js.map +0 -1
  65. package/src/behaviors/behavior.core.deserialize.ts +0 -60
  66. package/src/behaviors/behavior.core.serialize.ts +0 -44
  67. package/src/behaviors/behavior.core.style.ts +0 -19
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: !0 });
3
- var util_reverseSelection = require("../_chunks-cjs/util.reverse-selection.cjs"), util_blockOffsetsToSelection = require("../_chunks-cjs/util.block-offsets-to-selection.cjs"), util_sliceBlocks = require("../_chunks-cjs/util.slice-blocks.cjs");
3
+ var util_sliceBlocks = require("../_chunks-cjs/util.slice-blocks.cjs"), util_blockOffsetsToSelection = require("../_chunks-cjs/util.block-offsets-to-selection.cjs"), util_reverseSelection = require("../_chunks-cjs/util.reverse-selection.cjs");
4
4
  function isTextBlock(context, block) {
5
5
  return block._type === context.schema.block.name;
6
6
  }
@@ -53,7 +53,7 @@ function splitTextBlock({
53
53
  }, "children", {
54
54
  _key: lastChild._key
55
55
  }],
56
- offset: util_reverseSelection.isSpan(context, lastChild) ? lastChild.text.length : 0
56
+ offset: util_sliceBlocks.isSpan(context, lastChild) ? lastChild.text.length : 0
57
57
  }
58
58
  }
59
59
  }).at(0);
@@ -63,18 +63,18 @@ function splitTextBlock({
63
63
  after
64
64
  };
65
65
  }
66
- exports.blockOffsetToSpanSelectionPoint = util_reverseSelection.blockOffsetToSpanSelectionPoint;
67
- exports.getBlockEndPoint = util_reverseSelection.getBlockEndPoint;
68
- exports.getBlockStartPoint = util_reverseSelection.getBlockStartPoint;
69
- exports.getTextBlockText = util_reverseSelection.getTextBlockText;
70
- exports.isEmptyTextBlock = util_reverseSelection.isEmptyTextBlock;
71
- exports.isEqualSelectionPoints = util_reverseSelection.isEqualSelectionPoints;
72
- exports.isKeyedSegment = util_reverseSelection.isKeyedSegment;
73
- exports.isSpan = util_reverseSelection.isSpan;
74
- exports.reverseSelection = util_reverseSelection.reverseSelection;
75
- exports.spanSelectionPointToBlockOffset = util_reverseSelection.spanSelectionPointToBlockOffset;
76
- exports.blockOffsetsToSelection = util_blockOffsetsToSelection.blockOffsetsToSelection;
66
+ exports.blockOffsetToSpanSelectionPoint = util_sliceBlocks.blockOffsetToSpanSelectionPoint;
67
+ exports.getBlockEndPoint = util_sliceBlocks.getBlockEndPoint;
68
+ exports.getBlockStartPoint = util_sliceBlocks.getBlockStartPoint;
69
+ exports.getTextBlockText = util_sliceBlocks.getTextBlockText;
70
+ exports.isEmptyTextBlock = util_sliceBlocks.isEmptyTextBlock;
71
+ exports.isEqualSelectionPoints = util_sliceBlocks.isEqualSelectionPoints;
72
+ exports.isKeyedSegment = util_sliceBlocks.isKeyedSegment;
73
+ exports.isSpan = util_sliceBlocks.isSpan;
77
74
  exports.sliceBlocks = util_sliceBlocks.sliceBlocks;
75
+ exports.spanSelectionPointToBlockOffset = util_sliceBlocks.spanSelectionPointToBlockOffset;
76
+ exports.blockOffsetsToSelection = util_blockOffsetsToSelection.blockOffsetsToSelection;
77
+ exports.reverseSelection = util_reverseSelection.reverseSelection;
78
78
  exports.isTextBlock = isTextBlock;
79
79
  exports.mergeTextBlocks = mergeTextBlocks;
80
80
  exports.splitTextBlock = splitTextBlock;
@@ -1 +1 @@
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,6BAAAA,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
+ {"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,6BAAAA,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,iBAAO9B,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,8 +1,8 @@
1
- import { isSpan } from "../_chunks-es/util.reverse-selection.js";
2
- import { blockOffsetToSpanSelectionPoint, getBlockEndPoint, getBlockStartPoint, getTextBlockText, isEmptyTextBlock, isEqualSelectionPoints, isKeyedSegment, reverseSelection, spanSelectionPointToBlockOffset } from "../_chunks-es/util.reverse-selection.js";
1
+ import { sliceBlocks, isSpan } from "../_chunks-es/util.slice-blocks.js";
2
+ import { blockOffsetToSpanSelectionPoint, getBlockEndPoint, getBlockStartPoint, getTextBlockText, isEmptyTextBlock, isEqualSelectionPoints, isKeyedSegment, spanSelectionPointToBlockOffset } from "../_chunks-es/util.slice-blocks.js";
3
3
  import { parseBlock } from "../_chunks-es/util.block-offsets-to-selection.js";
4
4
  import { blockOffsetsToSelection } from "../_chunks-es/util.block-offsets-to-selection.js";
5
- import { sliceBlocks } from "../_chunks-es/util.slice-blocks.js";
5
+ import { reverseSelection } from "../_chunks-es/util.reverse-selection.js";
6
6
  function isTextBlock(context, block) {
7
7
  return block._type === context.schema.block.name;
8
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.33.3",
3
+ "version": "1.33.4",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -1,28 +1,6 @@
1
1
  import * as selectors from '../selectors'
2
2
  import {defineBehavior, raise} from './behavior.types'
3
3
 
4
- const toggleAnnotationOff = defineBehavior({
5
- on: 'annotation.toggle',
6
- guard: ({context, event}) =>
7
- selectors.isActiveAnnotation(event.annotation.name)({context}),
8
- actions: [
9
- ({event}) => [
10
- raise({type: 'annotation.remove', annotation: event.annotation}),
11
- ],
12
- ],
13
- })
14
-
15
- const toggleAnnotationOn = defineBehavior({
16
- on: 'annotation.toggle',
17
- guard: ({context, event}) =>
18
- !selectors.isActiveAnnotation(event.annotation.name)({context}),
19
- actions: [
20
- ({event}) => [
21
- raise({type: 'annotation.add', annotation: event.annotation}),
22
- ],
23
- ],
24
- })
25
-
26
4
  const addAnnotationOnCollapsedSelection = defineBehavior({
27
5
  on: 'annotation.add',
28
6
  guard: ({context}) => {
@@ -55,7 +33,5 @@ const addAnnotationOnCollapsedSelection = defineBehavior({
55
33
  })
56
34
 
57
35
  export const coreAnnotationBehaviors = {
58
- toggleAnnotationOff,
59
- toggleAnnotationOn,
60
36
  addAnnotationOnCollapsedSelection,
61
37
  }
@@ -1,26 +1,7 @@
1
1
  import {isHotkey} from '../internal-utils/is-hotkey'
2
- import * as selectors from '../selectors'
3
2
  import {defineBehavior, raise} from './behavior.types'
4
3
 
5
4
  export const coreDecoratorBehaviors = {
6
- toggleDecoratorOff: defineBehavior({
7
- on: 'decorator.toggle',
8
- guard: ({context, event}) =>
9
- selectors.isActiveDecorator(event.decorator)({context}),
10
- actions: [
11
- ({event}) => [
12
- raise({type: 'decorator.remove', decorator: event.decorator}),
13
- ],
14
- ],
15
- }),
16
- toggleDecoratorOn: defineBehavior({
17
- on: 'decorator.toggle',
18
- guard: ({context, event}) =>
19
- !selectors.isActiveDecorator(event.decorator)({context}),
20
- actions: [
21
- ({event}) => [raise({type: 'decorator.add', decorator: event.decorator})],
22
- ],
23
- }),
24
5
  strongShortcut: defineBehavior({
25
6
  on: 'key.down',
26
7
  guard: ({context, event}) =>
@@ -1,7 +1,7 @@
1
1
  import * as selectors from '../selectors'
2
2
  import {defineBehavior, raise} from './behavior.types'
3
3
 
4
- const atTheEndOfTextBlock = defineBehavior({
4
+ const breakingAtTheEndOfTextBlock = defineBehavior({
5
5
  on: 'insert.break',
6
6
  guard: ({context}) => {
7
7
  const focusTextBlock = selectors.getFocusTextBlock({context})
@@ -50,7 +50,7 @@ const atTheEndOfTextBlock = defineBehavior({
50
50
  ],
51
51
  })
52
52
 
53
- const atTheStartOfTextBlock = defineBehavior({
53
+ const breakingAtTheStartOfTextBlock = defineBehavior({
54
54
  on: 'insert.break',
55
55
  guard: ({context}) => {
56
56
  const focusTextBlock = selectors.getFocusTextBlock({context})
@@ -117,6 +117,6 @@ const atTheStartOfTextBlock = defineBehavior({
117
117
  })
118
118
 
119
119
  export const coreInsertBreakBehaviors = {
120
- atTheEndOfTextBlock,
121
- atTheStartOfTextBlock,
120
+ breakingAtTheEndOfTextBlock,
121
+ breakingAtTheStartOfTextBlock,
122
122
  }
@@ -6,34 +6,6 @@ import {defineBehavior, raise} from './behavior.types'
6
6
 
7
7
  const MAX_LIST_LEVEL = 10
8
8
 
9
- const toggleListItemOff = defineBehavior({
10
- on: 'list item.toggle',
11
- guard: ({context, event}) =>
12
- selectors.isActiveListItem(event.listItem)({context}),
13
- actions: [
14
- ({event}) => [
15
- raise({
16
- type: 'list item.remove',
17
- listItem: event.listItem,
18
- }),
19
- ],
20
- ],
21
- })
22
-
23
- const toggleListItemOn = defineBehavior({
24
- on: 'list item.toggle',
25
- guard: ({context, event}) =>
26
- !selectors.isActiveListItem(event.listItem)({context}),
27
- actions: [
28
- ({event}) => [
29
- raise({
30
- type: 'list item.add',
31
- listItem: event.listItem,
32
- }),
33
- ],
34
- ],
35
- })
36
-
37
9
  const clearListOnBackspace = defineBehavior({
38
10
  on: 'delete.backward',
39
11
  guard: ({context}) => {
@@ -216,8 +188,6 @@ const unindentListOnShiftTab = defineBehavior({
216
188
  })
217
189
 
218
190
  export const coreListBehaviors = {
219
- toggleListItemOff,
220
- toggleListItemOn,
221
191
  clearListOnBackspace,
222
192
  unindentListOnBackspace,
223
193
  clearListOnEnter,
@@ -1,43 +1,28 @@
1
1
  import {coreAnnotationBehaviors} from './behavior.core.annotations'
2
2
  import {coreBlockObjectBehaviors} from './behavior.core.block-objects'
3
3
  import {coreDecoratorBehaviors} from './behavior.core.decorators'
4
- import {coreDeserializeBehaviors} from './behavior.core.deserialize'
5
4
  import {coreInsertBreakBehaviors} from './behavior.core.insert-break'
6
5
  import {coreListBehaviors} from './behavior.core.lists'
7
- import {coreSerializeBehaviors} from './behavior.core.serialize'
8
- import {coreStyleBehaviors} from './behavior.core.style'
9
6
 
10
7
  /**
11
8
  * @beta
12
9
  */
13
10
  export const coreBehaviors = [
14
- coreAnnotationBehaviors.toggleAnnotationOff,
15
- coreAnnotationBehaviors.toggleAnnotationOn,
16
11
  coreAnnotationBehaviors.addAnnotationOnCollapsedSelection,
17
- coreDecoratorBehaviors.toggleDecoratorOff,
18
- coreDecoratorBehaviors.toggleDecoratorOn,
19
12
  coreDecoratorBehaviors.strongShortcut,
20
13
  coreDecoratorBehaviors.emShortcut,
21
14
  coreDecoratorBehaviors.underlineShortcut,
22
15
  coreDecoratorBehaviors.codeShortcut,
23
- coreDeserializeBehaviors.deserialize,
24
- coreDeserializeBehaviors['deserialization.success'],
25
16
  coreBlockObjectBehaviors.arrowDownOnLonelyBlockObject,
26
17
  coreBlockObjectBehaviors.arrowUpOnLonelyBlockObject,
27
18
  coreBlockObjectBehaviors.breakingBlockObject,
28
19
  coreBlockObjectBehaviors.deletingEmptyTextBlockAfterBlockObject,
29
20
  coreBlockObjectBehaviors.deletingEmptyTextBlockBeforeBlockObject,
30
- coreListBehaviors.toggleListItemOff,
31
- coreListBehaviors.toggleListItemOn,
32
21
  coreListBehaviors.clearListOnBackspace,
33
22
  coreListBehaviors.unindentListOnBackspace,
34
23
  coreListBehaviors.clearListOnEnter,
35
24
  coreListBehaviors.indentListOnTab,
36
25
  coreListBehaviors.unindentListOnShiftTab,
37
- coreInsertBreakBehaviors.atTheEndOfTextBlock,
38
- coreInsertBreakBehaviors.atTheStartOfTextBlock,
39
- coreSerializeBehaviors.serialize,
40
- coreSerializeBehaviors['serialization.success'],
41
- coreStyleBehaviors.toggleStyleOff,
42
- coreStyleBehaviors.toggleStyleOn,
26
+ coreInsertBreakBehaviors.breakingAtTheEndOfTextBlock,
27
+ coreInsertBreakBehaviors.breakingAtTheStartOfTextBlock,
43
28
  ]
@@ -0,0 +1,198 @@
1
+ import * as selectors from '../selectors'
2
+ import {defineBehavior, raise} from './behavior.types'
3
+
4
+ const toggleAnnotationOff = defineBehavior({
5
+ on: 'annotation.toggle',
6
+ guard: ({context, event}) =>
7
+ selectors.isActiveAnnotation(event.annotation.name)({context}),
8
+ actions: [
9
+ ({event}) => [
10
+ raise({type: 'annotation.remove', annotation: event.annotation}),
11
+ ],
12
+ ],
13
+ })
14
+
15
+ const toggleAnnotationOn = defineBehavior({
16
+ on: 'annotation.toggle',
17
+ guard: ({context, event}) =>
18
+ !selectors.isActiveAnnotation(event.annotation.name)({context}),
19
+ actions: [
20
+ ({event}) => [
21
+ raise({type: 'annotation.add', annotation: event.annotation}),
22
+ ],
23
+ ],
24
+ })
25
+
26
+ const toggleDecoratorOff = defineBehavior({
27
+ on: 'decorator.toggle',
28
+ guard: ({context, event}) =>
29
+ selectors.isActiveDecorator(event.decorator)({context}),
30
+ actions: [
31
+ ({event}) => [
32
+ raise({type: 'decorator.remove', decorator: event.decorator}),
33
+ ],
34
+ ],
35
+ })
36
+
37
+ const toggleDecoratorOn = defineBehavior({
38
+ on: 'decorator.toggle',
39
+ guard: ({context, event}) =>
40
+ !selectors.isActiveDecorator(event.decorator)({context}),
41
+ actions: [
42
+ ({event}) => [raise({type: 'decorator.add', decorator: event.decorator})],
43
+ ],
44
+ })
45
+
46
+ const toggleListItemOff = defineBehavior({
47
+ on: 'list item.toggle',
48
+ guard: ({context, event}) =>
49
+ selectors.isActiveListItem(event.listItem)({context}),
50
+ actions: [
51
+ ({event}) => [
52
+ raise({
53
+ type: 'list item.remove',
54
+ listItem: event.listItem,
55
+ }),
56
+ ],
57
+ ],
58
+ })
59
+
60
+ const toggleListItemOn = defineBehavior({
61
+ on: 'list item.toggle',
62
+ guard: ({context, event}) =>
63
+ !selectors.isActiveListItem(event.listItem)({context}),
64
+ actions: [
65
+ ({event}) => [
66
+ raise({
67
+ type: 'list item.add',
68
+ listItem: event.listItem,
69
+ }),
70
+ ],
71
+ ],
72
+ })
73
+
74
+ const toggleStyleOff = defineBehavior({
75
+ on: 'style.toggle',
76
+ guard: ({context, event}) => selectors.isActiveStyle(event.style)({context}),
77
+ actions: [({event}) => [raise({type: 'style.remove', style: event.style})]],
78
+ })
79
+
80
+ const toggleStyleOn = defineBehavior({
81
+ on: 'style.toggle',
82
+ guard: ({context, event}) => !selectors.isActiveStyle(event.style)({context}),
83
+ actions: [({event}) => [raise({type: 'style.add', style: event.style})]],
84
+ })
85
+
86
+ const raiseDeserializationSuccessOrFailure = defineBehavior({
87
+ on: 'deserialize',
88
+ guard: ({context, event}) => {
89
+ const deserializeEvents = context.converters.flatMap((converter) => {
90
+ const data = event.dataTransfer.getData(converter.mimeType)
91
+
92
+ if (!data) {
93
+ return []
94
+ }
95
+
96
+ return [
97
+ converter.deserialize({context, event: {type: 'deserialize', data}}),
98
+ ]
99
+ })
100
+
101
+ const firstSuccess = deserializeEvents.find(
102
+ (deserializeEvent) => deserializeEvent.type === 'deserialization.success',
103
+ )
104
+
105
+ if (!firstSuccess) {
106
+ return {
107
+ type: 'deserialization.failure',
108
+ mimeType: '*/*',
109
+ reason: deserializeEvents
110
+ .map((deserializeEvent) =>
111
+ deserializeEvent.type === 'deserialization.failure'
112
+ ? deserializeEvent.reason
113
+ : '',
114
+ )
115
+ .join(', '),
116
+ } as const
117
+ }
118
+
119
+ return firstSuccess
120
+ },
121
+ actions: [
122
+ ({event}, deserializeEvent) => [
123
+ raise({
124
+ ...deserializeEvent,
125
+ dataTransfer: event.dataTransfer,
126
+ }),
127
+ ],
128
+ ],
129
+ })
130
+
131
+ const raiseInsertBlocks = defineBehavior({
132
+ on: 'deserialization.success',
133
+ actions: [
134
+ ({event}) => [
135
+ raise({
136
+ type: 'insert.blocks',
137
+ blocks: event.data,
138
+ }),
139
+ ],
140
+ ],
141
+ })
142
+
143
+ const raiseSerializationSuccessOrFailure = defineBehavior({
144
+ on: 'serialize',
145
+ guard: ({context, event}) => {
146
+ if (context.converters.length === 0) {
147
+ return false
148
+ }
149
+
150
+ const serializeEvents = context.converters.map((converter) =>
151
+ converter.serialize({context, event}),
152
+ )
153
+
154
+ if (serializeEvents.length === 0) {
155
+ return false
156
+ }
157
+
158
+ return serializeEvents
159
+ },
160
+ actions: [
161
+ ({event}, serializeEvents) =>
162
+ serializeEvents.map((serializeEvent) =>
163
+ raise({
164
+ ...serializeEvent,
165
+ dataTransfer: event.dataTransfer,
166
+ }),
167
+ ),
168
+ ],
169
+ })
170
+
171
+ const raiseDataTransferSet = defineBehavior({
172
+ on: 'serialization.success',
173
+ actions: [
174
+ ({event}) => [
175
+ raise({
176
+ type: 'data transfer.set',
177
+ data: event.data,
178
+ dataTransfer: event.dataTransfer,
179
+ mimeType: event.mimeType,
180
+ }),
181
+ ],
182
+ ],
183
+ })
184
+
185
+ export const defaultBehaviors = [
186
+ toggleAnnotationOff,
187
+ toggleAnnotationOn,
188
+ toggleDecoratorOff,
189
+ toggleDecoratorOn,
190
+ toggleListItemOff,
191
+ toggleListItemOn,
192
+ toggleStyleOff,
193
+ toggleStyleOn,
194
+ raiseDeserializationSuccessOrFailure,
195
+ raiseInsertBlocks,
196
+ raiseSerializationSuccessOrFailure,
197
+ raiseDataTransferSet,
198
+ ]
@@ -1,15 +1,15 @@
1
1
  import {keyIs} from '../internal-utils/key-is'
2
2
  import {defineBehavior, raise} from './behavior.types'
3
3
 
4
- export const foundationalBehaviors = [
5
- /**
6
- * On WebKit, Shift+Enter results in an `insertParagraph` input event rather
7
- * than an `insertLineBreak` input event. This Behavior makes sure we catch
8
- * that `key.down` event beforehand and raise an `insert.soft break` manually.
9
- */
10
- defineBehavior({
11
- on: 'key.down',
12
- guard: ({event}) => keyIs.lineBreak(event.keyboardEvent),
13
- actions: [() => [raise({type: 'insert.soft break'})]],
14
- }),
15
- ]
4
+ /**
5
+ * On WebKit, Shift+Enter results in an `insertParagraph` input event rather
6
+ * than an `insertLineBreak` input event. This Behavior makes sure we catch
7
+ * that `key.down` event beforehand and raise an `insert.soft break` manually.
8
+ */
9
+ const raiseSoftBreak = defineBehavior({
10
+ on: 'key.down',
11
+ guard: ({event}) => keyIs.lineBreak(event.keyboardEvent),
12
+ actions: [() => [raise({type: 'insert.soft break'})]],
13
+ })
14
+
15
+ export const foundationalBehaviors = [raiseSoftBreak]
@@ -168,7 +168,7 @@ describe(converterTextHtml.serialize.name, () => {
168
168
  },
169
169
  }),
170
170
  ).toMatchObject({
171
- data: '<p>fizz buzz</p>',
171
+ data: '<p>fizz buz</p>',
172
172
  })
173
173
  })
174
174
 
@@ -11,6 +11,7 @@ import {
11
11
  } from 'xstate'
12
12
  import {performAction} from '../behavior-actions/behavior.actions'
13
13
  import {coreBehaviors} from '../behaviors/behavior.core'
14
+ import {defaultBehaviors} from '../behaviors/behavior.default'
14
15
  import {foundationalBehaviors} from '../behaviors/behavior.foundational'
15
16
  import {
16
17
  isCustomBehaviorEvent,
@@ -255,7 +256,7 @@ export const editorMachine = setup({
255
256
  'assign behaviors': assign({
256
257
  behaviors: ({event}) => {
257
258
  assertEvent(event, 'update behaviors')
258
- return new Set([...foundationalBehaviors, ...event.behaviors])
259
+ return new Set([...event.behaviors])
259
260
  },
260
261
  }),
261
262
  'assign schema': assign({
@@ -310,9 +311,11 @@ export const editorMachine = setup({
310
311
  ? event.defaultActionCallback
311
312
  : undefined
312
313
 
313
- const eventBehaviors = [...context.behaviors.values()].filter(
314
- (behavior) => behavior.on === event.behaviorEvent.type,
315
- )
314
+ const eventBehaviors = [
315
+ ...foundationalBehaviors,
316
+ ...context.behaviors.values(),
317
+ ...defaultBehaviors,
318
+ ].filter((behavior) => behavior.on === event.behaviorEvent.type)
316
319
 
317
320
  if (eventBehaviors.length === 0) {
318
321
  if (defaultActionCallback) {
@@ -474,10 +477,7 @@ export const editorMachine = setup({
474
477
  }).createMachine({
475
478
  id: 'editor',
476
479
  context: ({input}) => ({
477
- behaviors: new Set([
478
- ...foundationalBehaviors,
479
- ...(input.behaviors ?? coreBehaviors),
480
- ]),
480
+ behaviors: new Set([...(input.behaviors ?? coreBehaviors)]),
481
481
  converters: new Set(input.converters ?? []),
482
482
  keyGenerator: input.keyGenerator,
483
483
  pendingEvents: [],
@@ -1,102 +1,27 @@
1
1
  import {isPortableTextSpan, isPortableTextTextBlock} from '@sanity/types'
2
2
  import type {EditorSelector} from '../editor/editor-selector'
3
- import {isKeyedSegment} from '../utils/util.is-keyed-segment'
4
- import {reverseSelection} from '../utils/util.reverse-selection'
3
+ import {getSelectedSlice} from './selector.get-selected-slice'
5
4
 
6
5
  /**
7
6
  * @public
8
7
  */
9
8
  export const getSelectionText: EditorSelector<string> = ({context}) => {
10
- let text = ''
9
+ const selectedSlice = getSelectedSlice({context})
11
10
 
12
- const {value, selection} = context
13
-
14
- if (!value || !selection) {
15
- return text
16
- }
17
-
18
- const forwardSelection = selection.backward
19
- ? reverseSelection(selection)
20
- : selection
21
-
22
- if (!forwardSelection) {
23
- return text
24
- }
25
-
26
- const startBlockKey = isKeyedSegment(forwardSelection.anchor.path[0])
27
- ? forwardSelection.anchor.path[0]._key
28
- : undefined
29
- const endBlockKey = isKeyedSegment(forwardSelection.focus.path[0])
30
- ? forwardSelection.focus.path[0]._key
31
- : undefined
32
- const startChildKey = isKeyedSegment(forwardSelection.anchor.path[2])
33
- ? forwardSelection.anchor.path[2]._key
34
- : undefined
35
- const endChildKey = isKeyedSegment(forwardSelection.focus.path[2])
36
- ? forwardSelection.focus.path[2]._key
37
- : undefined
38
- let startFound = false
39
-
40
- if (!startBlockKey || !endBlockKey) {
41
- return text
42
- }
43
-
44
- for (const block of value) {
45
- if (block._key === startBlockKey) {
46
- if (!isPortableTextTextBlock(block)) {
47
- continue
48
- }
49
-
50
- for (const child of block.children) {
51
- if (child._key === startChildKey) {
52
- startFound = true
53
- }
54
-
55
- if (!startFound) {
56
- continue
57
- }
58
-
59
- if (isPortableTextSpan(child) && startChildKey) {
60
- if (child._key === startChildKey && child._key === endChildKey) {
61
- text =
62
- text +
63
- child.text.slice(
64
- forwardSelection.anchor.offset,
65
- forwardSelection.focus.offset,
66
- )
67
- } else if (child._key === startChildKey) {
68
- text = text + child.text.slice(forwardSelection.anchor.offset)
69
- } else if (child._key === endChildKey) {
70
- text = text + child.text.slice(0, forwardSelection.focus.offset)
71
- } else {
72
- text = text + child.text
73
- }
74
- }
75
-
76
- if (child._key === endChildKey) {
77
- break
78
- }
79
- }
80
- continue
11
+ return selectedSlice.reduce((text, block) => {
12
+ if (!isPortableTextTextBlock(block)) {
13
+ return text
81
14
  }
82
15
 
83
- if (block._key === endBlockKey) {
84
- if (!isPortableTextTextBlock(block)) {
85
- continue
86
- }
87
-
88
- for (const child of block.children) {
89
- if (isPortableTextSpan(child) && endChildKey) {
90
- text = text + child.text.slice(0, forwardSelection.focus.offset)
91
- }
92
-
93
- if (child._key === endChildKey) {
94
- break
16
+ return (
17
+ text +
18
+ block.children.reduce((text, child) => {
19
+ if (isPortableTextSpan(child)) {
20
+ return text + child.text
95
21
  }
96
- }
97
- break
98
- }
99
- }
100
22
 
101
- return text
23
+ return text
24
+ }, '')
25
+ )
26
+ }, '')
102
27
  }