diff --git a/.yarn/versions/07a9e382.yml b/.yarn/versions/07a9e382.yml new file mode 100644 index 00000000..206c26a6 --- /dev/null +++ b/.yarn/versions/07a9e382.yml @@ -0,0 +1,2 @@ +releases: + "@handlewithcare/react-prosemirror": patch diff --git a/README.md b/README.md index f2609764..cdfb4167 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ npm install @handlewithcare/react-prosemirror \ react@^19.1.0 \ react-dom@^19.1.0 \ react-reconciler@0.32.0 \ - prosemirror-view@1.41.7 \ + prosemirror-view@1.42.0 \ prosemirror-state \ prosemirror-model ``` @@ -47,7 +47,7 @@ yarn add @handlewithcare/react-prosemirror \ react@^19.1.0 \ react-dom@^19.1.0 \ react-reconciler@0.32.0 \ - prosemirror-view@1.41.7 \ + prosemirror-view@1.42.0 \ prosemirror-state \ prosemirror-model ``` @@ -753,10 +753,10 @@ Events for which this returns true are not handled by the editor. ### `useIgnoreMutation` ```tsx -type useIgnoreMutation = (stopEvent: (this: NodeView, view: EditorView, mutation: ViewMutationRecord) => boolean): void +type useIgnoreMutation = (ignoreMutation: (this: NodeView | MarkView, view: EditorView, mutation: ViewMutationRecord) => boolean): void ``` -This hook can be used within a node view component to register an +This hook can be used within a node view or mark view component to register an [ignoreMutation handler](https://prosemirror.net/docs/ref/#view.NodeView.ignoreMutation). Mutations for which this returns true are not handled by the editor. diff --git a/package.json b/package.json index 65df42e0..0f47d465 100644 --- a/package.json +++ b/package.json @@ -108,13 +108,13 @@ "prosemirror-history": "^1.5.0", "prosemirror-inputrules": "^1.5.1", "prosemirror-keymap": "^1.2.3", - "prosemirror-model": "^1.25.7", + "prosemirror-model": "^1.25.8", "prosemirror-schema-list": "^1.5.1", "prosemirror-state": "^1.4.4", "prosemirror-tables": "^1.8.5", "prosemirror-test-builder": "^1.1.1", "prosemirror-transform": "^1.12.0", - "prosemirror-view": "1.41.7", + "prosemirror-view": "1.42.0", "puppeteer-core": "^25.0.4", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -129,7 +129,7 @@ "webdriverio": "^9.18.1" }, "resolutions": { - "prosemirror-view": "1.41.7" + "prosemirror-view": "1.42.0" }, "peerDependencies": { "@tiptap/core": "^3.0.0", @@ -137,7 +137,7 @@ "@tiptap/react": "^3.0.0", "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", - "prosemirror-view": "1.41.7", + "prosemirror-view": "1.42.0", "react": ">=17 <20", "react-dom": ">=17 <20", "react-reconciler": ">=0.26.1 <=0.33.0" diff --git a/src/components/marks/ReactMarkView.tsx b/src/components/marks/ReactMarkView.tsx index 0677c33a..b8e4bdb7 100644 --- a/src/components/marks/ReactMarkView.tsx +++ b/src/components/marks/ReactMarkView.tsx @@ -13,7 +13,6 @@ import { IgnoreMutation, IgnoreMutationContext, } from "../../contexts/IgnoreMutationContext.js"; -import { DOMNode } from "../../dom.js"; import { useMarkViewDescription } from "../../hooks/useMarkViewDescription.js"; import { MarkViewComponentProps } from "./MarkViewComponentProps.js"; @@ -61,7 +60,7 @@ export const ReactMarkView = memo(function ReactMarkView({ () => ref.current, () => contentDOMRef.current ?? ref.current, () => ({ - dom: ref.current as DOMNode, + dom: ref.current as HTMLElement, contentDOM: contentDOMRef.current ?? ref.current, ignoreMutation(mutation) { const ignoreMutation = ignoreMutationRef.current; diff --git a/src/components/nodes/ReactNodeView.tsx b/src/components/nodes/ReactNodeView.tsx index 7ccd84d5..ccad03e6 100644 --- a/src/components/nodes/ReactNodeView.tsx +++ b/src/components/nodes/ReactNodeView.tsx @@ -24,7 +24,6 @@ import { StopEvent, StopEventContext, } from "../../contexts/StopEventContext.js"; -import { DOMNode } from "../../dom.js"; import { useForceUpdate } from "../../hooks/useForceUpdate.js"; import { useNodeViewDescription } from "../../hooks/useNodeViewDescription.js"; import { ChildNodeViews, wrapInDeco } from "../ChildNodeViews.js"; @@ -106,7 +105,7 @@ export const ReactNodeView = memo(function ReactNodeView({ setSelected(false); return { - dom: (nodeDOMRef.current ?? domRef.current) as DOMNode, + dom: (nodeDOMRef.current ?? domRef.current) as HTMLElement, contentDOM: contentDOMRef.current, update() { return true; diff --git a/src/contexts/IgnoreMutationContext.ts b/src/contexts/IgnoreMutationContext.ts index 5fa2a341..059349b4 100644 --- a/src/contexts/IgnoreMutationContext.ts +++ b/src/contexts/IgnoreMutationContext.ts @@ -1,8 +1,8 @@ -import { NodeView, ViewMutationRecord } from "prosemirror-view"; +import { MarkView, NodeView, ViewMutationRecord } from "prosemirror-view"; import { createContext } from "react"; export type IgnoreMutation = ( - this: NodeView, + this: NodeView | MarkView, mutation: ViewMutationRecord ) => boolean; diff --git a/src/hooks/useIgnoreMutation.ts b/src/hooks/useIgnoreMutation.ts index a28de074..5aa95da6 100644 --- a/src/hooks/useIgnoreMutation.ts +++ b/src/hooks/useIgnoreMutation.ts @@ -1,4 +1,9 @@ -import { EditorView, NodeView, ViewMutationRecord } from "prosemirror-view"; +import { + EditorView, + MarkView, + NodeView, + ViewMutationRecord, +} from "prosemirror-view"; import { useContext } from "react"; import { IgnoreMutationContext } from "../contexts/IgnoreMutationContext.js"; @@ -8,7 +13,7 @@ import { useEditorEventCallback } from "./useEditorEventCallback.js"; export function useIgnoreMutation( ignoreMutation: ( - this: NodeView, + this: NodeView | MarkView, view: EditorView, mutation: ViewMutationRecord ) => boolean diff --git a/src/hooks/useMarkViewDescription.ts b/src/hooks/useMarkViewDescription.ts index 9da6a7b7..8768556b 100644 --- a/src/hooks/useMarkViewDescription.ts +++ b/src/hooks/useMarkViewDescription.ts @@ -5,7 +5,6 @@ import { ReactEditorView } from "../ReactEditorView.js"; import { MarkViewComponentProps } from "../components/marks/MarkViewComponentProps.js"; import { ChildDescriptionsContext } from "../contexts/ChildDescriptionsContext.js"; import { EditorContext } from "../contexts/EditorContext.js"; -import { DOMNode } from "../dom.js"; import { MarkViewDesc, ReactMarkViewDesc, @@ -19,7 +18,7 @@ import { useEffectEvent } from "./useEffectEvent.js"; type Props = Omit; export function useMarkViewDescription( - getDOM: () => DOMNode | null, + getDOM: () => HTMLElement | null, getContentDOM: ( markView: { contentDOM?: HTMLElement | null } | null ) => HTMLElement | null, diff --git a/src/hooks/useNodeViewDescription.ts b/src/hooks/useNodeViewDescription.ts index 4f88d5ec..5c10e0bc 100644 --- a/src/hooks/useNodeViewDescription.ts +++ b/src/hooks/useNodeViewDescription.ts @@ -5,7 +5,6 @@ import { ReactEditorView } from "../ReactEditorView.js"; import { NodeViewComponentProps } from "../components/nodes/NodeViewComponentProps.js"; import { ChildDescriptionsContext } from "../contexts/ChildDescriptionsContext.js"; import { EditorContext } from "../contexts/EditorContext.js"; -import { DOMNode } from "../dom.js"; import { NodeViewDesc, ReactNodeViewDesc, @@ -19,7 +18,7 @@ import { useEffectEvent } from "./useEffectEvent.js"; type Props = Omit; export function useNodeViewDescription( - getDOM: () => DOMNode | null, + getDOM: () => HTMLElement | null, getContentDOM: ( nodeView: { contentDOM?: HTMLElement | null } | null ) => HTMLElement | null, diff --git a/src/viewdesc.ts b/src/viewdesc.ts index c1e73a97..02f644a7 100644 --- a/src/viewdesc.ts +++ b/src/viewdesc.ts @@ -764,12 +764,19 @@ export class CompositionViewDesc extends ViewDesc { /// Objects returned as mark views must conform to this interface. export interface MarkView { /// The outer DOM node that represents the document node. - dom: DOMNode; + dom: HTMLElement; /// The DOM node that should hold the mark's content. When this is not /// present, the `dom` property is used as the content DOM. contentDOM?: HTMLElement | null; + /// When given, this is called when the view is updating itself. It + /// will be given a mark (of the same type as the current one). When it + /// returns true, the existing DOM is kept and reused (its content is + /// still managed by ProseMirror); when it returns false, the mark view + /// is rebuilt. + update?: (mark: Mark) => boolean; + /// Called when a [mutation](#view.ViewMutationRecord) happens within the /// view. Return false if the editor should re-read the selection or re-parse /// the range around the mutation, true if it can safely be ignored. @@ -791,7 +798,7 @@ export class MarkViewDesc extends ViewDesc { children: ViewDesc[], getPos: () => number, public mark: Mark, - dom: DOMNode, + dom: HTMLElement, contentDOM: HTMLElement, public spec: MarkView ) { @@ -1083,9 +1090,9 @@ class CustomNodeViewDesc extends NodeViewDesc { node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, - dom: DOMNode, + dom: HTMLElement, contentDOM: HTMLElement | null, - nodeDOM: DOMNode, + nodeDOM: HTMLElement, readonly spec: NodeView ) { super( diff --git a/yarn.lock b/yarn.lock index b1763054..097a00d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1686,13 +1686,13 @@ __metadata: prosemirror-history: "npm:^1.5.0" prosemirror-inputrules: "npm:^1.5.1" prosemirror-keymap: "npm:^1.2.3" - prosemirror-model: "npm:^1.25.7" + prosemirror-model: "npm:^1.25.8" prosemirror-schema-list: "npm:^1.5.1" prosemirror-state: "npm:^1.4.4" prosemirror-tables: "npm:^1.8.5" prosemirror-test-builder: "npm:^1.1.1" prosemirror-transform: "npm:^1.12.0" - prosemirror-view: "npm:1.41.7" + prosemirror-view: "npm:1.42.0" puppeteer-core: "npm:^25.0.4" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" @@ -1711,7 +1711,7 @@ __metadata: "@tiptap/react": ^3.0.0 prosemirror-model: ^1.0.0 prosemirror-state: ^1.0.0 - prosemirror-view: 1.41.7 + prosemirror-view: 1.42.0 react: ">=17 <20" react-dom: ">=17 <20" react-reconciler: ">=0.26.1 <=0.33.0" @@ -12953,12 +12953,12 @@ __metadata: languageName: node linkType: hard -"prosemirror-model@npm:^1.0.0, prosemirror-model@npm:^1.20.0, prosemirror-model@npm:^1.21.0, prosemirror-model@npm:^1.24.1, prosemirror-model@npm:^1.25.0, prosemirror-model@npm:^1.25.4, prosemirror-model@npm:^1.25.7": - version: 1.25.7 - resolution: "prosemirror-model@npm:1.25.7" +"prosemirror-model@npm:^1.0.0, prosemirror-model@npm:^1.21.0, prosemirror-model@npm:^1.24.1, prosemirror-model@npm:^1.25.0, prosemirror-model@npm:^1.25.4, prosemirror-model@npm:^1.25.8": + version: 1.25.10 + resolution: "prosemirror-model@npm:1.25.10" dependencies: orderedmap: "npm:^2.0.0" - checksum: 10/516e3609a350bccc2dcb9215eccf7db1567c4f57914467a15884f017f00fc2b110e91332a708e935cb8da179897680ca6d9a64f7cceb0e3a6c543845d7eab2b2 + checksum: 10/c6c901031c9c18cdea029df5fdd802d2dc0bc3a1ebb852c89ae4eeab3672d15a1f92ed6e320583e523b1d26d5c3e44ba1d7a65c517353ae4dc2d17a9ce8485e9 languageName: node linkType: hard @@ -13040,14 +13040,14 @@ __metadata: languageName: node linkType: hard -"prosemirror-view@npm:1.41.7": - version: 1.41.7 - resolution: "prosemirror-view@npm:1.41.7" +"prosemirror-view@npm:1.42.0": + version: 1.42.0 + resolution: "prosemirror-view@npm:1.42.0" dependencies: - prosemirror-model: "npm:^1.20.0" + prosemirror-model: "npm:^1.25.8" prosemirror-state: "npm:^1.0.0" prosemirror-transform: "npm:^1.1.0" - checksum: 10/457cb83cdd677b9ccc8e579e53c9f2fc10316b6627952bffc415c843ccd20069efab15da0ee651541191930ce7e31e790c08f6ddbacfda47dc280aa47dca42db + checksum: 10/7430a30bafe4304fec31183c5f004ae98255c4087efb089b423b47ca0dc7efa93fc975db9fa08e7ec4941ba238edd52e271d8a67616a5d5a58ed8ef09932743d languageName: node linkType: hard