|
import { Config, DriverHook, getConfig, getCurrentDriver } from "./config"; |
|
import { Driver, DriveStep } from "./driver"; |
|
import { emit } from "./emitter"; |
|
import { onDriverClick } from "./events"; |
|
import { getState, setState, State } from "./state"; |
|
import { bringInView, getFocusableElements } from "./utils"; |
|
|
|
export type Side = "top" | "right" | "bottom" | "left" | "over"; |
|
export type Alignment = "start" | "center" | "end"; |
|
export type AllowedButtons = "next" | "previous" | "close"; |
|
|
|
export type Popover = { |
|
title?: string; |
|
description?: string; |
|
side?: Side; |
|
align?: Alignment; |
|
|
|
showButtons?: AllowedButtons[]; |
|
showProgress?: boolean; |
|
disableButtons?: AllowedButtons[]; |
|
|
|
popoverClass?: string; |
|
|
|
|
|
progressText?: string; |
|
doneBtnText?: string; |
|
nextBtnText?: string; |
|
prevBtnText?: string; |
|
|
|
|
|
onPopoverRender?: (popover: PopoverDOM, opts: { config: Config; state: State; driver: Driver }) => void; |
|
|
|
|
|
onNextClick?: DriverHook; |
|
onPrevClick?: DriverHook; |
|
onCloseClick?: DriverHook; |
|
}; |
|
|
|
export type PopoverDOM = { |
|
wrapper: HTMLElement; |
|
arrow: HTMLElement; |
|
title: HTMLElement; |
|
description: HTMLElement; |
|
footer: HTMLElement; |
|
progress: HTMLElement; |
|
previousButton: HTMLButtonElement; |
|
nextButton: HTMLButtonElement; |
|
closeButton: HTMLButtonElement; |
|
footerButtons: HTMLElement; |
|
}; |
|
|
|
export function hidePopover() { |
|
const popover = getState("popover"); |
|
if (!popover) { |
|
return; |
|
} |
|
|
|
popover.wrapper.style.display = "none"; |
|
} |
|
|
|
export function renderPopover(element: Element, step: DriveStep) { |
|
let popover = getState("popover"); |
|
if (popover) { |
|
document.body.removeChild(popover.wrapper); |
|
} |
|
|
|
popover = createPopover(); |
|
document.body.appendChild(popover.wrapper); |
|
|
|
const { |
|
title, |
|
description, |
|
showButtons, |
|
disableButtons, |
|
showProgress, |
|
|
|
nextBtnText = getConfig("nextBtnText") || "Next →", |
|
prevBtnText = getConfig("prevBtnText") || "← Previous", |
|
progressText = getConfig("progressText") || "{current} of {total}", |
|
} = step.popover || {}; |
|
|
|
popover.nextButton.innerHTML = nextBtnText; |
|
popover.previousButton.innerHTML = prevBtnText; |
|
popover.progress.innerHTML = progressText; |
|
|
|
if (title) { |
|
popover.title.innerHTML = title; |
|
popover.title.style.display = "block"; |
|
} else { |
|
popover.title.style.display = "none"; |
|
} |
|
|
|
if (description) { |
|
popover.description.innerHTML = description; |
|
popover.description.style.display = "block"; |
|
} else { |
|
popover.description.style.display = "none"; |
|
} |
|
|
|
const showButtonsConfig: AllowedButtons[] = showButtons || getConfig("showButtons")!; |
|
const showProgressConfig = showProgress || getConfig("showProgress") || false; |
|
const showFooter = |
|
showButtonsConfig?.includes("next") || showButtonsConfig?.includes("previous") || showProgressConfig; |
|
|
|
popover.closeButton.style.display = showButtonsConfig.includes("close") ? "block" : "none"; |
|
|
|
if (showFooter) { |
|
popover.footer.style.display = "flex"; |
|
|
|
popover.progress.style.display = showProgressConfig ? "block" : "none"; |
|
popover.nextButton.style.display = showButtonsConfig.includes("next") ? "block" : "none"; |
|
popover.previousButton.style.display = showButtonsConfig.includes("previous") ? "block" : "none"; |
|
} else { |
|
popover.footer.style.display = "none"; |
|
} |
|
|
|
const disabledButtonsConfig: AllowedButtons[] = disableButtons || getConfig("disableButtons")! || []; |
|
if (disabledButtonsConfig?.includes("next")) { |
|
popover.nextButton.disabled = true; |
|
popover.nextButton.classList.add("driver-popover-btn-disabled"); |
|
} |
|
|
|
if (disabledButtonsConfig?.includes("previous")) { |
|
popover.previousButton.disabled = true; |
|
popover.previousButton.classList.add("driver-popover-btn-disabled"); |
|
} |
|
|
|
if (disabledButtonsConfig?.includes("close")) { |
|
popover.closeButton.disabled = true; |
|
popover.closeButton.classList.add("driver-popover-btn-disabled"); |
|
} |
|
|
|
|
|
const popoverWrapper = popover.wrapper; |
|
popoverWrapper.style.display = "block"; |
|
popoverWrapper.style.left = ""; |
|
popoverWrapper.style.top = ""; |
|
popoverWrapper.style.bottom = ""; |
|
popoverWrapper.style.right = ""; |
|
|
|
popoverWrapper.id = "driver-popover-content"; |
|
popoverWrapper.setAttribute("role", "dialog"); |
|
popoverWrapper.setAttribute("aria-labelledby", "driver-popover-title"); |
|
popoverWrapper.setAttribute("aria-describedby", "driver-popover-description"); |
|
|
|
|
|
const popoverArrow = popover.arrow; |
|
popoverArrow.className = "driver-popover-arrow"; |
|
|
|
|
|
const customPopoverClass = step.popover?.popoverClass || getConfig("popoverClass") || ""; |
|
popoverWrapper.className = `driver-popover ${customPopoverClass}`.trim(); |
|
|
|
|
|
onDriverClick( |
|
popover.wrapper, |
|
e => { |
|
const target = e.target as HTMLElement; |
|
|
|
const onNextClick = step.popover?.onNextClick || getConfig("onNextClick"); |
|
const onPrevClick = step.popover?.onPrevClick || getConfig("onPrevClick"); |
|
const onCloseClick = step.popover?.onCloseClick || getConfig("onCloseClick"); |
|
|
|
if (target.classList.contains("driver-popover-next-btn")) { |
|
|
|
|
|
if (onNextClick) { |
|
return onNextClick(element, step, { |
|
config: getConfig(), |
|
state: getState(), |
|
driver: getCurrentDriver(), |
|
}); |
|
} else { |
|
return emit("nextClick"); |
|
} |
|
} |
|
|
|
if (target.classList.contains("driver-popover-prev-btn")) { |
|
if (onPrevClick) { |
|
return onPrevClick(element, step, { |
|
config: getConfig(), |
|
state: getState(), |
|
driver: getCurrentDriver(), |
|
}); |
|
} else { |
|
return emit("prevClick"); |
|
} |
|
} |
|
|
|
if (target.classList.contains("driver-popover-close-btn")) { |
|
if (onCloseClick) { |
|
return onCloseClick(element, step, { |
|
config: getConfig(), |
|
state: getState(), |
|
driver: getCurrentDriver(), |
|
}); |
|
} else { |
|
return emit("closeClick"); |
|
} |
|
} |
|
|
|
return undefined; |
|
}, |
|
target => { |
|
|
|
|
|
return ( |
|
!popover?.description.contains(target) && |
|
!popover?.title.contains(target) && |
|
typeof target.className === "string" && |
|
target.className.includes("driver-popover") |
|
); |
|
} |
|
); |
|
|
|
setState("popover", popover); |
|
|
|
const onPopoverRender = step.popover?.onPopoverRender || getConfig("onPopoverRender"); |
|
if (onPopoverRender) { |
|
onPopoverRender(popover, { |
|
config: getConfig(), |
|
state: getState(), |
|
driver: getCurrentDriver(), |
|
}); |
|
} |
|
|
|
repositionPopover(element, step); |
|
bringInView(popoverWrapper); |
|
|
|
|
|
const isToDummyElement = element.classList.contains("driver-dummy-element"); |
|
const focusableElement = getFocusableElements([popoverWrapper, ...(isToDummyElement ? [] : [element])]); |
|
if (focusableElement.length > 0) { |
|
focusableElement[0].focus(); |
|
} |
|
} |
|
|
|
type PopoverDimensions = { |
|
width: number; |
|
height: number; |
|
realWidth: number; |
|
realHeight: number; |
|
}; |
|
|
|
function getPopoverDimensions(): PopoverDimensions | undefined { |
|
const popover = getState("popover"); |
|
if (!popover?.wrapper) { |
|
return; |
|
} |
|
|
|
const boundingClientRect = popover.wrapper.getBoundingClientRect(); |
|
|
|
const stagePadding = getConfig("stagePadding") || 0; |
|
const popoverOffset = getConfig("popoverOffset") || 0; |
|
|
|
return { |
|
width: boundingClientRect.width + stagePadding + popoverOffset, |
|
height: boundingClientRect.height + stagePadding + popoverOffset, |
|
|
|
realWidth: boundingClientRect.width, |
|
realHeight: boundingClientRect.height, |
|
}; |
|
} |
|
|
|
function calculateTopForLeftRight( |
|
alignment: Alignment, |
|
config: { |
|
elementDimensions: DOMRect; |
|
popoverDimensions: PopoverDimensions; |
|
popoverPadding: number; |
|
popoverArrowDimensions: { width: number; height: number }; |
|
} |
|
): number { |
|
const { elementDimensions, popoverDimensions, popoverPadding, popoverArrowDimensions } = config; |
|
|
|
if (alignment === "start") { |
|
return Math.max( |
|
Math.min( |
|
elementDimensions.top - popoverPadding, |
|
window.innerHeight - popoverDimensions!.realHeight - popoverArrowDimensions.width |
|
), |
|
popoverArrowDimensions.width |
|
); |
|
} |
|
|
|
if (alignment === "end") { |
|
return Math.max( |
|
Math.min( |
|
elementDimensions.top - popoverDimensions?.realHeight + elementDimensions.height + popoverPadding, |
|
window.innerHeight - popoverDimensions?.realHeight - popoverArrowDimensions.width |
|
), |
|
popoverArrowDimensions.width |
|
); |
|
} |
|
|
|
if (alignment === "center") { |
|
return Math.max( |
|
Math.min( |
|
elementDimensions.top + elementDimensions.height / 2 - popoverDimensions?.realHeight / 2, |
|
window.innerHeight - popoverDimensions?.realHeight - popoverArrowDimensions.width |
|
), |
|
popoverArrowDimensions.width |
|
); |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
|
|
function calculateLeftForTopBottom( |
|
alignment: Alignment, |
|
config: { |
|
elementDimensions: DOMRect; |
|
popoverDimensions: PopoverDimensions; |
|
popoverPadding: number; |
|
popoverArrowDimensions: { width: number; height: number }; |
|
} |
|
): number { |
|
const { elementDimensions, popoverDimensions, popoverPadding, popoverArrowDimensions } = config; |
|
|
|
if (alignment === "start") { |
|
return Math.max( |
|
Math.min( |
|
elementDimensions.left - popoverPadding, |
|
window.innerWidth - popoverDimensions!.realWidth - popoverArrowDimensions.width |
|
), |
|
popoverArrowDimensions.width |
|
); |
|
} |
|
|
|
if (alignment === "end") { |
|
return Math.max( |
|
Math.min( |
|
elementDimensions.left - popoverDimensions?.realWidth + elementDimensions.width + popoverPadding, |
|
window.innerWidth - popoverDimensions?.realWidth - popoverArrowDimensions.width |
|
), |
|
popoverArrowDimensions.width |
|
); |
|
} |
|
|
|
if (alignment === "center") { |
|
return Math.max( |
|
Math.min( |
|
elementDimensions.left + elementDimensions.width / 2 - popoverDimensions?.realWidth / 2, |
|
window.innerWidth - popoverDimensions?.realWidth - popoverArrowDimensions.width |
|
), |
|
popoverArrowDimensions.width |
|
); |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
export function repositionPopover(element: Element, step: DriveStep) { |
|
const popover = getState("popover"); |
|
if (!popover) { |
|
return; |
|
} |
|
|
|
const { align = "start", side = "left" } = step?.popover || {}; |
|
|
|
|
|
const requiredAlignment: Alignment = align; |
|
const requiredSide: Side = element.id === "driver-dummy-element" ? "over" : side; |
|
const popoverPadding = getConfig("stagePadding") || 0; |
|
|
|
const popoverDimensions = getPopoverDimensions()!; |
|
const popoverArrowDimensions = popover.arrow.getBoundingClientRect(); |
|
const elementDimensions = element.getBoundingClientRect(); |
|
|
|
const topValue = elementDimensions.top - popoverDimensions!.height; |
|
let isTopOptimal = topValue >= 0; |
|
|
|
const bottomValue = window.innerHeight - (elementDimensions.bottom + popoverDimensions!.height); |
|
let isBottomOptimal = bottomValue >= 0; |
|
|
|
const leftValue = elementDimensions.left - popoverDimensions!.width; |
|
let isLeftOptimal = leftValue >= 0; |
|
|
|
const rightValue = window.innerWidth - (elementDimensions.right + popoverDimensions!.width); |
|
let isRightOptimal = rightValue >= 0; |
|
|
|
const noneOptimal = !isTopOptimal && !isBottomOptimal && !isLeftOptimal && !isRightOptimal; |
|
let popoverRenderedSide: Side = requiredSide; |
|
|
|
if (requiredSide === "top" && isTopOptimal) { |
|
isRightOptimal = isLeftOptimal = isBottomOptimal = false; |
|
} else if (requiredSide === "bottom" && isBottomOptimal) { |
|
isRightOptimal = isLeftOptimal = isTopOptimal = false; |
|
} else if (requiredSide === "left" && isLeftOptimal) { |
|
isRightOptimal = isTopOptimal = isBottomOptimal = false; |
|
} else if (requiredSide === "right" && isRightOptimal) { |
|
isLeftOptimal = isTopOptimal = isBottomOptimal = false; |
|
} |
|
|
|
if (requiredSide === "over") { |
|
const leftToSet = window.innerWidth / 2 - popoverDimensions!.realWidth / 2; |
|
const topToSet = window.innerHeight / 2 - popoverDimensions!.realHeight / 2; |
|
|
|
popover.wrapper.style.left = `${leftToSet}px`; |
|
popover.wrapper.style.right = `auto`; |
|
popover.wrapper.style.top = `${topToSet}px`; |
|
popover.wrapper.style.bottom = `auto`; |
|
} else if (noneOptimal) { |
|
const leftValue = window.innerWidth / 2 - popoverDimensions?.realWidth! / 2; |
|
const bottomValue = 10; |
|
|
|
popover.wrapper.style.left = `${leftValue}px`; |
|
popover.wrapper.style.right = `auto`; |
|
popover.wrapper.style.bottom = `${bottomValue}px`; |
|
popover.wrapper.style.top = `auto`; |
|
} else if (isLeftOptimal) { |
|
const leftToSet = Math.min( |
|
leftValue, |
|
window.innerWidth - popoverDimensions?.realWidth - popoverArrowDimensions.width |
|
); |
|
|
|
const topToSet = calculateTopForLeftRight(requiredAlignment, { |
|
elementDimensions, |
|
popoverDimensions, |
|
popoverPadding, |
|
popoverArrowDimensions, |
|
}); |
|
|
|
popover.wrapper.style.left = `${leftToSet}px`; |
|
popover.wrapper.style.top = `${topToSet}px`; |
|
popover.wrapper.style.bottom = `auto`; |
|
popover.wrapper.style.right = "auto"; |
|
|
|
popoverRenderedSide = "left"; |
|
} else if (isRightOptimal) { |
|
const rightToSet = Math.min( |
|
rightValue, |
|
window.innerWidth - popoverDimensions?.realWidth - popoverArrowDimensions.width |
|
); |
|
const topToSet = calculateTopForLeftRight(requiredAlignment, { |
|
elementDimensions, |
|
popoverDimensions, |
|
popoverPadding, |
|
popoverArrowDimensions, |
|
}); |
|
|
|
popover.wrapper.style.right = `${rightToSet}px`; |
|
popover.wrapper.style.top = `${topToSet}px`; |
|
popover.wrapper.style.bottom = `auto`; |
|
popover.wrapper.style.left = "auto"; |
|
|
|
popoverRenderedSide = "right"; |
|
} else if (isTopOptimal) { |
|
const topToSet = Math.min( |
|
topValue, |
|
window.innerHeight - popoverDimensions!.realHeight - popoverArrowDimensions.width |
|
); |
|
let leftToSet = calculateLeftForTopBottom(requiredAlignment, { |
|
elementDimensions, |
|
popoverDimensions, |
|
popoverPadding, |
|
popoverArrowDimensions, |
|
}); |
|
|
|
popover.wrapper.style.top = `${topToSet}px`; |
|
popover.wrapper.style.left = `${leftToSet}px`; |
|
popover.wrapper.style.bottom = `auto`; |
|
popover.wrapper.style.right = "auto"; |
|
|
|
popoverRenderedSide = "top"; |
|
} else if (isBottomOptimal) { |
|
const bottomToSet = Math.min( |
|
bottomValue, |
|
window.innerHeight - popoverDimensions?.realHeight - popoverArrowDimensions.width |
|
); |
|
|
|
let leftToSet = calculateLeftForTopBottom(requiredAlignment, { |
|
elementDimensions, |
|
popoverDimensions, |
|
popoverPadding, |
|
popoverArrowDimensions, |
|
}); |
|
|
|
popover.wrapper.style.left = `${leftToSet}px`; |
|
popover.wrapper.style.bottom = `${bottomToSet}px`; |
|
popover.wrapper.style.top = `auto`; |
|
popover.wrapper.style.right = "auto"; |
|
|
|
popoverRenderedSide = "bottom"; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!noneOptimal) { |
|
renderPopoverArrow(requiredAlignment, popoverRenderedSide, element); |
|
} else { |
|
popover.arrow.classList.add("driver-popover-arrow-none"); |
|
} |
|
} |
|
|
|
function renderPopoverArrow(alignment: Alignment, side: Side, element: Element) { |
|
const popover = getState("popover"); |
|
if (!popover) { |
|
return; |
|
} |
|
|
|
const elementDimensions = element.getBoundingClientRect(); |
|
const popoverDimensions = getPopoverDimensions()!; |
|
const popoverArrow = popover.arrow; |
|
|
|
const popoverWidth = popoverDimensions.width; |
|
const windowWidth = window.innerWidth; |
|
const elementWidth = elementDimensions.width; |
|
const elementLeft = elementDimensions.left; |
|
|
|
const popoverHeight = popoverDimensions.height; |
|
const windowHeight = window.innerHeight; |
|
const elementTop = elementDimensions.top; |
|
const elementHeight = elementDimensions.height; |
|
|
|
|
|
popoverArrow.className = "driver-popover-arrow"; |
|
|
|
let arrowSide = side; |
|
let arrowAlignment = alignment; |
|
|
|
if (side === "top") { |
|
if (elementLeft + elementWidth <= 0) { |
|
arrowSide = "right"; |
|
arrowAlignment = "end"; |
|
} else if (elementLeft + elementWidth - popoverWidth <= 0) { |
|
arrowSide = "top"; |
|
arrowAlignment = "start"; |
|
} |
|
if (elementLeft >= windowWidth) { |
|
arrowSide = "left"; |
|
arrowAlignment = "end"; |
|
} else if (elementLeft + popoverWidth >= windowWidth) { |
|
arrowSide = "top"; |
|
arrowAlignment = "end"; |
|
} |
|
} else if (side === "bottom") { |
|
if (elementLeft + elementWidth <= 0) { |
|
arrowSide = "right"; |
|
arrowAlignment = "start"; |
|
} else if (elementLeft + elementWidth - popoverWidth <= 0) { |
|
arrowSide = "bottom"; |
|
arrowAlignment = "start"; |
|
} |
|
if (elementLeft >= windowWidth) { |
|
arrowSide = "left"; |
|
arrowAlignment = "start"; |
|
} else if (elementLeft + popoverWidth >= windowWidth) { |
|
arrowSide = "bottom"; |
|
arrowAlignment = "end"; |
|
} |
|
} else if (side === "left") { |
|
if (elementTop + elementHeight <= 0) { |
|
arrowSide = "bottom"; |
|
arrowAlignment = "end"; |
|
} else if (elementTop + elementHeight - popoverHeight <= 0) { |
|
arrowSide = "left"; |
|
arrowAlignment = "start"; |
|
} |
|
|
|
if (elementTop >= windowHeight) { |
|
arrowSide = "top"; |
|
arrowAlignment = "end"; |
|
} else if (elementTop + popoverHeight >= windowHeight) { |
|
arrowSide = "left"; |
|
arrowAlignment = "end"; |
|
} |
|
} else if (side === "right") { |
|
if (elementTop + elementHeight <= 0) { |
|
arrowSide = "bottom"; |
|
arrowAlignment = "start"; |
|
} else if (elementTop + elementHeight - popoverHeight <= 0) { |
|
arrowSide = "right"; |
|
arrowAlignment = "start"; |
|
} |
|
|
|
if (elementTop >= windowHeight) { |
|
arrowSide = "top"; |
|
arrowAlignment = "start"; |
|
} else if (elementTop + popoverHeight >= windowHeight) { |
|
arrowSide = "right"; |
|
arrowAlignment = "end"; |
|
} |
|
} |
|
|
|
if (!arrowSide) { |
|
popoverArrow.classList.add("driver-popover-arrow-none"); |
|
} else { |
|
popoverArrow.classList.add(`driver-popover-arrow-side-${arrowSide}`); |
|
popoverArrow.classList.add(`driver-popover-arrow-align-${arrowAlignment}`); |
|
|
|
const elementRect = element.getBoundingClientRect(); |
|
const arrowRect = popoverArrow.getBoundingClientRect(); |
|
const stagePadding = getConfig("stagePadding") || 0; |
|
|
|
const isElementPartiallyInViewPort = |
|
elementRect.left - stagePadding < window.innerWidth && |
|
elementRect.right + stagePadding > 0 && |
|
elementRect.top - stagePadding < window.innerHeight && |
|
elementRect.bottom + stagePadding > 0; |
|
|
|
if (side === "bottom" && isElementPartiallyInViewPort) { |
|
const isArrowWithinElementBounds = |
|
arrowRect.x > elementRect.x && arrowRect.x + arrowRect.width < elementRect.x + elementRect.width; |
|
|
|
if (!isArrowWithinElementBounds) { |
|
popoverArrow.classList.remove(`driver-popover-arrow-align-${arrowAlignment}`); |
|
popoverArrow.classList.add(`driver-popover-arrow-none`); |
|
|
|
popover.wrapper.style.transform = `translateY(-${stagePadding / 2}px)`; |
|
} else { |
|
popover.wrapper.style.transform = `translateY(0)`; |
|
} |
|
|
|
|
|
|
|
|
|
} |
|
} |
|
} |
|
|
|
function createPopover(): PopoverDOM { |
|
const wrapper = document.createElement("div"); |
|
wrapper.classList.add("driver-popover"); |
|
|
|
const arrow = document.createElement("div"); |
|
arrow.classList.add("driver-popover-arrow"); |
|
|
|
const title = document.createElement("header"); |
|
title.id = "driver-popover-title"; |
|
title.classList.add("driver-popover-title"); |
|
title.style.display = "none"; |
|
title.innerText = "Popover Title"; |
|
|
|
const description = document.createElement("div"); |
|
description.id = "driver-popover-description"; |
|
description.classList.add("driver-popover-description"); |
|
description.style.display = "none"; |
|
description.innerText = "Popover description is here"; |
|
|
|
const closeButton = document.createElement("button"); |
|
closeButton.type = "button"; |
|
closeButton.classList.add("driver-popover-close-btn"); |
|
closeButton.setAttribute("aria-label", "Close"); |
|
closeButton.innerHTML = "×"; |
|
|
|
const footer = document.createElement("footer"); |
|
footer.classList.add("driver-popover-footer"); |
|
|
|
const progress = document.createElement("span"); |
|
progress.classList.add("driver-popover-progress-text"); |
|
progress.innerText = ""; |
|
|
|
const footerButtons = document.createElement("span"); |
|
footerButtons.classList.add("driver-popover-navigation-btns"); |
|
|
|
const previousButton = document.createElement("button"); |
|
previousButton.type = "button"; |
|
previousButton.classList.add("driver-popover-prev-btn"); |
|
previousButton.innerHTML = "← Previous"; |
|
|
|
const nextButton = document.createElement("button"); |
|
nextButton.type = "button"; |
|
nextButton.classList.add("driver-popover-next-btn"); |
|
nextButton.innerHTML = "Next →"; |
|
|
|
footerButtons.appendChild(previousButton); |
|
footerButtons.appendChild(nextButton); |
|
footer.appendChild(progress); |
|
footer.appendChild(footerButtons); |
|
|
|
wrapper.appendChild(closeButton); |
|
wrapper.appendChild(arrow); |
|
wrapper.appendChild(title); |
|
wrapper.appendChild(description); |
|
wrapper.appendChild(footer); |
|
|
|
return { |
|
wrapper, |
|
arrow, |
|
title, |
|
description, |
|
footer, |
|
previousButton, |
|
nextButton, |
|
closeButton, |
|
footerButtons, |
|
progress, |
|
}; |
|
} |
|
|
|
export function destroyPopover() { |
|
const popover = getState("popover"); |
|
if (!popover) { |
|
return; |
|
} |
|
|
|
popover.wrapper.parentElement?.removeChild(popover.wrapper); |
|
} |
|
|