@portabletext/editor 1.27.0 → 1.28.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 (34) hide show
  1. package/README.md +5 -5
  2. package/lib/_chunks-cjs/plugin.event-listener.cjs +302 -43
  3. package/lib/_chunks-cjs/plugin.event-listener.cjs.map +1 -1
  4. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs +88 -88
  5. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs.map +1 -1
  6. package/lib/_chunks-es/plugin.event-listener.js +302 -43
  7. package/lib/_chunks-es/plugin.event-listener.js.map +1 -1
  8. package/lib/_chunks-es/selector.is-at-the-start-of-block.js +88 -88
  9. package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -1
  10. package/lib/index.cjs +22 -21
  11. package/lib/index.cjs.map +1 -1
  12. package/lib/index.d.cts +257 -0
  13. package/lib/index.d.ts +257 -0
  14. package/lib/index.js +22 -21
  15. package/lib/index.js.map +1 -1
  16. package/lib/selectors/index.cjs +15 -3
  17. package/lib/selectors/index.cjs.map +1 -1
  18. package/lib/selectors/index.d.cts +18 -0
  19. package/lib/selectors/index.d.ts +18 -0
  20. package/lib/selectors/index.js +17 -4
  21. package/lib/selectors/index.js.map +1 -1
  22. package/package.json +3 -3
  23. package/src/behavior-actions/behavior.action.insert-break.ts +93 -83
  24. package/src/editor/PortableTextEditor.tsx +288 -1
  25. package/src/editor/components/DefaultObject.tsx +21 -0
  26. package/src/editor/components/Element.tsx +5 -5
  27. package/src/editor/components/Leaf.tsx +1 -6
  28. package/src/selectors/index.ts +4 -2
  29. package/src/selectors/selector.get-active-annotations.test.ts +122 -0
  30. package/src/selectors/selector.get-active-annotations.ts +30 -0
  31. package/src/selectors/selector.get-selection.ts +8 -0
  32. package/src/selectors/selector.get-value.ts +11 -0
  33. package/src/editor/nodes/DefaultAnnotation.tsx +0 -20
  34. package/src/editor/nodes/DefaultObject.tsx +0 -18
package/README.md CHANGED
@@ -36,13 +36,12 @@ yarn add @portabletext/editor
36
36
 
37
37
  ```
38
38
 
39
- Next, in your app or the component you're building, import `EditorProvider`, `EditorEventListener`, `PortableTextEditable`, `defineSchema`, and the types in the code below.
39
+ Next, in your app or the component you're building, import `EditorProvider`, `PortableTextEditable`, `defineSchema`, `EventListenerPlugin`, and the types in the code below.
40
40
 
41
41
  ```tsx
42
42
  // App.tsx
43
43
  import {
44
44
  defineSchema,
45
- EditorEventListener,
46
45
  EditorProvider,
47
46
  PortableTextEditable,
48
47
  } from '@portabletext/editor'
@@ -51,6 +50,7 @@ import type {
51
50
  RenderDecoratorFunction,
52
51
  RenderStyleFunction,
53
52
  } from '@portabletext/editor'
