From d1c70c264de9f8f44cf0266e366292d4fab71fa4 Mon Sep 17 00:00:00 2001 From: nflnkr Date: Sun, 28 Apr 2024 16:25:59 +0300 Subject: [PATCH] add widget selector polling split button widget class into fixed and normal --- src/widgets/button/ButtonWidget.tsx | 67 ++++++++++++++++++----- src/widgets/button/OpenQuizButton.tsx | 13 ++--- src/widgets/container/ContainerWidget.tsx | 42 ++++++++++---- src/widgets/pollForSelector.ts | 25 +++++++++ widget-test.html | 20 +++++-- 5 files changed, 128 insertions(+), 39 deletions(-) create mode 100644 src/widgets/pollForSelector.ts diff --git a/src/widgets/button/ButtonWidget.tsx b/src/widgets/button/ButtonWidget.tsx index 2c489ac..35447f5 100644 --- a/src/widgets/button/ButtonWidget.tsx +++ b/src/widgets/button/ButtonWidget.tsx @@ -1,31 +1,70 @@ import { Root, createRoot } from "react-dom/client"; import OpenQuizButton from "./OpenQuizButton"; -import { ComponentPropsWithoutRef } from "react"; +import { createPortal } from "react-dom"; +import { pollForSelector } from "../pollForSelector"; export class ButtonWidget { root: Root | undefined; element = document.createElement("div"); - constructor({ quizId, selector, fixedSide }: ComponentPropsWithoutRef) { - if (!fixedSide && !selector) throw new Error("ButtonWidget: Either selector or fixedSide params must be provided"); + constructor({ quizId, selector, selectorPollingTimeLimit = 60 }: { + quizId: string; + selector: string; + /** + * In seconds, null - polling disabled + */ + selectorPollingTimeLimit?: number | null; + }) { + const element = document.querySelector(selector); + if (element) { + this.root = createRoot(element); + this.root.render(); - this.element.style.setProperty("display", "none"); - document.body.appendChild(this.element); + return; + } - this.root = createRoot(this.element); + if (!selectorPollingTimeLimit) { + console.error(`Не удалось найти элемент ${selector} для вставки виджета`); + return; + } - this.root.render( - - ); + pollForSelector(selector, selectorPollingTimeLimit, (element) => { + this.root = createRoot(element); + this.root.render(); + }); } destroy() { if (this.root) this.root.unmount(); this.element.remove(); } -} +} + +export class ButtonWidgetFixed { + root: Root | undefined; + element = document.createElement("div"); + + constructor({ quizId, side }: { + quizId: string; + side: "left" | "right"; + }) { + this.element.style.setProperty("display", "none"); + document.body.appendChild(this.element); + + this.root = createRoot(this.element); + + this.root.render(createPortal( + , + document.body + )); + } + + destroy() { + if (this.root) this.root.unmount(); + this.element.remove(); + } +} diff --git a/src/widgets/button/OpenQuizButton.tsx b/src/widgets/button/OpenQuizButton.tsx index 8ad5ad8..3670fe3 100644 --- a/src/widgets/button/OpenQuizButton.tsx +++ b/src/widgets/button/OpenQuizButton.tsx @@ -1,22 +1,18 @@ import lightTheme from "@/utils/themes/light"; import { Button, ThemeProvider } from "@mui/material"; import { useState } from "react"; -import { createPortal } from "react-dom"; import QuizDialog from "../QuizDialog"; interface Props { - selector?: string; fixedSide?: "left" | "right"; quizId: string; } -export default function OpenQuizButton({ selector, quizId, fixedSide }: Props) { +export default function OpenQuizButton({ quizId, fixedSide }: Props) { const [isQuizDialogOpen, setIsQuizDialogOpen] = useState(false); - const portalContainer = !fixedSide && selector ? document.querySelector(selector)! : document.body; - - return createPortal( + return (