@portabletext/editor 3.0.7 → 3.0.9

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.
package/lib/index.js CHANGED
@@ -7,10 +7,11 @@ import { Element as Element$1, Text, Range, Editor, Node, Point, Path, Transform
7
7
  import { useSelected, useSlateSelector, useSlateStatic, ReactEditor, useSlate, Editable, withReact, Slate } from "slate-react";
8
8
  import debug$j from "debug";
9
9
  import { DOMEditor, isDOMNode, EDITOR_TO_PENDING_SELECTION, IS_FOCUSED, IS_READ_ONLY } from "slate-dom";
10
- import { getBlockEndPoint, getBlockStartPoint, getBlockKeyFromSelectionPoint, isSelectionCollapsed, isEqualSelectionPoints, getChildKeyFromSelectionPoint, blockOffsetToSpanSelectionPoint, defaultKeyGenerator, parseBlocks, parseBlock, parseAnnotation, parseSpan, parseInlineObject, isKeyedSegment, isListBlock, isTypedObject, getSelectionStartPoint, getSelectionEndPoint } from "./_chunks-es/util.slice-blocks.js";
10
+ import { getBlockEndPoint, getBlockStartPoint, getBlockKeyFromSelectionPoint, isSelectionCollapsed, isEqualSelectionPoints, getChildKeyFromSelectionPoint, blockOffsetToSpanSelectionPoint, defaultKeyGenerator, parseBlocks, parseBlock, parseAnnotation, parseMarkDefs, parseSpan, parseInlineObject, isKeyedSegment, isListBlock, isTypedObject, getSelectionStartPoint, getSelectionEndPoint } from "./_chunks-es/util.slice-blocks.js";
11
11
  import isEqual from "lodash/isEqual.js";
12
12
  import { isTextBlock, isSpan, compileSchema } from "@portabletext/schema";
13
13
  import { defineSchema } from "@portabletext/schema";
14
+ import { isEmptyTextBlock, sliceTextBlock, getTextBlockText } from "./_chunks-es/util.slice-text-block.js";
14
15
  import { getFocusInlineObject, isSelectionCollapsed as isSelectionCollapsed$1, getFocusTextBlock, getFocusSpan as getFocusSpan$1, getSelectedBlocks, isSelectionExpanded, getSelectionStartBlock, getSelectionEndBlock, isOverlappingSelection, getFocusBlock as getFocusBlock$1, isSelectingEntireBlocks, getSelectedValue, getActiveDecorators, isActiveAnnotation, getCaretWordSelection, getFocusBlockObject, getPreviousBlock, getNextBlock, getMarkState, getActiveAnnotationsMarks, isAtTheEndOfBlock, isAtTheStartOfBlock, getFirstBlock as getFirstBlock$1, getLastBlock as getLastBlock$1, getFocusListBlock, getSelectionStartPoint as getSelectionStartPoint$1, getSelectionEndPoint as getSelectionEndPoint$1, isActiveDecorator, getFocusChild as getFocusChild$1, getActiveAnnotations, getSelectedTextBlocks, isActiveListItem, isActiveStyle } from "./_chunks-es/selector.is-at-the-start-of-block.js";
15
16
  import { defineBehavior, forward, raise, effect } from "./behaviors/index.js";
16
17
  import uniq from "lodash/uniq.js";
@@ -20,9 +21,7 @@ import { htmlToBlocks } from "@portabletext/block-tools";
20
21
  import { toHTML } from "@portabletext/to-html";
21
22
  import { Schema } from "@sanity/schema";
22
23
  import flatten from "lodash/flatten.js";
23
- import omit from "lodash/omit.js";
24
- import { applyAll, unset, insert, set, setIfMissing, diffMatchPatch as diffMatchPatch$1 } from "@portabletext/patches";
25
- import { isEmptyTextBlock, sliceTextBlock, getTextBlockText } from "./_chunks-es/util.slice-text-block.js";
24
+ import { set, applyAll, unset, insert, setIfMissing, diffMatchPatch as diffMatchPatch$1 } from "@portabletext/patches";
26
25
  import { createDraft, finishDraft } from "immer";
27
26
  import { createKeyboardShortcut, code, underline, italic, bold, undo, redo } from "@portabletext/keyboard-shortcuts";
28
27
  import isPlainObject from "lodash/isPlainObject.js";
@@ -51,7 +50,7 @@ function toSlateBlock(block, {
51
50
  if (block && block._type === schemaTypes.block.name) {
52
51
  const textBlock = block;
53
52
  let hasInlines = !1;
54
- const hasMissingStyle = typeof textBlock.style > "u", hasMissingMarkDefs = typeof textBlock.markDefs > "u", hasMissingChildren = typeof textBlock.children > "u", children = (textBlock.children || []).map((child) => {
53
+ const hasMissingMarkDefs = typeof textBlock.markDefs > "u", hasMissingChildren = typeof textBlock.children > "u", children = (textBlock.children || []).map((child) => {
55
54
  const {
56
55
  _type: childType,
57
56
  _key: childKey,
@@ -74,12 +73,12 @@ function toSlateBlock(block, {
74
73
  __inline: !0
75
74
  }, keyMap)) : child;
76
75
  });
77
- return !hasMissingStyle && !hasMissingMarkDefs && !hasMissingChildren && !hasInlines && Element$1.isElement(block) ? block : (hasMissingStyle && (rest.style = schemaTypes.styles[0].name), keepObjectEquality({
76
+ return !hasMissingMarkDefs && !hasMissingChildren && !hasInlines && Element$1.isElement(block) ? block : keepObjectEquality({
78
77
  _type,
79
78
  _key,
80
79
  ...rest,
81
80
  children
82
- }, keyMap));
81
+ }, keyMap);
83
82
  }
84
83
  return keepObjectEquality({
85
84
  _type,
@@ -139,8 +138,16 @@ function fromSlateBlock(block, textBlockType, keyMap = {}) {
139
138
  ...typeof blockValue == "object" ? blockValue : {}
140
139
  }, keyMap);
141
140
  }
142
- function isEqualToEmptyEditor(children, schemaTypes) {
143
- return children === void 0 || children && Array.isArray(children) && children.length === 0 || children && Array.isArray(children) && children.length === 1 && Element$1.isElement(children[0]) && children[0]._type === schemaTypes.block.name && "style" in children[0] && children[0].style === schemaTypes.styles[0].name && !("listItem" in children[0]) && Array.isArray(children[0].children) && children[0].children.length === 1 && Text.isText(children[0].children[0]) && children[0].children[0]._type === "span" && !children[0].children[0].marks?.join("") && children[0].children[0].text === "";
141
+ function isEqualToEmptyEditor(blocks, schemaTypes) {
142
+ if (blocks.length !== 1)
143
+ return !1;
144
+ const firstBlock = blocks.at(0);
145
+ if (!firstBlock)
146
+ return !0;
147
+ if (!Element$1.isElement(firstBlock) || firstBlock._type !== schemaTypes.block.name || "listItem" in firstBlock || !("style" in firstBlock) || firstBlock.style !== schemaTypes.styles.at(0)?.name || !Array.isArray(firstBlock.children) || firstBlock.children.length !== 1)
148
+ return !1;
149
+ const firstChild = firstBlock.children.at(0);
150
+ return !(!firstChild || !Text.isText(firstChild) || !("_type" in firstChild) || firstChild._type !== schemaTypes.span.name || firstChild.text !== "" || firstChild.marks?.join(""));
144
151
  }
145
152
  function getFocusBlock({
146
153
  editor
@@ -2233,7 +2240,7 @@ const debug$g = debugWithName("component:Editable"), PortableTextEditable = forw
2233
2240
  onFocus && onFocus(event_2), event_2.isDefaultPrevented() || (relayActor.send({
2234
2241
  type: "focused",
2235
2242
  event: event_2
2236
- }), !slateEditor.selection && isEqualToEmptyEditor(slateEditor.children, editorActor.getSnapshot().context.schema) && (Transforms.select(slateEditor, Editor.start(slateEditor, [])), slateEditor.onChange()));
2243
+ }), !slateEditor.selection && slateEditor.children.length === 1 && isEmptyTextBlock(editorActor.getSnapshot().context, slateEditor.value.at(0)) && (Transforms.select(slateEditor, Editor.start(slateEditor, [])), slateEditor.onChange()));
2237
2244
  }, $[91] = editorActor, $[92] = onFocus, $[93] = relayActor, $[94] = slateEditor, $[95] = t22) : t22 = $[95];
2238
2245
  const handleOnFocus = t22;
2239
2246
  let t23;
@@ -3073,7 +3080,7 @@ function createWithPortableTextMarkModel(editorActor) {
3073
3080
  const {
3074
3081
  apply: apply2,
3075
3082
  normalizeNode
3076
- } = editor, decorators = editorActor.getSnapshot().context.schema.decorators.map((t) => t.name);
3083
+ } = editor, decorators = editorActor.getSnapshot().context.schema.decorators.map((t) => t.name), defaultStyle = editorActor.getSnapshot().context.schema.styles.at(0)?.name;
3077
3084
  return editor.normalizeNode = (nodeEntry) => {
3078
3085
  const [node, path] = nodeEntry;
3079
3086
  if (editor.isTextBlock(node)) {
@@ -3101,6 +3108,16 @@ function createWithPortableTextMarkModel(editorActor) {
3101
3108
  });
3102
3109
  return;
3103
3110
  }
3111
+ if (defaultStyle && editor.isTextBlock(node) && typeof node.style > "u") {
3112
+ debug$e("Adding .style to block node"), withNormalizeNode(editor, () => {
3113
+ Transforms.setNodes(editor, {
3114
+ style: defaultStyle
3115
+ }, {
3116
+ at: path
3117
+ });
3118
+ });
3119
+ return;
3120
+ }
3104
3121
  if (editor.isTextSpan(node) && !Array.isArray(node.marks)) {
3105
3122
  debug$e("Adding .marks to span node"), withNormalizeNode(editor, () => {
3106
3123
  Transforms.setNodes(editor, {
@@ -4247,32 +4264,58 @@ const debug$c = debugWithName("behavior.operation.history.redo"), historyRedoOpe
4247
4264
  const blockIndex = operation.editor.blockIndexMap.get(operation.at[0]._key);
4248
4265
  if (blockIndex === void 0)
4249
4266
  throw new Error(`Unable to find block index for block at ${JSON.stringify(operation.at)}`);
4250
- const block = operation.editor.value.at(blockIndex);
4251
- if (!block)
4267
+ const slateBlock = operation.editor.children.at(blockIndex);
4268
+ if (!slateBlock)
4252
4269
  throw new Error(`Unable to find block at ${JSON.stringify(operation.at)}`);
4253
- const {
4254
- _type,
4255
- ...filteredProps
4256
- } = operation.props, updatedBlock = {
4257
- ...block,
4258
- ...filteredProps
4259
- }, parsedBlock = parseBlock({
4260
- context,
4261
- block: updatedBlock,
4262
- options: {
4263
- normalize: !1,
4264
- removeUnusedMarkDefs: !1,
4265
- validateFields: !0
4266
- }
4267
- });
4268
- if (!parsedBlock)
4269
- throw new Error(`Unable to update block at ${JSON.stringify(operation.at)}`);
4270
- const slateBlock = toSlateBlock(parsedBlock, {
4271
- schemaTypes: context.schema
4272
- });
4273
- Transforms.setNodes(operation.editor, slateBlock, {
4274
- at: [blockIndex]
4275
- });
4270
+ if (isTextBlock(context, slateBlock)) {
4271
+ const filteredProps = {};
4272
+ for (const key of Object.keys(operation.props))
4273
+ if (!(key === "_type" || key === "children")) {
4274
+ if (key === "style") {
4275
+ context.schema.styles.some((style) => style.name === operation.props[key]) && (filteredProps[key] = operation.props[key]);
4276
+ continue;
4277
+ }
4278
+ if (key === "listItem") {
4279
+ context.schema.lists.some((list) => list.name === operation.props[key]) && (filteredProps[key] = operation.props[key]);
4280
+ continue;
4281
+ }
4282
+ if (key === "level") {
4283
+ filteredProps[key] = operation.props[key];
4284
+ continue;
4285
+ }
4286
+ if (key === "markDefs") {
4287
+ const {
4288
+ markDefs
4289
+ } = parseMarkDefs({
4290
+ context,
4291
+ markDefs: operation.props[key],
4292
+ options: {
4293
+ validateFields: !0
4294
+ }
4295
+ });
4296
+ filteredProps[key] = markDefs;
4297
+ continue;
4298
+ }
4299
+ context.schema.block.fields?.some((field) => field.name === key) && (filteredProps[key] = operation.props[key]);
4300
+ }
4301
+ Transforms.setNodes(operation.editor, filteredProps, {
4302
+ at: [blockIndex]
4303
+ });
4304
+ } else {
4305
+ const schemaDefinition = context.schema.blockObjects.find((definition) => definition.name === slateBlock._type), filteredProps = {};
4306
+ for (const key of Object.keys(operation.props))
4307
+ if (key !== "_type") {
4308
+ if (key === "_key") {
4309
+ filteredProps[key] = operation.props[key];
4310
+ continue;
4311
+ }
4312
+ schemaDefinition?.fields.some((field) => field.name === key) && (filteredProps[key] = operation.props[key]);
4313
+ }
4314
+ const patches = Object.entries(filteredProps).map(([key, value]) => key === "_key" ? set(value, ["_key"]) : set(value, ["value", key])), updatedSlateBlock = applyAll(slateBlock, patches);
4315
+ Transforms.setNodes(operation.editor, updatedSlateBlock, {
4316
+ at: [blockIndex]
4317
+ });
4318
+ }
4276
4319
  }, blockUnsetOperationImplementation = ({
4277
4320
  context,
4278
4321
  operation
@@ -4280,50 +4323,22 @@ const debug$c = debugWithName("behavior.operation.history.redo"), historyRedoOpe
4280
4323
  const blockKey = operation.at[0]._key, blockIndex = operation.editor.blockIndexMap.get(blockKey);
4281
4324
  if (blockIndex === void 0)
4282
4325
  throw new Error(`Unable to find block index for block key ${blockKey}`);
4283
- const block = blockIndex !== void 0 ? operation.editor.value.at(blockIndex) : void 0;
4284
- if (!block)
4326
+ const slateBlock = blockIndex !== void 0 ? operation.editor.children.at(blockIndex) : void 0;
4327
+ if (!slateBlock)
4285
4328
  throw new Error(`Unable to find block at ${JSON.stringify(operation.at)}`);
4286
- if (isTextBlock(context, block)) {
4287
- const propsToRemove = operation.props.filter((prop) => prop !== "_type"), updatedTextBlock = parseBlock({
4288
- context,
4289
- block: omit(block, propsToRemove),
4290
- options: {
4291
- normalize: !1,
4292
- removeUnusedMarkDefs: !0,
4293
- validateFields: !0
4294
- }
4295
- });
4296
- if (!updatedTextBlock)
4297
- throw new Error(`Unable to update block at ${JSON.stringify(operation.at)}`);
4298
- const propsToSet = {};
4299
- for (const prop of propsToRemove)
4300
- prop in updatedTextBlock ? propsToSet[prop] = updatedTextBlock[prop] : propsToSet[prop] = void 0;
4301
- Transforms.setNodes(operation.editor, propsToSet, {
4329
+ if (isTextBlock(context, slateBlock)) {
4330
+ const propsToRemove = operation.props.filter((prop) => prop !== "_type" && prop !== "_key" && prop !== "children");
4331
+ Transforms.unsetNodes(operation.editor, propsToRemove, {
4332
+ at: [blockIndex]
4333
+ }), operation.props.includes("_key") && Transforms.setNodes(operation.editor, {
4334
+ _key: context.keyGenerator()
4335
+ }, {
4302
4336
  at: [blockIndex]
4303
4337
  });
4304
4338
  return;
4305
4339
  }
4306
- const updatedBlockObject = parseBlock({
4307
- context,
4308
- block: omit(block, operation.props.filter((prop) => prop !== "_type")),
4309
- options: {
4310
- normalize: !1,
4311
- removeUnusedMarkDefs: !0,
4312
- validateFields: !0
4313
- }
4314
- });
4315
- if (!updatedBlockObject)
4316
- throw new Error(`Unable to update block at ${JSON.stringify(operation.at)}`);
4317
- const {
4318
- _type,
4319
- _key,
4320
- ...props
4321
- } = updatedBlockObject;
4322
- Transforms.setNodes(operation.editor, {
4323
- _type,
4324
- _key,
4325
- value: props
4326
- }, {
4340
+ const patches = operation.props.flatMap((key) => key === "_type" ? [] : key === "_key" ? set(context.keyGenerator(), ["_key"]) : unset(["value", key])), updatedSlateBlock = applyAll(slateBlock, patches);
4341
+ Transforms.setNodes(operation.editor, updatedSlateBlock, {
4327
4342
  at: [blockIndex]
4328
4343
  });
4329
4344
  }, childSetOperationImplementation = ({
@@ -4696,7 +4711,7 @@ function insertBlock(options) {
4696
4711
  at: nextPath
4697
4712
  }), select === "start" ? Transforms.select(editor, Editor.start(editor, nextPath)) : select === "end" && Transforms.select(editor, Editor.end(editor, nextPath));
4698
4713
  } else {
4699
- if (endBlock && isEqualToEmptyEditor([endBlock], context.schema)) {
4714
+ if (isEmptyTextBlock(context, endBlock)) {
4700
4715
  Transforms.insertNodes(editor, [block], {
4701
4716
  at: endBlockPath,
4702
4717
  select: !1
@@ -4753,14 +4768,14 @@ function insertBlock(options) {
4753
4768
  select: select !== "none"
4754
4769
  });
4755
4770
  const atAfterInsert = atBeforeInsert?.unref() ?? editor.selection;
4756
- select === "none" && atAfterInsert && Transforms.select(editor, atAfterInsert), focusBlock && isEqualToEmptyEditor([focusBlock], context.schema) && Transforms.removeNodes(editor, {
4771
+ select === "none" && atAfterInsert && Transforms.select(editor, atAfterInsert), isEmptyTextBlock(context, focusBlock) && Transforms.removeNodes(editor, {
4757
4772
  at: focusBlockPath
4758
4773
  });
4759
4774
  return;
4760
4775
  }
4761
4776
  if (editor.isTextBlock(endBlock) && editor.isTextBlock(block)) {
4762
4777
  const selectionStartPoint = Range.start(at);
4763
- if (isEqualToEmptyEditor([endBlock], context.schema)) {
4778
+ if (isEmptyTextBlock(context, endBlock)) {
4764
4779
  Transforms.insertNodes(editor, [block], {
4765
4780
  at: endBlockPath,
4766
4781
  select: !1