Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Strict mode and memoize node view components #142

Open
wants to merge 24 commits into
base: react-editor-view
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b376fcf
Fix strict mode
smoores-dev Sep 27, 2024
d6b9ca6
WIP: Memoize node view components
smoores-dev Sep 27, 2024
cd6a829
Fix some comments in react keys plugin
smoores-dev Sep 27, 2024
0257077
Sort children view descriptors
smoores-dev Sep 27, 2024
f4f95ad
Fix OutputSpec recursive reference
smoores-dev Oct 1, 2024
1b19e7c
Fix position calculation for markviews
smoores-dev Oct 1, 2024
ba08587
Cache return values of computeDocDeco and viewDecorations
smoores-dev Oct 1, 2024
3a18794
Fix useEditorViewLayoutEffect test
smoores-dev Oct 1, 2024
af77f6a
Pass position as a ref to a function to prevent rerenders
smoores-dev Oct 1, 2024
cdb926f
Give view descs the getPos closure, so that sorting works
smoores-dev Oct 4, 2024
0813243
Prevent unnecessary re-renders of the ChildElement component
smoores-dev Oct 4, 2024
0f227c7
Ensure that nodes re-render when their decorations change
smoores-dev Oct 6, 2024
84da502
Add a useSelectNode hook
smoores-dev Oct 11, 2024
390c7d5
Reduce wdio timeout
smoores-dev Oct 12, 2024
7d28798
Temp: enable info logging in wdio tests
smoores-dev Oct 12, 2024
1cdbe8e
Temp: limit to 1 test
smoores-dev Oct 12, 2024
4c1c7ca
Install chromedriver in CI
smoores-dev Oct 12, 2024
38795ba
Await inspect
smoores-dev Oct 12, 2024
ef1c4fd
Pin to a working version of Google Chrome
smoores-dev Oct 12, 2024
e0d5a1f
Simplify key calculation and fix trailing hack view sorting
smoores-dev Oct 22, 2024
1aae264
Prevent ChildElements from re-rendering when only the offset has changed
smoores-dev Oct 22, 2024
7fb7902
Quiet down wdio
smoores-dev Oct 22, 2024
b430944
Remove manual browser installation steps
smoores-dev Oct 22, 2024
d3f1191
Avoid copying and sorting entire childMap once per child
smoores-dev Oct 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
},
"rules": {
"no-console": ["error", { "allow": ["error"] }],
"react/prop-types": "off",
"react-hooks/exhaustive-deps": [
"warn",
{
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,5 @@ jobs:
- name: Install dependencies
run: yarn

- uses: browser-actions/setup-chrome@v1
- uses: browser-actions/setup-firefox@v1

- name: Test
run: yarn test
36 changes: 30 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ yarn add @nytimes/react-prosemirror
- [`useEditorEventListener`](#useeditoreventlistener-1)
- [`useEditorEffect`](#useeditoreffect-1)
- [`NodeViewComponentProps`](#nodeviewcomponentprops)
- [`useStopEvent`](#usestopevent)
- [`useSelectNode`](#useselectnode)
- [`widget`](#widget)

<!-- tocstop -->
Expand Down Expand Up @@ -573,12 +575,13 @@ export function SelectionWidget() {

```tsx
type NodeViewComponentProps = {
decorations: readonly Decoration[];
innerDecorations: DecorationSource;
node: Node;
children?: ReactNode | ReactNode[];
isSelected: boolean;
pos: number;
nodeProps: {
decorations: readonly Decoration[];
innerDecorations: DecorationSource;
node: Node;
children?: ReactNode | ReactNode[];
getPos: () => number;
};
} & HTMLAttributes<HTMLElement>;
```

Expand All @@ -594,6 +597,27 @@ and should pass them through to their top-level DOM element.
In addition to accepting these props, all node view components _must_ forward
their ref to their top-level DOM element.

### `useStopEvent`

```tsx
type useStopEvent = (stopEvent: (view: EditorView, event: Event) => boolean): void
```

This hook can be used within a node view component to register a
[stopEvent handler](https://prosemirror.net/docs/ref/#view.NodeView.stopEvent).
Events for which this returns true are not handled by the editor.

### `useSelectNode`

```tsx
type useSelectNode = (selectNode: () => void, deselectNode?: () => void): void
```

This hook can be used within a node view component to register
[selectNode and deselectNode handlers](https://prosemirror.net/docs/ref/#view.NodeView.selectNode).
The selectNode handler will only be called when a NodeSelection is created whose
node is this one.

### `widget`

```tsx
Expand Down
42 changes: 25 additions & 17 deletions demo/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import React, {
Ref,
StrictMode,
forwardRef,
useCallback,
useMemo,
useState,
} from "react";
import { createRoot } from "react-dom/client";
Expand Down Expand Up @@ -196,7 +198,7 @@ const Footnote = forwardRef(function Footnote(
});

const TestWidget = forwardRef(function TestWidget(
{ widget, pos, ...props }: WidgetViewComponentProps,
{ widget, getPos, ...props }: WidgetViewComponentProps,
ref: ForwardedRef<HTMLSpanElement>
) {
return (
Expand Down Expand Up @@ -303,6 +305,25 @@ function DemoEditor() {
const [state, setState] = useState(editorState);
const [showReactNodeViews, setShowReactNodeViews] = useState(true);

const nodeViews = useMemo(
() =>
showReactNodeViews
? {
paragraph: Paragraph,
list: List,
list_item: ListItem,
footnote: Footnote,
}
: undefined,
[showReactNodeViews]
);

const dispatchTransaction = useCallback(function (tr) {
setState((prev) => {
return prev.apply(tr);
});
}, []);

return (
<main>
<h1>React ProseMirror Demo</h1>
Expand All @@ -324,25 +345,12 @@ function DemoEditor() {
key={`${showReactNodeViews}`}
className="ProseMirror"
state={state}
dispatchTransaction={function (tr) {
setState((prev) => {
return prev.apply(tr);
});
}}
dispatchTransaction={dispatchTransaction}
plugins={plugins}
nodeViews={
showReactNodeViews
? {
paragraph: Paragraph,
list: List,
list_item: ListItem,
footnote: Footnote,
}
: undefined
}
nodeViews={nodeViews}
customNodeViews={showReactNodeViews ? undefined : customNodeViews}
>
<ProseMirrorDoc as={<article />} />
<ProseMirrorDoc />
</ProseMirror>
</main>
);
Expand Down
53 changes: 53 additions & 0 deletions docs/assets/index-B5SGPZtJ.js

Large diffs are not rendered by default.

53 changes: 0 additions & 53 deletions docs/assets/index-DM4UcNX5.js

This file was deleted.

2 changes: 1 addition & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React-ProseMirror Demo</title>
<script type="module" crossorigin src="/react-prosemirror/assets/index-DM4UcNX5.js"></script>
<script type="module" crossorigin src="/react-prosemirror/assets/index-B5SGPZtJ.js"></script>
<link rel="stylesheet" crossorigin href="/react-prosemirror/assets/index-DAGU9WLy.css">
</head>
<body>
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@
"@vitejs/plugin-react": "^4.3.1",
"@wdio/browser-runner": "^9.0.9",
"@wdio/cli": "^9.0.9",
"@wdio/dot-reporter": "^9.1.0",
"@wdio/mocha-framework": "^9.0.8",
"@wdio/spec-reporter": "^9.1.0",
"@wdio/types": "^9.0.8",
"@yarnpkg/sdks": "^3.0.0-rc.38",
"concurrently": "^7.6.0",
Expand Down
Loading
Loading