This commit is contained in:
Olivier Gagnon
2021-09-13 12:44:46 -04:00
parent 0ed93ec0a5
commit 8fba57fd24
22 changed files with 1331 additions and 841 deletions

31
package-lock.json generated
View File

@ -10,6 +10,7 @@
"license": "SEE LICENSE IN license.txt",
"dependencies": {
"@material-ui/core": "^4.11.3",
"@material-ui/icons": "^4.11.2",
"@monaco-editor/react": "^4.2.2",
"@types/js-beautify": "^1.13.2",
"@types/numeral": "0.0.25",
@ -3150,6 +3151,28 @@
"node": ">=8.0.0"
}
},
"node_modules/@material-ui/icons": {
"version": "4.11.2",
"resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz",
"integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==",
"dependencies": {
"@babel/runtime": "^7.4.4"
},
"engines": {
"node": ">=8.0.0"
},
"peerDependencies": {
"@material-ui/core": "^4.0.0",
"@types/react": "^16.8.6 || ^17.0.0",
"react": "^16.8.0 || ^17.0.0",
"react-dom": "^16.8.0 || ^17.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@material-ui/styles": {
"version": "4.11.3",
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.3.tgz",
@ -28366,6 +28389,14 @@
"react-transition-group": "^4.4.0"
}
},
"@material-ui/icons": {
"version": "4.11.2",
"resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz",
"integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==",
"requires": {
"@babel/runtime": "^7.4.4"
}
},
"@material-ui/styles": {
"version": "4.11.3",
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.3.tgz",

View File

@ -7,6 +7,7 @@
},
"dependencies": {
"@material-ui/core": "^4.11.3",
"@material-ui/icons": "^4.11.2",
"@monaco-editor/react": "^4.2.2",
"@types/js-beautify": "^1.13.2",
"@types/numeral": "0.0.25",

View File

@ -7,7 +7,7 @@ import * as React from "react";
import { Player } from "../../Player";
import { Exploit, ExploitName } from "../../Exploits/Exploit";
import { Accordion } from "../../ui/React/Accordion";
import { BBAccordion } from "../../ui/React/Accordion";
export function SourceFileMinus1(): React.ReactElement {
const exploits = Player.exploits;
@ -18,7 +18,7 @@ export function SourceFileMinus1(): React.ReactElement {
return (
<li key={-1}>
<Accordion
<BBAccordion
headerContent={
<>
Source-File -1: Exploits in the BitNodes

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
import React from "react";
import { AllServers } from "../Server/AllServers";
import { Accordion } from "../ui/React/Accordion";
import { BBAccordion } from "../ui/React/Accordion";
import { numeralWrapper } from "../ui/numeralFormat";
interface IServerProps {
@ -40,7 +40,7 @@ export function ServerAccordion(props: IServerProps): React.ReactElement {
files.sort((a: File, b: File): number => b.size - a.size);
return (
<Accordion
<BBAccordion
headerContent={
<>
{server.hostname} ({numeralWrapper.formatBigNumber(totalSize)}b)

View File

@ -4,7 +4,7 @@
import React from "react";
import { Gang } from "../Gang";
import { GangMember } from "../GangMember";
import { Accordion } from "../../ui/React/Accordion";
import { BBAccordion } from "../../ui/React/Accordion";
import { GangMemberAccordionContent } from "./GangMemberAccordionContent";
interface IProps {
@ -14,7 +14,7 @@ interface IProps {
export function GangMemberAccordion(props: IProps): React.ReactElement {
return (
<Accordion
<BBAccordion
panelInitiallyOpened={true}
headerContent={<>{props.member.name}</>}
panelContent={<GangMemberAccordionContent gang={props.gang} member={props.member} />}

View File

@ -1,11 +0,0 @@
export function unknownBladeburnerActionErrorMessage(functionName, actionType, actionName) {
return (
`ERROR: bladeburner.${functionName}() failed due to an invalid action specified. ` +
`Type: ${actionType}, Name: ${actionName}. Note that for contracts and operations, the ` +
`name of the operation is case-sensitive.`
);
}
export function unknownBladeburnerExceptionMessage(functionName, err) {
return `bladeburner.${functionName}() failed with exception: ` + err;
}

View File

@ -16,7 +16,7 @@ import ReactDOM from "react-dom";
let redPillFlag = false;
function hackWorldDaemon(currentNodeNumber, flume = false, quick = false) {
// Clear the screen
const container = document.getElementById("red-pill-content");
const container = document.getElementById("red-pill-container");
ReactDOM.unmountComponentAtNode(container);
Engine.loadRedPillContent();
ReactDOM.render(
@ -85,7 +85,7 @@ function enterBitNode(flume, destroyedBitNode, newBitNode) {
Player.intelligence = 1;
}
redPillFlag = false;
const container = document.getElementById("red-pill-content");
const container = document.getElementById("red-pill-container");
ReactDOM.unmountComponentAtNode(container);
// Set new Bit Node

View File

@ -18,7 +18,7 @@ import { PositionTypes } from "../data/PositionTypes";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Accordion } from "../../ui/React/Accordion";
import { BBAccordion } from "../../ui/React/Accordion";
import { Money } from "../../ui/React/Money";
import { createPopup } from "../../ui/React/createPopup";
@ -157,7 +157,8 @@ export class StockTicker extends React.Component<IProps, IState> {
createPopup(popupId, PlaceOrderPopup, {
text: "Enter the price for your Limit Order",
placeText: "Place Buy Limit Order",
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitBuy, this.state.position),
place: (price: number) =>
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitBuy, this.state.position),
popupId: popupId,
});
break;
@ -167,7 +168,8 @@ export class StockTicker extends React.Component<IProps, IState> {
createPopup(popupId, PlaceOrderPopup, {
text: "Enter the price for your Stop Order",
placeText: "Place Buy Stop Order",
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopBuy, this.state.position),
place: (price: number) =>
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopBuy, this.state.position),
popupId: popupId,
});
break;
@ -279,7 +281,8 @@ export class StockTicker extends React.Component<IProps, IState> {
createPopup(popupId, PlaceOrderPopup, {
text: "Enter the price for your Limit Order",
placeText: "Place Sell Limit Order",
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitSell, this.state.position),
place: (price: number) =>
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitSell, this.state.position),
popupId: popupId,
});
break;
@ -289,7 +292,8 @@ export class StockTicker extends React.Component<IProps, IState> {
createPopup(popupId, PlaceOrderPopup, {
text: "Enter the price for your Stop Order",
placeText: "Place Sell Stop Order",
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopSell, this.state.position),
place: (price: number) =>
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopSell, this.state.position),
popupId: popupId,
});
break;
@ -332,7 +336,7 @@ export class StockTicker extends React.Component<IProps, IState> {
render(): React.ReactNode {
return (
<li>
<Accordion
<BBAccordion
headerContent={<StockTickerHeaderText p={this.props.p} stock={this.props.stock} />}
panelContent={
<div>

View File

@ -265,7 +265,6 @@ const Engine = {
routing.navigateTo(Page.WorkInProgress);
},
// TODO reactify
loadRedPillContent: function () {
Engine.hideAllContent();
const mainMenu = document.getElementById("mainmenu-container");

View File

@ -67,27 +67,6 @@
<div id="generic-react-container"></div>
</div>
<div id="infiltration-container" class="generic-fullscreen-container"></div>
<!-- Generic Yes/No Pop Up box -->
<div id="yes-no-box-container" class="popup-box-container">
<div id="yes-no-box-content" class="popup-box-content">
<p id="yes-no-box-text"></p>
<button id="yes-no-box-yes" class="popup-box-button">Yes</button>
<button id="yes-no-box-no" class="popup-box-button">No</button>
</div>
</div>
<!-- Generic yes/no pop up box with text entry field -->
<div id="yes-no-text-input-box-container" class="popup-box-container">
<div id="yes-no-text-input-box-content" class="popup-box-content">
<p id="yes-no-text-input-box-text"></p>
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30" />
<button id="yes-no-text-input-box-yes" class="popup-box-button">Yes</button>
<button id="yes-no-text-input-box-no" class="popup-box-button">No</button>
</div>
</div>
<!-- Mission container -->
<div id="mission-container" class="generic-fullscreen-container"></div>
<!-- Work in progress screen -->
@ -101,9 +80,7 @@
</div>
<!-- Red Pill Container -->
<div id="red-pill-container" class="generic-fullscreen-container">
<div id="red-pill-content" class="generic-fullscreen-container-scroll"></div>
</div>
<div id="red-pill-container" class="generic-fullscreen-container"></div>
<!-- Cinematic Text Container -->
<div id="cinematic-text-container" class="generic-fullscreen-container"></div>

View File

@ -4,7 +4,7 @@
*/
import * as React from "react";
import { Accordion } from "../React/Accordion";
import { BBAccordion } from "../React/Accordion";
import { ServerAccordionContent } from "./ServerAccordionContent";
import { BaseServer } from "../../Server/BaseServer";
@ -34,7 +34,7 @@ export function ServerAccordion(props: IProps): React.ReactElement {
const headerTxt = `${paddedName} ${createProgressBarText(barOptions)}`;
return (
<Accordion
<BBAccordion
headerContent={<pre>{headerTxt}</pre>}
panelContent={<ServerAccordionContent workerScripts={props.workerScripts} />}
/>

View File

@ -6,7 +6,7 @@ import * as React from "react";
import { numeralWrapper } from "../numeralFormat";
import { Accordion } from "../React/Accordion";
import { BBAccordion } from "../React/Accordion";
import { AccordionButton } from "../React/AccordionButton";
import { killWorkerScript } from "../../Netscript/killWorkerScript";
@ -41,7 +41,7 @@ export function WorkerScriptAccordion(props: IProps): React.ReactElement {
const offlineEps = scriptRef.offlineExpGained / scriptRef.offlineRunningTime;
return (
<Accordion
<BBAccordion
headerClass="active-scripts-script-header"
headerContent={<>{props.workerScript.name}</>}
panelClass="active-scripts-script-panel"

View File

@ -16,7 +16,7 @@ type IState = {
panelOpened: boolean;
};
export class Accordion extends React.Component<IProps, IState> {
export class BBAccordion extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);

View File

@ -6,7 +6,7 @@
*/
import * as React from "react";
import { Accordion } from "./Accordion";
import { BBAccordion } from "./Accordion";
import { Augmentation } from "../../Augmentation/Augmentation";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
@ -26,7 +26,7 @@ export function AugmentationAccordion(props: IProps): React.ReactElement {
if (typeof props.aug.info === "string") {
return (
<Accordion
<BBAccordion
headerContent={<>{displayName}</>}
panelContent={
<p>
@ -41,7 +41,7 @@ export function AugmentationAccordion(props: IProps): React.ReactElement {
}
return (
<Accordion
<BBAccordion
headerContent={<>{displayName}</>}
panelContent={
<p>

47
src/ui/React/Button.tsx Normal file
View File

@ -0,0 +1,47 @@
/**
* Wrapper around material-ui's Button component that styles it with
* Bitburner's UI theme
*/
import React from "react";
import { Button as MuiButton, ButtonProps, makeStyles } from "@material-ui/core";
import { colors } from "./Theme";
const useStyles = makeStyles({
// Tries to emulate StdButton in buttons.scss
root: {
backgroundColor: "#333",
border: "1px solid #000",
color: colors.primary,
margin: "5px",
padding: "3px 5px",
"&:hover": {
backgroundColor: "#000",
},
borderRadius: 0,
},
textPrimary: {
color: "rgb( 144, 202, 249)",
},
textSecondary: {
color: "rgb(244, 143, 177)",
},
disabled: {
backgroundColor: "#333",
color: "#fff",
cursor: "default",
},
});
export const Button: React.FC<ButtonProps> = (props: ButtonProps) => {
return (
<MuiButton
{...props}
classes={{
...useStyles(),
...props.classes,
}}
/>
);
};

View File

@ -5,7 +5,6 @@
import React from "react";
import { Button, ButtonProps, makeStyles } from "@material-ui/core";
const useStyles = makeStyles({
// Tries to emulate StdButton in buttons.scss
root: {
@ -17,6 +16,8 @@ const useStyles = makeStyles({
"&:hover": {
backgroundColor: "#666",
},
borderRadius: 0,
},
textPrimary: {
color: "rgb( 144, 202, 249)",

337
src/ui/React/Options.tsx Normal file
View File

@ -0,0 +1,337 @@
import React from "react";
interface IProps {}
export function Options(props: IProps): React.ReactElement {
return (
<>
<h1>Game Options</h1>
</>
);
/*
<h1>Game Options</h1>
<br />
<div id="game-options-left-panel">
<!-- Netscript execution time -->
<fieldset>
<label for="settingsNSExecTimeRangeVal" class="tooltip"
>Netscript exec time:&nbsp;
<span class="tooltiptext">
The minimum number of milliseconds it takes to execute an operation in Netscript. Setting this too low
can result in poor performance if you have many scripts running. The default value is 25ms.
</span>
</label>
<input
class="optionRange"
type="range"
max="100"
min="10"
step="1"
name="settingsNSExecTimeRangeVal"
id="settingsNSExecTimeRangeVal"
value="25"
/>
<em id="settingsNSExecTimeRangeValLabel" style="font-style: normal"></em>
</fieldset>
<!-- Log capacity -->
<fieldset>
<label for="settingsNSLogRangeVal" class="tooltip"
>Netscript log size:&nbsp;&nbsp;
<span class="tooltiptext">
The maximum number of lines a script's logs can hold. Setting this too high can cause the game to use
a lot of memory if you have many scripts running. The default value is 50.
</span>
</label>
<input
class="optionRange"
type="range"
max="100"
min="20"
step="1"
name="settingsNSLogRangeVal"
id="settingsNSLogRangeVal"
value="50"
/>
<em id="settingsNSLogRangeValLabel" style="font-style: normal"></em>
</fieldset>
<!-- Port capacity -->
<fieldset>
<label for="settingsNSPortRangeVal" class="tooltip"
>Netscript port size:&nbsp;
<span class="tooltiptext">
The maximum number of entries that can be written to a port using Netscript's write() function.
Setting this too high can cause the game to use a lot of memory. The default value is 50.
</span>
</label>
<input
class="optionRange"
type="range"
max="100"
min="20"
step="1"
name="settingsNSPortRangeVal"
id="settingsNSPortRangeVal"
value="50"
/>
<em id="settingsNSPortRangeValLabel" style="font-style: normal"></em>
</fieldset>
<!-- Autosave Interval -->
<fieldset>
<label for="settingsAutosaveIntervalVal" class="tooltip"
>Autosave Interval:&nbsp;&nbsp;&nbsp;
<span class="tooltiptext">
The time (in seconds) between each autosave. Set to 0 to disable autosave.
</span>
</label>
<input
class="optionRange"
type="range"
max="600"
min="0"
step="1"
name="settingsAutosaveIntervalVal"
id="settingsAutosaveIntervalVal"
value="60"
/>
<em id="settingsAutosaveIntervalValLabel" style="font-style: normal"></em>
</fieldset>
<!-- Suppress messages -->
<fieldset>
<label for="settingsSuppressMessages" class="tooltip"
>Suppress Messages:
<span class="tooltiptext">
If this is set, then any messages you receive will not appear as popups on the screen. They will still
get sent to your home computer as '.msg' files and can be viewed with the 'cat' Terminal command.
</span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsSuppressMessages"
id="settingsSuppressMessages"
/>
</fieldset>
<!-- Suppress faction invites -->
<fieldset>
<label for="settingsSuppressFactionInvites" class="tooltip"
>Suppress Faction Invites:
<span class="tooltiptexthigh">
If this is set, then any faction invites you receive will not appear as popups on the screen. Your
outstanding faction invites can be viewed in the 'Factions' page.
</span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsSuppressFactionInvites"
id="settingsSuppressFactionInvites"
/>
</fieldset>
<!-- Suppress travel confirmation -->
<fieldset>
<label for="settingsSuppressTravelConfirmation" class="tooltip"
>Suppress Travel Confirmation:
<span class="tooltiptexthigh">
If this is set, the confirmation message before traveling will not show up. You will automatically be
deducted the travel cost as soon as you click.
</span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsSuppressTravelConfirmation"
id="settingsSuppressTravelConfirmation"
/>
</fieldset>
<!-- Suppress buy aug confirmation -->
<fieldset>
<label for="settingsSuppressBuyAugmentationConfirmation" class="tooltip"
>Suppress buy augmentation confirmation:
<span class="tooltiptexthigh">
If this is set, the confirmation message before buying augmentation will not show up.
</span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsSuppressBuyAugmentationConfirmation"
id="settingsSuppressBuyAugmentationConfirmation"
/>
</fieldset>
<!-- Hospitalization Popup -->
<fieldset>
<label for="settingsSuppressHospitalizationPopup" class="tooltip"
>Suppress Hospitalization popup:
<span class="tooltiptexthigh">
If this is set, a popup message will no longer be shown when you are hospitalized after taking too
much damage.
</span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsSuppressHospitalizationPopup"
id="settingsSuppressHospitalizationPopup"
/>
</fieldset>
<!-- Suppress Bladeburner popups -->
<fieldset>
<label for="settingsSuppressBladeburnerPopup" class="tooltip"
>Suppress Bladeburner Popup:
<span class="tooltiptext">
If this is set, then having your Bladeburner actions interrupted by being busy with something else
will not display a popup message.
</span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsSuppressBladeburnerPopup"
id="settingsSuppressBladeburnerPopup"
/>
</fieldset>
<!-- Disable Terminal and Navigation Shortcuts -->
<fieldset>
<label for="settingsDisableHotkeys" class="tooltip"
>Disable Hotkeys:
<span class="tooltiptexthigh">
If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled. This includes
Terminal commands, hotkeys to navigate between different parts of the game, and the "Save and Close
(Ctrl + b)" hotkey in the Text Editor.
</span>
</label>
<input class="optionCheckbox" type="checkbox" name="settingsDisableHotkeys" id="settingsDisableHotkeys" />
</fieldset>
<!-- View city as list of buttons instead of ASCII art. -->
<fieldset>
<label for="settingsDisableASCIIArt" class="tooltip"
>Disable ASCII art:
<span class="tooltiptexthigh"> If this is set all ASCII art will be disabled. </span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsDisableASCIIArt"
id="settingsDisableASCIIArt"
/>
</fieldset>
<!-- Disable text effects such as corruption. -->
<fieldset>
<label for="settingsDisableTextEffects" class="tooltip"
>Disable Text Effects:
<span class="tooltiptexthigh">
If this is set, text effects will not be displayed. This can help if text is difficult to read in
certain areas.
</span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsDisableTextEffects"
id="settingsDisableTextEffects"
/>
</fieldset>
<!-- Locale for displaying numbers -->
<fieldset>
<label for="settingsLocale" class="tooltip"
>Locale:
<span class="tooltiptexthigh"> Sets the locale for displaying numbers. Defaults to 'en' </span>
</label>
<select name="settingsLocale" id="settingsLocale" class="dropdown">
<option value="en">en</option>
<option value="bg">bg</option>
<option value="cs">cs</option>
<option value="da-dk">da-dk</option>
<option value="de">de</option>
<option value="en-au">en-au</option>
<option value="en-gb">en-gb</option>
<option value="es">es</option>
<option value="fr">fr</option>
<option value="hu">hu</option>
<option value="it">it</option>
<option value="lv">lv</option>
<option value="no">no</option>
<option value="pl">pl</option>
<option value="ru">ru</option>
</select>
</fieldset>
<!-- Donate button -->
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick" />
<input
type="hidden"
name="encrypted"
value="-----BEGIN PKCS7-----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-----END PKCS7-----
"
/>
<input
type="image"
src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif"
border="0"
name="submit"
alt="PayPal - The safer, easier way to pay online!"
/>
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1" />
</form>
</div>
<div id="game-options-right-panel">
<a class="a-link-button" href="https://bitburner.readthedocs.io/en/latest/changelog.html" target="_blank">
Changelog
</a>
<a class="a-link-button" href="https://bitburner.readthedocs.io/en/latest/index.html" target="_blank"
>Documentation</a
>
<a class="a-link-button" href="https://discord.gg/TFc3hKD" target="_blank">Discord</a>
<a class="a-link-button" href="https://www.reddit.com/r/bitburner" target="_blank">Subreddit</a>
<button id="save-game-link" class="a-link-button">Save Game</button>
<button id="delete-game-link" class="a-link-button">Delete Game</button>
<button id="export-game-link" class="a-link-button">Export Game</button>
<input type="file" id="import-game-file-selector" name="file" />
<button id="import-game-link" class="a-link-button">Import Game</button>
<button id="copy-save-to-clipboard-link" class="std-button">Copy Save data to Clipboard</button>
<button id="debug-delete-scripts-link" class="a-link-button tooltip">
Force kill all active scripts
<span class="tooltiptextleft">
Forcefully kill all active running scripts, in case there is a bug or some unexpected issue with the
game. After using this, save the game and then reload the page. This is different then normal kill in
that normal kill will tell the script to shut down while force kill just removes the references to it
(and it should crash on it's own). This will not remove the files on your computer. Just forcefully kill
all running instance of all scripts.
</span>
</button>
<button id="debug-soft-reset" class="a-link-button tooltip">
Soft Reset
<span class="tooltiptextleft">
Perform a soft reset. Resets everything as if you had just purchased an Augmentation.
</span>
</button>
<button id="debug-files" class="a-link-button tooltip">
Diagnose files
<span class="tooltiptextleft">
If your save file is extremely big you can use this button to view a map of all the files on every
server. Be careful there might be spoilers.
</span>
</button>
</div>
*/
}

36
src/ui/React/Select.tsx Normal file
View File

@ -0,0 +1,36 @@
/**
* Wrapper around material-ui's Button component that styles it with
* Bitburner's UI theme
*/
import React from "react";
import { Select as MuiSelect, ButtonProps, makeStyles } from "@material-ui/core";
import { colors } from "./Theme";
const useStyles = makeStyles({
// Tries to emulate StdButton in buttons.scss
root: {
backgroundColor: "#000",
color: colors.primarydark,
margin: "5px",
padding: "3px 5px",
"&:hover": {
backgroundColor: "#000",
},
borderRadius: 0,
},
});
export const Select: React.FC<ButtonProps> = (props: ButtonProps) => {
return (
<MuiSelect
native
{...props}
classes={{
...useStyles(),
...props.classes,
}}
/>
);
};

View File

@ -6,7 +6,7 @@
*/
import * as React from "react";
import { Accordion } from "./Accordion";
import { BBAccordion } from "./Accordion";
import { SourceFile } from "../../SourceFile/SourceFile";
@ -19,7 +19,7 @@ export function SourceFileAccordion(props: IProps): React.ReactElement {
const maxLevel = props.sf.n === 12 ? "∞" : "3";
return (
<Accordion
<BBAccordion
headerContent={
<>
{props.sf.name}

View File

@ -0,0 +1,56 @@
/**
* Wrapper around material-ui's Button component that styles it with
* Bitburner's UI colors
*/
import React from "react";
import { TextField as MuiTF, TextFieldProps, makeStyles } from "@material-ui/core";
import { colors } from "./Theme";
const useStyles = makeStyles({
// Tries to emulate StdButton in buttons.scss
root: {
backgroundColor: "#000",
color: "white",
borderRadius: 0,
"& .MuiInputBase-input": {
color: colors.primary, // Text color
},
"& .MuiInputBase-input::placeholder::before": {
color: colors.primarydarker,
userSelect: "none",
},
"& .MuiInput-underline:before": {
borderBottomColor: colors.primarydarker,
},
"& .MuiInput-underline:hover:before": {
borderBottomColor: colors.primarydark,
},
"& .MuiInput-underline:after": {
borderBottomColor: colors.primary,
},
"& .MuiInputLabel-root::before": {
color: colors.primarydark,
},
"& .MuiInputLabel-root": {
// The little label on the top-right
color: colors.primarydark, // unfocused
userSelect: "none",
"&.Mui-focused": {
color: colors.primary, // focused
},
},
},
});
export const TextField: React.FC<TextFieldProps> = (props: TextFieldProps) => {
return (
<MuiTF
{...props}
classes={{
...useStyles(),
...props.classes,
}}
/>
);
};

32
src/ui/React/Theme.tsx Normal file
View File

@ -0,0 +1,32 @@
import React from "react";
import { createMuiTheme } from "@material-ui/core/styles";
import { ThemeProvider } from "@material-ui/core/styles";
export const colors = {
primary: "#0f0",
primarydark: "#090",
primarydarker: "#030",
};
export const theme = createMuiTheme({
palette: {
primary: {
main: colors.primary,
dark: colors.primarydark,
},
},
typography: {
button: {
textTransform: "none",
},
},
});
interface IProps {
children: JSX.Element[] | JSX.Element;
}
export const Theme = ({ children }: IProps): React.ReactElement => (
<ThemeProvider theme={theme}>{children}</ThemeProvider>
);