analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
260 lines (253 loc) • 7.75 kB
JavaScript
// src/components/ThemeToggle/ThemeToggle.tsx
import { Moon, Sun } from "phosphor-react";
import { useState, useEffect as useEffect2 } from "react";
// src/components/SelectionButton/SelectionButton.tsx
import { forwardRef } from "react";
// src/utils/utils.ts
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
function cn(...inputs) {
return twMerge(clsx(inputs));
}
// src/components/SelectionButton/SelectionButton.tsx
import { jsx, jsxs } from "react/jsx-runtime";
var SelectionButton = forwardRef(
({ icon, label, selected = false, className = "", disabled, ...props }, ref) => {
const baseClasses = [
"inline-flex",
"items-center",
"justify-start",
"gap-2",
"p-4",
"rounded-xl",
"cursor-pointer",
"border",
"border-border-50",
"bg-background",
"text-sm",
"text-text-700",
"font-bold",
"shadow-soft-shadow-1",
"hover:bg-background-100",
"focus-visible:outline-none",
"focus-visible:ring-2",
"focus-visible:ring-indicator-info",
"focus-visible:ring-offset-0",
"focus-visible:shadow-none",
"active:ring-2",
"active:ring-primary-950",
"active:ring-offset-0",
"active:shadow-none",
"disabled:opacity-50",
"disabled:cursor-not-allowed"
];
const stateClasses = selected ? ["ring-primary-950", "ring-2", "ring-offset-0", "shadow-none"] : [];
const allClasses = [...baseClasses, ...stateClasses].join(" ");
return /* @__PURE__ */ jsxs(
"button",
{
ref,
type: "button",
className: cn(allClasses, className),
disabled,
"aria-pressed": selected,
...props,
children: [
/* @__PURE__ */ jsx("span", { className: "flex items-center justify-center w-6 h-6", children: icon }),
/* @__PURE__ */ jsx("span", { children: label })
]
}
);
}
);
SelectionButton.displayName = "SelectionButton";
var SelectionButton_default = SelectionButton;
// src/hooks/useTheme.ts
import { useEffect } from "react";
// src/store/themeStore.ts
import { create } from "zustand";
import { devtools, persist } from "zustand/middleware";
var applyThemeToDOM = (mode) => {
const htmlElement = document.documentElement;
const originalTheme = htmlElement.getAttribute("data-original-theme");
if (mode === "dark") {
htmlElement.setAttribute("data-theme", "dark");
return true;
} else if (mode === "light") {
if (originalTheme) {
htmlElement.setAttribute("data-theme", originalTheme);
}
return false;
} else if (mode === "system") {
const isSystemDark = window.matchMedia(
"(prefers-color-scheme: dark)"
).matches;
if (isSystemDark) {
htmlElement.setAttribute("data-theme", "dark");
return true;
} else if (originalTheme) {
htmlElement.setAttribute("data-theme", originalTheme);
return false;
}
}
return false;
};
var saveOriginalTheme = () => {
const htmlElement = document.documentElement;
const currentTheme = htmlElement.getAttribute("data-theme");
if (currentTheme && !htmlElement.getAttribute("data-original-theme")) {
htmlElement.setAttribute("data-original-theme", currentTheme);
}
};
var useThemeStore = create()(
devtools(
persist(
(set, get) => ({
// Initial state
themeMode: "system",
isDark: false,
// Actions
applyTheme: (mode) => {
const isDark = applyThemeToDOM(mode);
set({ isDark });
},
toggleTheme: () => {
const { themeMode, applyTheme } = get();
let newMode;
if (themeMode === "light") {
newMode = "dark";
} else if (themeMode === "dark") {
newMode = "light";
} else {
newMode = "dark";
}
set({ themeMode: newMode });
applyTheme(newMode);
},
setTheme: (mode) => {
const { applyTheme } = get();
set({ themeMode: mode });
applyTheme(mode);
},
initializeTheme: () => {
const { themeMode, applyTheme } = get();
saveOriginalTheme();
applyTheme(themeMode);
},
handleSystemThemeChange: () => {
const { themeMode, applyTheme } = get();
if (themeMode === "system") {
applyTheme("system");
}
}
}),
{
name: "theme-store",
// Nome da chave no localStorage
partialize: (state) => ({
themeMode: state.themeMode
})
// Só persiste o themeMode, não o isDark
}
),
{
name: "theme-store"
}
)
);
// src/hooks/useTheme.ts
var useTheme = () => {
const {
themeMode,
isDark,
toggleTheme,
setTheme,
initializeTheme,
handleSystemThemeChange
} = useThemeStore();
useEffect(() => {
initializeTheme();
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
mediaQuery.addEventListener("change", handleSystemThemeChange);
return () => {
mediaQuery.removeEventListener("change", handleSystemThemeChange);
};
}, [initializeTheme, handleSystemThemeChange]);
return {
themeMode,
isDark,
toggleTheme,
setTheme
};
};
// src/components/ThemeToggle/ThemeToggle.tsx
import { jsx as jsx2 } from "react/jsx-runtime";
var ThemeToggle = ({
variant = "default",
onToggle
}) => {
const { themeMode, setTheme } = useTheme();
const [tempTheme, setTempTheme] = useState(themeMode);
useEffect2(() => {
setTempTheme(themeMode);
}, [themeMode]);
const problemTypes = [
{
id: "light",
title: "Claro",
icon: /* @__PURE__ */ jsx2(Sun, { size: 24 })
},
{
id: "dark",
title: "Escuro",
icon: /* @__PURE__ */ jsx2(Moon, { size: 24 })
},
{
id: "system",
title: "Sistema",
icon: /* @__PURE__ */ jsx2(
"svg",
{
width: "25",
height: "25",
viewBox: "0 0 25 25",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
children: /* @__PURE__ */ jsx2(
"path",
{
d: "M12.5 2.75C15.085 2.75276 17.5637 3.78054 19.3916 5.6084C21.2195 7.43628 22.2473 9.915 22.25 12.5C22.25 14.4284 21.6778 16.3136 20.6064 17.917C19.5352 19.5201 18.0128 20.7699 16.2314 21.5078C14.4499 22.2458 12.489 22.4387 10.5977 22.0625C8.70642 21.6863 6.96899 20.758 5.60547 19.3945C4.24197 18.031 3.31374 16.2936 2.9375 14.4023C2.56129 12.511 2.75423 10.5501 3.49219 8.76855C4.23012 6.98718 5.47982 5.46483 7.08301 4.39355C8.68639 3.32221 10.5716 2.75 12.5 2.75ZM11.75 4.28516C9.70145 4.47452 7.7973 5.42115 6.41016 6.94043C5.02299 8.4599 4.25247 10.4426 4.25 12.5C4.25247 14.5574 5.02299 16.5401 6.41016 18.0596C7.7973 19.5789 9.70145 20.5255 11.75 20.7148V4.28516Z",
fill: "#525252"
}
)
}
)
}
];
const handleThemeSelect = (selectedTheme) => {
if (variant === "with-save") {
setTempTheme(selectedTheme);
} else {
setTheme(selectedTheme);
}
if (onToggle) {
onToggle(selectedTheme);
}
};
const currentTheme = variant === "with-save" ? tempTheme : themeMode;
return /* @__PURE__ */ jsx2("div", { className: "flex flex-row gap-2 sm:gap-4 py-2", children: problemTypes.map((type) => /* @__PURE__ */ jsx2(
SelectionButton_default,
{
icon: type.icon,
label: type.title,
selected: currentTheme === type.id,
onClick: () => handleThemeSelect(type.id),
className: "w-full p-2 sm:p-4"
},
type.id
)) });
};
export {
ThemeToggle
};
//# sourceMappingURL=index.mjs.map