Skip to content

Commit

Permalink
Start plumbing through decorations
Browse files Browse the repository at this point in the history
  • Loading branch information
smoores-dev committed Aug 1, 2023
1 parent 9787afb commit 0bbeb4c
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 9 deletions.
1 change: 1 addition & 0 deletions demo/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ root.render(<DemoEditor />);
// DecorationSet.create(state.doc, [
// Decoration.inline(5, 15, { class: "inline-deco" }),
// Decoration.node(35, 55, { class: "node-deco" }),
// Decoration.widget(40, () => document.createElement("div")),
// ])
// }
// >
Expand Down
13 changes: 11 additions & 2 deletions src/components/DocNodeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ import React, {
import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
import { NodeViewContext } from "../contexts/NodeViewContext.js";
import { NodeViewDesc, ViewDesc } from "../descriptors/ViewDesc.js";
import { DecorationSourceInternal } from "../prosemirror-internal/DecorationInternal.js";

import { NodeView } from "./NodeView.js";

type Props = {
node: Node;
contentEditable: boolean;
decorations: DecorationSourceInternal;
} & DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;

export const DocNodeView = forwardRef(function DocNodeView(
{ node, contentEditable, ...props }: Props,
{ node, contentEditable, decorations, ...props }: Props,
ref: ForwardedRef<HTMLDivElement>
) {
const { posToDesc, domToDesc } = useContext(NodeViewContext);
Expand Down Expand Up @@ -61,7 +63,14 @@ export const DocNodeView = forwardRef(function DocNodeView(
const innerPos = 0;
node.content.forEach((childNode, offset) => {
const childPos = innerPos + offset;
children.push(<NodeView key={childPos} node={childNode} pos={childPos} />);
children.push(
<NodeView
key={childPos}
node={childNode}
pos={childPos}
decorations={decorations.forChild(offset, childNode)}
/>
);
});

return (
Expand Down
4 changes: 3 additions & 1 deletion src/components/EditorView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { NodeViewContext } from "../contexts/NodeViewContext.js";
import { NodeViewDesc, ViewDesc } from "../descriptors/ViewDesc.js";
import { useContentEditable } from "../hooks/useContentEditable.js";
import { useSyncSelection } from "../hooks/useSyncSelection.js";
import { DecorationSourceInternal } from "../prosemirror-internal/DecorationInternal.js";
import { EditorViewInternal } from "../prosemirror-internal/EditorViewInternal.js";
import { DOMNode, DOMSelection } from "../prosemirror-internal/dom.js";
import {
Expand Down Expand Up @@ -61,7 +62,7 @@ export function EditorView(props: Props) {
// keymap = {},
nodeViews = {},
dispatchTransaction: dispatchProp,
// decorations = DecorationSet.empty,
decorations = DecorationSet.empty,
defaultState,
state: stateProp,
// ...mountProps
Expand Down Expand Up @@ -222,6 +223,7 @@ export function EditorView(props: Props) {
ref={mountRef}
node={state.doc}
contentEditable={editable}
decorations={decorations as unknown as DecorationSourceInternal}
// {...mountProps}
/>
{children}
Expand Down
28 changes: 23 additions & 5 deletions src/components/NodeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import React, {
import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
import { NodeViewContext } from "../contexts/NodeViewContext.js";
import { NodeViewDesc, ViewDesc } from "../descriptors/ViewDesc.js";
import { DecorationSourceInternal } from "../prosemirror-internal/DecorationInternal.js";

import { MarkView } from "./MarkView.js";
import { NodeViewComponentProps } from "./NodeViewComponentProps.js";
Expand All @@ -23,14 +24,16 @@ import { TrailingHackView } from "./TrailingHackView.js";
type Props = {
node: Node;
pos: number;
decorations: DecorationSourceInternal;
};

export function NodeView({ node, pos }: Props) {
export function NodeView({ node, pos, decorations }: Props) {
const { posToDesc, domToDesc, nodeViews, state } =
useContext(NodeViewContext);
const siblingDescriptors = useContext(ChildDescriptorsContext);
const childDescriptors: ViewDesc[] = [];
const domRef = useRef<HTMLElement | null>(null);
const nodeDomRef = useRef<HTMLElement | null>(null);

useLayoutEffect(() => {
if (!domRef.current) return;
Expand All @@ -44,7 +47,7 @@ export function NodeView({ node, pos }: Props) {
DecorationSet.empty,
domRef.current,
firstChildDesc?.dom.parentElement ?? null,
domRef.current,
nodeDomRef.current ?? domRef.current,
posToDesc,
domToDesc
);
Expand Down Expand Up @@ -75,7 +78,14 @@ export function NodeView({ node, pos }: Props) {
</ChildDescriptorsContext.Consumer>
);
} else {
content.push(<NodeView key={childPos} node={childNode} pos={childPos} />);
content.push(
<NodeView
key={childPos}
node={childNode}
pos={childPos}
decorations={decorations.forChild(offset, childNode)}
/>
);
}
});

Expand All @@ -97,7 +107,11 @@ export function NodeView({ node, pos }: Props) {

if (Component) {
return node.marks.reduce(
(element, mark) => <MarkView mark={mark}>{element}</MarkView>,
(element, mark) => (
<MarkView mark={mark} ref={nodeDomRef}>
{element}
</MarkView>
),
<Component
ref={domRef}
node={node}
Expand All @@ -117,7 +131,11 @@ export function NodeView({ node, pos }: Props) {

if (outputSpec) {
return node.marks.reduce(
(element, mark) => <MarkView mark={mark}>{element}</MarkView>,
(element, mark) => (
<MarkView ref={nodeDomRef} mark={mark}>
{element}
</MarkView>
),
<OutputSpec ref={domRef} outputSpec={outputSpec}>
{children}
</OutputSpec>
Expand Down
9 changes: 8 additions & 1 deletion src/prosemirror-internal/DecorationInternal.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Decoration } from "prosemirror-view";
import { Node } from "prosemirror-model";
import { Decoration, DecorationSource } from "prosemirror-view";
import { DecorationType } from "../decorations/DecorationType";
import { ReactWidgetType } from "../decorations/ReactWidgetType";

Expand All @@ -11,3 +12,9 @@ export interface ReactWidgetDecoration extends Decoration {
type: ReactWidgetType
inline: false
}

export interface DecorationSourceInternal extends DecorationSource {
locals(node: Node): readonly Decoration[]
forChild(offset: number, child: Node): DecorationSourceInternal
eq(other: DecorationSource): boolean
}

0 comments on commit 0bbeb4c

Please sign in to comment.