@atomazing-org/design-system
Version:
A library providing a set of useful utils, MUI style extensions, and components to build your application.
1 lines • 55.5 kB
Source Map (JSON)
{"version":3,"sources":["../src/components/DialogBtn.ts","../src/components/ErrorBoundary.tsx","../src/components/Loading.tsx","../src/components/PathName.ts","../src/context/ThemeContext.tsx","../src/context/ThemeProviderWrapper.tsx","../src/styles/themeConfig.ts","../src/styles/colorUtils.ts","../src/styles/commonComponents.ts","../src/styles/createTheme.ts","../src/styles/typography.ts","../src/styles/darkModeOptions.tsx","../src/styles/GlobalStyles.tsx","../src/styles/keyframes.ts","../src/utils/displayGreeting.ts","../src/utils/getDayIdentifier.ts","../src/utils/getSystemInfo.ts","../src/utils/timeAgo.ts","../src/utils/useResponsiveDisplay.ts","../src/utils/useSystemTheme.ts"],"sourcesContent":["import styled from \"@emotion/styled\";\nimport { Button } from \"@mui/material\";\n\nexport const DialogBtn = styled(Button)`\n padding: 10px 16px;\n border-radius: 16px;\n font-size: 16px;\n margin: 8px;\n`;\n","/* eslint-disable @typescript-eslint/class-methods-use-this -- only for ErrorBoundary*/\nimport React from \"react\";\nimport styled from \"@emotion/styled\";\nimport ErrorOutlineRounded from \"@mui/icons-material/ErrorOutlineRounded\";\nimport { Box } from \"@mui/material\";\n\nimport type { ErrorInfo } from \"react\";\n\ninterface ErrorBoundaryProps {\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error?: Error;\n}\n\n/**\n * ErrorBoundary component that catches and displays errors.\n */\n\nexport class ErrorBoundary extends React.Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = {\n hasError: false,\n };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return {\n hasError: true,\n error,\n };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n // eslint-disable-next-line no-console -- Выводим ошибку в консоль\n console.error(\"Error:\", error);\n // eslint-disable-next-line no-console -- Выводим ошибку в консоль\n console.error(\"Error Info:\", errorInfo);\n }\n\n render() {\n const { state, props } = this;\n if (state.hasError) {\n return (\n <Container>\n <ErrorHeader>\n <Box>Ошибка. </Box>\n </ErrorHeader>\n <h3>\n <Box style={{ color: \"#ff3131\", display: \"inline-block\" }}>\n <ErrorOutlineRounded\n sx={{ verticalAlign: \"middle\", mb: \"4px\" }}\n />{\" \"}\n ERROR:\n </Box>{\" \"}\n <Box translate=\"no\">\n [{state.error?.name}] {state.error?.message}\n </Box>\n <Box style={{ color: \"#ff3131\", display: \"inline-block\" }}>\n <ErrorOutlineRounded\n sx={{ verticalAlign: \"middle\", mb: \"4px\" }}\n />{\" \"}\n Stack:\n </Box>{\" \"}\n <Box translate=\"no\">[{state.error?.stack}]</Box>\n </h3>\n </Container>\n );\n }\n\n return props.children;\n }\n}\n\nconst Container = styled.div`\n margin: 0 8vw;\n @media (max-width: 768px) {\n margin: 0;\n }\n`;\n\nconst ErrorHeader = styled.h1`\n margin-top: 32px;\n margin-bottom: 32px;\n font-size: 36px;\n color: #ff3131;\n text-align: center;\n display: flex;\n align-items: center;\n justify-content: center;\n @media (max-width: 768px) {\n text-align: left;\n justify-content: left;\n font-size: 30px;\n margin-top: 0;\n margin-bottom: 0;\n }\n`;\n","import { useEffect, useState } from \"react\";\nimport styled from \"@emotion/styled\";\nimport { Box, CircularProgress } from \"@mui/material\";\n\nexport const Loading = () => {\n const [showLoading, setShowLoading] = useState<boolean>(false);\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setShowLoading(true);\n }, 100); // Show the loading spinner after 100 milliseconds\n\n return () => clearTimeout(timer);\n }, []);\n\n return (\n <Container>\n {showLoading && (\n <>\n <CircularProgress aria-label=\"loading\" size={80} thickness={4} />\n <h3 style={{ opacity: 0.8 }}>Loading Page...</h3>\n </>\n )}\n </Container>\n );\n};\n\nconst Container = styled(Box)`\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n justify-content: center;\n align-items: center;\n flex-direction: column;\n text-align: center;\n gap: 8px;\n`;\n","import styled from \"@emotion/styled\";\n\nexport const PathName = styled.code`\n background: #000000c8;\n color: white;\n padding: 4px 6px;\n border-radius: 8px;\n`;\n","import { createContext, useContext } from \"react\";\n\nimport type { ThemeContextProps } from \"../models\";\n\nexport const ThemeContext = createContext<ThemeContextProps | undefined>(\n undefined,\n);\n\nexport const useThemeSettings = (): ThemeContextProps => {\n const context = useContext(ThemeContext);\n if (!context)\n throw new Error(\n \"useThemeSettings must be used within ThemeProviderWrapper\",\n );\n return context;\n};\n","// src/context/ThemeProvider.tsx\nimport { useMemo, useState, useEffect } from \"react\";\nimport { ThemeProvider as EmotionThemeProvider } from \"@emotion/react\";\nimport { ThemeProvider as MuiThemeProvider } from \"@mui/material/styles\";\n\nimport { themes, createCustomTheme, isDarkMode, GlobalStyles } from \"../styles\";\nimport { useSystemTheme } from \"../utils\";\n\nimport { ThemeContext } from \"./ThemeContext\";\n\nimport type { FC, PropsWithChildren } from \"react\";\n\nexport const ThemeProviderWrapper: FC<PropsWithChildren> = ({ children }) => {\n const systemTheme = useSystemTheme();\n\n const [theme, setTheme] = useState<string>(() => {\n const stored = localStorage.getItem(\"appSettings\");\n return stored ? JSON.parse(stored).theme || \"system\" : \"system\";\n });\n\n const [darkMode, setDarkMode] = useState<\n \"light\" | \"dark\" | \"system\" | \"auto\"\n >(() => {\n const stored = localStorage.getItem(\"appSettings\");\n return stored ? JSON.parse(stored).darkMode || \"auto\" : \"auto\";\n });\n\n useEffect(() => {\n localStorage.setItem(\"appSettings\", JSON.stringify({ theme, darkMode }));\n }, [theme, darkMode]);\n\n const selectedTheme = useMemo(() => {\n if (systemTheme === \"unknown\") return themes[0].MuiTheme;\n if (theme === \"system\") {\n return systemTheme === \"dark\" ? themes[0].MuiTheme : themes[1].MuiTheme;\n }\n return themes.find((t) => t.name === theme)?.MuiTheme || themes[0].MuiTheme;\n }, [systemTheme, theme]);\n\n const mode = useMemo(\n () =>\n isDarkMode(darkMode, systemTheme, selectedTheme.palette.secondary.main)\n ? \"dark\"\n : \"light\",\n [darkMode, systemTheme, selectedTheme],\n );\n\n const muiTheme = useMemo(\n () =>\n createCustomTheme(\n selectedTheme.palette.primary.main,\n selectedTheme.palette.secondary.main,\n mode,\n ),\n [selectedTheme, mode],\n );\n\n const emotionTheme = useMemo(() => ({ darkMode: mode === \"dark\" }), [mode]);\n\n return (\n <ThemeContext.Provider value={{ theme, darkMode, setTheme, setDarkMode }}>\n <MuiThemeProvider theme={muiTheme}>\n <EmotionThemeProvider theme={emotionTheme}>\n <GlobalStyles />\n {children}\n </EmotionThemeProvider>\n </MuiThemeProvider>\n </ThemeContext.Provider>\n );\n};\n","export const ColorPalette = {\n fontDark: \"#101727\",\n fontLight: \"#f0f0f0\",\n darkMode: \"#383838\",\n lightMode: \"#ffffff\",\n purple: \"#b624ff\",\n red: \"#ff3131\",\n orange: \"#ff9318\",\n orangeDark: \"#ff9500\",\n} as const;\n\nexport const themeConfig: Record<\n string,\n { primaryColor: string; secondaryColor?: string }\n> = {\n Future: {\n primaryColor: \"#203959\",\n secondaryColor: \"#ffffff\",\n },\n Orange: {\n primaryColor: \"#f6883d\",\n secondaryColor: \"#ffffff\",\n },\n \"Neo Mint\": {\n primaryColor: \"#00f5d4\",\n secondaryColor: \"#e4fff8\",\n },\n \"Cyber Grape\": {\n primaryColor: \"#4b0082\",\n secondaryColor: \"#f4f0fa\",\n },\n \"Coral Glass\": {\n primaryColor: \"#ff6f61\",\n secondaryColor: \"#fef2f2\",\n },\n \"Blueberry Ice\": {\n primaryColor: \"#3f51b5\",\n secondaryColor: \"#e8eaf6\",\n },\n \"Dark Purple\": {\n // Default dark theme\n primaryColor: ColorPalette.purple,\n },\n \"Light Purple\": {\n // Default light theme\n primaryColor: ColorPalette.purple,\n secondaryColor: \"#edeef6\",\n },\n \"Dark Blue\": {\n primaryColor: \"#106cff\",\n secondaryColor: \"#090815\",\n },\n \"Light Blue\": {\n primaryColor: \"#278ad2\",\n secondaryColor: \"#dddaf6\",\n },\n \"Dark Pink\": {\n primaryColor: \"#f2369d\",\n secondaryColor: \"#191218\",\n },\n \"Light Pink\": {\n primaryColor: \"#e5369a\",\n secondaryColor: \"#ffe3ff\",\n },\n \"Blush Blossom\": {\n primaryColor: \"#EC407A\",\n secondaryColor: \"#FCE4EC\",\n },\n Cheesecake: {\n primaryColor: \"#E14C94\",\n secondaryColor: \"#FDF0D5\",\n },\n \"Mystic Coral\": {\n primaryColor: \"#ff7b9c\",\n secondaryColor: \"#4a2333\",\n },\n \"Dark Orange\": {\n primaryColor: \"#FF5631\",\n secondaryColor: \"#0D0D0D\",\n },\n \"Light Orange\": {\n primaryColor: \"#F26E56\",\n secondaryColor: \"#F6F6F6\",\n },\n Aurora: {\n primaryColor: \"#00e952\",\n secondaryColor: \"#011926\",\n },\n};\n","import { ColorPalette } from \"./themeConfig\";\n\n/**\n * Validates whether a given string is a valid 3- or 6-digit hex color code (e.g., \"#fff\" or \"#ffffff\").\n *\n * @param value - The string to check.\n * @returns `true` if the string is a valid hex color; otherwise, `false`.\n */\nexport const isHexColor = (value: string): boolean =>\n /^#([\\dA-Fa-f]{3}|[\\dA-Fa-f]{6})$/.test(value);\n\n/**\n * Determines the ideal font color (white or black) for contrast against a given background color.\n *\n * Uses luminance calculation (YIQ) to ensure accessibility and visual clarity.\n *\n * @param backgroundColor - A valid hex color (e.g., \"#ffffff\").\n * @returns A hex color string (`fontLight` or `fontDark`) suitable for overlay text.\n */\nexport const getFontColor = (backgroundColor: string): string => {\n if (!isHexColor(backgroundColor)) {\n // eslint-disable-next-line no-console -- Allow\n console.error(\"Invalid hex color provided:\", backgroundColor);\n return ColorPalette.fontDark;\n }\n\n const hex = backgroundColor.slice(1);\n\n const fullHex =\n hex.length === 3\n ? hex\n .split(\"\")\n .map((c) => c + c)\n .join(\"\")\n : hex;\n\n const r = Number.parseInt(fullHex.slice(0, 2), 16);\n const g = Number.parseInt(fullHex.slice(2, 4), 16);\n const b = Number.parseInt(fullHex.slice(4, 6), 16);\n\n const brightness = Math.round((r * 299 + g * 587 + b * 114) / 1000);\n\n return brightness > 128 ? ColorPalette.fontDark : ColorPalette.fontLight;\n};\n\n/**\n * Determines whether the ideal font color for a background is light (i.e., white).\n *\n * @param color - The background color in hex.\n * @returns `true` if white text is recommended; otherwise, `false`.\n */\nexport const isFontLight = (color: string): boolean =>\n getFontColor(color) === ColorPalette.fontLight;\n","import type { Theme } from \"@mui/material\";\n\n/**\n * Common component style overrides and default props shared across the design system.\n * This object should be spread into the `components` field of the MUI theme.\n */\nexport const commonComponentProps: Theme[\"components\"] = {\n MuiTooltip: {\n defaultProps: {\n disableInteractive: true,\n },\n styleOverrides: {\n tooltip: ({ theme }) => ({\n color: theme.palette.mode === \"dark\" ? \"#fff\" : \"#000\",\n backgroundColor:\n theme.palette.mode === \"dark\" ? \"#141431dd\" : \"#ededf3dd\",\n backdropFilter: \"blur(6px)\",\n WebkitBackdropFilter: \"blur(6px)\",\n padding: \"8px 16px\",\n borderRadius: theme.shape.borderRadius,\n fontSize: \"12px\",\n }),\n },\n },\n\n MuiButton: {\n styleOverrides: {\n root: ({ theme }) => ({\n padding: \"12px 24px\",\n borderRadius: theme.shape.borderRadius,\n }),\n contained: {\n boxShadow: \"none\",\n },\n },\n },\n\n MuiSkeleton: {\n styleOverrides: {\n root: ({ theme }) => ({\n borderRadius: theme.shape.borderRadius,\n }),\n },\n },\n\n MuiSelect: {\n styleOverrides: {\n root: ({ theme }) => ({\n borderRadius: theme.shape.borderRadius,\n }),\n select: {\n display: \"flex\",\n justifyContent: \"flex-start\",\n alignItems: \"center\",\n gap: \"4px\",\n },\n },\n },\n\n MuiDialog: {\n defaultProps: {\n slotProps: {\n paper: {\n style: {\n padding: \"12px\",\n borderRadius: 24, // оставить явно, если это критично\n minWidth: \"400px\",\n },\n },\n },\n },\n styleOverrides: {\n root: {\n \"& .MuiDialog-container\": {\n backdropFilter: \"blur(4px)\",\n },\n },\n },\n },\n\n MuiAvatar: {\n styleOverrides: {\n root: {\n fontWeight: 500,\n color: \"#fff\",\n },\n },\n },\n\n MuiAlert: {\n styleOverrides: {\n root: ({ theme }) => ({\n borderRadius: theme.shape.borderRadius,\n }),\n },\n },\n\n MuiTextField: {\n defaultProps: {\n variant: 'outlined', // по умолчанию, если нужно\n },\n styleOverrides: {\n root: ({ theme }) => ({\n \"& .MuiInputBase-root\": {\n borderRadius: theme.shape.borderRadius,\n },\n }),\n },\n },\n\n MuiOutlinedInput: {\n styleOverrides: {\n root: ({ theme }) => ({\n color: theme.palette.primary.main,\n '& fieldset': {\n borderColor: theme.palette.primary.main,\n },\n '&:hover fieldset': {\n borderColor: theme.palette.primary.dark,\n },\n '&.Mui-focused fieldset': {\n borderColor: theme.palette.primary.main,\n },\n }),\n },\n },\n\n MuiInputLabel: {\n styleOverrides: {\n root: ({ theme }) => ({\n color: theme.palette.primary.main,\n '&.Mui-focused': {\n color: theme.palette.primary.main,\n },\n }),\n },\n },\n MuiFormHelperText: {\n styleOverrides: {\n root: ({ theme }) => ({\n color: theme.palette.error.main,\n }),\n },\n },\n\n MuiPaper: {\n styleOverrides: {\n root: ({ theme }) => ({\n borderRadius: theme.shape.borderRadius,\n }),\n elevation8: ({ theme }) => ({\n borderRadius: theme.shape.borderRadius,\n }),\n },\n },\n\n MuiMenuItem: {\n styleOverrides: {\n root: ({ theme }) => ({\n borderRadius: theme.shape.borderRadius,\n }),\n },\n },\n\n MuiBottomNavigationAction: {\n styleOverrides: {\n root: ({ theme }) => ({\n borderRadius: theme.shape.borderRadius,\n padding: \"12px\",\n margin: 0,\n maxHeight: \"none\",\n }),\n },\n },\n\n MuiSvgIcon: {\n defaultProps: {\n color: \"primary\",\n },\n },\n\n MuiDialogContent: {\n styleOverrides: {\n root: {\n padding: 0,\n },\n },\n },\n\n MuiSlider: {\n styleOverrides: {\n valueLabel: ({ theme }) => ({\n borderRadius: theme.shape.borderRadius,\n padding: \"6px 14px\",\n color: theme.palette.mode === \"dark\" ? \"#fff\" : \"#000\",\n backgroundColor:\n theme.palette.mode === \"dark\" ? \"#141431dd\" : \"#ededf3dd\",\n \"&::before, &::after\": {\n display: \"none\",\n },\n }),\n },\n },\n\n MuiCircularProgress: {\n styleOverrides: {\n circle: {\n strokeLinecap: \"round\",\n },\n },\n },\n\n MuiTab: {\n styleOverrides: {\n root: ({ theme }) => ({\n borderRadius: theme.shape.borderRadius,\n }),\n },\n },\n\n MuiAccordion: {\n styleOverrides: {\n root: {\n \"&::before\": {\n display: \"none\",\n },\n },\n },\n },\n};\n","import { createTheme } from \"@mui/material\";\n\nimport { getFontColor } from \"./colorUtils\";\nimport { commonComponentProps } from \"./commonComponents\";\nimport { ColorPalette, themeConfig } from \"./themeConfig\";\nimport { muiTypography, typographyVariants } from \"./typography\";\n\nimport type { AppSettings, SystemTheme } from \"../models\";\nimport type { PaletteMode, Theme } from \"@mui/material\";\n\nexport const createCustomTheme = (\n primaryColor: string,\n backgroundColor = \"#232e58\",\n mode: PaletteMode = \"dark\",\n): Theme =>\n createTheme({\n palette: {\n primary: { main: primaryColor },\n secondary: { main: backgroundColor },\n warning: {\n main: mode === \"dark\" ? ColorPalette.orange : ColorPalette.orangeDark,\n },\n error: { main: ColorPalette.red },\n mode,\n },\n components: {\n ...commonComponentProps,\n MuiTypography: muiTypography,\n },\n typography: typographyVariants,\n shape: { borderRadius: 24 },\n });\n\n/**\n * A predefined list of named themes based on the `themeConfig` definition.\n */\nexport const themes: { name: string; MuiTheme: Theme }[] = Object.entries(\n themeConfig,\n).map(([name, config]) => ({\n name,\n MuiTheme: createCustomTheme(config.primaryColor, config.secondaryColor),\n}));\n\n/**\n * Determines whether dark mode should be enabled based on user settings and system conditions.\n *\n * @param darkMode - User preference: 'light' | 'dark' | 'system' | 'auto'.\n * @param systemTheme - Detected OS-level theme: 'light' | 'dark'.\n * @param backgroundColor - The background color to assess contrast in 'auto' mode.\n * @returns True if dark mode should be used.\n */\nexport const isDarkMode = (\n darkMode: AppSettings[\"darkMode\"],\n systemTheme: SystemTheme,\n backgroundColor: string,\n): boolean => {\n switch (darkMode) {\n case \"light\": {\n return false;\n }\n case \"dark\": {\n return true;\n }\n case \"system\": {\n return systemTheme === \"dark\";\n }\n case \"auto\": {\n return getFontColor(backgroundColor) === ColorPalette.fontLight;\n }\n default: {\n return false;\n }\n }\n};\n","import type {\n Components,\n Theme,\n TypographyVariantsOptions,\n} from \"@mui/material\";\n\n/**\n * Mapping of custom typography variants to corresponding HTML elements.\n */\nexport const muiTypography: Components<Theme>[\"MuiTypography\"] = {\n defaultProps: {\n variantMapping: {\n // TEXT REGULAR\n text_xl_regular: \"p\",\n text_lg_regular: \"p\",\n text_md_regular: \"p\",\n text_sm_regular: \"p\",\n text_xs_regular: \"p\",\n text_2xs_regular: \"p\",\n\n // TEXT BOLD\n text_xl_bold: \"p\",\n text_lg_bold: \"p\",\n text_md_bold: \"p\",\n text_sm_bold: \"p\",\n text_xs_bold: \"p\",\n text_2xs_bold: \"p\",\n\n // TEXT SEMIBOLD\n text_xl_semibold: \"p\",\n text_lg_semibold: \"p\",\n text_md_semibold: \"p\",\n text_sm_semibold: \"p\",\n text_xs_semibold: \"p\",\n text_2xs_semibold: \"p\",\n\n // TEXT THIN\n text_xl_thin: \"p\",\n text_lg_thin: \"p\",\n text_md_thin: \"p\",\n text_sm_thin: \"p\",\n text_xs_thin: \"p\",\n text_2xs_thin: \"p\",\n\n // HEADER REGULAR\n header_2xl_regular: \"h1\",\n header_xl_regular: \"h2\",\n header_lg_regular: \"h3\",\n header_md_regular: \"h4\",\n header_sm_regular: \"h5\",\n header_xs_regular: \"h6\",\n\n // DISPLAY BOLD\n header_2xl_bold: \"h1\",\n header_xl_bold: \"h2\",\n header_lg_bold: \"h3\",\n header_md_bold: \"h4\",\n header_sm_bold: \"h5\",\n header_xs_bold: \"h6\",\n },\n },\n};\n\n/**\n * Custom typography variant definitions with adjusted display sizes.\n */\nexport const typographyVariants: TypographyVariantsOptions = {\n text_xl_regular: { font: \"400 20px/30px inherit inherit\" },\n text_lg_regular: { font: \"400 18px/28px inherit inherit\" },\n text_md_regular: { font: \"400 16px/24px inherit inherit\" },\n text_sm_regular: { font: \"400 14px/20px inherit inherit\" },\n text_xs_regular: { font: \"400 12px/18px inherit inherit\" },\n text_2xs_regular: { font: \"400 10px/14px inherit inherit\" },\n\n text_xl_bold: { font: \"700 20px/30px inherit inherit\" },\n text_lg_bold: { font: \"700 18px/28px inherit inherit\" },\n text_md_bold: { font: \"700 16px/24px inherit inherit\" },\n text_sm_bold: { font: \"700 14px/20px inherit inherit\" },\n text_xs_bold: { font: \"700 12px/18px inherit inherit\" },\n text_2xs_bold: { font: \"700 10px/14px inherit inherit\" },\n\n text_xl_semibold: { font: \"600 20px/30px inherit inherit\" },\n text_lg_semibold: { font: \"600 18px/28px inherit inherit\" },\n text_md_semibold: { font: \"600 16px/24px inherit inherit\" },\n text_sm_semibold: { font: \"600 14px/20px inherit inherit\" },\n text_xs_semibold: { font: \"600 12px/18px inherit inherit\" },\n text_2xs_semibold: { font: \"600 10px/14px inherit inherit\" },\n\n text_xl_thin: { font: \"100 20px/30px inherit inherit\" },\n text_lg_thin: { font: \"100 18px/28px inherit inherit\" },\n text_md_thin: { font: \"100 16px/24px inherit inherit\" },\n text_sm_thin: { font: \"100 14px/20px inherit inherit\" },\n text_xs_thin: { font: \"100 12px/18px inherit inherit\" },\n text_2xs_thin: { font: \"100 10px/14px inherit inherit\" },\n\n header_2xl_regular: { font: \"400 48px/60px inherit inherit\" },\n header_xl_regular: { font: \"400 42px/54px inherit inherit\" },\n header_lg_regular: { font: \"400 36px/46px inherit inherit\" },\n header_md_regular: { font: \"400 30px/38px inherit inherit\" },\n header_sm_regular: { font: \"400 26px/34px inherit inherit\" },\n header_xs_regular: { font: \"400 22px/30px inherit inherit\" },\n\n header_2xl_bold: { font: \"700 48px/60px inherit inherit\" },\n header_xl_bold: { font: \"700 42px/54px inherit inherit\" },\n header_lg_bold: { font: \"700 36px/46px inherit inherit\" },\n header_md_bold: { font: \"700 30px/38px inherit inherit\" },\n header_sm_bold: { font: \"700 26px/34px inherit inherit\" },\n header_xs_bold: { font: \"700 22px/30px inherit inherit\" },\n};\n","import BrightnessAutoRoundedIcon from \"@mui/icons-material/BrightnessAutoRounded\";\nimport DarkModeRoundedIcon from \"@mui/icons-material/DarkModeRounded\";\nimport LightModeRoundedIcon from \"@mui/icons-material/LightModeRounded\";\nimport PersonalVideoRoundedIcon from \"@mui/icons-material/PersonalVideoRounded\";\n\nimport type { OptionItem } from \"../models\";\n\nconst OPTION_ICON_SIZE = 32;\n\nexport const darkModeOptions: OptionItem[] = [\n {\n label: \"Auto\",\n value: \"auto\",\n icon: (\n <BrightnessAutoRoundedIcon\n color=\"inherit\"\n sx={{ fontSize: OPTION_ICON_SIZE }}\n />\n ),\n },\n {\n label: \"System\",\n value: \"system\",\n icon: (\n <PersonalVideoRoundedIcon\n color=\"inherit\"\n sx={{ fontSize: OPTION_ICON_SIZE }}\n />\n ),\n },\n {\n label: \"Light\",\n value: \"light\",\n icon: (\n <LightModeRoundedIcon\n color=\"inherit\"\n sx={{ fontSize: OPTION_ICON_SIZE }}\n />\n ),\n },\n {\n label: \"Dark\",\n value: \"dark\",\n icon: (\n <DarkModeRoundedIcon\n color=\"inherit\"\n sx={{ fontSize: OPTION_ICON_SIZE }}\n />\n ),\n },\n];\n","import { useMemo } from \"react\";\nimport { Global, css } from \"@emotion/react\";\nimport { useTheme } from \"@mui/material/styles\";\n\nimport { getFontColor } from \"./colorUtils\";\n\nimport type { FC } from \"react\";\n\n/**\n * Injects global styles into the document using Emotion.\n * These styles include font setup, base HTML styles, custom scrollbars,\n * selection styling, and some accessibility tweaks.\n *\n * Uses the MUI theme to dynamically adjust colors for light/dark mode.\n */\nexport const GlobalStyles: FC = () => {\n const theme = useTheme();\n const isDarkMode = theme.palette.mode === \"dark\";\n\n const primaryColor = theme.palette.primary.main;\n const secondaryColor = theme.palette.secondary.main;\n\n const primaryFontColor = useMemo(\n () => getFontColor(primaryColor),\n [primaryColor],\n );\n const secondaryFontColor = useMemo(\n () => getFontColor(secondaryColor),\n [secondaryColor],\n );\n\n return (\n <Global\n styles={css`\n * {\n font-family: \"Poppins\", sans-serif !important;\n -webkit-tap-highlight-color: transparent;\n &::selection {\n background-color: ${`${primaryColor}e1`};\n color: ${primaryFontColor};\n }\n }\n\n html,\n body,\n #root {\n height: 100%;\n margin: 0;\n }\n\n :root {\n height: 100%;\n font-family: \"Poppins\", sans-serif;\n line-height: 1.5;\n font-weight: 400;\n color-scheme: ${isDarkMode ? \"dark\" : \"light\"};\n color: ${secondaryFontColor};\n font-synthesis: none;\n text-rendering: optimizeLegibility;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n -webkit-text-size-adjust: 100%;\n\n --rsbs-backdrop-bg: rgba(0, 0, 0, 0.3);\n --rsbs-bg: ${isDarkMode ? \"#383838\" : \"#ffffff\"};\n }\n\n body {\n margin: 0;\n height: 100%;\n overflow: auto;\n touch-action: manipulation;\n background: ${secondaryColor};\n background-attachment: fixed;\n background-size: cover;\n transition: 0.3s background;\n\n ::-webkit-scrollbar {\n width: 8px;\n background-color: ${secondaryColor};\n }\n ::-webkit-scrollbar-thumb {\n background-color: ${primaryColor};\n border-radius: 64px;\n }\n ::-webkit-scrollbar-thumb:hover {\n background-color: ${`${primaryColor}d8`};\n }\n ::-webkit-scrollbar-track {\n border-radius: 64px;\n background-color: ${secondaryColor};\n }\n }\n\n a {\n text-decoration: none;\n color: inherit;\n }\n\n img {\n user-select: none;\n }\n\n input[type=\"file\"]::-webkit-file-upload-button {\n display: none;\n }\n\n input[type=\"datetime-local\"]:placeholder-shown {\n color: transparent !important;\n }\n\n pre {\n background-color: #000000d7;\n color: white;\n padding: 16px;\n border-radius: 18px;\n overflow-x: auto;\n }\n\n .MuiDialogContent-root,\n .MuiDrawer-paper,\n .customScrollbar,\n textarea {\n ::-webkit-scrollbar {\n width: 8px;\n border-radius: 4px;\n background-color: #84848415;\n }\n ::-webkit-scrollbar-thumb {\n background-color: #8484844b;\n border-radius: 4px;\n }\n ::-webkit-scrollbar-thumb:hover {\n background-color: #84848476;\n }\n ::-webkit-scrollbar-track {\n border-radius: 4px;\n background-color: #84848415;\n }\n }\n\n /* react-spring-bottom-sheet styles */\n div[role=\"dialog\"] {\n border-radius: 42px 42px 0 0;\n z-index: 9999999;\n }\n\n div[data-rsbs-backdrop] {\n z-index: 999;\n }\n\n div[data-rsbs-header] {\n z-index: 999999;\n box-shadow: none;\n &::before {\n width: 60px;\n height: 6px;\n border-radius: 100px;\n background: ${isDarkMode ? \"#717171\" : \"#cfcfcf\"};\n margin-top: 3px;\n }\n }\n `}\n />\n );\n};\n","import { keyframes } from \"@emotion/react\";\n\n/**\n * Fade in from the left with slight movement on the X-axis.\n */\nexport const fadeInLeft = keyframes`\n from {\n opacity: 0;\n transform: translateX(-40px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n`;\n\n/**\n * Simple fade in animation (opacity only).\n */\nexport const fadeIn = keyframes`\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n`;\n\n/**\n * Slide in from the left side of the screen.\n */\nexport const slideIn = keyframes`\n from {\n transform: translateX(-100%);\n }\n to {\n transform: translateX(0);\n }\n`;\n\n/**\n * Slide in from the bottom of the screen.\n */\nexport const slideInBottom = keyframes`\n from {\n transform: translateY(100%);\n }\n to {\n transform: translateY(0);\n }\n`;\n\n/**\n * Scale from 0 to full size.\n */\nexport const scale = keyframes`\n from {\n transform: scale(0);\n }\n to {\n transform: scale(1);\n }\n`;\n\n/**\n * Creates a pulsating animation using scale and box-shadow.\n * Simulates a glowing effect.\n *\n * @param clr - The base color for the shadow in hex format.\n * @param shadowBlur - The maximum spread of the shadow during the pulse (default: 12).\n * @returns Emotion keyframes animation.\n */\nexport const pulseAnimation = (clr: string, shadowBlur = 12) => keyframes`\n 0% {\n transform: scale(0.95);\n box-shadow: 0 0 0 0 ${clr}b2;\n }\n 70% {\n transform: scale(1);\n box-shadow: 0 0 0 ${shadowBlur}px ${clr}00;\n }\n 100% {\n transform: scale(0.95);\n box-shadow: 0 0 0 0 ${clr}00;\n }\n`;\n\n/**\n * Creates a glowing pulse animation using drop-shadow.\n * Used in progress or highlight elements.\n *\n * @param clr - The glow color in hex.\n * @returns Emotion keyframes animation.\n */\nexport const progressPulse = (clr: string) => keyframes`\n 0% {\n filter: none;\n }\n 50% {\n filter: drop-shadow(0 0 10px ${clr}78);\n }\n 100% {\n filter: none;\n }\n`;\n\n/**\n * A bounce-scale animation used during logout transition.\n */\nexport const logoutAnimation = keyframes`\n 0% {\n transform: scale(1);\n opacity: 1;\n }\n 50% {\n transform: scale(0.9) translateX(-2px);\n opacity: 0.7;\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n }\n`;\n\n/**\n * Subtle bounce animation used for install app prompts.\n */\nexport const installAppAnimation = keyframes`\n 0% {\n transform: translateY(0);\n }\n 30% {\n transform: translateY(-5px);\n }\n 50% {\n transform: translateY(2px);\n }\n 70% {\n transform: translateY(-2px);\n }\n 100% {\n transform: translateY(0);\n }\n`;\n","/**\n * Returns a greeting based on the current time.\n * @returns {string} The appropriate greeting.\n */\nexport const displayGreeting = (): string => {\n const currentTime = new Date();\n const currentHour = currentTime.getHours();\n let greeting: string;\n if (currentHour < 12 && currentHour >= 5) {\n greeting = \"Доброе утро,\";\n } else if (currentHour < 18 && currentHour > 12) {\n greeting = \"Добрый день,\";\n } else {\n greeting = \"Добрый вечер,\";\n }\n\n return greeting;\n};\n","/**\n * Function to extract year, month, and day from a Date object\n */\nexport const getDayIdentifier = (date: Date) => {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\"); // Months are zero-based in JavaScript\n const day = String(date.getDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n};\n","/**\n * A list of supported operating systems.\n */\nexport type OperatingSystem =\n | \"Windows\"\n | \"macOS\"\n | \"Linux\"\n | \"iOS\"\n | \"Android\"\n | \"Unknown\";\n\n/**\n * A list of supported browsers.\n */\nexport type Browser = \"Chrome\" | \"Firefox\" | \"Safari\" | \"Edge\" | \"Unknown\";\n\nconst { userAgent } = globalThis.navigator;\n\n/**\n * Detects the user's operating system based on the user agent string.\n *\n * @returns {OperatingSystem} The name of the detected operating system.\n */\nexport const getOperatingSystem = (): OperatingSystem => {\n const ua = userAgent.toLowerCase();\n\n if (ua.includes(\"windows nt\")) return \"Windows\";\n if (ua.includes(\"iphone\") || ua.includes(\"ipad\") || ua.includes(\"ipod\"))\n return \"iOS\";\n if (ua.includes(\"mac\")) return \"macOS\";\n if (ua.includes(\"android\")) return \"Android\";\n if (ua.includes(\"linux\")) return \"Linux\";\n\n return \"Unknown\";\n};\n\n/**\n * Detects the user's browser based on the user agent string.\n *\n * @returns {Browser} The name of the detected browser.\n */\nexport const getBrowser = (): Browser => {\n const ua = userAgent.toLowerCase();\n\n // Order matters: Edge must come before Chrome\n if (ua.includes(\"edg\")) return \"Edge\";\n if (ua.includes(\"chrome\")) return \"Chrome\";\n if (ua.includes(\"firefox\")) return \"Firefox\";\n if (ua.includes(\"safari\")) return \"Safari\";\n\n return \"Unknown\";\n};\n\n/**\n * Basic information about the user's system (OS and browser).\n */\nexport const systemInfo = {\n os: getOperatingSystem(),\n browser: getBrowser(),\n};\n","/**\n * Converts a given date to a human-readable relative time string.\n *\n * @param {Date} date - The date to be converted.\n * @param lang\n * @returns {string} A string representing the relative time using `Intl` format (e.g., \"2 days ago\").\n */\nexport const timeAgo = (\n date: Date,\n lang = navigator.language || \"en-US\",\n): string => {\n // Get the current date and time\n const now = new Date();\n date = new Date(date);\n // Calculate the time difference in seconds\n const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);\n\n // Create an Intl.RelativeTimeFormat instance with the user's language\n const rtf = new Intl.RelativeTimeFormat(lang, { numeric: \"auto\" });\n\n // Determine the appropriate unit and format the result\n if (diffInSeconds < 60) {\n return rtf.format(-diffInSeconds, \"second\");\n }\n if (diffInSeconds < 3600) {\n const minutes = Math.floor(diffInSeconds / 60);\n return rtf.format(-minutes, \"minute\");\n }\n if (diffInSeconds < 86_400) {\n const hours = Math.floor(diffInSeconds / 3600);\n return rtf.format(-hours, \"hour\");\n }\n const days = Math.floor(diffInSeconds / 86_400);\n return rtf.format(-days, \"day\");\n};\n\nexport const timeAgoFromStart = (\n date: Date,\n lang = navigator.language || \"en-US\",\n): string => {\n const now = new Date();\n date = new Date(date);\n const difference = (date.getTime() - now.getTime()) / 1000;\n const differenceHours = Math.floor(difference / (60 * 60));\n const differenceMinutes = Math.floor(\n (difference - 60 * 60 * differenceHours) / 60,\n );\n const diffInSeconds = Math.floor(\n difference - 60 * 60 * differenceHours - 60 * differenceMinutes,\n );\n\n const rtf = new Intl.RelativeTimeFormat(lang, { numeric: \"auto\" });\n\n if (differenceMinutes === 0 && diffInSeconds < 60) {\n return rtf.format(diffInSeconds, \"second\");\n }\n if (differenceHours === 0 && differenceMinutes < 60) {\n return rtf.format(differenceMinutes, \"minute\");\n }\n if (differenceHours < 24) {\n const hours = `${new Intl.RelativeTimeFormat(lang, {\n numeric: \"auto\",\n }).format(differenceHours, \"hour\")}`;\n const minutes = ` ${new Intl.RelativeTimeFormat(lang, {\n localeMatcher: \"lookup\",\n numeric: \"always\",\n style: \"long\",\n }).format(differenceMinutes, \"minute\")}`.replace(/^\\D+/, \"\");\n return `${hours} ${minutes}`;\n }\n\n const days = Math.floor(diffInSeconds / 86_400);\n return rtf.format(days, \"day\");\n};\n","import { useEffect, useState } from \"react\";\n\n/**\n * A custom React hook to determine if the current device is a smaller device\n * based on the screen width.\n * @param [breakpoint=768] - The breakpoint in pixels at which a device is considered \"smaller\".\n * @returns {boolean} - A boolean value indicating whether the current device is a smaller device.\n */\nexport const useResponsiveDisplay = (breakpoint = 768): boolean => {\n const [isSmallerDevice, setIsSmallerDevice] = useState<boolean>(false);\n\n useEffect(() => {\n const checkScreenSize = () => {\n setIsSmallerDevice(window.innerWidth < breakpoint);\n };\n checkScreenSize();\n const handleResize = () => checkScreenSize();\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [breakpoint]);\n\n return isSmallerDevice;\n};\n","import { useState, useEffect } from \"react\";\n\nimport type { SystemTheme } from \"../models\";\n\n/**\n * A React hook to detect the system theme preference.\n * @returns The current system theme ('light', 'dark', or 'unknown').\n */\nexport const useSystemTheme = (): SystemTheme => {\n const [theme, setTheme] = useState<SystemTheme>(\"unknown\");\n useEffect(() => {\n const mediaQueryListener = (e: MediaQueryListEvent) => {\n setTheme(e.matches ? \"dark\" : \"light\");\n };\n\n const prefersDarkScheme = globalThis.matchMedia(\n \"(prefers-color-scheme: dark)\",\n );\n setTheme(prefersDarkScheme.matches ? \"dark\" : \"light\");\n\n // Listen for changes in system theme\n prefersDarkScheme.addEventListener(\"change\", mediaQueryListener);\n\n return () => {\n prefersDarkScheme.removeEventListener(\"change\", mediaQueryListener);\n };\n }, []);\n\n return theme;\n};\n"],"mappings":"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