@handlewithcare/react-prosemirror 2.9.0-tiptap.24 → 3.0.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 (143) hide show
  1. package/README.md +140 -75
  2. package/dist/cjs/StaticEditorView.js +0 -3
  3. package/dist/cjs/components/ChildNodeViews.js +4 -4
  4. package/dist/cjs/components/NativeWidgetView.js +2 -2
  5. package/dist/cjs/components/OutputSpec.js +10 -3
  6. package/dist/cjs/components/ProseMirror.js +11 -17
  7. package/dist/cjs/components/SeparatorHackView.js +2 -2
  8. package/dist/cjs/components/TrailingHackView.js +2 -2
  9. package/dist/cjs/components/WidgetView.js +2 -2
  10. package/dist/cjs/components/marks/DefaultMarkView.js +2 -1
  11. package/dist/cjs/components/marks/MarkView.js +2 -2
  12. package/dist/cjs/components/marks/{CustomMarkView.js → MarkViewConstructorView.js} +16 -7
  13. package/dist/cjs/components/marks/ReactMarkView.js +26 -6
  14. package/dist/cjs/components/nodes/DefaultNodeView.js +3 -2
  15. package/dist/cjs/components/nodes/DocNodeView.js +7 -6
  16. package/dist/cjs/components/nodes/NodeView.js +17 -6
  17. package/dist/cjs/components/nodes/{CustomNodeView.js → NodeViewConstructorView.js} +22 -9
  18. package/dist/cjs/components/nodes/ReactNodeView.js +59 -17
  19. package/dist/cjs/contexts/{ChildDescriptorsContext.js → ChildDescriptionsContext.js} +3 -3
  20. package/dist/cjs/hooks/useEditor.js +0 -4
  21. package/dist/cjs/hooks/useEditorEventCallback.js +1 -1
  22. package/dist/cjs/hooks/useMarkViewDescription.js +24 -21
  23. package/dist/cjs/hooks/useNodePos.js +18 -0
  24. package/dist/cjs/hooks/{useNodeViewDescriptor.js → useNodeViewDescription.js} +30 -25
  25. package/dist/cjs/index.js +8 -0
  26. package/dist/cjs/refs.js +28 -0
  27. package/dist/cjs/viewdesc.js +18 -5
  28. package/dist/esm/StaticEditorView.js +0 -3
  29. package/dist/esm/components/ChildNodeViews.js +4 -4
  30. package/dist/esm/components/NativeWidgetView.js +2 -2
  31. package/dist/esm/components/OutputSpec.js +10 -3
  32. package/dist/esm/components/ProseMirror.js +11 -17
  33. package/dist/esm/components/SeparatorHackView.js +2 -2
  34. package/dist/esm/components/TrailingHackView.js +2 -2
  35. package/dist/esm/components/WidgetView.js +2 -2
  36. package/dist/esm/components/marks/DefaultMarkView.js +2 -1
  37. package/dist/esm/components/marks/MarkView.js +2 -2
  38. package/dist/esm/components/marks/{CustomMarkView.js → MarkViewConstructorView.js} +14 -5
  39. package/dist/esm/components/marks/ReactMarkView.js +26 -6
  40. package/dist/esm/components/nodes/DefaultNodeView.js +3 -2
  41. package/dist/esm/components/nodes/DocNodeView.js +8 -7
  42. package/dist/esm/components/nodes/NodeView.js +7 -4
  43. package/dist/esm/components/nodes/{CustomNodeView.js → NodeViewConstructorView.js} +20 -7
  44. package/dist/esm/components/nodes/ReactNodeView.js +59 -17
  45. package/dist/esm/contexts/{ChildDescriptorsContext.js → ChildDescriptionsContext.js} +1 -1
  46. package/dist/esm/hooks/useEditor.js +0 -4
  47. package/dist/esm/hooks/useEditorEffect.js +0 -4
  48. package/dist/esm/hooks/useEditorEventCallback.js +6 -4
  49. package/dist/esm/hooks/useMarkViewDescription.js +26 -23
  50. package/dist/esm/hooks/useNodePos.js +15 -0
  51. package/dist/esm/hooks/{useNodeViewDescriptor.js → useNodeViewDescription.js} +29 -24
  52. package/dist/esm/index.js +2 -0
  53. package/dist/esm/refs.js +18 -0
  54. package/dist/esm/viewdesc.js +13 -6
  55. package/dist/tsconfig.tsbuildinfo +1 -1
  56. package/dist/types/AbstractEditorView.d.ts +0 -1
  57. package/dist/types/StaticEditorView.d.ts +0 -1
  58. package/dist/types/components/OutputSpec.d.ts +2 -1
  59. package/dist/types/components/ProseMirror.d.ts +3 -11
  60. package/dist/types/components/ProseMirrorDoc.d.ts +2 -2
  61. package/dist/types/components/marks/DefaultMarkView.d.ts +1 -1
  62. package/dist/types/components/marks/MarkViewComponentProps.d.ts +4 -3
  63. package/dist/types/components/marks/{CustomMarkView.d.ts → MarkViewConstructorView.d.ts} +1 -1
  64. package/dist/types/components/nodes/DefaultNodeView.d.ts +1 -1
  65. package/dist/types/components/nodes/DocNodeView.d.ts +2 -2
  66. package/dist/types/components/nodes/NodeView.d.ts +1 -0
  67. package/dist/types/components/nodes/NodeViewComponentProps.d.ts +4 -3
  68. package/dist/types/components/{CustomNodeView.d.ts → nodes/NodeViewConstructorView.d.ts} +1 -1
  69. package/dist/types/constants.d.ts +1 -1
  70. package/dist/types/contexts/{ChildDescriptorsContext.d.ts → ChildDescriptionsContext.d.ts} +1 -1
  71. package/dist/types/hooks/useEditorEffect.d.ts +0 -4
  72. package/dist/types/hooks/useEditorEventCallback.d.ts +6 -4
  73. package/dist/types/hooks/useMarkViewDescription.d.ts +6 -9
  74. package/dist/types/hooks/useNodePos.d.ts +9 -0
  75. package/dist/types/hooks/{useNodeViewDescriptor.d.ts → useNodeViewDescription.d.ts} +5 -9
  76. package/dist/types/index.d.ts +2 -0
  77. package/dist/types/props.d.ts +26 -26
  78. package/dist/types/refs.d.ts +2 -0
  79. package/dist/types/viewdesc.d.ts +4 -0
  80. package/package.json +12 -20
  81. package/dist/cjs/components/CustomNodeView.js +0 -132
  82. package/dist/cjs/components/DefaultNodeView.js +0 -67
  83. package/dist/cjs/components/DocNodeView.js +0 -96
  84. package/dist/cjs/components/MarkView.js +0 -119
  85. package/dist/cjs/components/NodeView.js +0 -86
  86. package/dist/cjs/components/NodeViewComponentProps.js +0 -4
  87. package/dist/cjs/components/ReactNodeView.js +0 -174
  88. package/dist/cjs/components/marks/OldMarkView.js +0 -120
  89. package/dist/cjs/tiptap/ReactProseMirrorNodeView.js +0 -26
  90. package/dist/cjs/tiptap/TiptapEditor.js +0 -34
  91. package/dist/cjs/tiptap/TiptapEditorContent.js +0 -142
  92. package/dist/cjs/tiptap/TiptapEditorView.js +0 -118
  93. package/dist/cjs/tiptap/TiptapNodeView.js +0 -26
  94. package/dist/cjs/tiptap/contexts/TiptapEditorContext.js +0 -12
  95. package/dist/cjs/tiptap/extensions/ReactProseMirror.js +0 -40
  96. package/dist/cjs/tiptap/hooks/useIsInReactProseMirror.js +0 -15
  97. package/dist/cjs/tiptap/hooks/useTiptapEditor.js +0 -43
  98. package/dist/cjs/tiptap/hooks/useTiptapEditorEffect.js +0 -35
  99. package/dist/cjs/tiptap/hooks/useTiptapEditorEventCallback.js +0 -35
  100. package/dist/cjs/tiptap/index.js +0 -48
  101. package/dist/cjs/tiptap/tiptapNodeView.js +0 -237
  102. package/dist/esm/components/CustomNodeView.js +0 -81
  103. package/dist/esm/components/DefaultNodeView.js +0 -16
  104. package/dist/esm/components/DocNodeView.js +0 -45
  105. package/dist/esm/components/MarkView.js +0 -68
  106. package/dist/esm/components/NodeView.js +0 -35
  107. package/dist/esm/components/NodeViewComponentProps.js +0 -1
  108. package/dist/esm/components/ReactNodeView.js +0 -123
  109. package/dist/esm/components/marks/OldMarkView.js +0 -69
  110. package/dist/esm/tiptap/ReactProseMirrorNodeView.js +0 -22
  111. package/dist/esm/tiptap/TiptapEditor.js +0 -24
  112. package/dist/esm/tiptap/TiptapEditorContent.js +0 -91
  113. package/dist/esm/tiptap/TiptapEditorView.js +0 -69
  114. package/dist/esm/tiptap/TiptapNodeView.js +0 -22
  115. package/dist/esm/tiptap/contexts/TiptapEditorContext.js +0 -2
  116. package/dist/esm/tiptap/extensions/ReactProseMirror.js +0 -30
  117. package/dist/esm/tiptap/hooks/useIsInReactProseMirror.js +0 -5
  118. package/dist/esm/tiptap/hooks/useTiptapEditor.js +0 -33
  119. package/dist/esm/tiptap/hooks/useTiptapEditorEffect.js +0 -42
  120. package/dist/esm/tiptap/hooks/useTiptapEditorEventCallback.js +0 -35
  121. package/dist/esm/tiptap/index.js +0 -9
  122. package/dist/esm/tiptap/tiptapNodeView.js +0 -205
  123. package/dist/types/components/DefaultNodeView.d.ts +0 -3
  124. package/dist/types/components/DocNodeView.d.ts +0 -12
  125. package/dist/types/components/MarkView.d.ts +0 -9
  126. package/dist/types/components/NodeView.d.ts +0 -11
  127. package/dist/types/components/NodeViewComponentProps.d.ts +0 -12
  128. package/dist/types/components/ReactNodeView.d.ts +0 -13
  129. package/dist/types/components/marks/OldMarkView.d.ts +0 -10
  130. package/dist/types/components/nodes/CustomNodeView.d.ts +0 -12
  131. package/dist/types/tiptap/ReactProseMirrorNodeView.d.ts +0 -15
  132. package/dist/types/tiptap/TiptapEditor.d.ts +0 -6
  133. package/dist/types/tiptap/TiptapEditorContent.d.ts +0 -19
  134. package/dist/types/tiptap/TiptapEditorView.d.ts +0 -16
  135. package/dist/types/tiptap/TiptapNodeView.d.ts +0 -15
  136. package/dist/types/tiptap/contexts/TiptapEditorContext.d.ts +0 -6
  137. package/dist/types/tiptap/extensions/ReactProseMirror.d.ts +0 -9
  138. package/dist/types/tiptap/hooks/useIsInReactProseMirror.d.ts +0 -1
  139. package/dist/types/tiptap/hooks/useTiptapEditor.d.ts +0 -4
  140. package/dist/types/tiptap/hooks/useTiptapEditorEffect.d.ts +0 -21
  141. package/dist/types/tiptap/hooks/useTiptapEditorEventCallback.d.ts +0 -13
  142. package/dist/types/tiptap/index.d.ts +0 -9
  143. package/dist/types/tiptap/tiptapNodeView.d.ts +0 -50
