commit
9a37b55b80
@ -38,6 +38,9 @@ class SettingsStore {
|
||||
? window.RendererProcessVariable?.theme?.type === "dark"
|
||||
? Dark
|
||||
: Base
|
||||
: window.matchMedia &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? Dark
|
||||
: Base;
|
||||
trustedDomains = [];
|
||||
trustedDomainsType = 0;
|
||||
|
@ -2,13 +2,15 @@ import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { tablet, hugeMobile } from "@docspace/components/utils/device";
|
||||
|
||||
import Base from "../themes/base";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 32px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0px 5px 20px rgba(4, 15, 27, 0.07);
|
||||
background: ${(props) => props.theme.formWrapper.background};
|
||||
box-shadow: ${(props) => props.theme.formWrapper.boxShadow};
|
||||
border-radius: 12px;
|
||||
max-width: 320px;
|
||||
min-width: 320px;
|
||||
@ -24,13 +26,17 @@ const StyledWrapper = styled.div`
|
||||
box-shadow: none;
|
||||
max-width: 343px;
|
||||
min-width: 343px;
|
||||
background: #ffffff;
|
||||
background: transparent;
|
||||
}
|
||||
`;
|
||||
|
||||
StyledWrapper.defaultProps = { theme: Base };
|
||||
|
||||
const FormWrapper = (props) => {
|
||||
const { children } = props;
|
||||
return <StyledWrapper>{children}</StyledWrapper>;
|
||||
return <StyledWrapper {...props}>{children}</StyledWrapper>;
|
||||
};
|
||||
|
||||
FormWrapper.defaultProps = { theme: Base };
|
||||
|
||||
export default FormWrapper;
|
||||
|
@ -17,7 +17,7 @@ const StyledOuter = styled.div`
|
||||
}
|
||||
path {
|
||||
fill: ${(props) =>
|
||||
props.color ? props.color : props.theme.iconButton.color};
|
||||
props.color ? props.color : props.theme.iconButton.color} !important;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
|
@ -368,7 +368,6 @@ class PasswordInput extends React.Component {
|
||||
<>
|
||||
<InputBlock
|
||||
className="input-relative"
|
||||
id={id}
|
||||
name={inputName}
|
||||
hasError={hasError}
|
||||
isDisabled={isDisabled}
|
||||
@ -412,10 +411,12 @@ class PasswordInput extends React.Component {
|
||||
style,
|
||||
simpleView,
|
||||
isDisabled,
|
||||
id,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<StyledInput
|
||||
id={id}
|
||||
onValidateInput={onValidateInput}
|
||||
className={className}
|
||||
style={style}
|
||||
|
@ -2732,6 +2732,8 @@ const Base = {
|
||||
login: {
|
||||
linkColor: link,
|
||||
textColor: gray,
|
||||
navBackground: "#F8F9F9",
|
||||
headerColor: black,
|
||||
|
||||
register: {
|
||||
backgroundColor: grayLight,
|
||||
@ -2975,6 +2977,11 @@ const Base = {
|
||||
border: "1px solid #eceef1",
|
||||
},
|
||||
},
|
||||
|
||||
formWrapper: {
|
||||
background: white,
|
||||
boxShadow: "0px 5px 20px rgba(4, 15, 27, 0.07)",
|
||||
},
|
||||
};
|
||||
|
||||
export default Base;
|
||||
|
@ -2738,6 +2738,8 @@ const Dark = {
|
||||
login: {
|
||||
linkColor: "#E06A1B",
|
||||
textColor: "#858585",
|
||||
navBackground: "#282828",
|
||||
headerColor: white,
|
||||
|
||||
register: {
|
||||
backgroundColor: "#292929",
|
||||
@ -2980,6 +2982,11 @@ const Dark = {
|
||||
border: "1px solid #858585",
|
||||
},
|
||||
},
|
||||
|
||||
formWrapper: {
|
||||
background: black,
|
||||
boxShadow: "0px 5px 20px rgba(0, 0, 0, 0.16);",
|
||||
},
|
||||
};
|
||||
|
||||
export default Dark;
|
||||
|
1
packages/login/index.d.ts
vendored
1
packages/login/index.d.ts
vendored
@ -96,6 +96,7 @@ declare global {
|
||||
capabilities: ICapabilities;
|
||||
match: MatchType;
|
||||
currentColorScheme: ITheme;
|
||||
isAuth: boolean;
|
||||
}
|
||||
|
||||
interface DevRequest {
|
||||
|
@ -5,6 +5,7 @@ import InvalidRoute from "./components/Invalid";
|
||||
import CodeLogin from "./components/CodeLogin";
|
||||
import initLoginStore from "../store";
|
||||
import { Provider as MobxProvider } from "mobx-react";
|
||||
import SimpleNav from "../client/components/sub-components/SimpleNav";
|
||||
|
||||
interface ILoginProps extends IInitialState {
|
||||
isDesktopEditor?: boolean;
|
||||
@ -13,6 +14,7 @@ const App: React.FC<ILoginProps> = (props) => {
|
||||
const loginStore = initLoginStore(props.currentColorScheme);
|
||||
return (
|
||||
<MobxProvider {...loginStore}>
|
||||
<SimpleNav />
|
||||
<Switch>
|
||||
<Route path="/login/error">
|
||||
<InvalidRoute />
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { useState, useCallback } from "react";
|
||||
import React, { useEffect, useState, useCallback } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { ButtonsWrapper, LoginFormWrapper } from "./StyledLogin";
|
||||
import Logo from "../../../../../public/images/docspace.big.react.svg";
|
||||
import Text from "@docspace/components/text";
|
||||
@ -20,6 +21,8 @@ import FormWrapper from "@docspace/components/form-wrapper";
|
||||
import Register from "./sub-components/register-container";
|
||||
import { ColorTheme, ThemeType } from "@docspace/common/components/ColorTheme";
|
||||
import SSOIcon from "../../../../../public/images/sso.react.svg";
|
||||
import { Dark, Base } from "@docspace/components/themes";
|
||||
import { useMounted } from "../helpers/useMounted";
|
||||
|
||||
interface ILoginProps extends IInitialState {
|
||||
isDesktopEditor?: boolean;
|
||||
@ -31,6 +34,9 @@ const Login: React.FC<ILoginProps> = ({
|
||||
capabilities,
|
||||
isDesktopEditor,
|
||||
match,
|
||||
currentColorScheme,
|
||||
theme,
|
||||
setTheme,
|
||||
}) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [moreAuthVisible, setMoreAuthVisible] = useState(false);
|
||||
@ -40,6 +46,16 @@ const Login: React.FC<ILoginProps> = ({
|
||||
const { ssoLabel, ssoUrl } = capabilities;
|
||||
|
||||
const { t } = useTranslation(["Login", "Common"]);
|
||||
const mounted = useMounted();
|
||||
|
||||
useEffect(() => {
|
||||
const theme =
|
||||
window.matchMedia &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? Dark
|
||||
: Base;
|
||||
setTheme(theme);
|
||||
}, []);
|
||||
|
||||
const ssoExists = () => {
|
||||
if (ssoUrl) return true;
|
||||
@ -155,13 +171,40 @@ const Login: React.FC<ILoginProps> = ({
|
||||
setRecoverDialogVisible(!recoverDialogVisible);
|
||||
};
|
||||
|
||||
const getBgPattern = () => {
|
||||
switch (currentColorScheme.id) {
|
||||
case 1:
|
||||
return "url('/static/images/background.pattern.react.svg')";
|
||||
case 2:
|
||||
return "url('/static/images/background.pattern.orange.react.svg')";
|
||||
case 3:
|
||||
return "url('/static/images/background.pattern.green.react.svg')";
|
||||
case 4:
|
||||
return "url('/static/images/background.pattern.red.react.svg')";
|
||||
case 5:
|
||||
return "url('/static/images/background.pattern.purple.react.svg')";
|
||||
case 6:
|
||||
return "url('/static/images/background.pattern.lightBlue.react.svg')";
|
||||
case 7:
|
||||
return "url('/static/images/background.pattern.black.react.svg')";
|
||||
default:
|
||||
return "url('/static/images/background.pattern.react.svg')";
|
||||
}
|
||||
};
|
||||
|
||||
const bgPattern = getBgPattern();
|
||||
|
||||
if (!mounted) return <></>;
|
||||
|
||||
return (
|
||||
<LoginFormWrapper
|
||||
id="login-page"
|
||||
enabledJoin={enabledJoin}
|
||||
isDesktop={isDesktopEditor}
|
||||
className="with-background-pattern"
|
||||
//className="with-background-pattern"
|
||||
bgPattern={bgPattern}
|
||||
>
|
||||
<ColorTheme themeId={ThemeType.LinkForgotPassword}>
|
||||
<ColorTheme themeId={ThemeType.LinkForgotPassword} theme={theme}>
|
||||
<Logo className="logo-wrapper" />
|
||||
<Text
|
||||
fontSize="23px"
|
||||
@ -171,7 +214,7 @@ const Login: React.FC<ILoginProps> = ({
|
||||
>
|
||||
{greetingSettings}
|
||||
</Text>
|
||||
<FormWrapper>
|
||||
<FormWrapper id="login-form" theme={theme}>
|
||||
{ssoExists() && <ButtonsWrapper>{ssoButton()}</ButtonsWrapper>}
|
||||
{oauthDataExists() && (
|
||||
<>
|
||||
@ -225,9 +268,19 @@ const Login: React.FC<ILoginProps> = ({
|
||||
emailPlaceholderText={t("RecoverContactEmailPlaceholder")}
|
||||
/>
|
||||
</ColorTheme>
|
||||
{!checkIsSSR() && enabledJoin && <Register enabledJoin={enabledJoin} />}
|
||||
{!checkIsSSR() && enabledJoin && (
|
||||
<Register
|
||||
enabledJoin={enabledJoin}
|
||||
currentColorScheme={currentColorScheme}
|
||||
/>
|
||||
)}
|
||||
</LoginFormWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default Login;
|
||||
export default inject(({ loginStore }) => {
|
||||
return {
|
||||
theme: loginStore.theme,
|
||||
setTheme: loginStore.setTheme,
|
||||
};
|
||||
})(observer(Login));
|
||||
|
@ -57,6 +57,7 @@ export const LoginContainer = styled.div`
|
||||
width: 100%;
|
||||
padding-bottom: 32px;
|
||||
min-height: 32px;
|
||||
color: ${(props) => props.theme.login.headerColor};
|
||||
|
||||
@media ${hugeMobile} {
|
||||
padding-top: 32px;
|
||||
@ -68,7 +69,7 @@ export const LoginContainer = styled.div`
|
||||
}
|
||||
|
||||
.or-label {
|
||||
margin: 0 8px;
|
||||
margin: 0 32px;
|
||||
}
|
||||
|
||||
.line {
|
||||
@ -133,11 +134,9 @@ export const LoginContainer = styled.div`
|
||||
}
|
||||
|
||||
.auth-form-container {
|
||||
margin: 32px 213px 0 213px;
|
||||
width: 320px;
|
||||
|
||||
@media ${tablet} {
|
||||
margin: 32px 0 0 0;
|
||||
width: 100%;
|
||||
}
|
||||
@media ${hugeMobile} {
|
||||
@ -145,6 +144,14 @@ export const LoginContainer = styled.div`
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.field-body{
|
||||
input, .password-input > div {
|
||||
background: ${(props) => props.theme.input.backgroundColor};
|
||||
color: ${(props) => props.theme.input.color};
|
||||
border-color: ${(props) => props.theme.input.borderColor};
|
||||
}
|
||||
}
|
||||
|
||||
.login-forgot-wrapper {
|
||||
margin-bottom: 14px;
|
||||
.login-checkbox-wrapper {
|
||||
@ -155,6 +162,22 @@ export const LoginContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
svg{
|
||||
margin-right: 8px !important;
|
||||
rect{
|
||||
fill: ${(props) => props.theme.checkbox.fillColor};
|
||||
stroke: ${(props) => props.theme.checkbox.borderColor};
|
||||
}
|
||||
|
||||
path{
|
||||
fill: ${(props) => props.theme.checkbox.arrowColor};
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox-text{
|
||||
color: ${(props) => props.theme.checkbox.arrowColor};
|
||||
}
|
||||
|
||||
label {
|
||||
justify-content: center;
|
||||
}
|
||||
@ -207,6 +230,10 @@ export const LoginContainer = styled.div`
|
||||
height: 46px;
|
||||
padding-bottom: 64px;
|
||||
|
||||
path:last-child {
|
||||
fill: ${(props) => props.theme.client.home.logoColor};
|
||||
}
|
||||
|
||||
@media ${hugeMobile} {
|
||||
display: none;
|
||||
}
|
||||
@ -216,6 +243,7 @@ export const LoginContainer = styled.div`
|
||||
interface ILoginFormWrapperProps {
|
||||
enabledJoin?: boolean;
|
||||
isDesktop?: boolean;
|
||||
bgPattern?: string;
|
||||
}
|
||||
|
||||
export const LoginFormWrapper = styled.div`
|
||||
@ -228,4 +256,19 @@ export const LoginFormWrapper = styled.div`
|
||||
: css`1fr`};
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
|
||||
background-image: ${props => props.bgPattern};
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: 100% 100%;
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
@media (max-width: 428px) {
|
||||
background-image: none;
|
||||
height: calc(100vh - 48px);
|
||||
}
|
||||
|
||||
`;
|
||||
|
@ -253,6 +253,7 @@ const LoginForm: React.FC<ILoginFormProps> = ({
|
||||
errorMessage={!password.trim() ? t("Common:RequiredField") : ""} //TODO: Add wrong password server error
|
||||
>
|
||||
<PasswordInput
|
||||
className="password-input"
|
||||
simpleView={true}
|
||||
passwordSettings={settings}
|
||||
id="password"
|
||||
@ -275,6 +276,7 @@ const LoginForm: React.FC<ILoginFormProps> = ({
|
||||
<div className="login-checkbox-wrapper">
|
||||
<div className="remember-wrapper">
|
||||
<Checkbox
|
||||
id="login-checkbox"
|
||||
className="login-checkbox"
|
||||
isChecked={isChecked}
|
||||
onChange={onChangeCheckbox}
|
||||
@ -282,6 +284,7 @@ const LoginForm: React.FC<ILoginFormProps> = ({
|
||||
helpButton={
|
||||
!checkIsSSR() && (
|
||||
<HelpButton
|
||||
color="#A3A9AE"
|
||||
helpButtonHeaderContent={t("CookieSettingsTitle")}
|
||||
tooltipContent={
|
||||
<Text fontSize="12px">{t("RememberHelper")}</Text>
|
||||
@ -319,7 +322,7 @@ const LoginForm: React.FC<ILoginFormProps> = ({
|
||||
id="submit"
|
||||
className="login-button"
|
||||
primary
|
||||
size="normal"
|
||||
size="medium"
|
||||
scale={true}
|
||||
label={
|
||||
isLoading ? t("Common:LoadingProcessing") : t("Common:LoginButton")
|
||||
@ -352,7 +355,7 @@ const LoginForm: React.FC<ILoginFormProps> = ({
|
||||
color="#316DAA"
|
||||
type="action"
|
||||
isHovered={true}
|
||||
className="recover-link"
|
||||
className="login-link recover-link"
|
||||
onClick={onRecoverDialogVisible}
|
||||
>
|
||||
{t("RecoverAccess")}
|
||||
|
@ -0,0 +1,34 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { hugeMobile } from "@docspace/components/utils/device";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
const StyledNav = styled.div`
|
||||
display: none;
|
||||
height: 48px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: ${(props) => props.theme.login.navBackground};
|
||||
|
||||
svg {
|
||||
path:last-child {
|
||||
fill: ${(props) => props.theme.client.home.logoColor};
|
||||
}
|
||||
}
|
||||
@media ${hugeMobile} {
|
||||
display: flex;
|
||||
}
|
||||
`;
|
||||
|
||||
const SimpleNav = ({ theme }) => {
|
||||
return (
|
||||
<StyledNav theme={theme}>
|
||||
<ReactSVG src="/static/images/logo.docspace.react.svg" />
|
||||
</StyledNav>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ loginStore }) => {
|
||||
return { theme: loginStore.theme };
|
||||
})(observer(SimpleNav));
|
@ -16,6 +16,7 @@ interface IRegisterProps {
|
||||
trustedDomainsType?: number;
|
||||
trustedDomains?: string[];
|
||||
theme?: any;
|
||||
currentColorScheme: ITheme;
|
||||
}
|
||||
|
||||
const StyledRegister = styled(Box)`
|
||||
@ -41,6 +42,7 @@ const Register: React.FC<IRegisterProps> = (props) => {
|
||||
trustedDomainsType,
|
||||
trustedDomains,
|
||||
theme,
|
||||
currentColorScheme,
|
||||
} = props;
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
@ -108,7 +110,7 @@ const Register: React.FC<IRegisterProps> = (props) => {
|
||||
return enabledJoin && !isAuthenticated ? (
|
||||
<>
|
||||
<StyledRegister onClick={onRegisterClick}>
|
||||
<Text color={theme.login.register.textColor}>{t("Register")}</Text>
|
||||
<Text color={currentColorScheme.accentColor}>{t("Register")}</Text>
|
||||
</StyledRegister>
|
||||
|
||||
{visible && (
|
||||
|
15
packages/login/src/client/helpers/useMounted.ts
Normal file
15
packages/login/src/client/helpers/useMounted.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export const useMounted = () => {
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
|
||||
return () => {
|
||||
setMounted(false);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return mounted;
|
||||
};
|
@ -31,7 +31,7 @@ app.use("/login", express.static(path.resolve(path.join(__dirname, "client"))));
|
||||
|
||||
app.use(logger("dev", { stream: stream }));
|
||||
|
||||
app.get("*", async (req: ILoginRequest, res: Response) => {
|
||||
app.get("*", async (req: ILoginRequest, res: Response, next) => {
|
||||
const { i18n, cookies, headers, query, t, url } = req;
|
||||
let initialState: IInitialState;
|
||||
let assets: assetsType;
|
||||
@ -41,6 +41,11 @@ app.get("*", async (req: ILoginRequest, res: Response) => {
|
||||
try {
|
||||
initialState = await getInitialState(query);
|
||||
|
||||
if (initialState.isAuth) {
|
||||
res.redirect('/');
|
||||
next();
|
||||
}
|
||||
|
||||
let currentLanguage = initialState.portalSettings.culture;
|
||||
|
||||
if (cookies && cookies[LANGUAGE]) {
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
getCapabilities,
|
||||
getAppearanceTheme,
|
||||
} from "@docspace/common/api/settings";
|
||||
import { checkIsAuthenticated } from "@docspace/common/api/user";
|
||||
|
||||
export const getAssets = (): assetsType => {
|
||||
const manifest = fs.readFileSync(
|
||||
@ -55,7 +56,8 @@ export const getInitialState = async (
|
||||
buildInfo: IBuildInfo,
|
||||
providers: ProvidersType,
|
||||
capabilities: ICapabilities,
|
||||
availableThemes: IThemes;
|
||||
availableThemes: IThemes,
|
||||
isAuth: any;
|
||||
|
||||
[
|
||||
portalSettings,
|
||||
@ -63,12 +65,14 @@ export const getInitialState = async (
|
||||
providers,
|
||||
capabilities,
|
||||
availableThemes,
|
||||
isAuth,
|
||||
] = await Promise.all([
|
||||
getSettings(),
|
||||
getBuildVersion(),
|
||||
getAuthProviders(),
|
||||
getCapabilities(),
|
||||
getAppearanceTheme(),
|
||||
checkIsAuthenticated()
|
||||
]);
|
||||
|
||||
const currentColorScheme = availableThemes.themes.find((theme) => {
|
||||
@ -82,6 +86,7 @@ export const getInitialState = async (
|
||||
capabilities,
|
||||
match: query,
|
||||
currentColorScheme,
|
||||
isAuth
|
||||
};
|
||||
|
||||
return initialState;
|
||||
|
@ -83,6 +83,75 @@ const template: Template = (
|
||||
<!-- <meta name="apple-mobile-web-app-capable" content="yes" /> -->
|
||||
<link rel="apple-touch-icon" href="/appIcon-180.png" />
|
||||
${styleTags}
|
||||
|
||||
<style>
|
||||
@media (prefers-color-scheme: light) {
|
||||
body {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#login-page > div > svg > path:last-child {
|
||||
fill: #333;
|
||||
}
|
||||
|
||||
#login-page > div > p {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#login-form {
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 5px 20px rgba(4, 15, 27, 0.07);
|
||||
}
|
||||
|
||||
#login, #password > div, #password > div > input {
|
||||
background: #fff;
|
||||
border-color: #D0D5DA;
|
||||
}
|
||||
|
||||
#login-checkbox > svg > rect {
|
||||
fill: #fff;
|
||||
stroke: #D0D5DA;
|
||||
}
|
||||
|
||||
#login-checkbox > div > span {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
#login-page > div > svg > path:last-child {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
#login-page > div > p {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#login-form {
|
||||
background-color: #333;
|
||||
box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
#login, #password > div, #password > div > input {
|
||||
background: #282828;
|
||||
border-color: #474747;
|
||||
}
|
||||
|
||||
#login-checkbox > svg > rect {
|
||||
fill: #282828;
|
||||
stroke: #474747;
|
||||
}
|
||||
|
||||
#login-checkbox > div > span {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<noscript> You need to enable JavaScript to run this app. </noscript>
|
||||
|
@ -1,15 +1,22 @@
|
||||
import { makeAutoObservable } from "mobx";
|
||||
import { getAppearanceTheme } from "@docspace/common/api/settings";
|
||||
import { Base } from "@docspace/components/themes";
|
||||
|
||||
class LoginStore {
|
||||
currentColorScheme: ITheme | null = null;
|
||||
appearanceTheme: IThemes | [] = [];
|
||||
selectedThemeId: number | null = null;
|
||||
theme = Base;
|
||||
|
||||
constructor(currentColorScheme: ITheme) {
|
||||
makeAutoObservable(this);
|
||||
this.currentColorScheme = currentColorScheme;
|
||||
}
|
||||
|
||||
setTheme = (theme) => {
|
||||
this.theme = theme;
|
||||
}
|
||||
|
||||
setCurrentColorScheme = (currentColorScheme: ITheme) => {
|
||||
this.currentColorScheme = currentColorScheme;
|
||||
};
|
||||
|
5
public/images/background.pattern.black.react.svg
Normal file
5
public/images/background.pattern.black.react.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="1440" height="1024" viewBox="0 0 1440 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.1" fill-rule="evenodd" clip-rule="evenodd" d="M64.6252 690.408L-919.12 986.976C-1004.49 1013.18 -1013.6 1072.53 -939.494 1119.65L-74.1381 1702.89C14.1367 1767.84 98.0781 1792.04 227.343 1745.01L1209.66 1449.78C1295.03 1423.58 1304.14 1364.23 1230.04 1317.1L403.802 732.878C315.028 664.676 226.063 647.445 64.6252 690.408Z" fill="#6E6E6E"/>
|
||||
<path opacity="0.15" fill-rule="evenodd" clip-rule="evenodd" d="M1209.36 391.601L2228.17 575.78C2315.2 592.373 2330.62 649.928 2262.64 704.433L1472.4 1373.42C1405.32 1431.31 1281.37 1464.53 1197.69 1447.04L178.872 1262.86C91.8424 1246.27 76.4229 1188.71 144.405 1134.21L934.649 465.22C1012.63 397.338 1126.59 377.497 1209.36 391.601Z" fill="#6E6E6E"/>
|
||||
<path opacity="0.2" fill-rule="evenodd" clip-rule="evenodd" d="M967.484 836.396L881.673 1868.31C875.172 1956.68 926.767 1986.47 997.002 1934.91L1847.63 1344.62C1920.9 1294.81 1985.06 1183.66 1989.83 1098.29L2075.64 66.374C2082.14 -21.9972 2030.55 -51.7898 1960.31 -0.221198L1109.68 590.062C1023.94 647.831 975.285 752.781 967.484 836.396Z" fill="#6E6E6E"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
5
public/images/background.pattern.green.react.svg
Normal file
5
public/images/background.pattern.green.react.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="1440" height="1024" viewBox="0 0 1440 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.1" fill-rule="evenodd" clip-rule="evenodd" d="M64.6252 690.408L-919.12 986.976C-1004.49 1013.18 -1013.6 1072.53 -939.494 1119.65L-74.1381 1702.89C14.1367 1767.84 98.0781 1792.04 227.343 1745.01L1209.66 1449.78C1295.03 1423.58 1304.14 1364.23 1230.04 1317.1L403.802 732.878C315.028 664.676 226.063 647.445 64.6252 690.408Z" fill="#22C386"/>
|
||||
<path opacity="0.15" fill-rule="evenodd" clip-rule="evenodd" d="M1209.36 391.601L2228.17 575.78C2315.2 592.373 2330.62 649.928 2262.64 704.433L1472.4 1373.42C1405.32 1431.31 1281.37 1464.53 1197.69 1447.04L178.872 1262.86C91.8424 1246.27 76.4229 1188.71 144.405 1134.21L934.649 465.22C1012.63 397.338 1126.59 377.497 1209.36 391.601Z" fill="#22C386"/>
|
||||
<path opacity="0.2" fill-rule="evenodd" clip-rule="evenodd" d="M967.484 836.396L881.673 1868.31C875.172 1956.68 926.767 1986.47 997.002 1934.91L1847.63 1344.62C1920.9 1294.81 1985.06 1183.66 1989.83 1098.29L2075.64 66.374C2082.14 -21.9972 2030.55 -51.7898 1960.31 -0.221198L1109.68 590.062C1023.94 647.831 975.285 752.781 967.484 836.396Z" fill="#22C386"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
5
public/images/background.pattern.lightBlue.react.svg
Normal file
5
public/images/background.pattern.lightBlue.react.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="1440" height="1024" viewBox="0 0 1440 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.1" fill-rule="evenodd" clip-rule="evenodd" d="M64.6252 690.408L-919.12 986.976C-1004.49 1013.18 -1013.6 1072.53 -939.494 1119.65L-74.1381 1702.89C14.1367 1767.84 98.0781 1792.04 227.343 1745.01L1209.66 1449.78C1295.03 1423.58 1304.14 1364.23 1230.04 1317.1L403.802 732.878C315.028 664.676 226.063 647.445 64.6252 690.408Z" fill="#13B7EC"/>
|
||||
<path opacity="0.15" fill-rule="evenodd" clip-rule="evenodd" d="M1209.36 391.601L2228.17 575.78C2315.2 592.373 2330.62 649.928 2262.64 704.433L1472.4 1373.42C1405.32 1431.31 1281.37 1464.53 1197.69 1447.04L178.872 1262.86C91.8424 1246.27 76.4229 1188.71 144.405 1134.21L934.649 465.22C1012.63 397.338 1126.59 377.497 1209.36 391.601Z" fill="#13B7EC"/>
|
||||
<path opacity="0.2" fill-rule="evenodd" clip-rule="evenodd" d="M967.484 836.396L881.673 1868.31C875.172 1956.68 926.767 1986.47 997.002 1934.91L1847.63 1344.62C1920.9 1294.81 1985.06 1183.66 1989.83 1098.29L2075.64 66.374C2082.14 -21.9972 2030.55 -51.7898 1960.31 -0.221198L1109.68 590.062C1023.94 647.831 975.285 752.781 967.484 836.396Z" fill="#13B7EC"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
5
public/images/background.pattern.orange.react.svg
Normal file
5
public/images/background.pattern.orange.react.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="1440" height="1024" viewBox="0 0 1440 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.1" fill-rule="evenodd" clip-rule="evenodd" d="M64.6252 690.408L-919.12 986.976C-1004.49 1013.18 -1013.6 1072.53 -939.494 1119.65L-74.1381 1702.89C14.1367 1767.84 98.0781 1792.04 227.343 1745.01L1209.66 1449.78C1295.03 1423.58 1304.14 1364.23 1230.04 1317.1L403.802 732.878C315.028 664.676 226.063 647.445 64.6252 690.408Z" fill="#FF9933"/>
|
||||
<path opacity="0.15" fill-rule="evenodd" clip-rule="evenodd" d="M1209.36 391.601L2228.17 575.78C2315.2 592.373 2330.62 649.928 2262.64 704.433L1472.4 1373.42C1405.32 1431.31 1281.37 1464.53 1197.69 1447.04L178.872 1262.86C91.8424 1246.27 76.4229 1188.71 144.405 1134.21L934.649 465.22C1012.63 397.338 1126.59 377.497 1209.36 391.601Z" fill="#FF9933"/>
|
||||
<path opacity="0.2" fill-rule="evenodd" clip-rule="evenodd" d="M967.484 836.396L881.673 1868.31C875.172 1956.68 926.767 1986.47 997.002 1934.91L1847.63 1344.62C1920.9 1294.81 1985.06 1183.66 1989.83 1098.29L2075.64 66.374C2082.14 -21.9972 2030.55 -51.7898 1960.31 -0.221198L1109.68 590.062C1023.94 647.831 975.285 752.781 967.484 836.396Z" fill="#FF9933"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
5
public/images/background.pattern.purple.react.svg
Normal file
5
public/images/background.pattern.purple.react.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="1440" height="1024" viewBox="0 0 1440 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.1" fill-rule="evenodd" clip-rule="evenodd" d="M64.6252 690.408L-919.12 986.976C-1004.49 1013.18 -1013.6 1072.53 -939.494 1119.65L-74.1381 1702.89C14.1367 1767.84 98.0781 1792.04 227.343 1745.01L1209.66 1449.78C1295.03 1423.58 1304.14 1364.23 1230.04 1317.1L403.802 732.878C315.028 664.676 226.063 647.445 64.6252 690.408Z" fill="#8570BD"/>
|
||||
<path opacity="0.15" fill-rule="evenodd" clip-rule="evenodd" d="M1209.36 391.601L2228.17 575.78C2315.2 592.373 2330.62 649.928 2262.64 704.433L1472.4 1373.42C1405.32 1431.31 1281.37 1464.53 1197.69 1447.04L178.872 1262.86C91.8424 1246.27 76.4229 1188.71 144.405 1134.21L934.649 465.22C1012.63 397.338 1126.59 377.497 1209.36 391.601Z" fill="#8570BD"/>
|
||||
<path opacity="0.2" fill-rule="evenodd" clip-rule="evenodd" d="M967.484 836.396L881.673 1868.31C875.172 1956.68 926.767 1986.47 997.002 1934.91L1847.63 1344.62C1920.9 1294.81 1985.06 1183.66 1989.83 1098.29L2075.64 66.374C2082.14 -21.9972 2030.55 -51.7898 1960.31 -0.221198L1109.68 590.062C1023.94 647.831 975.285 752.781 967.484 836.396Z" fill="#8570BD"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
5
public/images/background.pattern.red.react.svg
Normal file
5
public/images/background.pattern.red.react.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="1440" height="1024" viewBox="0 0 1440 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.1" fill-rule="evenodd" clip-rule="evenodd" d="M64.6252 690.408L-919.12 986.976C-1004.49 1013.18 -1013.6 1072.53 -939.494 1119.65L-74.1381 1702.89C14.1367 1767.84 98.0781 1792.04 227.343 1745.01L1209.66 1449.78C1295.03 1423.58 1304.14 1364.23 1230.04 1317.1L403.802 732.878C315.028 664.676 226.063 647.445 64.6252 690.408Z" fill="#F27564"/>
|
||||
<path opacity="0.15" fill-rule="evenodd" clip-rule="evenodd" d="M1209.36 391.601L2228.17 575.78C2315.2 592.373 2330.62 649.928 2262.64 704.433L1472.4 1373.42C1405.32 1431.31 1281.37 1464.53 1197.69 1447.04L178.872 1262.86C91.8424 1246.27 76.4229 1188.71 144.405 1134.21L934.649 465.22C1012.63 397.338 1126.59 377.497 1209.36 391.601Z" fill="#F27564"/>
|
||||
<path opacity="0.2" fill-rule="evenodd" clip-rule="evenodd" d="M967.484 836.396L881.673 1868.31C875.172 1956.68 926.767 1986.47 997.002 1934.91L1847.63 1344.62C1920.9 1294.81 1985.06 1183.66 1989.83 1098.29L2075.64 66.374C2082.14 -21.9972 2030.55 -51.7898 1960.31 -0.221198L1109.68 590.062C1023.94 647.831 975.285 752.781 967.484 836.396Z" fill="#F27564"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
18
yarn.lock
18
yarn.lock
@ -5847,9 +5847,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0, @types/node@npm:^18.6.1":
|
||||
version: 18.11.2
|
||||
resolution: "@types/node@npm:18.11.2"
|
||||
checksum: 0ff5c90fb9ab653e018b858479aea4d2f763b07b31f9502383d408936f525ca37cac82ea27774a0dd0356ff9badba2792a6a3fff94f79fd7c82ee2a892c43ed5
|
||||
version: 18.11.3
|
||||
resolution: "@types/node@npm:18.11.3"
|
||||
checksum: 3a2a9142d891a90a195c296149bf64a69cc0abcc42f543be911ab22b2e0ead85ff077f90af92f0f13f6e3e5e72501469200fd753dfd1101825d4646a89d3ee47
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -8646,9 +8646,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001125, caniuse-lite@npm:^1.0.30001400":
|
||||
version: 1.0.30001422
|
||||
resolution: "caniuse-lite@npm:1.0.30001422"
|
||||
checksum: 29c950944b33ce242068402e679a5651d1289033381dcad7295cf14b589a6bd93d5bf32aa458bacaba9b25597731e0278c84ee588910ae774eab0585be88df62
|
||||
version: 1.0.30001423
|
||||
resolution: "caniuse-lite@npm:1.0.30001423"
|
||||
checksum: fe443f323f5dc6a858ef7d7deddb93db5e5f9a35e22970c4a65c4ef793bb696c1e2f038df572722d9edf29021e43ed16f5131faafde783563bd0d9eccf486592
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -16351,13 +16351,13 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"loader-utils@npm:^2.0.0":
|
||||
version: 2.0.2
|
||||
resolution: "loader-utils@npm:2.0.2"
|
||||
version: 2.0.3
|
||||
resolution: "loader-utils@npm:2.0.3"
|
||||
dependencies:
|
||||
big.js: ^5.2.2
|
||||
emojis-list: ^3.0.0
|
||||
json5: ^2.1.2
|
||||
checksum: 9078d1ed47cadc57f4c6ddbdb2add324ee7da544cea41de3b7f1128e8108fcd41cd3443a85b7ee8d7d8ac439148aa221922774efe4cf87506d4fb054d5889303
|
||||
checksum: d055c61ce5927b64cb4af40218606603a7d3a39adb7b6eec116bb31d19203875950e478152dea056de404eced8e87e9bfd336ec636591ded040ea451f63c7d88
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user