53
+ import {EventListenerPlugin} from '@portabletext/editor/plugins'
54
54
  ```
55
55
 
56
56
  ### Define the Schema
@@ -104,7 +104,6 @@ Add `useState` from React, then scaffold out a basic application component. For
104
104
  // app.tsx
105
105
  import {
106
106
  defineSchema,
107
- EditorEventListener,
108
107
  EditorProvider,
109
108
  PortableTextEditable,
110
109
  } from '@portabletext/editor'
@@ -113,6 +112,7 @@ import type {
113
112
  RenderDecoratorFunction,
114
113
  RenderStyleFunction,
115
114
  } from '@portabletext/editor'
115
+ import {EventListenerPlugin} from '@portabletext/editor/plugins'
116
116
  import {useState} from 'react'
117
117
 
118
118
  const schemaDefinition = defineSchema({
@@ -133,7 +133,7 @@ function App() {
133
133
  initialValue: value,
134
134
  }}
135
135
  >
136
- <EditorEventListener
136
+ <EventListenerPlugin
137
137
  on={(event) => {
138
138
  if (event.type === 'mutation') {
139
139
  setValue(event.value)
@@ -311,7 +311,7 @@ function App() {
311
311
  initialValue: value,
312
312
  }}
313
313
  >
314
- <EditorEventListener
314
+ <EventListenerPlugin
315
315
  on={(event) => {
316
316
  if (event.type === 'mutation') {
317
317
  setValue(event.value)
@@ -4848,51 +4848,54 @@ const blockSetBehaviorActionImplementation = ({
4848
4848
  return;
4849
4849
  const anchorBlockPath = editor.selection.anchor.path.slice(0, 1), focusBlockPath = editor.selection.focus.path.slice(0, 1), focusBlock = slate.Node.descendant(editor, focusBlockPath);
4850
4850
  if (editor.isTextBlock(focusBlock) && anchorBlockPath[0] === focusBlockPath[0]) {
4851
- slate.Editor.withoutNormalizing(editor, () => {
4852
- if (!editor.selection)
4853
- return;
4854
- slate.Transforms.splitNodes(editor, {
4855
- at: editor.selection
4856
- });
4857
- const [nextNode, nextNodePath] = slate.Editor.node(editor, slate.Path.next(focusBlockPath), {
4858
- depth: 1
4859
- });
4860
- if (slate.Transforms.setSelection(editor, {
4861
- anchor: {
4862
- path: [...nextNodePath, 0],
4863
- offset: 0
4864
- },
4865
- focus: {
4866
- path: [...nextNodePath, 0],
4867
- offset: 0
4868
- }
4869
- }), editor.isTextBlock(nextNode) && nextNode.markDefs && nextNode.markDefs.length > 0) {
4870
- const newMarkDefKeys = /* @__PURE__ */ new Map(), prevNodeSpans = Array.from(slate.Node.children(editor, focusBlockPath)).map((entry) => entry[0]).filter((node) => editor.isTextSpan(node)), children = slate.Node.children(editor, nextNodePath);
4871
- for (const [child, childPath] of children) {
4872
- if (!editor.isTextSpan(child))
4873
- continue;
4874
- const marks = child.marks ?? [];
4875
- for (const mark of marks)
4876
- schema2.decorators.some((decorator) => decorator.value === mark) || prevNodeSpans.some((prevNodeSpan) => prevNodeSpan.marks?.includes(mark)) && !newMarkDefKeys.has(mark) && newMarkDefKeys.set(mark, keyGenerator());
4877
- const newMarks = marks.map((mark) => newMarkDefKeys.get(mark) ?? mark);
4878
- isEqual__default.default(marks, newMarks) || slate.Transforms.setNodes(editor, {
4879
- marks: newMarks
4880
- }, {
4881
- at: childPath
4882
- });
4883
- }
4884
- const newMarkDefs = nextNode.markDefs.map((markDef) => ({
4885
- ...markDef,
4886
- _key: newMarkDefKeys.get(markDef._key) ?? markDef._key
4887
- }));
4888
- isEqual__default.default(nextNode.markDefs, newMarkDefs) || slate.Transforms.setNodes(editor, {
4889
- markDefs: newMarkDefs
4851
+ slate.Transforms.splitNodes(editor, {
4852
+ at: editor.selection
4853
+ });
4854
+ const [nextBlock, nextBlockPath] = slate.Editor.node(editor, slate.Path.next(focusBlockPath), {
4855
+ depth: 1
4856
+ }), nextChild = slate.Node.child(nextBlock, 0);
4857
+ if (!editor.isTextSpan(nextChild) && slate.Transforms.insertNodes(editor, {
4858
+ _key: context.keyGenerator(),
4859
+ _type: "span",
4860
+ text: "",
4861
+ marks: []
4862
+ }, {
4863
+ at: [nextBlockPath[0], 0]
4864
+ }), slate.Transforms.setSelection(editor, {
4865
+ anchor: {
4866
+ path: [...nextBlockPath, 0],
4867
+ offset: 0
4868
+ },
4869
+ focus: {
4870
+ path: [...nextBlockPath, 0],
4871
+ offset: 0
4872
+ }
4873
+ }), editor.isTextBlock(nextBlock) && nextBlock.markDefs && nextBlock.markDefs.length > 0) {
4874
+ const newMarkDefKeys = /* @__PURE__ */ new Map(), prevNodeSpans = Array.from(slate.Node.children(editor, focusBlockPath)).map((entry) => entry[0]).filter((node) => editor.isTextSpan(node)), children = slate.Node.children(editor, nextBlockPath);
4875
+ for (const [child, childPath] of children) {
4876
+ if (!editor.isTextSpan(child))
4877
+ continue;
4878
+ const marks = child.marks ?? [];
4879
+ for (const mark of marks)
4880
+ schema2.decorators.some((decorator) => decorator.value === mark) || prevNodeSpans.some((prevNodeSpan) => prevNodeSpan.marks?.includes(mark)) && !newMarkDefKeys.has(mark) && newMarkDefKeys.set(mark, keyGenerator());
4881
+ const newMarks = marks.map((mark) => newMarkDefKeys.get(mark) ?? mark);
4882
+ isEqual__default.default(marks, newMarks) || slate.Transforms.setNodes(editor, {
4883
+ marks: newMarks
4890
4884
  }, {
4891
- at: nextNodePath,
4892
- match: (node) => editor.isTextBlock(node)
4885
+ at: childPath
4893
4886
  });
4894
4887
  }
4895
- }), editor.onChange();
4888
+ const newMarkDefs = nextBlock.markDefs.map((markDef) => ({
4889
+ ...markDef,
4890
+ _key: newMarkDefKeys.get(markDef._key) ?? markDef._key
4891
+ }));
4892
+ isEqual__default.default(nextBlock.markDefs, newMarkDefs) || slate.Transforms.setNodes(editor, {
4893
+ markDefs: newMarkDefs
4894
+ }, {
4895
+ at: nextBlockPath,
4896
+ match: (node) => editor.isTextBlock(node)
4897
+ });
4898
+ }
4896
4899
  return;
4897
4900
  }
4898
4901
  slate.Transforms.splitNodes(editor, {
@@ -6346,30 +6349,224 @@ class PortableTextEditor extends React.Component {
6346
6349
  /* @__PURE__ */ jsxRuntime.jsx(EditorActorContext.Provider, { value: this.editor._internal.editorActor, children: /* @__PURE__ */ jsxRuntime.jsx(slateReact.Slate, { editor: this.editor._internal.slateEditor.instance, initialValue: this.editor._internal.slateEditor.initialValue, children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorContext.Provider, { value: this, children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorSelectionProvider, { editorActor: this.editor._internal.editorActor, children: this.props.children }) }) }) })
6347
6350
  ] });
6348
6351
  }
6349
- // Static API methods
6352
+ /**
6353
+ * @deprecated
6354
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6355
+ *
6356
+ * ```
6357
+ * import * as selectors from '@portabletext/editor/selectors'
6358
+ * const editor = useEditor()
6359
+ * const isActive = useEditorSelector(editor, selectors.getActiveAnnotations)
6360
+ * ```
6361
+ */
6350
6362
  static activeAnnotations = (editor) => editor && editor.editable ? editor.editable.activeAnnotations() : [];
6363
+ /**
6364
+ * @deprecated
6365
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6366
+ *
6367
+ * ```
6368
+ * import * as selectors from '@portabletext/editor/selectors'
6369
+ * const editor = useEditor()
6370
+ * const isActive = useEditorSelector(editor, selectors.isActiveAnnotation(...))
6371
+ * ```
6372
+ */
6351
6373
  static isAnnotationActive = (editor, annotationType) => editor && editor.editable ? editor.editable.isAnnotationActive(annotationType) : !1;
6374
+ /**
6375
+ * @deprecated
6376
+ * Use `editor.send(...)` instead
6377
+ *
6378
+ * ```
6379
+ * const editor = useEditor()
6380
+ * editor.send({
6381
+ * type: 'annotation.add',
6382
+ * annotation: {
6383
+ * name: '...',
6384
+ * value: {...},
6385
+ * }
6386
+ * })
6387
+ * ```
6388
+ */
6352
6389
  static addAnnotation = (editor, type, value) => editor.editable?.addAnnotation(type, value);
6390
+ /**
6391
+ * @deprecated
6392
+ * Use `editor.send(...)` instead
6393
+ *
6394
+ * ```
6395
+ * const editor = useEditor()
6396
+ * editor.send({
6397
+ * type: 'blur',
6398
+ * })
6399
+ * ```
6400
+ */
6353
6401
  static blur = (editor) => {
6354
6402
  debug("Host blurred"), editor.editable?.blur();
6355
6403
  };
6356
6404
  static delete = (editor, selection, options) => editor.editable?.delete(selection, options);
6357
6405
  static findDOMNode = (editor, element) => editor.editable?.findDOMNode(element);
6358
6406
  static findByPath = (editor, path) => editor.editable?.findByPath(path) || [];
6407
+ /**
6408
+ * @deprecated
6409
+ * Use `editor.send(...)` instead
6410
+ *
6411
+ * ```
6412
+ * const editor = useEditor()
6413
+ * editor.send({
6414
+ * type: 'focus',
6415
+ * })
6416
+ * ```
6417
+ */
6359
6418
  static focus = (editor) => {
6360
6419
  debug("Host requesting focus"), editor.editable?.focus();
6361
6420
  };
6421
+ /**
6422
+ * @deprecated
6423
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6424
+ *
6425
+ * ```
6426
+ * import * as selectors from '@portabletext/editor/selectors'
6427
+ * const editor = useEditor()
6428
+ * const focusBlock = useEditorSelector(editor, selectors.getFocusBlock)
6429
+ * ```
6430
+ */
6362
6431
  static focusBlock = (editor) => editor.editable?.focusBlock();
6432
+ /**
6433
+ * @deprecated
6434
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6435
+ *
6436
+ * ```
6437
+ * import * as selectors from '@portabletext/editor/selectors'
6438
+ * const editor = useEditor()
6439
+ * const focusChild = useEditorSelector(editor, selectors.getFocusChild)
6440
+ * ```
6441
+ */
6363
6442
  static focusChild = (editor) => editor.editable?.focusChild();
6443
+ /**
6444
+ * @deprecated
6445
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6446
+ *
6447
+ * ```
6448
+ * import * as selectors from '@portabletext/editor/selectors'
6449
+ * const editor = useEditor()
6450
+ * const selection = useEditorSelector(editor, selectors.getSelection)
6451
+ * ```
6452
+ */
6364
6453
  static getSelection = (editor) => editor.editable ? editor.editable.getSelection() : null;
6454
+ /**
6455
+ * @deprecated
6456
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6457
+ *
6458
+ * ```
6459
+ * import * as selectors from '@portabletext/editor/selectors'
6460
+ * const editor = useEditor()
6461
+ * const value = useEditorSelector(editor, selectors.getValue)
6462
+ * ```
6463
+ */
6365
6464
  static getValue = (editor) => editor.editable?.getValue();
6465
+ /**
6466
+ * @deprecated
6467
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6468
+ *
6469
+ * ```
6470
+ * import * as selectors from '@portabletext/editor/selectors'
6471
+ * const editor = useEditor()
6472
+ * const isActive = useEditorSelector(editor, selectors.isActiveStyle(...))
6473
+ * ```
6474
+ */
6366
6475
  static hasBlockStyle = (editor, blockStyle) => editor.editable?.hasBlockStyle(blockStyle);
6476
+ /**
6477
+ * @deprecated
6478
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6479
+ *
6480
+ * ```
6481
+ * import * as selectors from '@portabletext/editor/selectors'
6482
+ * const editor = useEditor()
6483
+ * const isActive = useEditorSelector(editor, selectors.isActiveListItem(...))
6484
+ * ```
6485
+ */
6367
6486
  static hasListStyle = (editor, listStyle) => editor.editable?.hasListStyle(listStyle);
6487
+ /**
6488
+ * @deprecated
6489
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6490
+ *
6491
+ * ```
6492
+ * import * as selectors from '@portabletext/editor/selectors'
6493
+ * const editor = useEditor()
6494
+ * const isSelectionCollapsed = useEditorSelector(editor, selectors.isSelectionCollapsed)
6495
+ * ```
6496
+ */
6368
6497
  static isCollapsedSelection = (editor) => editor.editable?.isCollapsedSelection();
6498
+ /**
6499
+ * @deprecated
6500
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6501
+ *
6502
+ * ```
6503
+ * import * as selectors from '@portabletext/editor/selectors'
6504
+ * const editor = useEditor()
6505
+ * const isSelectionExpanded = useEditorSelector(editor, selectors.isSelectionExpanded)
6506
+ * ```
6507
+ */
6369
6508
  static isExpandedSelection = (editor) => editor.editable?.isExpandedSelection();
6509
+ /**
6510
+ * @deprecated
6511
+ * Use built-in selectors or write your own: https://www.portabletext.org/reference/selectors/
6512
+ *
6513
+ * ```
6514
+ * import * as selectors from '@portabletext/editor/selectors'
6515
+ * const editor = useEditor()
6516
+ * const isActive = useEditorSelector(editor, selectors.isActiveDecorator(...))
6517
+ * ```
6518
+ */
6370
6519
  static isMarkActive = (editor, mark) => editor.editable?.isMarkActive(mark);
6520
+ /**
6521
+ * @deprecated
6522
+ * Use `editor.send(...)` instead
6523
+ *
6524
+ * ```
6525
+ * const editor = useEditor()
6526
+ * editor.send({
6527
+ * type: 'insert.span',
6528
+ * text: '...',
6529
+ * annotations: [{name: '...', value: {...}}],
6530
+ * decorators: ['...'],
6531
+ * })
6532
+ * editor.send({
6533
+ * type: 'insert.inline object',
6534
+ * inlineObject: {
6535
+ * name: '...',
6536
+ * value: {...},
6537
+ * },
6538
+ * })
6539
+ * ```
6540
+ */
6371
6541
  static insertChild = (editor, type, value) => (debug("Host inserting child"), editor.editable?.insertChild(type, value));
6542
+ /**
6543
+ * @deprecated
6544
+ * Use `editor.send(...)` instead
6545
+ *
6546
+ * ```
6547
+ * const editor = useEditor()
6548
+ * editor.send({
6549
+ * type: 'insert.block object',
6550
+ * blockObject: {
6551
+ * name: '...',
6552
+ * value: {...},
6553
+ * },
6554
+ * placement: 'auto' | 'after' | 'before',
6555
+ * })
6556
+ * ```
6557
+ */
6372
6558
  static insertBlock = (editor, type, value) => editor.editable?.insertBlock(type, value);
6559
+ /**
6560
+ * @deprecated
6561
+ * Use `editor.send(...)` instead
6562
+ *
6563
+ * ```
6564
+ * const editor = useEditor()
6565
+ * editor.send({
6566
+ * type: 'insert.break',
6567
+ * })
6568
+ * ```
6569
+ */
6373
6570
  static insertBreak = (editor) => editor.editable?.insertBreak();
6374
6571
  static isVoid = (editor, element) => editor.editable?.isVoid(element);
6375
6572
  static isObjectPath = (_editor, path) => {
@@ -6378,12 +6575,74 @@ class PortableTextEditor extends React.Component {
6378
6575
  return path.length > 1 && path[1] !== "children" || isChildObjectEditPath;
6379
6576
  };
6380
6577
  static marks = (editor) => editor.editable?.marks();
6578
+ /**
6579
+ * @deprecated
6580
+ * Use `editor.send(...)` instead
6581
+ *
6582
+ * ```
6583
+ * const editor = useEditor()
6584
+ * editor.send({
6585
+ * type: 'select',
6586
+ * selection: {...},
6587
+ * })
6588
+ * ```
6589
+ */
6381
6590
  static select = (editor, selection) => {
6382
6591
  debug("Host setting selection", selection), editor.editable?.select(selection);
6383
6592
  };
6593
+ /**
6594
+ * @deprecated
6595
+ * Use `editor.send(...)` instead
6596
+ *
6597
+ * ```
6598
+ * const editor = useEditor()
6599
+ * editor.send({
6600
+ * type: 'annotation.remove',
6601
+ * annotation: {
6602
+ * name: '...',
6603
+ * },
6604
+ * })
6605
+ * ```
6606
+ */
6384
6607
  static removeAnnotation = (editor, type) => editor.editable?.removeAnnotation(type);
6608
+ /**
6609
+ * @deprecated
6610
+ * Use `editor.send(...)` instead
6611
+ *
6612
+ * ```
6613
+ * const editor = useEditor()
6614
+ * editor.send({
6615
+ * type: 'style.toggle',
6616
+ * style: '...',
6617
+ * })
6618
+ * ```
6619
+ */
6385
6620
  static toggleBlockStyle = (editor, blockStyle) => (debug("Host is toggling block style"), editor.editable?.toggleBlockStyle(blockStyle));
6621
+ /**
6622
+ * @deprecated
6623
+ * Use `editor.send(...)` instead
6624
+ *
6625
+ * ```
6626
+ * const editor = useEditor()
6627
+ * editor.send({
6628
+ * type: 'list item.toggle',
6629
+ * listItem: '...',
6630
+ * })
6631
+ * ```
6632
+ */
6386
6633
  static toggleList = (editor, listStyle) => editor.editable?.toggleList(listStyle);
6634
+ /**
6635
+ * @deprecated
6636
+ * Use `editor.send(...)` instead
6637
+ *
6638
+ * ```
6639
+ * const editor = useEditor()
6640
+ * editor.send({
6641
+ * type: 'decorator.toggle',
6642
+ * decorator: '...',
6643
+ * })
6644
+ * ```
6645
+ */
6387
6646
  static toggleMark = (editor, mark) => {
6388
6647
  debug("Host toggling mark", mark), editor.editable?.toggleMark(mark);
6389
6648
  };