react-custom-tours
Version:
A library with tips that you can attach to blocks on your sites so that users can more easily understand how to use your site
217 lines (216 loc) • 9.84 kB
JavaScript
import { jsxs as g, jsx as s, Fragment as M } from "react/jsx-runtime";
import { useRef as B, useMemo as N, useEffect as v, useState as k, createContext as S, useContext as $ } from "react";
import { mockDomRect as z } from "./shared/mock-data/index.js";
import O from "./shared/ui/spinner/index.js";
import { getRectById as _ } from "./shared/utils/getRectById.js";
import { createPortal as A } from "react-dom";
import './assets/useTips.css';const D = "_wrapper_2z7aw_3", V = "_dark_2z7aw_17", Z = "_relative_2z7aw_22", F = "_block_2z7aw_28", b = {
wrapper: D,
dark: V,
relative: Z,
block: F
}, K = "_wrapper_1hvjj_1", U = "_header_1hvjj_17", Y = "_leftHeader_1hvjj_22", q = "_count_1hvjj_27", G = "_close_1hvjj_34", J = "_textWrapper_1hvjj_50", Q = "_footer_1hvjj_62", C = {
wrapper: K,
header: U,
leftHeader: Y,
count: q,
close: G,
textWrapper: J,
footer: Q
}, X = (e) => {
const { item: n, prevItem: i, nextItem: r, itemRect: t, countItems: o, itemIdx: a, isLoading: c, onPrev: p, onNext: w, onClose: u } = e, { isHiddenClose: l, highlightPadding: f } = L(), d = 10, m = {}, I = `${a + 1} / ${o}`, y = B(null), h = N(() => l ? o - 1 === a : !0, [a, o, l]), x = y?.current?.getBoundingClientRect() || z, j = x?.width || 0, E = f ?? 0, H = window.innerWidth - t.right, R = t.left + t.width / 2 > window.innerWidth / 2 ? "right" : "left", P = R === "left" ? t.left : H, W = j + P > window.innerWidth ? P * -1 + 8 : 0;
return m.maxWidth = n?.maxWidth || t.right, t.height > window.innerHeight - (x?.height || 200) ? (m.top = d, m[R] = W || d) : (t.top + t.height / 2 > window.innerHeight / 2 ? m.bottom = t.height + d + E : m.top = t.height + d + E, m[R] = W), /* @__PURE__ */ g("div", { ref: y, style: m, className: C.wrapper, children: [
/* @__PURE__ */ g("header", { className: C.header, children: [
/* @__PURE__ */ g("div", { className: C.leftHeader, children: [
/* @__PURE__ */ s("span", { className: C.count, "data-testid": "tooltip-count", title: `Номер подсказки - (${I})`, children: I }),
c && /* @__PURE__ */ s(O, {})
] }),
h && /* @__PURE__ */ s(
"button",
{
className: C.close,
onClick: u,
type: "button",
"data-testid": "tooltip-close",
title: "Закрыть подсказки",
children: /* @__PURE__ */ s("svg", { width: "8", height: "8", viewBox: "0 0 8 8", children: /* @__PURE__ */ s("path", { d: "M7.8228 0.183264C7.76667 0.127012 7.69999 0.0823841 7.62658 0.0519343C7.55318 0.0214845 7.47448 0.00581086 7.39501 0.00581086C7.31554 0.00581086 7.23685 0.0214845 7.16345 0.0519343C7.09004 0.0823841 7.02336 0.127012 6.96722 0.183264L4 3.14442L1.03278 0.177196C0.976598 0.121018 0.909905 0.0764551 0.836505 0.0460517C0.763104 0.0156483 0.684434 5.91933e-10 0.604986 0C0.525539 -5.91934e-10 0.446868 0.0156483 0.373468 0.0460517C0.300068 0.0764551 0.233374 0.121018 0.177196 0.177196C0.121018 0.233374 0.0764551 0.300068 0.0460517 0.373468C0.0156483 0.446868 -5.91933e-10 0.525539 0 0.604986C5.91934e-10 0.684434 0.0156483 0.763104 0.0460517 0.836505C0.0764551 0.909905 0.121018 0.976598 0.177196 1.03278L3.14442 4L0.177196 6.96722C0.121018 7.0234 0.0764551 7.0901 0.0460517 7.1635C0.0156483 7.2369 0 7.31557 0 7.39501C0 7.47446 0.0156483 7.55313 0.0460517 7.62653C0.0764551 7.69993 0.121018 7.76663 0.177196 7.8228C0.233374 7.87898 0.300068 7.92355 0.373468 7.95395C0.446868 7.98435 0.525539 8 0.604986 8C0.684434 8 0.763104 7.98435 0.836505 7.95395C0.909905 7.92355 0.976598 7.87898 1.03278 7.8228L4 4.85558L6.96722 7.8228C7.0234 7.87898 7.0901 7.92355 7.1635 7.95395C7.2369 7.98435 7.31557 8 7.39501 8C7.47446 8 7.55313 7.98435 7.62653 7.95395C7.69993 7.92355 7.76663 7.87898 7.8228 7.8228C7.87898 7.76663 7.92355 7.69993 7.95395 7.62653C7.98435 7.55313 8 7.47446 8 7.39501C8 7.31557 7.98435 7.2369 7.95395 7.1635C7.92355 7.0901 7.87898 7.0234 7.8228 6.96722L4.85558 4L7.8228 1.03278C8.05339 0.802195 8.05339 0.413846 7.8228 0.183264Z" }) })
}
)
] }),
/* @__PURE__ */ g("div", { className: C.textWrapper, children: [
n?.title && /* @__PURE__ */ s("h4", { "data-testid": "tooltip-title", title: n.title, children: n.title }),
/* @__PURE__ */ s("p", { "data-testid": "tooltip-text", title: n.text, children: n.text })
] }),
/* @__PURE__ */ g("footer", { className: C.footer, children: [
i && /* @__PURE__ */ s(
"button",
{
disabled: !i || c,
onClick: p,
type: "button",
"data-testid": "tooltip-prev",
title: "Предыдущая подсказка",
children: "Назад"
}
),
/* @__PURE__ */ g(
"button",
{
disabled: c,
title: r ? "Следующая подсказка" : "Закрыть",
onClick: r ? w : u,
type: "button",
"data-testid": "tooltip-next",
children: [
r ? "Далее" : "Все понятно",
r && /* @__PURE__ */ s("svg", { width: "10", height: "8", viewBox: "0 0 10 8", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ s(
"path",
{
d: "M1.0271 3.63123H8.5271M8.5271 3.63123L5.5271 0.631226M8.5271 3.63123L5.5271 6.63123",
stroke: "white",
strokeWidth: "1.25",
strokeLinecap: "round",
strokeLinejoin: "round"
}
) })
]
}
)
] })
] });
}, ee = (e) => {
const { setIsShow: n } = L();
v(() => {
if (!e) return;
const i = (r) => {
r.code === "Escape" && n(!1);
};
return window.addEventListener("keydown", i), () => window.removeEventListener("keydown", i);
}, [e]);
};
function te(e) {
return "--rct-" + e.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
}
const oe = (e) => {
const { customColors: n, theme: i } = L();
v(() => {
n && Object.entries(n[i || "light"]).forEach(([r, t]) => {
e?.current?.style.setProperty(te(r), t);
});
}, [n, e, i]);
}, ne = ({ data: e }) => {
const { setIsShow: n, theme: i, escapeToClose: r, highlightPadding: t } = L(), [o, a] = k(e[0]), [c, p] = k(_(o.nodeId)), w = B(null), [u, l] = k(!1), f = e[e.indexOf(o) + 1], d = e[e.indexOf(o) - 1], m = async () => {
o?.onClick?.nextButton && (l(!0), await o?.onClick?.nextButton(), l(!1)), a(f), p(_(f.nodeId));
}, I = async () => {
o?.onClick?.prevButton && (l(!0), await o?.onClick?.prevButton(), l(!1)), a(d), p(_(d.nodeId));
}, y = async () => {
o?.onClick?.closeButton && (l(!0), await o?.onClick?.closeButton(), l(!1)), n(!1);
};
return ee(!!r), oe(w), v(() => {
const h = () => {
p(_(o.nodeId));
};
return window.addEventListener("resize", h), window.addEventListener("scroll", h), () => {
window.removeEventListener("resize", h), window.removeEventListener("scroll", h);
};
}, [o]), v(() => {
o?.node?.scrollIntoView({
behavior: "smooth",
block: c.height > window.innerHeight - 200 ? "start" : "center",
inline: "nearest"
});
}, [o]), v(() => {
a(e[0]), p(_(e[0]?.nodeId));
}, [e]), v(() => {
const h = w?.current;
if (!h) return;
const x = (j) => {
j.stopPropagation();
};
return h.addEventListener("mousedown", x), () => {
h.removeEventListener("mousedown", x);
};
}, [w?.current]), A(
/* @__PURE__ */ s(
"div",
{
className: `${b.wrapper} ${i === "dark" ? b.dark : ""}`,
ref: w,
"data-testid": "tips-active-layout",
children: /* @__PURE__ */ s("div", { className: b.relative, children: /* @__PURE__ */ s(
"div",
{
className: b.block,
style: {
width: c.width + (t || 0),
height: c.height + (t || 0),
left: c.left - (t ? t / 2 : 0),
top: c.top - (t ? t / 2 : 0),
borderRadius: o?.node?.style.borderRadius
},
children: /* @__PURE__ */ s(
X,
{
isLoading: u,
countItems: e.length,
itemIdx: e.indexOf(o),
item: o,
itemRect: c,
nextItem: f,
prevItem: d,
onNext: m,
onPrev: I,
onClose: y
}
)
}
) })
}
),
document.body
);
}, ie = "You are trying to show a tour, but the DOM nodes for this tour are not found in the DOM Tree, please check it!", se = ({ children: e }) => {
const { data: n, isShow: i } = L();
return /* @__PURE__ */ g(M, { children: [
/* @__PURE__ */ s(re, { data: n, isShow: i }),
e
] });
}, re = ({ isShow: e, data: n }) => {
if (!e || !n) return null;
const i = n.filter((r) => r?.node).sort((r, t) => r.idx - t.idx);
return i.length === 0 ? (console.warn(ie), null) : /* @__PURE__ */ s(ne, { data: i });
}, T = S({}), ue = (e) => {
const { children: n, tips: i, theme: r, customColors: t, escapeToClose: o, isHiddenClose: a, highlightPadding: c } = e, [p, w] = k(null), [u, l] = k(!1);
v(() => {
u && w(
i.map((d) => ({
...d,
node: document.getElementById(d.nodeId)
}))
);
}, [i, u]);
const f = N(
() => ({
data: p,
isShow: u,
theme: r,
escapeToClose: o,
customColors: t,
isHiddenClose: a,
highlightPadding: c,
setIsShow: l
}),
[p, u, r, o, l, t, a, c]
);
return /* @__PURE__ */ s(T.Provider, { value: f, children: /* @__PURE__ */ s(se, { children: n }) });
}, L = () => $(T);
export {
ue as T,
X as a,
ee as b,
oe as c,
ne as d,
se as e,
T as f,
L as u
};