refactor: improve portal provider logic

This commit is contained in:
thecodrr
2022-06-22 13:50:08 +05:00
parent 89f5ed0464
commit 0c669a5aea
27 changed files with 128 additions and 245 deletions

File diff suppressed because one or more lines are too long

View File

@@ -10,12 +10,11 @@ var __assign = (this && this.__assign) || function () {
return __assign.apply(this, arguments);
};
import { jsx as _jsx } from "react/jsx-runtime";
import { useCallback, useRef } from "react";
import { forwardRef, useCallback, useRef } from "react";
import { useEffect } from "react";
import { Button as RebassButton } from "rebass";
export function Button(props) {
export var Button = forwardRef(function (props, forwardedRef) {
var buttonRef = useRef();
var touchStartTime = useRef(0);
useEffect(function () {
if (!buttonRef.current)
return;
@@ -23,59 +22,21 @@ export function Button(props) {
passive: false,
capture: true,
});
// buttonRef.current.addEventListener("touchmove", onTouchMove, {
// passive: false,
// capture: true,
// });
// buttonRef.current.addEventListener("touchend", onTouchEnd, {
// passive: false,
// capture: true,
// });
// buttonRef.current.addEventListener("touchstart", onTouchStart, {
// passive: false,
// capture: true,
// });
return function () {
var _a;
(_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener("mousedown", onMouseDown, {
capture: true,
});
// buttonRef.current?.removeEventListener("touchmove", onTouchMove, {
// capture: true,
// });
// buttonRef.current?.removeEventListener("touchend", onTouchEnd, {
// capture: true,
// });
// buttonRef.current?.removeEventListener("touchstart", onTouchStart, {
// capture: true,
// });
};
}, []);
var onMouseDown = useCallback(function (e) {
e.preventDefault();
}, []);
// const onTouchEnd = useCallback((e) => {
// e.preventDefault();
// const now = Date.now();
// setTimeout(() => {
// console.log(now, touchStartTime.current);
// if (touchStartTime.current === 0) return;
// if (now - touchStartTime.current > 300) return;
// //@ts-ignore
// props.onClick(e);
// }, 1);
// }, []);
// const onTouchStart = useCallback((e) => {
// touchStartTime.current = Date.now();
// console.log("HELLO!");
// e.preventDefault();
// }, []);
// const onTouchMove = useCallback((e) => {
// console.log("HELLO!");
// touchStartTime.current = 0;
// }, []);
return (_jsx(RebassButton, __assign({}, props, { ref: function (ref) {
buttonRef.current = ref;
// props.ref = ref;
if (typeof forwardedRef === "function")
forwardedRef(ref);
else if (forwardedRef)
forwardedRef.current = ref;
}, onClick: props.onClick, onMouseDown: function () { } })));
}
});

View File

