@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.
- package/README.md +140 -75
- package/dist/cjs/StaticEditorView.js +0 -3
- package/dist/cjs/components/ChildNodeViews.js +4 -4
- package/dist/cjs/components/NativeWidgetView.js +2 -2
- package/dist/cjs/components/OutputSpec.js +10 -3
- package/dist/cjs/components/ProseMirror.js +11 -17
- package/dist/cjs/components/SeparatorHackView.js +2 -2
- package/dist/cjs/components/TrailingHackView.js +2 -2
- package/dist/cjs/components/WidgetView.js +2 -2
- package/dist/cjs/components/marks/DefaultMarkView.js +2 -1
- package/dist/cjs/components/marks/MarkView.js +2 -2
- package/dist/cjs/components/marks/{CustomMarkView.js → MarkViewConstructorView.js} +16 -7
- package/dist/cjs/components/marks/ReactMarkView.js +26 -6
- package/dist/cjs/components/nodes/DefaultNodeView.js +3 -2
- package/dist/cjs/components/nodes/DocNodeView.js +7 -6
- package/dist/cjs/components/nodes/NodeView.js +17 -6
- package/dist/cjs/components/nodes/{CustomNodeView.js → NodeViewConstructorView.js} +22 -9
- package/dist/cjs/components/nodes/ReactNodeView.js +59 -17
- package/dist/cjs/contexts/{ChildDescriptorsContext.js → ChildDescriptionsContext.js} +3 -3
- package/dist/cjs/hooks/useEditor.js +0 -4
- package/dist/cjs/hooks/useEditorEventCallback.js +1 -1
- package/dist/cjs/hooks/useMarkViewDescription.js +24 -21
- package/dist/cjs/hooks/useNodePos.js +18 -0
- package/dist/cjs/hooks/{useNodeViewDescriptor.js → useNodeViewDescription.js} +30 -25
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/refs.js +28 -0
- package/dist/cjs/viewdesc.js +18 -5
- package/dist/esm/StaticEditorView.js +0 -3
- package/dist/esm/components/ChildNodeViews.js +4 -4
- package/dist/esm/components/NativeWidgetView.js +2 -2
- package/dist/esm/components/OutputSpec.js +10 -3
- package/dist/esm/components/ProseMirror.js +11 -17
- package/dist/esm/components/SeparatorHackView.js +2 -2
- package/dist/esm/components/TrailingHackView.js +2 -2
- package/dist/esm/components/WidgetView.js +2 -2
- package/dist/esm/components/marks/DefaultMarkView.js +2 -1
- package/dist/esm/components/marks/MarkView.js +2 -2
- package/dist/esm/components/marks/{CustomMarkView.js → MarkViewConstructorView.js} +14 -5
- package/dist/esm/components/marks/ReactMarkView.js +26 -6
- package/dist/esm/components/nodes/DefaultNodeView.js +3 -2
- package/dist/esm/components/nodes/DocNodeView.js +8 -7
- package/dist/esm/components/nodes/NodeView.js +7 -4
- package/dist/esm/components/nodes/{CustomNodeView.js → NodeViewConstructorView.js} +20 -7
- package/dist/esm/components/nodes/ReactNodeView.js +59 -17
- package/dist/esm/contexts/{ChildDescriptorsContext.js → ChildDescriptionsContext.js} +1 -1
- package/dist/esm/hooks/useEditor.js +0 -4
- package/dist/esm/hooks/useEditorEffect.js +0 -4
- package/dist/esm/hooks/useEditorEventCallback.js +6 -4
- package/dist/esm/hooks/useMarkViewDescription.js +26 -23
- package/dist/esm/hooks/useNodePos.js +15 -0
- package/dist/esm/hooks/{useNodeViewDescriptor.js → useNodeViewDescription.js} +29 -24
- package/dist/esm/index.js +2 -0
- package/dist/esm/refs.js +18 -0
- package/dist/esm/viewdesc.js +13 -6
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/AbstractEditorView.d.ts +0 -1
- package/dist/types/StaticEditorView.d.ts +0 -1
- package/dist/types/components/OutputSpec.d.ts +2 -1
- package/dist/types/components/ProseMirror.d.ts +3 -11
- package/dist/types/components/ProseMirrorDoc.d.ts +2 -2
- package/dist/types/components/marks/DefaultMarkView.d.ts +1 -1
- package/dist/types/components/marks/MarkViewComponentProps.d.ts +4 -3
- package/dist/types/components/marks/{CustomMarkView.d.ts → MarkViewConstructorView.d.ts} +1 -1
- package/dist/types/components/nodes/DefaultNodeView.d.ts +1 -1
- package/dist/types/components/nodes/DocNodeView.d.ts +2 -2
- package/dist/types/components/nodes/NodeView.d.ts +1 -0
- package/dist/types/components/nodes/NodeViewComponentProps.d.ts +4 -3
- package/dist/types/components/{CustomNodeView.d.ts → nodes/NodeViewConstructorView.d.ts} +1 -1
- package/dist/types/constants.d.ts +1 -1
- package/dist/types/contexts/{ChildDescriptorsContext.d.ts → ChildDescriptionsContext.d.ts} +1 -1
- package/dist/types/hooks/useEditorEffect.d.ts +0 -4
- package/dist/types/hooks/useEditorEventCallback.d.ts +6 -4
- package/dist/types/hooks/useMarkViewDescription.d.ts +6 -9
- package/dist/types/hooks/useNodePos.d.ts +9 -0
- package/dist/types/hooks/{useNodeViewDescriptor.d.ts → useNodeViewDescription.d.ts} +5 -9
- package/dist/types/index.d.ts +2 -0
- package/dist/types/props.d.ts +26 -26
- package/dist/types/refs.d.ts +2 -0
- package/dist/types/viewdesc.d.ts +4 -0
- package/package.json +12 -20
- package/dist/cjs/components/CustomNodeView.js +0 -132
- package/dist/cjs/components/DefaultNodeView.js +0 -67
- package/dist/cjs/components/DocNodeView.js +0 -96
- package/dist/cjs/components/MarkView.js +0 -119
- package/dist/cjs/components/NodeView.js +0 -86
- package/dist/cjs/components/NodeViewComponentProps.js +0 -4
- package/dist/cjs/components/ReactNodeView.js +0 -174
- package/dist/cjs/components/marks/OldMarkView.js +0 -120
- package/dist/cjs/tiptap/ReactProseMirrorNodeView.js +0 -26
- package/dist/cjs/tiptap/TiptapEditor.js +0 -34
- package/dist/cjs/tiptap/TiptapEditorContent.js +0 -142
- package/dist/cjs/tiptap/TiptapEditorView.js +0 -118
- package/dist/cjs/tiptap/TiptapNodeView.js +0 -26
- package/dist/cjs/tiptap/contexts/TiptapEditorContext.js +0 -12
- package/dist/cjs/tiptap/extensions/ReactProseMirror.js +0 -40
- package/dist/cjs/tiptap/hooks/useIsInReactProseMirror.js +0 -15
- package/dist/cjs/tiptap/hooks/useTiptapEditor.js +0 -43
- package/dist/cjs/tiptap/hooks/useTiptapEditorEffect.js +0 -35
- package/dist/cjs/tiptap/hooks/useTiptapEditorEventCallback.js +0 -35
- package/dist/cjs/tiptap/index.js +0 -48
- package/dist/cjs/tiptap/tiptapNodeView.js +0 -237
- package/dist/esm/components/CustomNodeView.js +0 -81
- package/dist/esm/components/DefaultNodeView.js +0 -16
- package/dist/esm/components/DocNodeView.js +0 -45
- package/dist/esm/components/MarkView.js +0 -68
- package/dist/esm/components/NodeView.js +0 -35
- package/dist/esm/components/NodeViewComponentProps.js +0 -1
- package/dist/esm/components/ReactNodeView.js +0 -123
- package/dist/esm/components/marks/OldMarkView.js +0 -69
- package/dist/esm/tiptap/ReactProseMirrorNodeView.js +0 -22
- package/dist/esm/tiptap/TiptapEditor.js +0 -24
- package/dist/esm/tiptap/TiptapEditorContent.js +0 -91
- package/dist/esm/tiptap/TiptapEditorView.js +0 -69
- package/dist/esm/tiptap/TiptapNodeView.js +0 -22
- package/dist/esm/tiptap/contexts/TiptapEditorContext.js +0 -2
- package/dist/esm/tiptap/extensions/ReactProseMirror.js +0 -30
- package/dist/esm/tiptap/hooks/useIsInReactProseMirror.js +0 -5
- package/dist/esm/tiptap/hooks/useTiptapEditor.js +0 -33
- package/dist/esm/tiptap/hooks/useTiptapEditorEffect.js +0 -42
- package/dist/esm/tiptap/hooks/useTiptapEditorEventCallback.js +0 -35
- package/dist/esm/tiptap/index.js +0 -9
- package/dist/esm/tiptap/tiptapNodeView.js +0 -205
- package/dist/types/components/DefaultNodeView.d.ts +0 -3
- package/dist/types/components/DocNodeView.d.ts +0 -12
- package/dist/types/components/MarkView.d.ts +0 -9
- package/dist/types/components/NodeView.d.ts +0 -11
- package/dist/types/components/NodeViewComponentProps.d.ts +0 -12
- package/dist/types/components/ReactNodeView.d.ts +0 -13
- package/dist/types/components/marks/OldMarkView.d.ts +0 -10
- package/dist/types/components/nodes/CustomNodeView.d.ts +0 -12
- package/dist/types/tiptap/ReactProseMirrorNodeView.d.ts +0 -15
- package/dist/types/tiptap/TiptapEditor.d.ts +0 -6
- package/dist/types/tiptap/TiptapEditorContent.d.ts +0 -19
- package/dist/types/tiptap/TiptapEditorView.d.ts +0 -16
- package/dist/types/tiptap/TiptapNodeView.d.ts +0 -15
- package/dist/types/tiptap/contexts/TiptapEditorContext.d.ts +0 -6
- package/dist/types/tiptap/extensions/ReactProseMirror.d.ts +0 -9
- package/dist/types/tiptap/hooks/useIsInReactProseMirror.d.ts +0 -1
- package/dist/types/tiptap/hooks/useTiptapEditor.d.ts +0 -4
- package/dist/types/tiptap/hooks/useTiptapEditorEffect.d.ts +0 -21
- package/dist/types/tiptap/hooks/useTiptapEditorEventCallback.d.ts +0 -13
- package/dist/types/tiptap/index.d.ts +0 -9
- 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
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
|
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
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
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.
|
|
426
|
-
//
|
|
427
|
-
//
|
|
428
|
-
//
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
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
|
-
|
|
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
|
-
|
|
467
|
-
[nodeType: string]:
|
|
468
|
-
NodeViewComponentProps & RefAttributes<any>
|
|
469
|
-
>;
|
|
506
|
+
nodeViewComponents?: {
|
|
507
|
+
[nodeType: string]: ComponentType<NodeViewComponentProps>;
|
|
470
508
|
};
|
|
471
|
-
|
|
509
|
+
nodeViews?: {
|
|
472
510
|
[nodeType: string]: NodeViewConstructor;
|
|
473
511
|
};
|
|
474
|
-
|
|
475
|
-
[markType: string]:
|
|
476
|
-
MarkViewComponentProps & RefAttributes<any>
|
|
477
|
-
>;
|
|
512
|
+
markViewComponents?: {
|
|
513
|
+
[markType: string]: ComponentType<MarkViewComponentProps>;
|
|
478
514
|
};
|
|
479
|
-
|
|
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=
|
|
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
|
-
|
|
656
|
-
|
|
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
|
-
|
|
782
|
+
arguments:
|
|
719
783
|
|
|
720
|
-
- `pos`
|
|
721
|
-
- `order`
|
|
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
|
|
|
@@ -17,11 +17,12 @@ _export(exports, {
|
|
|
17
17
|
}
|
|
18
18
|
});
|
|
19
19
|
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
20
|
-
const
|
|
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
|
|
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(
|
|
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
|
|
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)(
|
|
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,
|
|
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
|
|
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
|
|
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 {
|
|
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
|
-
...
|
|
86
|
-
...
|
|
81
|
+
...nodeViewComponents,
|
|
82
|
+
...markViewComponents
|
|
87
83
|
},
|
|
88
84
|
constructors: nodeViewConstructors
|
|
89
85
|
};
|
|
90
86
|
}, [
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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(
|
|
118
|
-
value:
|
|
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
|
|
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)(
|
|
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
|
|
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)(
|
|
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
|
|
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)(
|
|
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(
|
|
68
|
+
return /*#__PURE__*/ _react.default.createElement(_MarkViewConstructorView.MarkViewConstructorView, {
|
|
69
69
|
constructor: constructor,
|
|
70
70
|
...props
|
|
71
71
|
});
|