mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 12:15:44 +01:00
build theme editor
This commit is contained in:
parent
f9a4eadb71
commit
80560ce9f6
34
dist/vendor.bundle.js
vendored
34
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -97,6 +97,39 @@ interface IDefaultSettings {
|
||||
* Whether the user should be displayed a popup message when his Bladeburner actions are cancelled.
|
||||
*/
|
||||
SuppressBladeburnerPopup: boolean;
|
||||
|
||||
/*
|
||||
* Theme colors
|
||||
*/
|
||||
theme: {
|
||||
[key: string]: string | undefined;
|
||||
primarylight: string;
|
||||
primary: string;
|
||||
primarydark: string;
|
||||
errorlight: string;
|
||||
error: string;
|
||||
errordark: string;
|
||||
secondarylight: string;
|
||||
secondary: string;
|
||||
secondarydark: string;
|
||||
warninglight: string;
|
||||
warning: string;
|
||||
warningdark: string;
|
||||
infolight: string;
|
||||
info: string;
|
||||
infodark: string;
|
||||
welllight: string;
|
||||
well: string;
|
||||
white: string;
|
||||
black: string;
|
||||
hp: string;
|
||||
money: string;
|
||||
hack: string;
|
||||
combat: string;
|
||||
cha: string;
|
||||
int: string;
|
||||
rep: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,7 +151,7 @@ interface ISettings extends IDefaultSettings {
|
||||
MonacoInsertSpaces: boolean;
|
||||
}
|
||||
|
||||
const defaultSettings: IDefaultSettings = {
|
||||
export const defaultSettings: IDefaultSettings = {
|
||||
ActiveScriptsServerPageSize: 10,
|
||||
ActiveScriptsScriptPageSize: 10,
|
||||
AutosaveInterval: 60,
|
||||
@ -138,6 +171,35 @@ const defaultSettings: IDefaultSettings = {
|
||||
SuppressMessages: false,
|
||||
SuppressTravelConfirmation: false,
|
||||
SuppressBladeburnerPopup: false,
|
||||
|
||||
theme: {
|
||||
primarylight: "#0f0",
|
||||
primary: "#0c0",
|
||||
primarydark: "#090",
|
||||
errorlight: "#f00",
|
||||
error: "#c00",
|
||||
errordark: "#900",
|
||||
secondarylight: "#AAA",
|
||||
secondary: "#888",
|
||||
secondarydark: "#666",
|
||||
warninglight: "#ff0",
|
||||
warning: "#cc0",
|
||||
warningdark: "#990",
|
||||
infolight: "#69f",
|
||||
info: "#36c",
|
||||
infodark: "#039",
|
||||
welllight: "#444",
|
||||
well: "#222",
|
||||
white: "#fff",
|
||||
black: "#000",
|
||||
hp: "#dd3434",
|
||||
money: "#ffd700",
|
||||
hack: "#adff2f",
|
||||
combat: "#faffdf",
|
||||
cha: "#a671d1",
|
||||
int: "#6495ed",
|
||||
rep: "#faffdf",
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
@ -168,6 +230,35 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
||||
SuppressBladeburnerPopup: defaultSettings.SuppressBladeburnerPopup,
|
||||
MonacoTheme: "vs-dark",
|
||||
MonacoInsertSpaces: false,
|
||||
|
||||
theme: {
|
||||
primarylight: defaultSettings.theme.primarylight,
|
||||
primary: defaultSettings.theme.primary,
|
||||
primarydark: defaultSettings.theme.primarydark,
|
||||
errorlight: defaultSettings.theme.errorlight,
|
||||
error: defaultSettings.theme.error,
|
||||
errordark: defaultSettings.theme.errordark,
|
||||
secondarylight: defaultSettings.theme.secondarylight,
|
||||
secondary: defaultSettings.theme.secondary,
|
||||
secondarydark: defaultSettings.theme.secondarydark,
|
||||
warninglight: defaultSettings.theme.warninglight,
|
||||
warning: defaultSettings.theme.warning,
|
||||
warningdark: defaultSettings.theme.warningdark,
|
||||
infolight: defaultSettings.theme.infolight,
|
||||
info: defaultSettings.theme.info,
|
||||
infodark: defaultSettings.theme.infodark,
|
||||
welllight: defaultSettings.theme.welllight,
|
||||
well: defaultSettings.theme.well,
|
||||
white: defaultSettings.theme.white,
|
||||
black: defaultSettings.theme.black,
|
||||
hp: defaultSettings.theme.hp,
|
||||
money: defaultSettings.theme.money,
|
||||
hack: defaultSettings.theme.hack,
|
||||
combat: defaultSettings.theme.combat,
|
||||
cha: defaultSettings.theme.cha,
|
||||
int: defaultSettings.theme.int,
|
||||
rep: defaultSettings.theme.rep,
|
||||
},
|
||||
init() {
|
||||
Object.assign(Settings, defaultSettings);
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
import { TTheme as Theme, ThemeEvents } from "./ui/React/Theme";
|
||||
import { TTheme as Theme, ThemeEvents, refreshTheme } from "./ui/React/Theme";
|
||||
import { LoadingScreen } from "./ui/LoadingScreen";
|
||||
import "./engineStyle";
|
||||
|
||||
@ -13,6 +13,7 @@ ReactDOM.render(
|
||||
);
|
||||
|
||||
function rerender() {
|
||||
refreshTheme();
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
<LoadingScreen />
|
||||
|
@ -18,7 +18,6 @@ import Button from "@mui/material/Button";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import SaveIcon from "@mui/icons-material/Save";
|
||||
|
||||
import { colors } from "./Theme";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { use } from "../Context";
|
||||
|
||||
|
@ -26,6 +26,7 @@ import UploadIcon from "@mui/icons-material/Upload";
|
||||
import { FileDiagnosticModal } from "../../Diagnostic/FileDiagnosticModal";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { ConfirmationModal } from "./ConfirmationModal";
|
||||
import { ThemeEditorModal } from "./ThemeEditorModal";
|
||||
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { save, deleteGame } from "../../db";
|
||||
@ -80,6 +81,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
const [locale, setLocale] = useState(Settings.Locale);
|
||||
const [diagnosticOpen, setDiagnosticOpen] = useState(false);
|
||||
const [deleteGameOpen, setDeleteOpen] = useState(false);
|
||||
const [themeEditorOpen, setThemeEditorOpen] = useState(false);
|
||||
|
||||
function handleExecTimeChange(event: any, newValue: number | number[]): void {
|
||||
setExecTime(newValue as number);
|
||||
@ -600,6 +602,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
>
|
||||
<Button onClick={() => setDiagnosticOpen(true)}>Diagnose files</Button>
|
||||
</Tooltip>
|
||||
<Button onClick={() => setThemeEditorOpen(true)}>Theme editor</Button>
|
||||
</Box>
|
||||
<Box>
|
||||
<Link href="https://github.com/danielyxie/bitburner/issues/new" target="_blank">
|
||||
@ -632,6 +635,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
onClose={() => setDeleteOpen(false)}
|
||||
confirmationText={"Really delete your game? (It's permanent!)"}
|
||||
/>
|
||||
<ThemeEditorModal open={themeEditorOpen} onClose={() => setThemeEditorOpen(false)} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -5,23 +5,25 @@
|
||||
|
||||
import React from "react";
|
||||
import { Select as MuiSelect, SelectProps } from "@mui/material";
|
||||
import makeStyles from '@mui/styles/makeStyles';
|
||||
import { colors } from "./Theme";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
|
||||
const useStyles = makeStyles({
|
||||
// Tries to emulate StdButton in buttons.scss
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
backgroundColor: colors.well,
|
||||
color: colors.primarydark,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
color: theme.palette.primary.dark,
|
||||
margin: "5px",
|
||||
padding: "3px 5px",
|
||||
"&:after": {
|
||||
backgroundColor: colors.well,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
|
||||
borderRadius: 0,
|
||||
},
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
export const Select: React.FC<SelectProps> = (props: SelectProps) => {
|
||||
return (
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
import { createTheme, ThemeProvider, Theme, StyledEngineProvider } from "@mui/material/styles";
|
||||
import { EventEmitter } from "../../utils/EventEmitter";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
|
||||
export const ThemeEvents = new EventEmitter<[]>();
|
||||
|
||||
@ -28,83 +29,49 @@ declare module "@mui/material/styles" {
|
||||
};
|
||||
}
|
||||
}
|
||||
export let colors = {
|
||||
primarylight: "#0f0",
|
||||
primary: "#0c0",
|
||||
primarydark: "#090",
|
||||
|
||||
errorlight: "#f00",
|
||||
error: "#c00",
|
||||
errordark: "#900",
|
||||
|
||||
secondarylight: "#AAA",
|
||||
secondary: "#888",
|
||||
secondarydark: "#666",
|
||||
|
||||
warninglight: "#ff0",
|
||||
warning: "#cc0",
|
||||
warningdark: "#990",
|
||||
|
||||
infolight: "#69f",
|
||||
info: "#36c",
|
||||
infodark: "#039",
|
||||
|
||||
welllight: "#444",
|
||||
well: "#222",
|
||||
white: "#fff",
|
||||
black: "#000",
|
||||
|
||||
hp: "#dd3434",
|
||||
money: "#ffd700",
|
||||
hack: "#adff2f",
|
||||
combat: "#faffdf",
|
||||
cha: "#a671d1",
|
||||
int: "#6495ed",
|
||||
rep: "#faffdf",
|
||||
};
|
||||
|
||||
let theme: Theme;
|
||||
|
||||
function refreshTheme() {
|
||||
export function refreshTheme() {
|
||||
theme = createTheme({
|
||||
colors: {
|
||||
hp: "#dd3434",
|
||||
money: "#ffd700",
|
||||
hack: "#adff2f",
|
||||
combat: "#faffdf",
|
||||
cha: "#a671d1",
|
||||
int: "#6495ed",
|
||||
rep: "#faffdf",
|
||||
hp: Settings.theme.hp,
|
||||
money: Settings.theme.money,
|
||||
hack: Settings.theme.hack,
|
||||
combat: Settings.theme.combat,
|
||||
cha: Settings.theme.cha,
|
||||
int: Settings.theme.int,
|
||||
rep: Settings.theme.rep,
|
||||
},
|
||||
palette: {
|
||||
primary: {
|
||||
light: colors.primarylight,
|
||||
main: colors.primary,
|
||||
dark: colors.primarydark,
|
||||
light: Settings.theme.primarylight,
|
||||
main: Settings.theme.primary,
|
||||
dark: Settings.theme.primarydark,
|
||||
},
|
||||
secondary: {
|
||||
light: colors.secondarylight,
|
||||
main: colors.secondary,
|
||||
dark: colors.secondarydark,
|
||||
light: Settings.theme.secondarylight,
|
||||
main: Settings.theme.secondary,
|
||||
dark: Settings.theme.secondarydark,
|
||||
},
|
||||
error: {
|
||||
light: colors.errorlight,
|
||||
main: colors.error,
|
||||
dark: colors.errordark,
|
||||
light: Settings.theme.errorlight,
|
||||
main: Settings.theme.error,
|
||||
dark: Settings.theme.errordark,
|
||||
},
|
||||
info: {
|
||||
light: colors.infolight,
|
||||
main: colors.info,
|
||||
dark: colors.infodark,
|
||||
light: Settings.theme.infolight,
|
||||
main: Settings.theme.info,
|
||||
dark: Settings.theme.infodark,
|
||||
},
|
||||
warning: {
|
||||
light: colors.warninglight,
|
||||
main: colors.warning,
|
||||
dark: colors.warningdark,
|
||||
light: Settings.theme.warninglight,
|
||||
main: Settings.theme.warning,
|
||||
dark: Settings.theme.warningdark,
|
||||
},
|
||||
background: {
|
||||
default: colors.black,
|
||||
paper: colors.well,
|
||||
default: Settings.theme.black,
|
||||
paper: Settings.theme.well,
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
@ -117,13 +84,13 @@ function refreshTheme() {
|
||||
MuiInputBase: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: colors.well,
|
||||
color: colors.primary,
|
||||
backgroundColor: Settings.theme.well,
|
||||
color: Settings.theme.primary,
|
||||
},
|
||||
input: {
|
||||
"&::placeholder": {
|
||||
userSelect: "none",
|
||||
color: colors.primarydark,
|
||||
color: Settings.theme.primarydark,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -132,18 +99,18 @@ function refreshTheme() {
|
||||
MuiInput: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: colors.well,
|
||||
backgroundColor: Settings.theme.well,
|
||||
borderBottomColor: "#fff",
|
||||
},
|
||||
underline: {
|
||||
"&:hover": {
|
||||
borderBottomColor: colors.primarydark,
|
||||
borderBottomColor: Settings.theme.primarydark,
|
||||
},
|
||||
"&:before": {
|
||||
borderBottomColor: colors.primary,
|
||||
borderBottomColor: Settings.theme.primary,
|
||||
},
|
||||
"&:after": {
|
||||
borderBottomColor: colors.primarylight,
|
||||
borderBottomColor: Settings.theme.primarylight,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -152,10 +119,10 @@ function refreshTheme() {
|
||||
MuiInputLabel: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: colors.primarydark, // why is this switched?
|
||||
color: Settings.theme.primarydark, // why is this switched?
|
||||
userSelect: "none",
|
||||
"&:before": {
|
||||
color: colors.primarylight,
|
||||
color: Settings.theme.primarylight,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -164,10 +131,10 @@ function refreshTheme() {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: "#333",
|
||||
border: "1px solid " + colors.well,
|
||||
// color: colors.primary,
|
||||
border: "1px solid " + Settings.theme.well,
|
||||
// color: Settings.theme.primary,
|
||||
"&:hover": {
|
||||
backgroundColor: colors.black,
|
||||
backgroundColor: Settings.theme.black,
|
||||
},
|
||||
|
||||
borderRadius: 0,
|
||||
@ -177,21 +144,21 @@ function refreshTheme() {
|
||||
MuiSelect: {
|
||||
styleOverrides: {
|
||||
icon: {
|
||||
color: colors.primary,
|
||||
color: Settings.theme.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiMenu: {
|
||||
styleOverrides: {
|
||||
list: {
|
||||
backgroundColor: colors.well,
|
||||
backgroundColor: Settings.theme.well,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiMenuItem: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: colors.primary,
|
||||
color: Settings.theme.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -205,14 +172,14 @@ function refreshTheme() {
|
||||
MuiAccordionDetails: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: colors.black,
|
||||
backgroundColor: Settings.theme.black,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiIconButton: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: colors.primary,
|
||||
color: Settings.theme.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -220,8 +187,8 @@ function refreshTheme() {
|
||||
styleOverrides: {
|
||||
tooltip: {
|
||||
fontSize: "1em",
|
||||
color: colors.primary,
|
||||
backgroundColor: colors.well,
|
||||
color: Settings.theme.primary,
|
||||
backgroundColor: Settings.theme.well,
|
||||
borderRadius: 0,
|
||||
border: "2px solid white",
|
||||
maxWidth: "100vh",
|
||||
@ -231,8 +198,8 @@ function refreshTheme() {
|
||||
MuiSlider: {
|
||||
styleOverrides: {
|
||||
valueLabel: {
|
||||
color: colors.primary,
|
||||
backgroundColor: colors.well,
|
||||
color: Settings.theme.primary,
|
||||
backgroundColor: Settings.theme.well,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -244,34 +211,34 @@ function refreshTheme() {
|
||||
display: "none",
|
||||
},
|
||||
scrollbarWidth: "none", // firefox
|
||||
backgroundColor: colors.black,
|
||||
backgroundColor: Settings.theme.black,
|
||||
},
|
||||
paperAnchorDockedLeft: {
|
||||
borderRight: "1px solid " + colors.welllight,
|
||||
borderRight: "1px solid " + Settings.theme.welllight,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiDivider: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: colors.welllight,
|
||||
backgroundColor: Settings.theme.welllight,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiFormControlLabel: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: colors.primary,
|
||||
color: Settings.theme.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiSwitch: {
|
||||
styleOverrides: {
|
||||
switchBase: {
|
||||
color: colors.primarydark,
|
||||
color: Settings.theme.primarydark,
|
||||
},
|
||||
track: {
|
||||
backgroundColor: colors.welllight,
|
||||
backgroundColor: Settings.theme.welllight,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -279,15 +246,15 @@ function refreshTheme() {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
borderRadius: 0,
|
||||
backgroundColor: colors.black,
|
||||
border: "1px solid " + colors.welllight,
|
||||
backgroundColor: Settings.theme.black,
|
||||
border: "1px solid " + Settings.theme.welllight,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTablePagination: {
|
||||
styleOverrides: {
|
||||
select: {
|
||||
color: colors.primary,
|
||||
color: Settings.theme.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
115
src/ui/React/ThemeEditorModal.tsx
Normal file
115
src/ui/React/ThemeEditorModal.tsx
Normal file
@ -0,0 +1,115 @@
|
||||
import React, { useState } from "react";
|
||||
import { Modal } from "./Modal";
|
||||
import Button from "@mui/material/Button";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import DoneIcon from "@mui/icons-material/Done";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import ReplyIcon from "@mui/icons-material/Reply";
|
||||
import { ThemeEvents } from "./Theme";
|
||||
import { Settings, defaultSettings } from "../../Settings/Settings";
|
||||
|
||||
interface IProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
function ColorEditor({ name }: { name: string }): React.ReactElement {
|
||||
const [color, setColor] = useState(Settings.theme[name]);
|
||||
if (color === undefined) return <></>;
|
||||
const valid = color.match(/#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})/g);
|
||||
|
||||
function set(): void {
|
||||
if (!valid) return;
|
||||
Settings.theme[name] = color;
|
||||
ThemeEvents.emit();
|
||||
}
|
||||
|
||||
function revert(): void {
|
||||
Settings.theme[name] = defaultSettings.theme[name];
|
||||
setColor(defaultSettings.theme[name]);
|
||||
ThemeEvents.emit();
|
||||
}
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setColor(event.target.value);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<TextField
|
||||
sx={{ mx: 1 }}
|
||||
label={name}
|
||||
value={color}
|
||||
onChange={onChange}
|
||||
variant="standard"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<>
|
||||
<IconButton onClick={set} disabled={!valid}>
|
||||
<DoneIcon color={valid ? "primary" : "error"} />
|
||||
</IconButton>
|
||||
<IconButton onClick={revert}>
|
||||
<ReplyIcon color="primary" />
|
||||
</IconButton>
|
||||
</>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function ThemeEditorModal(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Button color="primary">primary</Button>
|
||||
<Button color="secondary">secondary</Button>
|
||||
<Button color="warning">warning</Button>
|
||||
<Button color="info">info</Button>
|
||||
<Button color="error">error</Button>
|
||||
<Typography color="primary">primary</Typography>
|
||||
<Typography color="secondary">secondary</Typography>
|
||||
<Typography color="warning">warning</Typography>
|
||||
<Typography color="info">info</Typography>
|
||||
<Typography color="error">error</Typography>
|
||||
<br />
|
||||
<ColorEditor name="primarylight" />
|
||||
<ColorEditor name="primary" />
|
||||
<ColorEditor name="primarydark" />
|
||||
|
||||
<br />
|
||||
<ColorEditor name="errorlight" />
|
||||
<ColorEditor name="error" />
|
||||
<ColorEditor name="errordark" />
|
||||
|
||||
<br />
|
||||
<ColorEditor name="secondarylight" />
|
||||
<ColorEditor name="secondary" />
|
||||
<ColorEditor name="secondarydark" />
|
||||
|
||||
<br />
|
||||
<ColorEditor name="warninglight" />
|
||||
<ColorEditor name="warning" />
|
||||
<ColorEditor name="warningdark" />
|
||||
|
||||
<br />
|
||||
<ColorEditor name="infolight" />
|
||||
<ColorEditor name="info" />
|
||||
<ColorEditor name="infodark" />
|
||||
|
||||
<br />
|
||||
<ColorEditor name="welllight" />
|
||||
<ColorEditor name="well" />
|
||||
<ColorEditor name="white" />
|
||||
<ColorEditor name="black" />
|
||||
|
||||
<br />
|
||||
<ColorEditor name="hp" />
|
||||
<ColorEditor name="money" />
|
||||
<ColorEditor name="hack" />
|
||||
<ColorEditor name="combat" />
|
||||
<ColorEditor name="cha" />
|
||||
<ColorEditor name="int" />
|
||||
<ColorEditor name="rep" />
|
||||
</Modal>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user