move widget types to package
This commit is contained in:
parent
8276355ed5
commit
81cbe420c5
2
.gitignore
vendored
2
.gitignore
vendored
@ -11,7 +11,7 @@ node_modules
|
||||
dist
|
||||
dist-package
|
||||
dist-ssr
|
||||
widget
|
||||
/widget
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
|
22
lib/model/widget/banner.ts
Normal file
22
lib/model/widget/banner.ts
Normal file
@ -0,0 +1,22 @@
|
||||
export interface BannerWidgetComponentProps {
|
||||
quizId: string;
|
||||
position: "topleft" | "topright" | "bottomleft" | "bottomright";
|
||||
onWidgetClose?: () => void;
|
||||
appealText?: string;
|
||||
quizHeaderText?: string;
|
||||
buttonTextColor?: string;
|
||||
buttonBackgroundColor?: string;
|
||||
/**
|
||||
* Открыть квиз через X секунд, 0 - сразу
|
||||
*/
|
||||
autoShowQuizTime?: number | null;
|
||||
openOnLeaveAttempt?: boolean;
|
||||
buttonFlash?: boolean;
|
||||
hideOnMobile?: boolean;
|
||||
withShadow?: boolean;
|
||||
rounded?: boolean;
|
||||
bannerFullWidth?: boolean;
|
||||
pulsation?: boolean;
|
||||
}
|
||||
|
||||
export type BannerWidgetParams = Omit<BannerWidgetComponentProps, "onWidgetClose">;
|
29
lib/model/widget/button.ts
Normal file
29
lib/model/widget/button.ts
Normal file
@ -0,0 +1,29 @@
|
||||
export interface ButtonWidgetComponentProps {
|
||||
quizId: string;
|
||||
fixedSide?: "left" | "right";
|
||||
dialogDimensions?: { width: string; height: string; };
|
||||
/**
|
||||
* Открыть квиз через X секунд, 0 - сразу
|
||||
*/
|
||||
autoShowQuizTime?: number | null;
|
||||
hideOnMobile?: boolean;
|
||||
openOnLeaveAttempt?: boolean;
|
||||
buttonFlash?: boolean;
|
||||
withShadow?: boolean;
|
||||
rounded?: boolean;
|
||||
buttonText?: string;
|
||||
buttonTextColor?: string;
|
||||
buttonBackgroundColor?: string;
|
||||
}
|
||||
|
||||
export type ButtonWidgetParams = Omit<ButtonWidgetComponentProps, "fixedSide"> & {
|
||||
selector: string;
|
||||
/**
|
||||
* In seconds, null - polling disabled
|
||||
*/
|
||||
selectorPollingTimeLimit?: number | null;
|
||||
};
|
||||
|
||||
export type ButtonWidgetFixedParams = Omit<ButtonWidgetComponentProps, "selector"> & {
|
||||
fixedSide: "left" | "right";
|
||||
};
|
15
lib/model/widget/container.ts
Normal file
15
lib/model/widget/container.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { ButtonWidgetComponentProps } from "./button";
|
||||
|
||||
export type ContainerWidgetComponentProps = ButtonWidgetComponentProps & {
|
||||
quizId: string;
|
||||
showButtonOnMobile?: boolean;
|
||||
dimensions?: { width: string; height: string; };
|
||||
};
|
||||
|
||||
export type ContainerWidgetParams = ContainerWidgetComponentProps & {
|
||||
selector: string;
|
||||
/**
|
||||
* In seconds, null - polling disabled
|
||||
*/
|
||||
selectorPollingTimeLimit?: number | null;
|
||||
};
|
12
lib/model/widget/popup.ts
Normal file
12
lib/model/widget/popup.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export interface PopupWidgetComponentProps {
|
||||
quizId: string;
|
||||
dialogDimensions?: { width: string; height: string; };
|
||||
/**
|
||||
* Открыть квиз через X секунд, 0 - сразу
|
||||
*/
|
||||
autoShowQuizTime?: number | null;
|
||||
hideOnMobile?: boolean;
|
||||
openOnLeaveAttempt?: boolean;
|
||||
}
|
||||
|
||||
export type PopupWidgetParams = PopupWidgetComponentProps;
|
20
lib/model/widget/side.ts
Normal file
20
lib/model/widget/side.ts
Normal file
@ -0,0 +1,20 @@
|
||||
export interface SideWidgetComponentProps {
|
||||
quizId: string;
|
||||
position: "left" | "right";
|
||||
buttonBackgroundColor?: string;
|
||||
buttonTextColor?: string;
|
||||
dialogDimensions?: { width: string; height: string; };
|
||||
fullScreen?: boolean;
|
||||
buttonFlash?: boolean;
|
||||
/**
|
||||
* Скрывать виджет первые X секунд
|
||||
*/
|
||||
autoOpenTime?: number;
|
||||
/**
|
||||
* Открыть квиз через X секунд, 0 - сразу
|
||||
*/
|
||||
autoShowQuizTime?: number | null;
|
||||
hideOnMobile?: boolean;
|
||||
}
|
||||
|
||||
export type SideWidgetParams = SideWidgetComponentProps;
|
@ -1,15 +1,13 @@
|
||||
import { BannerWidgetParams } from "@/model/widget/banner";
|
||||
import { Root, createRoot } from "react-dom/client";
|
||||
import QuizBanner from "./QuizBanner";
|
||||
import { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
|
||||
type Props = Omit<ComponentPropsWithoutRef<typeof QuizBanner>, "onClose">;
|
||||
|
||||
export class BannerWidget {
|
||||
root: Root | undefined;
|
||||
element = document.createElement("div");
|
||||
|
||||
constructor(props: Props) {
|
||||
constructor(props: BannerWidgetParams) {
|
||||
this.element.style.setProperty("display", "none");
|
||||
document.body.appendChild(this.element);
|
||||
|
||||
@ -18,7 +16,7 @@ export class BannerWidget {
|
||||
this.render(props);
|
||||
}
|
||||
|
||||
render(props: Props) {
|
||||
render(props: BannerWidgetParams) {
|
||||
this.root?.render(
|
||||
<QuizBanner
|
||||
{...props}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { BannerWidgetComponentProps } from "@/model/widget/banner";
|
||||
import lightTheme from "@/utils/themes/light";
|
||||
import { Box, Button, Fade, IconButton, ThemeProvider, Typography, useMediaQuery } from "@mui/material";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
@ -10,27 +11,6 @@ import { useQuizCompletionStatus } from "../shared/useQuizCompletionStatus";
|
||||
|
||||
const PADDING = 10;
|
||||
|
||||
interface Props {
|
||||
quizId: string;
|
||||
position: "topleft" | "topright" | "bottomleft" | "bottomright";
|
||||
onWidgetClose?: () => void;
|
||||
appealText?: string;
|
||||
quizHeaderText?: string;
|
||||
buttonTextColor?: string;
|
||||
buttonBackgroundColor?: string;
|
||||
/**
|
||||
* Открыть квиз через X секунд, 0 - сразу
|
||||
*/
|
||||
autoShowQuizTime?: number | null;
|
||||
openOnLeaveAttempt?: boolean;
|
||||
buttonFlash?: boolean;
|
||||
hideOnMobile?: boolean;
|
||||
withShadow?: boolean;
|
||||
rounded?: boolean;
|
||||
bannerFullWidth?: boolean;
|
||||
pulsation?: boolean;
|
||||
}
|
||||
|
||||
export default function QuizBanner({
|
||||
quizId,
|
||||
position,
|
||||
@ -47,7 +27,7 @@ export default function QuizBanner({
|
||||
rounded = false,
|
||||
bannerFullWidth = false,
|
||||
pulsation = false,
|
||||
}: Props) {
|
||||
}: BannerWidgetComponentProps) {
|
||||
const isMobile = useMediaQuery("(max-width: 600px)");
|
||||
const [isQuizShown, setIsQuizShown] = useState<boolean>(false);
|
||||
const [isFlashEnabled, setIsFlashEnabled] = useState<boolean>(buttonFlash);
|
||||
|
@ -1,22 +1,14 @@
|
||||
import { ComponentPropsWithoutRef } from "react";
|
||||
import { ButtonWidgetFixedParams, ButtonWidgetParams } from "@/model/widget/button";
|
||||
import { createPortal } from "react-dom";
|
||||
import { Root, createRoot } from "react-dom/client";
|
||||
import { pollForSelector } from "../shared/pollForSelector";
|
||||
import OpenQuizButton from "./OpenQuizButton";
|
||||
import { createPortal } from "react-dom";
|
||||
|
||||
|
||||
type ButtonWidgetProps = Omit<ComponentPropsWithoutRef<typeof OpenQuizButton>, "fixedSide">;
|
||||
|
||||
export class ButtonWidget {
|
||||
root: Root | undefined;
|
||||
|
||||
constructor(props: ButtonWidgetProps & {
|
||||
selector: string;
|
||||
/**
|
||||
* In seconds, null - polling disabled
|
||||
*/
|
||||
selectorPollingTimeLimit?: number | null;
|
||||
}) {
|
||||
constructor(props: ButtonWidgetParams) {
|
||||
const { selector, selectorPollingTimeLimit = 60 } = props;
|
||||
|
||||
const element = document.querySelector(selector);
|
||||
@ -38,7 +30,7 @@ export class ButtonWidget {
|
||||
});
|
||||
}
|
||||
|
||||
render(props: ButtonWidgetProps) {
|
||||
render(props: Omit<ButtonWidgetParams, "selector" | "selectorPollingTimeLimit">) {
|
||||
this.root?.render(<OpenQuizButton {...props} />);
|
||||
}
|
||||
|
||||
@ -47,15 +39,11 @@ export class ButtonWidget {
|
||||
}
|
||||
}
|
||||
|
||||
type ButtonWidgetFixedProps = Omit<ComponentPropsWithoutRef<typeof OpenQuizButton>, "selector"> & {
|
||||
fixedSide: "left" | "right";
|
||||
};
|
||||
|
||||
export class ButtonWidgetFixed {
|
||||
root: Root | undefined;
|
||||
element = document.createElement("div");
|
||||
|
||||
constructor(props: ButtonWidgetFixedProps) {
|
||||
constructor(props: ButtonWidgetFixedParams) {
|
||||
this.element.style.setProperty("display", "none");
|
||||
document.body.appendChild(this.element);
|
||||
|
||||
@ -64,7 +52,7 @@ export class ButtonWidgetFixed {
|
||||
this.render(props);
|
||||
}
|
||||
|
||||
render(props: ButtonWidgetFixedProps) {
|
||||
render(props: ButtonWidgetFixedParams) {
|
||||
this.root?.render(createPortal(<OpenQuizButton {...props} />, document.body));
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { ButtonWidgetComponentProps } from "@/model/widget/button";
|
||||
import lightTheme from "@/utils/themes/light";
|
||||
import { Button, ThemeProvider, useMediaQuery } from "@mui/material";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
@ -9,24 +10,6 @@ import { useQuizCompletionStatus } from "../shared/useQuizCompletionStatus";
|
||||
const WIDGET_DEFAULT_WIDTH = "600px";
|
||||
const WIDGET_DEFAULT_HEIGHT = "80%";
|
||||
|
||||
interface Props {
|
||||
quizId: string;
|
||||
fixedSide?: "left" | "right";
|
||||
dialogDimensions?: { width: string; height: string; };
|
||||
/**
|
||||
* Открыть квиз через X секунд, 0 - сразу
|
||||
*/
|
||||
autoShowQuizTime?: number | null;
|
||||
hideOnMobile?: boolean;
|
||||
openOnLeaveAttempt?: boolean;
|
||||
buttonFlash?: boolean;
|
||||
withShadow?: boolean;
|
||||
rounded?: boolean;
|
||||
buttonText?: string;
|
||||
buttonTextColor?: string;
|
||||
buttonBackgroundColor?: string;
|
||||
}
|
||||
|
||||
export default function OpenQuizButton({
|
||||
quizId,
|
||||
fixedSide,
|
||||
@ -40,7 +23,7 @@ export default function OpenQuizButton({
|
||||
buttonText = "Пройти квиз",
|
||||
buttonTextColor,
|
||||
buttonBackgroundColor,
|
||||
}: Props) {
|
||||
}: ButtonWidgetComponentProps) {
|
||||
const isMobile = useMediaQuery("(max-width: 600px)");
|
||||
const [isQuizShown, setIsQuizShown] = useState<boolean>(false);
|
||||
const isQuizCompleted = useQuizCompletionStatus(quizId);
|
||||
|
@ -1,21 +1,13 @@
|
||||
import { ComponentPropsWithoutRef } from "react";
|
||||
import { ContainerWidgetParams } from "@/model/widget/container";
|
||||
import { Root, createRoot } from "react-dom/client";
|
||||
import { pollForSelector } from "../shared/pollForSelector";
|
||||
import QuizContainer from "./QuizContainer";
|
||||
|
||||
|
||||
type Props = ComponentPropsWithoutRef<typeof QuizContainer>;
|
||||
|
||||
export class ContainerWidget {
|
||||
root: Root | undefined;
|
||||
|
||||
constructor(props: Props & {
|
||||
selector: string;
|
||||
/**
|
||||
* In seconds, null - polling disabled
|
||||
*/
|
||||
selectorPollingTimeLimit?: number | null;
|
||||
}) {
|
||||
constructor(props: ContainerWidgetParams) {
|
||||
const { selector, selectorPollingTimeLimit = 60 } = props;
|
||||
|
||||
const element = document.querySelector(selector);
|
||||
@ -37,7 +29,7 @@ export class ContainerWidget {
|
||||
});
|
||||
}
|
||||
|
||||
render(props: Props) {
|
||||
render(props: Omit<ContainerWidgetParams, "selector" | "selectorPollingTimeLimit">) {
|
||||
this.root?.render(<QuizContainer {...props} />);
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,10 @@
|
||||
import QuizAnswerer from "@/components/QuizAnswerer";
|
||||
import { ContainerWidgetComponentProps } from "@/model/widget/container";
|
||||
import { Box, useMediaQuery } from "@mui/material";
|
||||
import { ComponentPropsWithoutRef } from "react";
|
||||
import OpenQuizButton from "../button/OpenQuizButton";
|
||||
|
||||
|
||||
type Props = ComponentPropsWithoutRef<typeof OpenQuizButton> & {
|
||||
quizId: string;
|
||||
showButtonOnMobile?: boolean;
|
||||
dimensions?: { width: string; height: string; };
|
||||
};
|
||||
|
||||
export default function QuizContainer(props: Props) {
|
||||
export default function QuizContainer(props: ContainerWidgetComponentProps) {
|
||||
const { quizId, dimensions, showButtonOnMobile = false } = props;
|
||||
const isMobile = useMediaQuery("(max-width: 600px)");
|
||||
|
||||
|
@ -1,15 +1,13 @@
|
||||
import { PopupWidgetParams } from "@/model/widget/popup";
|
||||
import { Root, createRoot } from "react-dom/client";
|
||||
import { ComponentPropsWithoutRef } from "react";
|
||||
import QuizPopup from "./QuizPopup";
|
||||
|
||||
|
||||
type Props = ComponentPropsWithoutRef<typeof QuizPopup>;
|
||||
|
||||
export class PopupWidget {
|
||||
root: Root | undefined;
|
||||
element = document.createElement("div");
|
||||
|
||||
constructor(props: Props) {
|
||||
constructor(props: PopupWidgetParams) {
|
||||
this.element.style.setProperty("display", "none");
|
||||
document.body.appendChild(this.element);
|
||||
|
||||
@ -18,7 +16,7 @@ export class PopupWidget {
|
||||
this.render(props);
|
||||
}
|
||||
|
||||
render(props: Props) {
|
||||
render(props: PopupWidgetParams) {
|
||||
this.root?.render(<QuizPopup {...props} />);
|
||||
}
|
||||
|
||||
|
@ -2,29 +2,19 @@ import { useEffect, useRef, useState } from "react";
|
||||
import QuizDialog from "../shared/QuizDialog";
|
||||
import { useQuizCompletionStatus } from "../shared/useQuizCompletionStatus";
|
||||
import { useMediaQuery } from "@mui/material";
|
||||
import { PopupWidgetComponentProps } from "@/model/widget/popup";
|
||||
|
||||
|
||||
const WIDGET_DEFAULT_WIDTH = "600px";
|
||||
const WIDGET_DEFAULT_HEIGHT = "80%";
|
||||
|
||||
interface Props {
|
||||
quizId: string;
|
||||
dialogDimensions?: { width: string; height: string; };
|
||||
/**
|
||||
* Открыть квиз через X секунд, 0 - сразу
|
||||
*/
|
||||
autoShowQuizTime?: number | null;
|
||||
hideOnMobile?: boolean;
|
||||
openOnLeaveAttempt?: boolean;
|
||||
}
|
||||
|
||||
export default function QuizPopup({
|
||||
quizId,
|
||||
dialogDimensions,
|
||||
autoShowQuizTime = null,
|
||||
hideOnMobile = false,
|
||||
openOnLeaveAttempt = false,
|
||||
}: Props) {
|
||||
}: PopupWidgetComponentProps) {
|
||||
const initialIsQuizShown = (autoShowQuizTime !== null || openOnLeaveAttempt) ? false : true;
|
||||
|
||||
const [isQuizShown, setIsQuizShown] = useState<boolean>(initialIsQuizShown);
|
||||
|
@ -6,31 +6,13 @@ import QuizDialog from "../shared/QuizDialog";
|
||||
import RunningStripe from "../shared/RunningStripe";
|
||||
import { useAutoOpenTimer } from "../shared/useAutoOpenTimer";
|
||||
import { useQuizCompletionStatus } from "../shared/useQuizCompletionStatus";
|
||||
import { SideWidgetComponentProps } from "@/model/widget/side";
|
||||
|
||||
|
||||
const PADDING = 10;
|
||||
const WIDGET_DEFAULT_WIDTH = "600px";
|
||||
const WIDGET_DEFAULT_HEIGHT = "800px";
|
||||
|
||||
interface Props {
|
||||
quizId: string;
|
||||
position: "left" | "right";
|
||||
buttonBackgroundColor?: string;
|
||||
buttonTextColor?: string;
|
||||
dialogDimensions?: { width: string; height: string; };
|
||||
fullScreen?: boolean;
|
||||
buttonFlash?: boolean;
|
||||
/**
|
||||
* Скрывать виджет первые X секунд
|
||||
*/
|
||||
autoOpenTime?: number;
|
||||
/**
|
||||
* Открыть квиз через X секунд, 0 - сразу
|
||||
*/
|
||||
autoShowQuizTime?: number | null;
|
||||
hideOnMobile?: boolean;
|
||||
}
|
||||
|
||||
export default function QuizSideButton({
|
||||
quizId,
|
||||
position,
|
||||
@ -42,7 +24,7 @@ export default function QuizSideButton({
|
||||
autoOpenTime = 0,
|
||||
autoShowQuizTime = null,
|
||||
hideOnMobile = false,
|
||||
}: Props) {
|
||||
}: SideWidgetComponentProps) {
|
||||
const [isQuizShown, setIsQuizShown] = useState<boolean>(false);
|
||||
const isMobile = useMediaQuery("(max-width: 600px)");
|
||||
const isQuizCompleted = useQuizCompletionStatus(quizId);
|
||||
|
@ -1,15 +1,13 @@
|
||||
import { SideWidgetParams } from "@/model/widget/side";
|
||||
import { Root, createRoot } from "react-dom/client";
|
||||
import QuizSideButton from "./QuizSideButton";
|
||||
import { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
|
||||
type Props = ComponentPropsWithoutRef<typeof QuizSideButton>;
|
||||
|
||||
export class SideWidget {
|
||||
root: Root | undefined;
|
||||
element = document.createElement("div");
|
||||
|
||||
constructor(props: Props) {
|
||||
constructor(props: SideWidgetParams) {
|
||||
this.element.style.setProperty("display", "none");
|
||||
document.body.appendChild(this.element);
|
||||
|
||||
@ -18,7 +16,7 @@ export class SideWidget {
|
||||
this.render(props);
|
||||
}
|
||||
|
||||
render(props: Props) {
|
||||
render(props: SideWidgetParams) {
|
||||
this.root?.render(<QuizSideButton {...props} />);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user