UNPKG

@sk1llahh/react-bvi

Version:

React BVI — библиотека для добавления режима слабовидящих на любой сайт. Панель настроек доступности: контрастность, шрифты, цвета, TTS, изображения и др.

612 lines (611 loc) 22.9 kB
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 };