package/README.md CHANGED
@@ -16,7 +16,7 @@ releases, and are not guaranteed to work with other versions of
16
16
  prosemirror-view. Ensure that your version of prosemirror-view matches the
17
17
  version in React ProseMirror's peer dependencies!
18
18
 
19
- _Note_: React ProseMirror does not require a specific verson of React, React
19
+ _Note_: React ProseMirror does not require a specific version of React, React
20
20
  DOM, or React Reconciler. **However**, you must ensure that your React
21
21
  Reconciler version matches your React/React DOM versions.
22
22
 
@@ -85,6 +85,7 @@ import "prosemirror-view/style/prosemirror.css";
85
85
  - [`useEditorEventListener`](#useeditoreventlistener-1)
86
86
  - [`useEditorEffect`](#useeditoreffect-1)
87
87
  - [`NodeViewComponentProps`](#nodeviewcomponentprops)
88
+ - [`useNodePos`](#usenodepos)
88
89
  - [`useStopEvent`](#usestopevent)
89
90
  - [`useIgnoreMutation`](#useignoremutation)
90
91
  - [`useSelectNode`](#useselectnode)
@@ -115,7 +116,7 @@ differences between the rendering approaches taken by each framework. The first
115
116
  phase of a React update should be free of side effects, which requires that
116
117
  updates to the ProseMirror View happen in the second phase. This means that
117
118
  during the first phase, React components actually have access to a different
118
- (newer) version of the EditorState than the one in the Editorview. As a result
119
+ (newer) version of the EditorState than the one in the EditorView. As a result
119
120
  code that dispatches transactions may dispatch transactions based on incorrect
120
121
  state. Code that invokes methods of the ProseMirror view may make bad
121
122
  assumptions about its state that cause incorrect behavior or errors.
@@ -212,7 +213,7 @@ export function ProseMirrorEditor() {
212
213
 
213
214
  The `EditorView` interface exposes several useful methods that provide access to
214
215
  the DOM or data derived from its layout, such as `coordsFromPos`. These methods
215
- should only be accessed outside of the render cycle, to ensure that the DOM has
216
+ should only be accessed outside the render cycle, to ensure that the DOM has
216
217
  been updated to match the latest state. React ProseMirror provides two hooks to
217
218
  enable this access pattern: `useEditorEffect` and `useEditorEventCallback`. Both
218
219
  of these hooks can be used from any children of the ProseMirror component.
@@ -290,14 +291,14 @@ export function ProseMirrorEditor() {
290
291
  #### `useEditorEventCallback`
291
292
 
292
293
  It's also often necessary to dispatch transactions or execute side effects in
293
- response to user actions, like mouse clicks and keyboard events. Note: if you
294
- need to respond to keyboard events from _within_ the `contenteditable` element,
295
- you should instead use [`useEditorEventListener`](#useEditorEventListener).
294
+ response to user actions, like mouse clicks and keyboard events.
296
295
 
297
- However, if you need to dispatch a transaction in response to some event
298
- dispatched from a React component, like a tooltip or a toolbar button, you can
299
- use `useEditorEventCallback` to create a stable function reference that can
300
- safely access the latest value of the `EditorView`.
296
+ You can use `useEditorEventCallback` to create a stable function reference that
297
+ can safely access the latest value of the `EditorView`.
298
+
299
+ _Note_: if you need to respond to keyboard events from _within_ the
300
+ `contenteditable` element, you should instead use
301
+ [`useEditorEventListener`](#useEditorEventListener).
301
302
 
302
303
  ```tsx
303
304
  // BoldButton.tsx
@@ -365,40 +366,38 @@ semantics for ProseMirror's `handleDOMEvents` prop:
365
366
  want to prevent the default contenteditable behavior, you must call
366
367
  `event.preventDefault`.
367
368
 
368
- You can use this hook to implement custom behavior in your NodeViews:
369
+ You can use this hook to implement custom behavior in your node views:
369
370
 
370
371
  ```tsx
371
- import { forwardRef, Ref } from "react";
372
372
  import {
373
373
  useEditorEventListener,
374
374
  NodeViewComponentProps,
375
+ useMergedDOMRefs,
375
376
  } from "@handlewithcare/react-prosemirror";
376
377
 
377
- const Paragraph = forwardRef<HTMLParagraphElement, NodeViewComponentProps>(
378
- function Paragraph({ children, nodeProps, ...props }, ref) {
379
- useEditorEventListener("keydown", (view, event) => {
380
- const { pos, node } = nodeProps;
381
-
382
- if (event.code !== "ArrowDown") {
383
- return false;
384
- }
385
- const nodeEnd = pos + node.nodeSize;
386
- const { selection } = view.state;
387
- if (selection.anchor < pos || selection.anchor > nodeEnd) {
388
- return false;
389
- }
390
- event.preventDefault();
391
- alert("No down keys allowed!");
392
- return true;
393
- });
394
-
395
- return (
396
- <p {...props} ref={ref}>
397
- {children}
398
- </p>
399
- );
400
- }
401
- );
378
+ function Paragraph({ children, nodeProps, ref, ...props }) {
379
+ useEditorEventListener("keydown", (view, event) => {
380
+ const { pos, node } = nodeProps;
381
+
382
+ if (event.code !== "ArrowDown") {
383
+ return false;
384
+ }
385
+ const nodeEnd = pos + node.nodeSize;
386
+ const { selection } = view.state;
387
+ if (selection.anchor < pos || selection.anchor > nodeEnd) {
388
+ return false;
389
+ }
390
+ event.preventDefault();
391
+ alert("No down keys allowed!");
392
+ return true;
393
+ });
394
+
395
+ return (
396
+ <p {...props} ref={useMergedDOMRefs(ref, nodeProps.contentDOMRef)}>
397
+ {children}
398
+ </p>
399
+ );
400
+ }
402
401
  ```
403
402
 
404
403
  ### Building node views with React
@@ -410,43 +409,61 @@ special other than fulfill the
410
409
  [`NodeViewComponentProps`](#nodeviewcomponentprops) interface.
411
410
 
412
411
  ```tsx
413
- import { forwardRef, Ref } from "react";
414
412
  import {
415
413
  ProseMirror,
416
414
  ProseMirrorDoc,
417
415
  useEditorEventCallback,
418
416
  NodeViewComponentProps,
417
+ useMergedDOMRefs,
419
418
  reactKeys,
420
419
  } from "@handlewithcare/react-prosemirror";
421
420
  import { EditorState } from "prosemirror-state";
422
421
  import { schema } from "prosemirror-schema-basic";
423
422
 
424
423
  // Paragraph is more or less a normal React component, taking and rendering
425
- // its children. All node view components _must_ forward refs to their top-level
426
- // DOM elements. All node view components _should_ spread all of the props that they
427
- // receive onto their top-level DOM elements; this is required for node Decorations
428
- // that apply attributes rather than wrapping nodes in an additional element.
429
- const Paragraph = forwardRef<HTMLParagraphElement, NodeViewComponentProps>(
430
- function Paragraph({ children, nodeProps, ...props }, ref) {
431
- const onClick = useEditorEventCallback((view) =>
432
- view.dispatch(view.state.tr.deleteSelection())
433
- );
434
-
435
- return (
436
- <p {...props} ref={ref} onClick={onClick}>
437
- {children}
438
- </p>
439
- );
440
- }
441
- );
424
+ // its children. Some guidelines:
425
+ //
426
+ // - All node view components _must_ pass refs to their top-level
427
+ // DOM elements.
428
+ // - All node view components that render children _must_ pass nodeProps.contentDOMRef
429
+ // to the parent element of `children`. If this is also the top-level DOM
430
+ // element, use `useMergedDOMRefs` to apply both refs
431
+ // - All node view components _should_ spread all of the props that they
432
+ // receive onto their top-level DOM elements; this is required for node Decorations
433
+ // that apply attributes rather than wrapping nodes in an additional element.
434
+ //
435
+ // Note: we are accessing `ref` as a prop here, which has been available since React 19.
436
+ // If you are using React <=18, you will need to use forwardRef to access `ref`.
437
+ function Paragraph({ children, nodeProps, ref, ...props }) {
438
+ const onClick = useEditorEventCallback((view) =>
439
+ view.dispatch(view.state.tr.deleteSelection())
440
+ );
441
+
442
+ return (
443
+ <p
444
+ {...props}
445
+ ref={useMergedDOMRefs(ref, nodeProps.contentDOMRef)}
446
+ onClick={onClick}
447
+ >
448
+ {children}
449
+ </p>
450
+ );
451
+ }
452
+
453
+ // **IMPORTANT**: Define nodeViewComponents _outside_ of your editor
454
+ // component. It should be a stable reference.
455
+ //
456
+ // If you need to define it within a React component for some reason,
457
+ // ensure that it is properly memoized with `useMemo` or the React Compiler.
458
+ const nodeViewComponents = {
459
+ paragraph: Paragraph,
460
+ };
442
461
 
443
462
  function ProseMirrorEditor() {
444
463
  return (
445
464
  <ProseMirror
446
465
  defaultState={EditorState.create({ schema, plugins: [reactKeys()] })}
447
- nodeViews={{
448
- paragraph: Paragraph,
449
- }}
466
+ nodeViewComponents={nodeViewComponents}
450
467
  >
451
468
  <ProseMirrorDoc />
452
469
  </ProseMirror>
@@ -454,6 +471,29 @@ function ProseMirrorEditor() {
454
471
  }
455
472
  ```
456
473
 
474
+ If your node view component is more complex, and the top level DOM element does
475
+ not directly render `children`, use `ref` and `nodeProps.contentDOMRef`
476
+ separately:
477
+
478
+ ```tsx
479
+ function FancyParagraph({ children, nodeProps, ref, ...props }) {
480
+ const onClick = useEditorEventCallback((view) =>
481
+ view.dispatch(view.state.tr.deleteSelection())
482
+ );
483
+
484
+ return (
485
+ <div
486
+ {...props}
487
+ className={cx(props.className, "fancy-paragraph")}
488
+ ref={ref}
489
+ onClick={onClick}
490
+ >
491
+ <p ref={nodeProps.contentDOMRef}>{children}</p>
492
+ </div>
493
+ );
494
+ }
495
+ ```
496
+
457
497
  ## API
458
498
 
459
499
  ### `ProseMirror`
@@ -463,20 +503,16 @@ type ProseMirror = (
463
503
  props: DirectEditorProps &
464
504
  ({ defaultState: EditorState } | { state: EditorState }) & {
465
505
  children: ReactNode;
466
- nodeViews?: {
467
- [nodeType: string]: ForwardRefExoticComponent<
468
- NodeViewComponentProps & RefAttributes<any>
469
- >;
506
+ nodeViewComponents?: {
507
+ [nodeType: string]: ComponentType<NodeViewComponentProps>;
470
508
  };
471
- customNodeViews?: {
509
+ nodeViews?: {
472
510
  [nodeType: string]: NodeViewConstructor;
473
511
  };
474
- markViews?: {
475
- [markType: string]: ForwardRefExoticComponent<
476
- MarkViewComponentProps & RefAttributes<any>
477
- >;
512
+ markViewComponents?: {
513
+ [markType: string]: ComponentType<MarkViewComponentProps>;
478
514
  };
479
- customMarkViews?: {
515
+ markViews?: {
480
516
  [markType: string]: MarkViewConstructor;
481
517
  };
482
518
  }
@@ -516,7 +552,7 @@ Renders the actual editable ProseMirror document.
516
552
 
517
553
  This **must** be passed as a child to the `ProseMirror` component. It may be
518
554
  wrapped in any other components, and other children may be passed before or
519
- after
555
+ after.
520
556
 
521
557
  Example usage:
522
558
 
@@ -535,7 +571,7 @@ export function ProseMirrorEditor() {
535
571
  >
536
572
  <ToolBar />
537
573
  <SomeWrapper>
538
- <ProseMirrorDoc as={<article />} />
574
+ <ProseMirrorDoc as="article" />
539
575
  </SomeWrapper>
540
576
  <Footnotes />
541
577
  </ProseMirror>
@@ -639,7 +675,9 @@ interface NodeViewComponentProps extends AllHTMLAttributes<HTMLElement> = {
639
675
  innerDecorations: DecorationSource;
640
676
  node: Node;
641
677
  getPos: () => number;
678
+ contentDOMRef: Exclude<Ref<any>, null>;
642
679
  };
680
+ ref: LegacyRef<any>;
643
681
  };
644
682
  ```
645
683
 
@@ -650,10 +688,36 @@ by the default ProseMirror EditorView implementation.
650
688
 
651
689
  Node view components may also be passed _any_ other valid HTML attribute props,
652
690
  and should pass them through to their top-level DOM element.
691
+
692
+ In addition to accepting these props, all node view components _must_ pass their
693
+ ref to their top-level DOM element. All node view components that render their
694
+ `children` _must_ pass `nodeProps.contentDOMRef` to the parent element of
695
+ `children`.
696
+
653
697
  [See the above example](#building-node-views-with-react) for more details.
654
698
 
655
- In addition to accepting these props, all node view components _must_ forward
656
- their ref to their top-level DOM element.
699
+ ### `useNodePos`
700
+
701
+ ```ts
702
+ type useNodePos = () => number;
703
+ ```
704
+
705
+ Like prosemirror-view’s `NodeViewConstructor` API, React ProseMirror passes a
706
+ `getPos` function to all node view components. This function will return the
707
+ current position of the node in the document.
708
+
709
+ `getPos` is guaranteed to always return the correct value for the current node,
710
+ but it will not subscribe a node view component to updates to its position. This
711
+ means that _it is only safe to use `getPos` in a callback or effect_. It is
712
+ _not_ safe to use in a render function, because changes to the node's position
713
+ will not trigger a re-render of the node view component.
714
+
715
+ It’s best to avoid relying on the node’s position in the render function,
716
+ because that will require that your node view component re-render on every
717
+ update to the document. But if you have an infrequently used node, or small
718
+ enough documents that you don't have to worry about this, you can use the
719
+ `useNodePos` function to get an up-to-date node position after every document
720
+ update.
657
721
 
658
722
  ### `useStopEvent`
659
723
 
@@ -715,10 +779,10 @@ components.
715
779
 
716
780
  A [command](https://prosemirror.net/docs/ref/#state.Command) creator that can be
717
781
  used to reorder adjacent nodes in a document. The command creator takes two
718
- argumnts:
782
+ arguments:
719
783
 
720
- - `pos` - The `start` position of the parent of the nodes being reordered
721
- - `order` - The new order for the nodes, expressed as an array of indices. For
784
+ - `pos` The `start` position of the parent of the nodes being reordered
785
+ - `order` The new order for the nodes, expressed as an array of indices. For
722
786
  example, to swap the first two nodes in a set of three, `order` would be set
723
787
  to `[1, 0, 2]`. To move the first node to the end, and keep the other two in
724
788
  relative order, set `order` to `[1, 2, 0]`.
@@ -746,6 +810,7 @@ component remounts.
746
810
  ## Migrations
747
811
 
748
812
  - [Migrating from v1 to v2](migration-guides/v2.md)
813
+ - [Migrating from v2 to v3](migration-guides/v3.md)
749
814
 
750
815
  ## Looking for someone to collaborate with?
751
816
 
@@ -27,9 +27,6 @@ let StaticEditorView = class StaticEditorView {
27
27
  get state() {
28
28
  return this.props.state;
29
29
  }
30
- get isDestroyed() {
31
- return false;
32
- }
33
30
  setProps(props) {
34
31
  return this.update({
35
32
  ...this.props,
@@ -17,11 +17,12 @@ _export(exports, {
17
17
  }
18
18
  });
19
19
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
20
- const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
20
+ const _ChildDescriptionsContext = require("../contexts/ChildDescriptionsContext.js");
21
21
  const _EditorContext = require("../contexts/EditorContext.js");
22
22
  const _iterDeco = require("../decorations/iterDeco.js");
23
23
  const _useReactKeys = require("../hooks/useReactKeys.js");
24
24
  const _props = require("../props.js");
25
+ const _viewdesc = require("../viewdesc.js");
25
26
  const _NativeWidgetView = require("./NativeWidgetView.js");
26
27
  const _SeparatorHackView = require("./SeparatorHackView.js");
27
28
  const _TextNodeView = require("./TextNodeView.js");
@@ -82,8 +83,7 @@ function wrapInDeco(reactNode, deco) {
82
83
  return /*#__PURE__*/ (0, _react.cloneElement)(reactNode, (0, _props.mergeReactProps)(reactNode.props, props));
83
84
  }
84
85
  function areChildrenEqual(a, b) {
85
- return a.type === b.type && a.marks.every((mark)=>mark.isInSet(b.marks)) && b.marks.every((mark)=>mark.isInSet(a.marks)) && a.key === b.key && (a.type === "node" ? a.outerDeco?.length === b.outerDeco?.length && a.outerDeco?.every((prevDeco)=>b.outerDeco?.some((nextDeco)=>prevDeco.from === nextDeco.from && prevDeco.to && nextDeco.to && // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
- prevDeco.type.eq(nextDeco.type))) && a.innerDeco.eq(b.innerDeco) : true) && a.node === b.node && a.widget === b.widget;
86
+ return a.type === b.type && a.marks.every((mark)=>mark.isInSet(b.marks)) && b.marks.every((mark)=>mark.isInSet(a.marks)) && a.key === b.key && (a.type !== "node" || b.type !== "node" || a.node.eq(b.node) && (0, _viewdesc.sameOuterDeco)(a.outerDeco, b.outerDeco) && a.innerDeco.eq(b.innerDeco)) && a.widget === b.widget;
87
87
  }
88
88
  const ChildView = /*#__PURE__*/ (0, _react.memo)(function ChildView(param) {
89
89
  let { child, getInnerPos } = param;
@@ -106,7 +106,7 @@ const ChildView = /*#__PURE__*/ (0, _react.memo)(function ChildView(param) {
106
106
  }) : child.type === "hack" ? /*#__PURE__*/ _react.default.createElement(child.component, {
107
107
  key: child.key,
108
108
  getPos: getPos
109
- }) : child.node.isText ? /*#__PURE__*/ _react.default.createElement(_ChildDescriptorsContext.ChildDescriptorsContext.Consumer, {
109
+ }) : child.node.isText ? /*#__PURE__*/ _react.default.createElement(_ChildDescriptionsContext.ChildDescriptionsContext.Consumer, {
110
110
  key: child.key
111
111
  }, (param)=>{
112
112
  let { siblingsRef, parentRef } = param;
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "NativeWidgetView", {
9
9
  }
10
10
  });
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
- const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
12
+ const _ChildDescriptionsContext = require("../contexts/ChildDescriptionsContext.js");
13
13
  const _useClientLayoutEffect = require("../hooks/useClientLayoutEffect.js");
14
14
  const _useEditorEffect = require("../hooks/useEditorEffect.js");
15
15
  const _viewdesc = require("../viewdesc.js");
@@ -56,7 +56,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
56
56
  }
57
57
  function NativeWidgetView(param) {
58
58
  let { widget, getPos } = param;
59
- const { siblingsRef, parentRef } = (0, _react.useContext)(_ChildDescriptorsContext.ChildDescriptorsContext);
59
+ const { siblingsRef, parentRef } = (0, _react.useContext)(_ChildDescriptionsContext.ChildDescriptionsContext);
60
60
  const viewDescRef = (0, _react.useRef)(null);
61
61
  const rootDomRef = (0, _react.useRef)(null);
62
62
  (0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "OutputSpec", {
10
10
  });
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
12
  const _props = require("../props.js");
13
+ const _refs = require("../refs.js");
13
14
  function _getRequireWildcardCache(nodeInterop) {
14
15
  if (typeof WeakMap !== "function") return null;
15
16
  var cacheBabelInterop = new WeakMap();
@@ -72,7 +73,8 @@ function _interop_require_wildcard(obj, nodeInterop) {
72
73
  return false;
73
74
  }
74
75
  const ForwardedOutputSpec = /*#__PURE__*/ (0, _react.memo)(/*#__PURE__*/ (0, _react.forwardRef)(function OutputSpec(param, ref) {
75
- let { outputSpec, isMark, children, ...propOverrides } = param;
76
+ let { outputSpec, isMark, contentDOMRef, children, ...propOverrides } = param;
77
+ const mergedRef = (0, _refs.useMergedDOMRefs)(ref, contentDOMRef);
76
78
  if (typeof outputSpec === "string") {
77
79
  return /*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, outputSpec);
78
80
  }
@@ -98,10 +100,14 @@ const ForwardedOutputSpec = /*#__PURE__*/ (0, _react.memo)(/*#__PURE__*/ (0, _re
98
100
  if (i < outputSpec.length - 1 || i > start) {
99
101
  throw new RangeError("Content hole must be the only child of its parent node");
100
102
  }
101
- return /*#__PURE__*/ (0, _react.createElement)(tagName, props, children);
103
+ return /*#__PURE__*/ (0, _react.createElement)(tagName, {
104
+ ...props,
105
+ ref: ref ? mergedRef : contentDOMRef
106
+ }, children);
102
107
  }
103
108
  content.push(/*#__PURE__*/ _react.default.createElement(ForwardedOutputSpec, {
104
- outputSpec: child
109
+ outputSpec: child,
110
+ contentDOMRef: contentDOMRef
105
111
  }, children));
106
112
  }
107
113
  // https://prosemirror.net/docs/ref/#model.MarkSpec.toDOM
@@ -109,6 +115,7 @@ const ForwardedOutputSpec = /*#__PURE__*/ (0, _react.memo)(/*#__PURE__*/ (0, _re
109
115
  // marked content is placed. Otherwise, it is appended to the top node.
110
116
  if (isMark && !hasHole(outputSpec)) {
111
117
  content.push(children);
118
+ props.ref = mergedRef;
112
119
  }
113
120
  return /*#__PURE__*/ (0, _react.createElement)(tagName, props, ...content);
114
121
  }));
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "ProseMirror", {
9
9
  }
10
10
  });
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
- const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
12
+ const _ChildDescriptionsContext = require("../contexts/ChildDescriptionsContext.js");
13
13
  const _EditorContext = require("../contexts/EditorContext.js");
14
14
  const _EditorStateContext = require("../contexts/EditorStateContext.js");
15
15
  const _NodeViewContext = require("../contexts/NodeViewContext.js");
@@ -62,7 +62,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
62
62
  function getPos() {
63
63
  return -1;
64
64
  }
65
- const rootChildDescriptorsContextValue = {
65
+ const rootChildDescriptionsContextValue = {
66
66
  parentRef: {
67
67
  current: undefined
68
68
  },
@@ -71,39 +71,33 @@ const rootChildDescriptorsContextValue = {
71
71
  }
72
72
  };
73
73
  function ProseMirrorInner(param) {
74
- let { className, children, nodeViews, customNodeViews, markViews, customMarkViews, ...props } = param;
74
+ let { children, nodeViewComponents, markViewComponents, ...props } = param;
75
75
  const [mount, setMount] = (0, _react.useState)(null);
76
- const { editor, state } = (0, _useEditor.useEditor)(mount, {
77
- ...props,
78
- nodeViews: customNodeViews,
79
- markViews: customMarkViews
80
- });
76
+ const { editor, state } = (0, _useEditor.useEditor)(mount, props);
81
77
  const nodeViewConstructors = editor.view.nodeViews;
82
78
  const nodeViewContextValue = (0, _react.useMemo)(()=>{
83
79
  return {
84
80
  components: {
85
- ...nodeViews,
86
- ...markViews
81
+ ...nodeViewComponents,
82
+ ...markViewComponents
87
83
  },
88
84
  constructors: nodeViewConstructors
89
85
  };
90
86
  }, [
91
- markViews,
92
- nodeViewConstructors,
93
- nodeViews
87
+ markViewComponents,
88
+ nodeViewComponents,
89
+ nodeViewConstructors
94
90
  ]);
95
91
  const node = state.doc;
96
92
  const decorations = (0, _computeDocDeco.computeDocDeco)(editor.view);
97
93
  const innerDecorations = (0, _viewDecorations.viewDecorations)(editor.view, editor.cursorWrapper);
98
94
  const docNodeViewContextValue = (0, _react.useMemo)(()=>({
99
- className,
100
95
  setMount,
101
96
  node,
102
97
  getPos,
103
98
  decorations,
104
99
  innerDecorations
105
100
  }), [
106
- className,
107
101
  node,
108
102
  decorations,
109
103
  innerDecorations
@@ -114,8 +108,8 @@ function ProseMirrorInner(param) {
114
108
  value: state
115
109
  }, /*#__PURE__*/ _react.default.createElement(_NodeViewContext.NodeViewContext.Provider, {
116
110
  value: nodeViewContextValue
117
- }, /*#__PURE__*/ _react.default.createElement(_ChildDescriptorsContext.ChildDescriptorsContext.Provider, {
118
- value: rootChildDescriptorsContextValue
111
+ }, /*#__PURE__*/ _react.default.createElement(_ChildDescriptionsContext.ChildDescriptionsContext.Provider, {
112
+ value: rootChildDescriptionsContextValue
119
113
  }, /*#__PURE__*/ _react.default.createElement(_ProseMirrorDoc.DocNodeViewContext.Provider, {
120
114
  value: docNodeViewContextValue
121
115
  }, children)))));
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "SeparatorHackView", {
10
10
  });
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
12
  const _browser = require("../browser.js");
13
- const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
13
+ const _ChildDescriptionsContext = require("../contexts/ChildDescriptionsContext.js");
14
14
  const _useClientLayoutEffect = require("../hooks/useClientLayoutEffect.js");
15
15
  const _viewdesc = require("../viewdesc.js");
16
16
  function _getRequireWildcardCache(nodeInterop) {
@@ -56,7 +56,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
56
56
  }
57
57
  function SeparatorHackView(param) {
58
58
  let { getPos } = param;
59
- const { siblingsRef, parentRef } = (0, _react.useContext)(_ChildDescriptorsContext.ChildDescriptorsContext);
59
+ const { siblingsRef, parentRef } = (0, _react.useContext)(_ChildDescriptionsContext.ChildDescriptionsContext);
60
60
  const viewDescRef = (0, _react.useRef)(null);
61
61
  const ref = (0, _react.useRef)(null);
62
62
  const [shouldRender, setShouldRender] = (0, _react.useState)(false);
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "TrailingHackView", {
9
9
  }
10
10
  });
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
- const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
12
+ const _ChildDescriptionsContext = require("../contexts/ChildDescriptionsContext.js");
13
13
  const _useClientLayoutEffect = require("../hooks/useClientLayoutEffect.js");
14
14
  const _viewdesc = require("../viewdesc.js");
15
15
  function _getRequireWildcardCache(nodeInterop) {
@@ -55,7 +55,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
55
55
  }
56
56
  function TrailingHackView(param) {
57
57
  let { getPos } = param;
58
- const { siblingsRef, parentRef } = (0, _react.useContext)(_ChildDescriptorsContext.ChildDescriptorsContext);
58
+ const { siblingsRef, parentRef } = (0, _react.useContext)(_ChildDescriptionsContext.ChildDescriptionsContext);
59
59
  const viewDescRef = (0, _react.useRef)(null);
60
60
  const ref = (0, _react.useRef)(null);
61
61
  (0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "WidgetView", {
9
9
  }
10
10
  });
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
- const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
12
+ const _ChildDescriptionsContext = require("../contexts/ChildDescriptionsContext.js");
13
13
  const _useClientLayoutEffect = require("../hooks/useClientLayoutEffect.js");
14
14
  const _viewdesc = require("../viewdesc.js");
15
15
  function _getRequireWildcardCache(nodeInterop) {
@@ -55,7 +55,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
55
55
  }
56
56
  function WidgetView(param) {
57
57
  let { widget, getPos } = param;
58
- const { siblingsRef, parentRef } = (0, _react.useContext)(_ChildDescriptorsContext.ChildDescriptorsContext);
58
+ const { siblingsRef, parentRef } = (0, _react.useContext)(_ChildDescriptionsContext.ChildDescriptionsContext);
59
59
  const viewDescRef = (0, _react.useRef)(null);
60
60
  const domRef = (0, _react.useRef)(null);
61
61
  (0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
@@ -52,7 +52,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
52
52
  return newObj;
53
53
  }
54
54
  const DefaultMarkView = /*#__PURE__*/ (0, _react.forwardRef)(function DefaultMarkView(param, ref) {
55
- let { markProps: { mark, inline }, children, ...props } = param;
55
+ let { markProps: { mark, inline, contentDOMRef }, children, ...props } = param;
56
56
  const spec = (0, _react.useMemo)(()=>mark.type.spec.toDOM?.(mark, inline), [
57
57
  mark,
58
58
  inline
@@ -63,6 +63,7 @@ const DefaultMarkView = /*#__PURE__*/ (0, _react.forwardRef)(function DefaultMar
63
63
  return /*#__PURE__*/ _react.default.createElement(_OutputSpec.OutputSpec, {
64
64
  ...props,
65
65
  outputSpec: spec,
66
+ contentDOMRef: contentDOMRef,
66
67
  ref: ref,
67
68
  isMark: true
68
69
  }, children);
@@ -10,8 +10,8 @@ Object.defineProperty(exports, "MarkView", {
10
10
  });
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
12
  const _NodeViewContext = require("../../contexts/NodeViewContext.js");
13
- const _CustomMarkView = require("./CustomMarkView.js");
14
13
  const _DefaultMarkView = require("./DefaultMarkView.js");
14
+ const _MarkViewConstructorView = require("./MarkViewConstructorView.js");
15
15
  const _ReactMarkView = require("./ReactMarkView.js");
16
16
  function _getRequireWildcardCache(nodeInterop) {
17
17
  if (typeof WeakMap !== "function") return null;
@@ -65,7 +65,7 @@ const MarkView = /*#__PURE__*/ (0, _react.memo)(function MarkView(props) {
65
65
  const Component = (0, _react.useMemo)(()=>{
66
66
  if (constructor) {
67
67
  return function MarkView(props) {
68
- return /*#__PURE__*/ _react.default.createElement(_CustomMarkView.CustomMarkView, {
68
+ return /*#__PURE__*/ _react.default.createElement(_MarkViewConstructorView.MarkViewConstructorView, {
69
69
  constructor: constructor,
70
70
  ...props
71
71
  });