fix: all popups not opening properly

This commit is contained in:
thecodrr
2022-06-20 11:52:13 +05:00
parent 9e405670ca
commit 41c1128023
15 changed files with 94 additions and 40 deletions

View File

@@ -19,6 +19,7 @@ export declare type PopupWrapperProps = {
isOpen: boolean;
onClosed?: () => void;
renderPopup: (closePopup: () => void) => React.ReactNode;
autoCloseOnUnmount?: boolean;
} & Partial<Omit<PopupPresenterProps, "onClose">>;
export declare function PopupWrapper(props: PopupWrapperProps): null;
declare type ShowPopupOptions = {

View File

@@ -146,7 +146,7 @@ export function PopupPresenter(props) {
return _jsx(_PopupPresenter, __assign({}, props));
}
export function PopupWrapper(props) {
var id = props.id, group = props.group, position = props.position, renderPopup = props.renderPopup, isOpen = props.isOpen, onClosed = props.onClosed, presenterProps = __rest(props, ["id", "group", "position", "renderPopup", "isOpen", "onClosed"]);
var id = props.id, group = props.group, position = props.position, renderPopup = props.renderPopup, isOpen = props.isOpen, onClosed = props.onClosed, autoCloseOnUnmount = props.autoCloseOnUnmount, presenterProps = __rest(props, ["id", "group", "position", "renderPopup", "isOpen", "onClosed", "autoCloseOnUnmount"]);
var closePopup = useToolbarStore(function (store) { return store.closePopup; });
var openPopup = useToolbarStore(function (store) { return store.openPopup; });
var closePopupGroup = useToolbarStore(function (store) { return store.closePopupGroup; });
@@ -165,17 +165,18 @@ export function PopupWrapper(props) {
onClosed === null || onClosed === void 0 ? void 0 : onClosed();
}, [isPopupOpen]);
useEffect(function () {
console.log("Opening popup", id, isOpen);
if (isOpen)
openPopup({ id: id, group: group });
else
closePopup(id);
}, [isOpen, id, group, openPopup]);
useEffect(function () {
if (!autoCloseOnUnmount)
return;
return function () {
PopupRenderer === null || PopupRenderer === void 0 ? void 0 : PopupRenderer.closePopup(id);
};
}, [id]);
}, [autoCloseOnUnmount, id]);
useEffect(function () {
if (PopupRenderer && isPopupOpen) {
PopupRenderer.openPopup(id, function () { return (_jsx(PopupPresenter, __assign({ isOpen: isPopupOpen, onClose: function () { return closePopup(id); }, position: position, blocking: true, focusOnRender: true }, presenterProps, { children: _jsx(Box, __assign({ sx: {

View File

@@ -6,13 +6,16 @@ export declare type PopupRendererProps = PropsWithChildren<{
editor: Editor;
}>;
declare type PopupRendererState = {
popups: Record<string, React.FunctionComponent>;
popups: {
id: string;
popup: React.FunctionComponent;
}[];
};
export declare class PopupRenderer extends React.Component<PopupRendererProps> {
export declare class PopupRenderer extends React.Component<PopupRendererProps, PopupRendererState, PopupRendererState> {
popupContainer: HTMLDivElement | null;
state: PopupRendererState;
openPopup(id: string, popup: React.FunctionComponent): void;
closePopup(id: string): void;
openPopup: (id: string, popup: React.FunctionComponent) => void;
closePopup: (id: string) => void;
render(): React.ReactNode;
}
export declare function usePopupRenderer(): PopupRenderer | null;

View File

@@ -40,6 +40,15 @@ var __read = (this && this.__read) || function (o, n) {
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { useContext } from "react";
export var PopupRendererContext = React.createContext(null);
@@ -50,23 +59,36 @@ var PopupRenderer = /** @class */ (function (_super) {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.popupContainer = null;
_this.state = {
popups: {},
popups: [],
};
_this.openPopup = function (id, popup) {
if (!popup)
return;
_this.setState(function (prev) {
return {
popups: __spreadArray(__spreadArray([], __read(prev.popups), false), [{ id: id, popup: popup }], false),
};
});
};
_this.closePopup = function (id) {
_this.setState(function (prev) {
var index = prev.popups.findIndex(function (p) { return p.id === id; });
if (index <= -1)
return prev;
console.log(index, id, prev.popups[index]);
var clone = prev.popups.slice();
clone.splice(index, 1);
return {
popups: clone,
};
});
};
return _this;
}
PopupRenderer.prototype.openPopup = function (id, popup) {
var _a;
this.setState({ popups: __assign(__assign({}, this.state.popups), (_a = {}, _a[id] = popup, _a)) });
};
PopupRenderer.prototype.closePopup = function (id) {
var _a;
this.setState({ popups: __assign(__assign({}, this.state.popups), (_a = {}, _a[id] = null, _a)) });
};
PopupRenderer.prototype.render = function () {
return (_jsxs(PopupRendererContext.Provider, __assign({ value: this }, { children: [this.props.children, _jsxs(EditorContext.Provider, __assign({ value: this.props.editor }, { children: [Object.entries(this.state.popups).map(function (_a) {
var _b = __read(_a, 2), id = _b[0], Popup = _b[1];
if (!Popup)
return null;
return (_jsxs(PopupRendererContext.Provider, __assign({ value: this }, { children: [this.props.children, _jsxs(EditorContext.Provider, __assign({ value: this.props.editor }, { children: [this.state.popups.map(function (_a) {
var id = _a.id, Popup = _a.popup;
console.log(id, Popup);
return _jsx(Popup, {}, id);
}), _jsx("div", { id: "popup-container" })] }))] })));
};

View File

@@ -4,6 +4,7 @@ import { ToolId } from "../tools";
declare type MoreToolsProps = ToolProps & {
popupId: string;
tools: ToolId[];
autoCloseOnUnmount?: boolean;
};
export declare function MoreTools(props: MoreToolsProps): JSX.Element;
export {};

View File

@@ -33,7 +33,7 @@ import { useToolbarLocation } from "../stores/toolbar-store";
import { getToolbarElement } from "../utils/dom";
import { ToolbarGroup } from "./toolbar-group";
export function MoreTools(props) {
var popupId = props.popupId, editor = props.editor, tools = props.tools;
var popupId = props.popupId, editor = props.editor, tools = props.tools, autoCloseOnUnmount = props.autoCloseOnUnmount;
var toolbarLocation = useToolbarLocation();
var isBottom = toolbarLocation === "bottom";
var buttonRef = useRef();
@@ -44,7 +44,7 @@ export function MoreTools(props) {
align: "center",
location: isBottom ? "top" : "below",
yOffset: isBottom ? 10 : 5,
}, focusOnRender: false, blocking: false, renderPopup: function () { return (_jsx(ToolbarGroup, { tools: tools, editor: editor, sx: {
}, autoCloseOnUnmount: autoCloseOnUnmount, focusOnRender: false, blocking: false, renderPopup: function () { return (_jsx(ToolbarGroup, { tools: tools, editor: editor, sx: {
flex: 1,
p: 1,
// TODO: we cannot put a fix height here

View File

@@ -72,7 +72,7 @@ export function ColorTool(props) {
},
}, onOpen: function () {
setIsOpen(function (s) { return !s; });
}, toggled: isOpen }, { children: _jsx(PopupWrapper, { isOpen: isOpen, id: title, group: "color", position: {
}, toggled: isOpen }, { children: _jsx(PopupWrapper, { isOpen: isOpen, id: props.icon, group: "color", position: {
isTargetAbsolute: true,
target: getToolbarElement(),
align: isBottom ? "center" : "end",

View File

@@ -41,7 +41,7 @@ export function ImageSettings(props) {
return null;
var image = useMemo(function () { return findSelectedNode(editor, "image"); }, []);
var float = ((image === null || image === void 0 ? void 0 : image.attrs) || {}).float;
return (_jsx(MoreTools, __assign({}, props, { popupId: "imageSettings", tools: float
return (_jsx(MoreTools, __assign({}, props, { autoCloseOnUnmount: true, popupId: "imageSettings", tools: float
? ["imageAlignLeft", "imageAlignRight", "imageProperties"]
: [
"imageAlignLeft",

View File

@@ -44,7 +44,7 @@ export function TableSettings(props) {
var isBottom = useToolbarLocation() === "bottom";
if (!editor.isActive("table") || !isBottom)
return null;
return (_jsx(MoreTools, __assign({}, props, { popupId: "tableSettings", tools: [
return (_jsx(MoreTools, __assign({}, props, { autoCloseOnUnmount: true, popupId: "tableSettings", tools: [
"insertColumnLeft",
"insertColumnRight",
"insertRowAbove",

View File

@@ -224,6 +224,7 @@ export type PopupWrapperProps = {
isOpen: boolean;
onClosed?: () => void;
renderPopup: (closePopup: () => void) => React.ReactNode;
autoCloseOnUnmount?: boolean;
} & Partial<Omit<PopupPresenterProps, "onClose">>;
export function PopupWrapper(props: PopupWrapperProps) {
let {
@@ -233,6 +234,7 @@ export function PopupWrapper(props: PopupWrapperProps) {
renderPopup,
isOpen,
onClosed,
autoCloseOnUnmount,
...presenterProps
} = props;
const closePopup = useToolbarStore((store) => store.closePopup);
@@ -256,16 +258,16 @@ export function PopupWrapper(props: PopupWrapperProps) {
}, [isPopupOpen]);
useEffect(() => {
console.log("Opening popup", id, isOpen);
if (isOpen) openPopup({ id, group });
else closePopup(id);
}, [isOpen, id, group, openPopup]);
useEffect(() => {
if (!autoCloseOnUnmount) return;
return () => {
PopupRenderer?.closePopup(id);
};
}, [id]);
}, [autoCloseOnUnmount, id]);
useEffect(() => {
if (PopupRenderer && isPopupOpen) {

View File

@@ -9,28 +9,48 @@ export const PopupRendererContext = React.createContext<PopupRenderer | null>(
export const EditorContext = React.createContext<Editor | null>(null);
export type PopupRendererProps = PropsWithChildren<{ editor: Editor }>;
type PopupRendererState = { popups: Record<string, React.FunctionComponent> };
export class PopupRenderer extends React.Component<PopupRendererProps> {
type PopupRendererState = {
popups: { id: string; popup: React.FunctionComponent }[];
};
export class PopupRenderer extends React.Component<
PopupRendererProps,
PopupRendererState,
PopupRendererState
> {
popupContainer: HTMLDivElement | null = null;
state: PopupRendererState = {
popups: {} as Record<string, React.FunctionComponent>,
popups: [] as PopupRendererState["popups"],
};
openPopup(id: string, popup: React.FunctionComponent) {
this.setState({ popups: { ...this.state.popups, [id]: popup } });
}
openPopup = (id: string, popup: React.FunctionComponent) => {
if (!popup) return;
this.setState((prev) => {
return {
popups: [...prev.popups, { id, popup }],
};
});
};
closePopup(id: string) {
this.setState({ popups: { ...this.state.popups, [id]: null } });
}
closePopup = (id: string) => {
this.setState((prev) => {
const index = prev.popups.findIndex((p) => p.id === id);
if (index <= -1) return prev;
console.log(index, id, prev.popups[index]);
const clone = prev.popups.slice();
clone.splice(index, 1);
return {
popups: clone,
};
});
};
render(): React.ReactNode {
return (
<PopupRendererContext.Provider value={this}>
{this.props.children}
<EditorContext.Provider value={this.props.editor}>
{Object.entries(this.state.popups).map(([id, Popup]) => {
if (!Popup) return null;
{this.state.popups.map(({ id, popup: Popup }) => {
console.log(id, Popup);
return <Popup key={id} />;
})}
<div id="popup-container" />

View File

@@ -10,9 +10,10 @@ import { ToolbarGroup } from "./toolbar-group";
type MoreToolsProps = ToolProps & {
popupId: string;
tools: ToolId[];
autoCloseOnUnmount?: boolean;
};
export function MoreTools(props: MoreToolsProps) {
const { popupId, editor, tools } = props;
const { popupId, editor, tools, autoCloseOnUnmount } = props;
const toolbarLocation = useToolbarLocation();
const isBottom = toolbarLocation === "bottom";
const buttonRef = useRef<HTMLButtonElement | null>();
@@ -39,6 +40,7 @@ export function MoreTools(props: MoreToolsProps) {
location: isBottom ? "top" : "below",
yOffset: isBottom ? 10 : 5,
}}
autoCloseOnUnmount={autoCloseOnUnmount}
focusOnRender={false}
blocking={false}
renderPopup={() => (

View File

@@ -55,7 +55,7 @@ export function ColorTool(props: ColorToolProps) {
>
<PopupWrapper
isOpen={isOpen}
id={title}
id={props.icon}
group={"color"}
position={{
isTargetAbsolute: true,

View File

@@ -24,6 +24,7 @@ export function ImageSettings(props: ToolProps) {
return (
<MoreTools
{...props}
autoCloseOnUnmount
popupId="imageSettings"
tools={
float

View File

@@ -27,6 +27,7 @@ export function TableSettings(props: ToolProps) {
return (
<MoreTools
{...props}
autoCloseOnUnmount
popupId="tableSettings"
tools={[
"insertColumnLeft",