react-utterances-client
Version:
Another React component for using Utterances 🔮 on your website!
115 lines (114 loc) • 4.49 kB
JavaScript
"use client";
import { jsx as S, jsxs as J, Fragment as T } from "react/jsx-runtime";
import * as s from "react";
import k from "classcat";
import { useSyncExternalStore as B } from "use-sync-external-store/shim";
const D = ".utterances{position:relative;box-sizing:border-box;width:100%;max-width:760px;margin-left:auto;margin-right:auto}.utterances-frame{color-scheme:light;position:absolute;left:0;right:0;width:1px;min-width:100%;max-width:100%;height:100%;border:0}";
function R(t, n) {
window.dispatchEvent(new StorageEvent("storage", { key: t, newValue: n }));
}
const I = (t, n, i) => {
t.setItem(n, i), R(n, i);
}, G = (t, n) => {
t.removeItem(n), R(n);
}, M = (t, n) => t.getItem(n), H = (t) => (window.addEventListener("storage", t), () => window.removeEventListener("storage", t)), K = () => "", m = (t) => t === "session" ? window.sessionStorage : window.localStorage;
function Q(t) {
const n = "utterances-session", r = B(H, () => M(m(t), n), K), a = s.useCallback(
(l) => {
try {
const c = typeof l == "function" ? l(r || "") : l;
c == null ? G(m(t), n) : I(m(t), n, c);
} catch (c) {
console.warn(c);
}
},
[n, r, t]
);
return s.useEffect(() => {
M(m(t), n) === null && I(m(t), n, "");
}, [n, t]), [r || "", a];
}
const V = "preferred-color-scheme", U = "https://utteranc.es", W = `${U}/utterances.html`, _ = ({
repo: t,
theme: n = "github-light",
label: i,
issueNumber: r,
issueTerm: a,
tokenStorage: l = "local",
loading: c = "lazy",
onLoad: u,
onError: $,
placeholder: d = !1,
containerClassName: z,
containerStyle: P,
iframeClassName: j,
iframeStyle: q
}) => {
const [h, w] = s.useState({}), [y, A] = s.useState(!1), [x, v] = Q(l);
s.useEffect(() => {
const e = document.createElement("style");
return e.appendChild(document.createTextNode(D)), document.head.appendChild(e), () => {
document.head.removeChild(e);
};
}, []), s.useEffect(() => {
const e = {};
e.repo = t, n === V ? e.theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "github-dark" : "github-light" : e.theme = n, i && (e.label = i), r && (e["issue-number"] = String(r)), a && (Array.isArray(a) ? e["issue-term"] = a.join(" ") : e["issue-term"] = a);
const o = new URL(location.href), p = o.searchParams.get("utterances");
p && (v(p), o.searchParams.delete("utterances"), history.replaceState(void 0, document.title, o.href));
const E = document.querySelector("link[rel='canonical']");
e.url = E ? E.href : o.origin + o.pathname + o.search, e.origin = o.origin, e.pathname = o.pathname.length < 2 ? "index" : o.pathname.slice(1).replace(/\.\w+$/, ""), e.title = document.title;
const b = document.querySelector("meta[name='description']");
e.description = b ? b.content : "";
const L = encodeURIComponent(e.description).length;
L > 1e3 && (e.description = e.description.slice(
0,
Math.floor(e.description.length * 1e3 / L)
));
const C = document.querySelector(
"meta[property='og:title'],meta[name='og:title']"
);
return e["og:title"] = C ? C.content : "", e.session = p || x || "", w(e), () => {
w({});
};
}, [t, n, i, r, a, l, x, v]);
const g = s.useRef(null), f = s.useCallback((e) => {
if (e.origin !== U)
return;
const o = e.data;
o && o.type === "resize" && o.height && g.current && (g.current.style.height = `${o.height}px`);
}, []);
s.useEffect(() => (window.addEventListener("message", f), () => window.removeEventListener("message", f)), [f]);
const N = s.useMemo(() => JSON.stringify(h) !== "{}", [h]), O = s.useCallback(
(e) => {
A(!0), u && u(e);
},
[u]
), F = s.useMemo(() => typeof d == "boolean" ? d ? /* @__PURE__ */ S("p", { children: "Loading comments..." }) : null : d, [d]);
return /* @__PURE__ */ S(
"div",
{
className: k(["utterances", z]),
ref: g,
style: P,
children: N && /* @__PURE__ */ J(T, { children: [
/* @__PURE__ */ S(
"iframe",
{
className: k(["utterances-frame", j]),
title: "Comments",
scrolling: "no",
src: `${W}?${new URLSearchParams(h)}`,
loading: d ? "eager" : c,
style: { display: !y && d ? "none" : "block", ...q },
onLoad: O,
onError: $
}
),
!y && F
] })
}
);
};
export {
_ as Utterances
};