react-dev-companion
Version:
A fun dev companion for React Devs
121 lines (120 loc) • 4.3 kB
JavaScript
import { jsx as s, jsxs as b } from "react/jsx-runtime";
import * as i from "react";
const d = i.createContext(void 0);
function T({ children: e }) {
const [o, n] = i.useState(() => {
const t = localStorage.getItem("@dev-companion/active-time");
return t ? JSON.parse(t) : 0;
}), r = (t) => {
n(t), localStorage.setItem("@dev-companion/active-time", JSON.stringify(t));
}, c = () => {
n(0), localStorage.setItem("@dev-companion/active-time", JSON.stringify(0));
};
return /* @__PURE__ */ s(d.Provider, { value: { activeTime: o, updateActiveTime: r, resetActiveTime: c }, children: e });
}
const h = () => {
const e = i.useContext(d);
if (!e) throw new Error("useAppContext must be used within an AppProvider");
return e;
}, g = 3e5, x = 3e5;
function k() {
const { activeTime: e, updateActiveTime: o, resetActiveTime: n } = h(), r = i.useRef(null), c = i.useRef(null), t = i.useRef(null), l = i.useCallback(() => {
t.current !== null && clearTimeout(t.current), t.current = setTimeout(() => {
n();
}, x);
}, [n]);
return i.useEffect(() => {
const u = () => {
r.current === null && (r.current = setInterval(() => {
o(e + 1e3);
}, 1e3));
}, m = () => {
r.current !== null && clearInterval(r.current), r.current = null;
};
document.hidden ? c.current = Date.now() : u();
const f = () => {
if (document.hidden) {
m(), c.current = Date.now();
return;
}
if (c.current !== null) {
const a = Date.now() - c.current;
c.current = null, a > g ? n() : o(e + a);
}
u();
}, p = () => {
l(), r.current || u();
};
return document.addEventListener("visibilitychange", f), v.forEach((a) => document.addEventListener(a, p)), () => {
m(), document.removeEventListener("visibilitychange", f), v.forEach((a) => document.removeEventListener(a, p));
};
}, [o, e, l, n]), { activeTime: e };
}
const v = ["mousemove", "keydown", "scroll", "click", "scroll"];
function w(e) {
const o = Math.floor(e / 1e3), n = Math.floor(o / 60), r = o % 60, c = n > 0 ? `${n} min` : "", t = `${r} sec`;
return c ? `${c} ${t}` : t;
}
function A({ direction: e = "bottom-right", resetOnClick: o = !1 }) {
const { activeTime: n } = k(), { resetActiveTime: r } = h(), c = w(n), t = n < 5e3;
return /* @__PURE__ */ b(
"div",
{
className: `fixed flex flex-col
${e === "top-left" ? "top-8 left-6" : ""}
${e === "top-right" ? "top-8 right-6" : ""}
${e === "bottom-left" ? "bottom-8 left-6" : ""}
${e === "bottom-right" ? "bottom-8 right-6" : ""}
`,
children: [
/* @__PURE__ */ s(
"button",
{
...o && { onClick: r },
className: "p-2 rounded-full size-fit button peer cursor-pointer z-10 text-white bg-black ",
children: /* @__PURE__ */ s(
"video",
{
className: "size-10",
autoPlay: !0,
muted: !0,
playsInline: !0,
loop: !t,
children: /* @__PURE__ */ s(
"source",
{
src: t ? "https://raw.githubusercontent.com/khxif/react-dev-companion/main/src/assets/cat-wakeup.mp4" : "https://raw.githubusercontent.com/khxif/react-dev-companion/main/src/assets/cat-walk.mp4",
type: "video/mp4"
}
)
},
t ? "wakeup" : "walk"
)
}
),
/* @__PURE__ */ s(
"span",
{
className: `w-28 px-2 py-1 rounded-md absolute text-center mb-0.5
text-xs hidden peer-hover:block bottom-full text-gray-200 bg-black
${e === "top-left" ? "-left-5" : ""}
${e === "top-right" ? "-right-6" : ""}
${e === "bottom-left" ? "-left-5" : ""}
${e === "bottom-right" ? "-right-6" : ""}
`,
children: c
}
)
]
}
);
}
function C({ ...e }) {
const [o, n] = i.useState(!1);
return i.useEffect(() => {
n(!0);
}, []), !o || process.env.NODE_ENV !== "development" ? null : /* @__PURE__ */ s(T, { children: /* @__PURE__ */ s(A, { ...e }) });
}
export {
C as Companion
};