@sk1llahh/react-bvi
Version:
React BVI — библиотека для добавления режима слабовидящих на любой сайт. Панель настроек доступности: контрастность, шрифты, цвета, TTS, изображения и др.
612 lines (611 loc) • 22.9 kB
JavaScript
import { jsxs as c, jsx as l, Fragment as $ } from "react/jsx-runtime";
import { useEffect as N, useState as f, createContext as M, useContext as R } from "react";
import { useTranslation as I } from "react-i18next";
import o from "classnames";
const m = {
speak(i, e = "ru-RU") {
if (typeof window > "u") return;
if (!("speechSynthesis" in window)) {
console.warn("BVI: SpeechSynthesis is not supported in this browser");
return;
}
if (!i) return;
window.speechSynthesis.cancel();
const t = new SpeechSynthesisUtterance(i);
t.lang = e, t.rate = 1, t.pitch = 1, window.speechSynthesis.speak(t);
},
stop() {
typeof window > "u" || "speechSynthesis" in window && window.speechSynthesis.cancel();
}
}, V = () => {
const { state: i } = A();
N(() => {
if (!i.active || !i.tts) return;
function e(t) {
const r = t.target;
if (!r || r.closest && r.closest(".bvi-panel")) return;
const n = r.innerText || r.textContent;
n && m.speak(n);
}
return document.addEventListener("click", e), () => document.removeEventListener("click", e);
}, [i.active, i.tts]);
};
function W() {
const [i, e] = f(() => ({
width: typeof window < "u" ? window.innerWidth : 0,
height: typeof window < "u" ? window.innerHeight : 0
}));
return N(() => {
if (typeof window > "u") return;
function t() {
e({
width: window.innerWidth,
height: window.innerHeight
});
}
return t(), window.addEventListener("resize", t), () => window.removeEventListener("resize", t);
}, []), i;
}
const _ = () => {
const { t: i } = I(), e = W(), {
state: t,
toggleActive: r,
setTheme: n,
setSize: s,
setImagesMode: d,
setLineHeight: T,
setLetterSpacing: H,
setFontFamily: S,
setFlashIframe: x,
resetToDefaults: F,
setTtsEnabled: C,
speakPage: j,
stopSpeak: ee,
togglePanelHidden: p
} = A();
V();
const [P, E] = f(!1), [O, q] = f(!1);
return t.active ? /* @__PURE__ */ c(
"div",
{
className: o("bvi-panel", { "bvi-fixed-top": t.fixedPanel }, { "bvi-panel-hidden": t.panelHidden }),
children: [
/* @__PURE__ */ l("div", { className: "bvi-container-fluid", children: /* @__PURE__ */ l("div", { className: "bvi-row bvi-no-gutters", children: /* @__PURE__ */ l("div", { className: "bvi-col-12", children: /* @__PURE__ */ c("div", { className: "bvi-panel-toggler", children: [
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-toggler",
className: "bvi-link",
onClick: (a) => {
a.preventDefault(), q((v) => !v);
},
children: "Меню"
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-toggler-close",
className: "bvi-link",
onClick: (a) => {
a.preventDefault(), r();
},
children: i("bvi.button")
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-toggler-menu-hide",
className: "bvi-link",
onClick: (a) => {
a.preventDefault(), p();
},
children: /* @__PURE__ */ l("i", { className: "bvi-images bvi-images-minus-square-o" })
}
)
] }) }) }) }),
/* @__PURE__ */ c("div", { className: o("bvi-panel-container", e.width > 992 ? "bvi-container" : "bvi-container-fluid"), style: e.width > 992 ? {} : { display: O ? "block" : "none" }, children: [
/* @__PURE__ */ c("div", { className: "bvi-row bvi-no-gutters", children: [
/* @__PURE__ */ c("div", { className: "bvi-col-6 bvi-col-sm-6 bvi-col-md-3 bvi-col-lg-3 bvi-col-xl-3 bvi-text-center", children: [
/* @__PURE__ */ c("div", { className: "bvi-title", children: [
i("bvi.font-size"),
" ",
/* @__PURE__ */ l("span", { id: "bvi-font-size", children: t.size }),
" px"
] }),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-font-size-less",
className: "bvi-link",
onClick: (a) => {
a.preventDefault(), s(Math.max(14, Number(t.size) - 2));
},
children: "A -"
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-font-size-more",
className: "bvi-link",
onClick: (a) => {
a.preventDefault(), s(Math.min(40, Number(t.size) + 2));
},
children: "A +"
}
)
] }),
/* @__PURE__ */ c("div", { className: "bvi-col-6 bvi-col-sm-6 bvi-col-md-3 bvi-col-lg-3 bvi-col-xl-3 bvi-text-center", children: [
/* @__PURE__ */ l("div", { className: "bvi-title", children: i("bvi.color") }),
[
"white",
"black",
"blue",
"brown",
"green"
].map((a) => /* @__PURE__ */ l(
"a",
{
href: "#",
id: `bvi-theme-${a}`,
className: o("bvi-link", `bvi-link-${a}`, { active: t.theme === a }),
onClick: (v) => {
v.preventDefault(), n(a);
},
children: "Ц"
},
a
))
] }),
/* @__PURE__ */ c("div", { className: "bvi-col-6 bvi-col-sm-6 bvi-col-md-3 bvi-col-lg-3 bvi-col-xl-2 bvi-text-center", children: [
/* @__PURE__ */ l("div", { className: "bvi-title", children: i("bvi.image") }),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-images-true",
className: o("bvi-link", { active: t.images === "true" }),
onClick: (a) => {
a.preventDefault(), d("true");
},
children: /* @__PURE__ */ l("i", { className: "bvi-images bvi-images-on" })
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-images-false",
className: o("bvi-link", { active: t.images === "false" }),
onClick: (a) => {
a.preventDefault(), d("false");
},
children: /* @__PURE__ */ l("i", { className: "bvi-images bvi-images-off" })
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-images-grayscale",
className: o("bvi-link", { active: t.images === "grayscale" }),
onClick: (a) => {
a.preventDefault(), d("grayscale");
},
children: /* @__PURE__ */ l("i", { className: "bvi-images bvi-images-adjust" })
}
)
] }),
/* @__PURE__ */ c("div", { className: "bvi-col-6 bvi-col-sm-6 bvi-col-md-3 bvi-col-lg-3 bvi-col-xl-4 bvi-text-center", children: [
/* @__PURE__ */ l("div", { className: "bvi-title", children: i("bvi.add") }),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-tts-true",
className: o("bvi-link", { active: t.tts }),
onClick: (a) => {
a.preventDefault(), C(!0);
},
children: /* @__PURE__ */ l("i", { className: "bvi-images bvi-images-volume-on" })
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-tts-false",
className: o("bvi-link", { active: !t.tts }),
onClick: (a) => {
a.preventDefault(), C(!1);
},
children: /* @__PURE__ */ l("i", { className: "bvi-images bvi-images-volume-off" })
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-setting",
className: "bvi-link",
onClick: (a) => {
a.preventDefault(), E((v) => !v);
},
children: i("bvi.setting")
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-panel-close",
className: "bvi-link",
onClick: (a) => {
a.preventDefault(), r();
},
children: /* @__PURE__ */ l("i", { className: "bvi-images bvi-images-eye-slash" })
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-panel-hide",
className: "bvi-link",
onClick: (a) => {
a.preventDefault(), p();
},
children: /* @__PURE__ */ l("i", { className: "bvi-images bvi-images-minus-square-o" })
}
)
] })
] }),
/* @__PURE__ */ l("div", { className: "bvi-setting-menu", style: { display: P ? "block" : "none" }, children: /* @__PURE__ */ c("div", { className: "bvi-row bvi-no-gutters", children: [
/* @__PURE__ */ c("div", { className: "bvi-col-sm-12 bvi-col-md-6 bvi-col-lg-4 bvi-col-xl-4 bvi-text-center", children: [
/* @__PURE__ */ l("div", { className: "bvi-title", children: i("bvi.line-height") }),
[
["normal", i("bvi.l-h-default")],
["average", i("bvi.l-h-middle")],
["big", i("bvi.l-h-big")]
].map(([a, v]) => /* @__PURE__ */ l(
"a",
{
href: "#",
id: `bvi-line-height-${a}`,
className: o("bvi-link", { active: t.lineHeight === a }),
onClick: (y) => {
y.preventDefault(), T(a);
},
children: v
},
a
))
] }),
/* @__PURE__ */ c("div", { className: "bvi-col-sm-12 bvi-col-md-6 bvi-col-lg-5 bvi-col-xl-5 bvi-text-center", children: [
/* @__PURE__ */ l("div", { className: "bvi-title", children: i("bvi.letter-spacing") }),
[
["normal", i("bvi.l-s-1")],
["average", i("bvi.l-s-15")],
["big", i("bvi.l-s-2")]
].map(([a, v]) => /* @__PURE__ */ l(
"a",
{
href: "#",
id: `bvi-letter-spacing-${a}`,
className: o("bvi-link", { active: t.letterSpacing === a }),
onClick: (y) => {
y.preventDefault(), H(a);
},
children: v
},
a
))
] }),
/* @__PURE__ */ c("div", { className: "bvi-col-sm-12 bvi-col-md-6 bvi-col-lg-3 bvi-col-xl-3 bvi-text-center", children: [
/* @__PURE__ */ l("div", { className: "bvi-title", children: i("bvi.font-family") }),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-font-family-arial",
className: o("bvi-link", { active: t.fontFamily === "arial" }),
onClick: (a) => {
a.preventDefault(), S("arial");
},
children: i("bvi.ff-arial")
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-font-family-times",
className: o("bvi-link", { active: t.fontFamily === "times" }),
onClick: (a) => {
a.preventDefault(), S("times");
},
children: i("bvi.ff-times")
}
)
] }),
/* @__PURE__ */ c("div", { className: "bvi-col-sm-12 bvi-col-md-6 bvi-col-lg-6 bvi-col-xl-6 bvi-text-center", children: [
/* @__PURE__ */ l("div", { className: "bvi-title", children: i("bvi.elements") }),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-flash-iframe-true",
className: o("bvi-link", { active: t.flashIframe == "true" }),
onClick: (a) => {
a.preventDefault(), x(!0);
},
children: i("bvi.on")
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-flash-iframe-false",
className: o("bvi-link", { active: t.flashIframe == "false" }),
onClick: (a) => {
a.preventDefault(), x(!1);
},
children: i("bvi.off")
}
)
] }),
/* @__PURE__ */ c("div", { className: "bvi-col-sm-12 bvi-col-md-12 bvi-col-lg-6 bvi-col-xl-6 bvi-text-right", children: [
/* @__PURE__ */ l("div", { className: "bvi-title", children: " " }),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-settings-default",
className: "bvi-link",
onClick: (a) => {
a.preventDefault(), F();
},
children: i("bvi.default_settings")
}
),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-setting-close",
className: "bvi-link",
onClick: (a) => {
a.preventDefault(), E(!1);
},
children: i("bvi.close_panel")
}
)
] })
] }) })
] }),
/* @__PURE__ */ l(
"a",
{
href: "#",
id: "bvi-panel-show",
className: "bvi-link bvi-link-top",
style: { display: t.panelHidden ? "block" : "none" },
onClick: (a) => {
a.preventDefault(), p();
},
children: /* @__PURE__ */ l("i", { className: "bvi-images bvi-images-eye" })
}
)
]
}
) : null;
}, G = ".bvi-body", z = () => document.querySelector(G) || document.body, u = (i) => Array.from(i.querySelectorAll("img")), g = (i) => Array.from(i.querySelectorAll("svg")), h = (i) => Array.from(
i.querySelectorAll(
'object[type="image/svg+xml"], embed[type="image/svg+xml"]'
)
), w = (i) => Array.from(i.querySelectorAll("*")), U = (i) => {
if (!i || i === "none") return null;
const e = i.match(/^url\(["']?(.*)["']?\)$/);
return e ? e[1] : null;
}, k = (i, e = "Изображение") => {
const t = i.getAttribute("alt") || i.getAttribute("aria-label") || i.getAttribute("title") || e, r = i.getAttribute("class") || "bvi-class-none", n = i.id || "", s = document.createElement("div");
s.className = `${r} bvi-img`, n && (s.id = n), s.textContent = t;
const d = i.naturalWidth || i.width || i.clientWidth || i.getBoundingClientRect().width || null;
d && (s.style.width = `${d}px`), s.style.height = "100%", i.insertAdjacentElement("afterend", s);
}, J = (i) => {
u(i).forEach((e) => {
e.style.display = "";
const t = e.getAttribute("data-bvi-img-original");
t && (e.src = t);
}), g(i).forEach((e) => {
const t = e.getAttribute("data-bvi-original-display");
e.style.display = t !== null ? t : "", e.removeAttribute("data-bvi-original-display");
}), h(i).forEach((e) => {
const t = e.getAttribute("data-bvi-original-display");
e.style.display = t !== null ? t : "", e.removeAttribute("data-bvi-original-display");
}), w(i).forEach((e) => {
const t = e.getAttribute("data-bvi-background-image-original");
t && (e.style.backgroundImage = `url("${t}")`);
});
}, Y = (i) => {
u(i).forEach((e) => {
e.getAttribute("data-bvi-img-original") || e.setAttribute("data-bvi-img-original", e.src), e.getAttribute("data-bvi-original-display") || e.setAttribute("data-bvi-original-display", e.style.display || ""), e.style.display = "none", k(e, "Изображение");
}), g(i).forEach((e) => {
e.getAttribute("data-bvi-original-display") || e.setAttribute("data-bvi-original-display", e.style.display || ""), e.style.display = "none", k(e, "SVG изображение");
}), h(i).forEach((e) => {
e.getAttribute("data-bvi-original-display") || e.setAttribute("data-bvi-original-display", e.style.display || ""), e.style.display = "none", k(e, "SVG изображение");
});
}, K = (i) => {
u(i).forEach((e) => {
e.style.display = "", e.classList.add("bvi-img"), e.getAttribute("data-bvi-img-original") || e.setAttribute("data-bvi-img-original", e.src);
}), g(i).forEach((e) => {
e.style.display = "", e.classList.add("bvi-img");
}), h(i).forEach((e) => {
e.style.display = "", e.classList.add("bvi-img");
}), w(i).forEach((e) => {
const r = window.getComputedStyle(e).backgroundImage, n = U(r);
n && (e.classList.contains("bvi-background-image") || e.classList.add("bvi-background-image"), e.getAttribute("data-bvi-background-image-original") || e.setAttribute("data-bvi-background-image-original", n));
});
}, Q = (i) => {
const e = z();
e.querySelectorAll("div.bvi-img").forEach((t) => t.remove()), i === "true" || i === !0 ? J(e) : i === "false" || i === !1 ? Y(e) : i === "grayscale" && K(e), e.setAttribute("data-bvi-images", i);
}, D = (i) => {
Q(i);
}, X = () => {
const i = z();
u(i).forEach((e) => {
e.style.display = e.getAttribute("data-bvi-original-display") || "", e.removeAttribute("data-bvi-original-display");
const t = e.getAttribute("data-bvi-img-original");
t && (e.src = t), e.classList.remove("bvi-img"), e.removeAttribute("data-bvi-img-original");
}), g(i).forEach((e) => {
const t = e.getAttribute("data-bvi-original-display");
e.style.display = t !== null ? t : "", e.removeAttribute("data-bvi-original-display"), e.classList.remove("bvi-img");
}), h(i).forEach((e) => {
const t = e.getAttribute("data-bvi-original-display");
e.style.display = t !== null ? t : "", e.removeAttribute("data-bvi-original-display"), e.classList.remove("bvi-img");
}), i.querySelectorAll("div.bvi-img").forEach((e) => e.remove()), w(i).forEach((e) => {
const t = e.getAttribute("data-bvi-background-image-original");
t && (e.style.backgroundImage = `url("${t}")`, e.classList.remove("bvi-background-image"), e.removeAttribute("data-bvi-background-image-original"));
}), i.removeAttribute("data-bvi-images");
}, B = M(null), L = "bvi-react-state", b = {
active: !1,
theme: "white",
// white | black | blue | brown | green
size: "30",
images: "true",
// "true" | "false" | "grayscale"
lineHeight: "normal",
// normal | average | big
letterSpacing: "normal",
// normal | average | big
fontFamily: "default",
// default | arial | times
flashIframe: "true",
// "true" | "false"
fixedPanel: !1,
panelHidden: !1,
tts: !0
}, Z = () => {
if (typeof window > "u") return b;
try {
const i = localStorage.getItem(L);
if (!i) return b;
const e = JSON.parse(i);
return { ...b, ...e };
} catch {
return b;
}
}, ne = ({ children: i }) => {
const [e, t] = f(Z);
N(() => {
if (!(typeof window > "u"))
try {
localStorage.setItem(L, JSON.stringify(e));
} catch {
console.log("BVI: failed");
}
}, [e]);
const r = {
state: e,
toggleActive: () => t((n) => (n.active ? D(n.images) : X(), { ...n, active: !n.active, images: n.active ? n.images : "true" })),
setTheme: (n) => t((s) => ({ ...s, theme: n })),
setSize: (n) => t((s) => ({
...s,
size: String(n)
})),
setImagesMode: (n) => {
D(n), t((s) => ({
...s,
images: n
}));
},
setLineHeight: (n) => t((s) => ({
...s,
lineHeight: n
})),
setLetterSpacing: (n) => t((s) => ({
...s,
letterSpacing: n
})),
setFontFamily: (n) => t((s) => ({
...s,
fontFamily: n
})),
setFlashIframe: (n) => t((s) => ({
...s,
flashIframe: n ? "true" : "false"
})),
togglePanelHidden: () => t((n) => ({
...n,
panelHidden: !n.panelHidden
})),
setTtsEnabled: (n) => {
n || m.stop(), t((s) => ({
...s,
tts: n
}));
},
resetToDefaults: () => t((n) => ({
...b,
images: "true",
active: n.active
})),
speakPage: () => {
if (!e.tts || typeof document > "u") return;
const n = document.body.innerText || document.body.textContent || "";
m.speak(n.slice(0, 8e3));
},
stopSpeak: () => {
m.stop();
}
};
return /* @__PURE__ */ l(B.Provider, { value: r, children: e.active ? /* @__PURE__ */ c($, { children: [
/* @__PURE__ */ l(_, {}),
/* @__PURE__ */ l(
"div",
{
className: "bvi-body",
"data-bvi-active": e.active,
"data-bvi-theme": e.theme,
"data-bvi-size": e.size,
"data-bvi-images": e.images,
"data-bvi-line-height": e.lineHeight,
"data-bvi-letter-spacing": e.letterSpacing,
"data-bvi-font-family": e.fontFamily,
"data-bvi-flash-iframe": e.flashIframe,
children: i
}
)
] }) : i });
};
function A() {
const i = R(B);
if (!i)
throw new Error("useBvi must be used within BviProvider");
return i;
}
const se = ({ children: i }) => {
const { t: e } = I(), { state: t, toggleActive: r } = A();
return /* @__PURE__ */ l(
"button",
{
type: "button",
className: o("bvi-open"),
onClick: r,
children: t.active ? e("bvi.button") : i || e("bvi.title")
}
);
};
export {
se as BviButton,
ne as BviProvider,
A as useBvi
};