@@ -33,11 +33,11 @@ export function Menu(props) {
var hoverTimeout = useRef();
var onAction = useCallback(function (e, item) {
e === null || e === void 0 ? void 0 : e.stopPropagation();
if (onClose)
onClose();
if (item.onClick) {
item.onClick();
}
if (onClose)
onClose();
}, [onClose]);
var _b = useFocus(items, function (e) {
var item = items[focusIndex];

View File

@@ -11,8 +11,7 @@ var __assign = (this && this.__assign) || function () {
};
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useRef } from "react";
import { Flex, Text } from "rebass";
import { Button } from "../button";
import { Flex, Text, Button } from "rebass";
import { Icon } from "../../toolbar/components/icon";
import { Icons } from "../../toolbar/icons";
import { useToolbarLocation } from "../../toolbar/stores/toolbar-store";

View File

@@ -164,6 +164,7 @@ export var CodeBlock = Node.create({
toggleCodeBlock: function (attributes) {
return function (_a) {
var commands = _a.commands;
console.log("TOGGLING!");
return commands.toggleNode(_this.name, "paragraph", attributes);
};
},

View File

@@ -2,21 +2,19 @@ import React from "react";
import { NodeView, Decoration, DecorationSource } from "prosemirror-view";
import { Node as PMNode } from "prosemirror-model";
import { PortalProviderAPI } from "./react-portal-provider";
import { EventDispatcher } from "./event-dispatcher";
import { ReactNodeViewProps, ReactNodeViewOptions, GetPosNode, ForwardRef, ContentDOM } from "./types";
import { Editor, NodeViewRendererProps } from "@tiptap/core";
export declare class ReactNodeView<P extends ReactNodeViewProps> implements NodeView {
protected readonly editor: Editor;
protected readonly getPos: GetPosNode;
protected readonly portalProviderAPI: PortalProviderAPI;
protected readonly eventDispatcher: EventDispatcher;
protected readonly options: ReactNodeViewOptions<P>;
private domRef;
private contentDOMWrapper?;
contentDOM: HTMLElement | undefined;
node: PMNode;
isDragging: boolean;
constructor(node: PMNode, editor: Editor, getPos: GetPosNode, portalProviderAPI: PortalProviderAPI, eventDispatcher: EventDispatcher, options: ReactNodeViewOptions<P>);
portalProviderAPI: PortalProviderAPI;
constructor(node: PMNode, editor: Editor, getPos: GetPosNode, options: ReactNodeViewOptions<P>);
/**
* This method exists to move initialization logic out of the constructor,
* so object can be initialized properly before calling render first time.

View File

@@ -38,15 +38,15 @@ import { jsx as _jsx } from "react/jsx-runtime";
import { NodeSelection } from "prosemirror-state";
import { ThemeProvider } from "emotion-theming";
var ReactNodeView = /** @class */ (function () {
function ReactNodeView(node, editor, getPos, portalProviderAPI, eventDispatcher, options) {
function ReactNodeView(node, editor, getPos, options) {
var _this = this;
this.editor = editor;
this.getPos = getPos;
this.portalProviderAPI = portalProviderAPI;
this.eventDispatcher = eventDispatcher;
this.options = options;
this.isDragging = false;
this.handleRef = function (node) { return _this._handleRef(node); };
this.portalProviderAPI = editor.storage
.portalProviderAPI;
this.node = node;
}
/**
@@ -84,6 +84,7 @@ var ReactNodeView = /** @class */ (function () {
};
ReactNodeView.prototype.renderReactComponent = function (component) {
if (!this.domRef || !component || !this.portalProviderAPI) {
console.warn("Cannot render node view", this.editor.storage);
return;
}
this.portalProviderAPI.render(component, this.domRef);
@@ -337,6 +338,6 @@ export function createNodeView(component, options) {
return function (_a) {
var node = _a.node, getPos = _a.getPos, editor = _a.editor;
var _getPos = function () { return (typeof getPos === "boolean" ? -1 : getPos()); };
return new ReactNodeView(node, editor, _getPos, editor.storage.portalProviderAPI, editor.storage.eventDispatcher, __assign(__assign({}, options), { component: component })).init();
return new ReactNodeView(node, editor, _getPos, __assign(__assign({}, options), { component: component })).init();
};
}

View File

@@ -1,8 +1,6 @@
import React from "react";
import React, { PropsWithChildren } from "react";
import { EventDispatcher } from "./event-dispatcher";
export declare type BasePortalProviderProps = {
render: (portalProviderAPI: PortalProviderAPI) => React.ReactChild | JSX.Element | null;
};
export declare type BasePortalProviderProps = PropsWithChildren<{}>;
export declare type Portals = Map<HTMLElement, React.ReactChild>;
export declare type PortalRendererState = {
portals: Portals;
@@ -19,11 +17,12 @@ export declare class PortalProviderAPI extends EventDispatcher {
forceUpdate(): void;
remove(container: HTMLElement): void;
}
export declare function usePortalProvider(): PortalProviderAPI | undefined;
export declare class PortalProvider extends React.Component<BasePortalProviderProps> {
static displayName: string;
portalProviderAPI: PortalProviderAPI;
constructor(props: BasePortalProviderProps);
render(): JSX.Element | React.ReactChild | null;
render(): JSX.Element;
componentDidUpdate(): void;
}
export declare class PortalRenderer extends React.Component<{

View File

@@ -13,6 +13,17 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
@@ -29,8 +40,8 @@ var __read = (this && this.__read) || function (o, n) {
}
return ar;
};
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
import React from "react";
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React, { useContext } from "react";
import { createPortal, unstable_renderSubtreeIntoContainer, unmountComponentAtNode, } from "react-dom";
import { EventDispatcher } from "./event-dispatcher";
var PortalProviderAPI = /** @class */ (function (_super) {
@@ -72,6 +83,10 @@ var PortalProviderAPI = /** @class */ (function (_super) {
return PortalProviderAPI;
}(EventDispatcher));
export { PortalProviderAPI };
var PortalProviderContext = React.createContext(undefined);
export function usePortalProvider() {
return useContext(PortalProviderContext);
}
var PortalProvider = /** @class */ (function (_super) {
__extends(PortalProvider, _super);
function PortalProvider(props) {
@@ -80,7 +95,7 @@ var PortalProvider = /** @class */ (function (_super) {
return _this;
}
PortalProvider.prototype.render = function () {
return this.props.render(this.portalProviderAPI);
return (_jsxs(PortalProviderContext.Provider, __assign({ value: this.portalProviderAPI }, { children: [this.props.children, _jsx(PortalRenderer, { portalProviderAPI: this.portalProviderAPI })] })));
};
PortalProvider.prototype.componentDidUpdate = function () {
this.portalProviderAPI.forceUpdate();

View File

@@ -1,7 +1,5 @@
import React from "react";
import { Node as PMNode } from "prosemirror-model";
import { PortalProviderAPI } from "./react-portal-provider";
import { EventDispatcher } from "./event-dispatcher";
import { ReactNodeViewOptions, GetPosNode, SelectionBasedReactNodeViewProps, ForwardRef } from "./types";
import { ReactNodeView } from "./react-node-view";
import { Editor, NodeViewRendererProps } from "@tiptap/core";
@@ -33,7 +31,7 @@ export declare class SelectionBasedNodeView<P extends SelectionBasedReactNodeVie
private selectionChangeState;
pos: number;
posEnd: number | undefined;
constructor(node: PMNode, editor: Editor, getPos: GetPosNode, portalProviderAPI: PortalProviderAPI, eventDispatcher: EventDispatcher, options: ReactNodeViewOptions<P>);
constructor(node: PMNode, editor: Editor, getPos: GetPosNode, options: ReactNodeViewOptions<P>);
render(props?: P, forwardRef?: ForwardRef): React.ReactElement<any> | null;
/**
* Update current node's start and end positions.

View File

@@ -55,8 +55,8 @@ import { ThemeProvider } from "emotion-theming";
*/
var SelectionBasedNodeView = /** @class */ (function (_super) {
__extends(SelectionBasedNodeView, _super);
function SelectionBasedNodeView(node, editor, getPos, portalProviderAPI, eventDispatcher, options) {
var _this = _super.call(this, node, editor, getPos, portalProviderAPI, eventDispatcher, options) || this;
function SelectionBasedNodeView(node, editor, getPos, options) {
var _this = _super.call(this, node, editor, getPos, options) || this;
_this.pos = -1;
_this.isNodeInsideSelection = function (from, to, pos, posEnd) {
var _a;
@@ -174,6 +174,6 @@ export function createSelectionBasedNodeView(component, options) {
return function (_a) {
var node = _a.node, getPos = _a.getPos, editor = _a.editor;
var _getPos = function () { return (typeof getPos === "boolean" ? -1 : getPos()); };
return new SelectionBasedNodeView(node, editor, _getPos, editor.storage.portalProviderAPI, editor.storage.eventDispatcher, __assign(__assign({}, options), { component: component })).init();
return new SelectionBasedNodeView(node, editor, _getPos, __assign(__assign({}, options), { component: component })).init();
};
}

View File

@@ -53,7 +53,7 @@ export function TableNodeView(editor) {
__extends(TableNode, _super);
function TableNode(node, cellMinWidth) {
var _this = _super.call(this, node, editor, function () { return 0; }, // todo
editor.storage.portalProviderAPI, editor.storage.eventDispatcher, {
{
component: TableComponent,
shouldUpdate: function (prev, next) {
return prev.type === next.type;

View File

@@ -3,10 +3,8 @@ import { EditorOptions } from "@tiptap/react";
import Toolbar from "./toolbar";
import { Theme } from "@notesnook/theme";
import { AttachmentOptions } from "./extensions/attachment";
import { PortalProviderAPI } from "./extensions/react";
declare const useTiptap: (options?: Partial<EditorOptions & AttachmentOptions & {
theme: Theme;
portalProviderAPI: PortalProviderAPI;
}>, deps?: React.DependencyList) => import("@tiptap/react").Editor | null;
}>, deps?: import("react").DependencyList) => import("@tiptap/react").Editor | null;
export { useTiptap, Toolbar };
export * from "./extensions/react";

View File

@@ -53,7 +53,7 @@ import { EmbedNode } from "./extensions/embed";
import { CodeBlock } from "./extensions/code-block";
import { ListItem } from "./extensions/list-item";
import { Link } from "./extensions/link";
import { EventDispatcher, NodeViewSelectionNotifier, } from "./extensions/react";
import { NodeViewSelectionNotifier, usePortalProvider, } from "./extensions/react";
import { OutlineList } from "./extensions/outline-list";
import { OutlineListItem } from "./extensions/outline-list-item";
import { Table } from "./extensions/table";
@@ -64,8 +64,9 @@ EditorView.prototype.updateState = function updateState(state) {
};
var useTiptap = function (options, deps) {
if (options === void 0) { options = {}; }
var theme = options.theme, onCreate = options.onCreate, onDownloadAttachment = options.onDownloadAttachment, onOpenAttachmentPicker = options.onOpenAttachmentPicker, portalProviderAPI = options.portalProviderAPI, restOptions = __rest(options, ["theme", "onCreate", "onDownloadAttachment", "onOpenAttachmentPicker", "portalProviderAPI"]);
var eventDispatcher = useMemo(function () { return new EventDispatcher(); }, []);
if (deps === void 0) { deps = []; }
var theme = options.theme, onDownloadAttachment = options.onDownloadAttachment, onOpenAttachmentPicker = options.onOpenAttachmentPicker, restOptions = __rest(options, ["theme", "onDownloadAttachment", "onOpenAttachmentPicker"]);
var PortalProviderAPI = usePortalProvider();
var defaultOptions = useMemo(function () { return ({
extensions: [
NodeViewSelectionNotifier,
@@ -128,27 +129,15 @@ var useTiptap = function (options, deps) {
OutlineList,
ListItem,
],
onCreate: function (_a) {
onBeforeCreate: function (_a) {
var editor = _a.editor;
if (theme) {
editor.storage.theme = theme;
}
if (portalProviderAPI)
editor.storage.portalProviderAPI = portalProviderAPI;
if (eventDispatcher)
editor.storage.eventDispatcher = eventDispatcher;
if (onCreate)
onCreate({ editor: editor });
editor.storage.portalProviderAPI = PortalProviderAPI;
},
injectCSS: false,
}); }, [
theme,
onCreate,
onDownloadAttachment,
onOpenAttachmentPicker,
portalProviderAPI,
eventDispatcher,
]);
}); }, [theme, onDownloadAttachment, onOpenAttachmentPicker, PortalProviderAPI]);
var editor = useEditor(__assign(__assign({}, defaultOptions), restOptions), deps);
/**
* Add editor to global for use in React Native.

View File

@@ -98,7 +98,7 @@ export function TablePopup(props) {
columns: cellLocation.column,
rows: cellLocation.row,
});
} })); }) })), _jsxs(Flex, __assign({ sx: {
} }, index)); }) })), _jsxs(Flex, __assign({ sx: {
display: ["flex", "none", "none"],
my: 1,
alignItems: "center",

View File

@@ -37,7 +37,7 @@ import { showPopup } from "../../components/popup-presenter";
import { ImageUploadPopup } from "../popups/image-upload";
import { Button } from "../../components/button";
export function InsertBlock(props) {
var buttonRef = useRef();
var buttonRef = useRef(null);
var _a = __read(useState(false), 2), isOpen = _a[0], setIsOpen = _a[1];
var toolbarLocation = useToolbarLocation();
var isMobile = useIsMobile();

View File

@@ -1,94 +1,41 @@
import React, { useCallback, useRef } from "react";
import { forwardRef, useCallback, useRef } from "react";
import { useEffect } from "react";
import { Button as RebassButton, ButtonProps } from "rebass";
export function Button(props: ButtonProps) {
const buttonRef = useRef<HTMLButtonElement>();
const touchStartTime = useRef(0);
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(props: ButtonProps, forwardedRef) => {
const buttonRef = useRef<HTMLButtonElement>();
useEffect(() => {
if (!buttonRef.current) return;
useEffect(() => {
if (!buttonRef.current) return;
buttonRef.current.addEventListener("mousedown", onMouseDown, {
passive: false,
capture: true,
});
// buttonRef.current.addEventListener("touchmove", onTouchMove, {
// passive: false,
// capture: true,
// });
// buttonRef.current.addEventListener("touchend", onTouchEnd, {
// passive: false,
// capture: true,
// });
// buttonRef.current.addEventListener("touchstart", onTouchStart, {
// passive: false,
// capture: true,
// });
return () => {
buttonRef.current?.removeEventListener("mousedown", onMouseDown, {
buttonRef.current.addEventListener("mousedown", onMouseDown, {
passive: false,
capture: true,
});
// buttonRef.current?.removeEventListener("touchmove", onTouchMove, {
// capture: true,
// });
// buttonRef.current?.removeEventListener("touchend", onTouchEnd, {
// capture: true,
// });
return () => {
buttonRef.current?.removeEventListener("mousedown", onMouseDown, {
capture: true,
});
};
}, []);
// buttonRef.current?.removeEventListener("touchstart", onTouchStart, {
// capture: true,
// });
};
}, []);
const onMouseDown = useCallback((e: MouseEvent) => {
e.preventDefault();
}, []);
const onMouseDown = useCallback((e: MouseEvent) => {
e.preventDefault();
}, []);
// const onTouchEnd = useCallback((e) => {
// e.preventDefault();
// const now = Date.now();
// setTimeout(() => {
// console.log(now, touchStartTime.current);
// if (touchStartTime.current === 0) return;
// if (now - touchStartTime.current > 300) return;
// //@ts-ignore
// props.onClick(e);
// }, 1);
// }, []);
// const onTouchStart = useCallback((e) => {
// touchStartTime.current = Date.now();
// console.log("HELLO!");
// e.preventDefault();
// }, []);
// const onTouchMove = useCallback((e) => {
// console.log("HELLO!");
// touchStartTime.current = 0;
// }, []);
return (
<RebassButton
{...props}
ref={(ref) => {
buttonRef.current = ref;
// props.ref = ref;
}}
onClick={props.onClick}
onMouseDown={() => {}}
// onTouchEnd={() => {}}
// onTouchMove={() => {}}
// // {
// // touchStartTime.current = 0;
// // }}
// onTouchStart={() => {}}
/>
);
}
return (
<RebassButton
{...props}
ref={(ref) => {
buttonRef.current = ref;
if (typeof forwardedRef === "function") forwardedRef(ref);
else if (forwardedRef) forwardedRef.current = ref;
}}
onClick={props.onClick}
onMouseDown={() => {}}
/>
);
}
);

View File

@@ -26,10 +26,11 @@ export function Menu(props: MenuProps) {
const onAction = useCallback(
(e, item) => {
e?.stopPropagation();
if (onClose) onClose();
if (item.onClick) {
item.onClick();
}
if (onClose) onClose();
},
[onClose]
);

View File

@@ -1,6 +1,5 @@
import { useRef } from "react";
import { Flex, Text } from "rebass";
import { Button } from "../button";
import { Flex, Text, Button } from "rebass";
import { Icon } from "../../toolbar/components/icon";
import { Icons } from "../../toolbar/icons";
import { useToolbarLocation } from "../../toolbar/stores/toolbar-store";

View File

@@ -207,6 +207,7 @@ export const CodeBlock = Node.create<CodeBlockOptions>({
toggleCodeBlock:
(attributes) =>
({ commands }) => {
console.log("TOGGLING!");
return commands.toggleNode(this.name, "paragraph", attributes);
},
changeCodeBlockIndentation:

View File

@@ -22,15 +22,16 @@ export class ReactNodeView<P extends ReactNodeViewProps> implements NodeView {
contentDOM: HTMLElement | undefined;
node: PMNode;
isDragging = false;
portalProviderAPI: PortalProviderAPI;
constructor(
node: PMNode,
protected readonly editor: Editor,
protected readonly getPos: GetPosNode,
protected readonly portalProviderAPI: PortalProviderAPI,
protected readonly eventDispatcher: EventDispatcher,
protected readonly options: ReactNodeViewOptions<P>
) {
this.portalProviderAPI = editor.storage
.portalProviderAPI as PortalProviderAPI;
this.node = node;
}
@@ -76,6 +77,7 @@ export class ReactNodeView<P extends ReactNodeViewProps> implements NodeView {
component: () => React.ReactElement<any> | null
) {
if (!this.domRef || !component || !this.portalProviderAPI) {
console.warn("Cannot render node view", this.editor.storage);
return;
}
@@ -416,17 +418,10 @@ export function createNodeView<TProps extends ReactNodeViewProps>(
return ({ node, getPos, editor }: NodeViewRendererProps) => {
const _getPos = () => (typeof getPos === "boolean" ? -1 : getPos());
return new ReactNodeView<TProps>(
node,
editor,
_getPos,
editor.storage.portalProviderAPI,
editor.storage.eventDispatcher,
{
...options,
component,
}
).init();
return new ReactNodeView<TProps>(node, editor, _getPos, {
...options,
component,
}).init();
};
}

View File

@@ -1,4 +1,4 @@
import React from "react";
import React, { PropsWithChildren, useContext } from "react";
import {
createPortal,
unstable_renderSubtreeIntoContainer,
@@ -6,11 +6,7 @@ import {
} from "react-dom";
import { EventDispatcher } from "./event-dispatcher";
export type BasePortalProviderProps = {
render: (
portalProviderAPI: PortalProviderAPI
) => React.ReactChild | JSX.Element | null;
};
export type BasePortalProviderProps = PropsWithChildren<{}>;
export type Portals = Map<HTMLElement, React.ReactChild>;
@@ -71,6 +67,12 @@ export class PortalProviderAPI extends EventDispatcher {
}
}
}
const PortalProviderContext = React.createContext<
PortalProviderAPI | undefined
>(undefined);
export function usePortalProvider() {
return useContext(PortalProviderContext);
}
export class PortalProvider extends React.Component<BasePortalProviderProps> {
static displayName = "PortalProvider";
@@ -83,7 +85,12 @@ export class PortalProvider extends React.Component<BasePortalProviderProps> {
}
render() {
return this.props.render(this.portalProviderAPI);
return (
<PortalProviderContext.Provider value={this.portalProviderAPI}>
{this.props.children}
<PortalRenderer portalProviderAPI={this.portalProviderAPI} />
</PortalProviderContext.Provider>
);
}
componentDidUpdate() {

View File

@@ -57,11 +57,9 @@ export class SelectionBasedNodeView<
node: PMNode,
editor: Editor,
getPos: GetPosNode,
portalProviderAPI: PortalProviderAPI,
eventDispatcher: EventDispatcher,
options: ReactNodeViewOptions<P>
) {
super(node, editor, getPos, portalProviderAPI, eventDispatcher, options);
super(node, editor, getPos, options);
this.updatePos();
@@ -251,16 +249,9 @@ export function createSelectionBasedNodeView<
) {
return ({ node, getPos, editor }: NodeViewRendererProps) => {
const _getPos = () => (typeof getPos === "boolean" ? -1 : getPos());
return new SelectionBasedNodeView(
node,
editor,
_getPos,
editor.storage.portalProviderAPI,
editor.storage.eventDispatcher,
{
...options,
component,
}
).init();
return new SelectionBasedNodeView(node, editor, _getPos, {
...options,
component,
}).init();
};
}

View File

@@ -77,8 +77,6 @@ export function TableNodeView(editor: Editor) {
node,
editor,
() => 0, // todo
editor.storage.portalProviderAPI,
editor.storage.eventDispatcher,
{
component: TableComponent,
shouldUpdate: (prev, next) => {

View File

@@ -4,7 +4,7 @@ import Placeholder from "@tiptap/extension-placeholder";
import Underline from "@tiptap/extension-underline";
import { EditorOptions, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import { useMemo } from "react";
import { useEffect, useMemo } from "react";
import { EditorView } from "prosemirror-view";
import Toolbar from "./toolbar";
import TextAlign from "@tiptap/extension-text-align";
@@ -36,6 +36,7 @@ import {
PortalProviderAPI,
EventDispatcher,
NodeViewSelectionNotifier,
usePortalProvider,
} from "./extensions/react";
import { OutlineList } from "./extensions/outline-list";
import { OutlineListItem } from "./extensions/outline-list-item";
@@ -47,21 +48,16 @@ EditorView.prototype.updateState = function updateState(state) {
};
const useTiptap = (
options: Partial<
EditorOptions &
AttachmentOptions & { theme: Theme; portalProviderAPI: PortalProviderAPI }
> = {},
deps?: React.DependencyList
options: Partial<EditorOptions & AttachmentOptions & { theme: Theme }> = {},
deps: React.DependencyList = []
) => {
const {
theme,
onCreate,
onDownloadAttachment,
onOpenAttachmentPicker,
portalProviderAPI,
...restOptions
} = options;
const eventDispatcher = useMemo(() => new EventDispatcher(), []);
const PortalProviderAPI = usePortalProvider();
const defaultOptions = useMemo<Partial<EditorOptions>>(
() => ({
@@ -127,27 +123,15 @@ const useTiptap = (
OutlineList,
ListItem,
],
onCreate: ({ editor }) => {
onBeforeCreate: ({ editor }) => {
if (theme) {
editor.storage.theme = theme;
}
if (portalProviderAPI)
editor.storage.portalProviderAPI = portalProviderAPI;
if (eventDispatcher) editor.storage.eventDispatcher = eventDispatcher;
if (onCreate) onCreate({ editor });
editor.storage.portalProviderAPI = PortalProviderAPI;
},
injectCSS: false,
}),
[
theme,
onCreate,
onDownloadAttachment,
onOpenAttachmentPicker,
portalProviderAPI,
eventDispatcher,
]
[theme, onDownloadAttachment, onOpenAttachmentPicker, PortalProviderAPI]
);
const editor = useEditor(

View File

@@ -81,6 +81,7 @@ export function TablePopup(props: TablePopupProps) {
.fill(0)
.map((_, index) => (
<Box
key={index}
data-index={index}
height={cellSize || 15}
sx={{

View File

@@ -24,7 +24,7 @@ import { ImageUploadPopup } from "../popups/image-upload";
import { Button } from "../../components/button";
export function InsertBlock(props: ToolProps) {
const buttonRef = useRef<HTMLButtonElement | null>();
const buttonRef = useRef<HTMLButtonElement>(null);
const [isOpen, setIsOpen] = useState(false);
const toolbarLocation = useToolbarLocation();
const isMobile = useIsMobile();