From f73d00d2c46c7490caf93aecef4f56080490f7da Mon Sep 17 00:00:00 2001 From: Aleksej Komarov Date: Fri, 17 Apr 2020 09:53:08 +0300 Subject: [PATCH] WIP --- tgui/packages/common/math.js | 37 +++- tgui/packages/tgui/components/ProgressBar.js | 8 +- tgui/packages/tgui/components/Tabs.js | 176 ++++----------- tgui/packages/tgui/format.js | 11 +- tgui/packages/tgui/index.js | 6 +- tgui/packages/tgui/interfaces/Achievements.js | 205 ++++++++++-------- tgui/packages/tgui/interfaces/Cargo.js | 63 +++--- tgui/packages/tgui/interfaces/KitchenSink.js | 110 +++++----- tgui/packages/tgui/polyfills.js | 5 - .../tgui/styles/components/Button.scss | 24 -- .../packages/tgui/styles/components/Tabs.scss | 77 ++++--- 11 files changed, 336 insertions(+), 386 deletions(-) delete mode 100644 tgui/packages/tgui/polyfills.js diff --git a/tgui/packages/common/math.js b/tgui/packages/common/math.js index f2918c5c111..cc7a309563e 100644 --- a/tgui/packages/common/math.js +++ b/tgui/packages/common/math.js @@ -2,13 +2,15 @@ * Limits a number to the range between 'min' and 'max'. */ export const clamp = (value, min, max) => { - return Math.max(min, Math.min(value, max)); + return value < min ? min : value > max ? max : value; }; /** * Limits a number between 0 and 1. */ -export const clamp01 = value => clamp(value, 0, 1); +export const clamp01 = value => { + return value < 0 ? 0 : value > 1 ? 1 : value; +}; /** * Scales a number to fit into the range between min and max. @@ -18,10 +20,35 @@ export const scale = (value, min, max) => { }; /** - * Returns a rounded number. - * TODO: Replace this native rounding function with a more robust one. + * Robust number rounding. + * + * Adapted from Locutus, see: http://locutus.io/php/math/round/ + * + * @param {number} value + * @param {number} precision + * @return {number} */ -export const round = value => Math.round(value); +export const round = (value, precision) => { + if (!value || isNaN(value)) { + return value; + } + // helper variables + let m, f, isHalf, sgn; + // making sure precision is integer + precision |= 0; + m = Math.pow(10, precision); + value *= m; + // sign of the number + sgn = (value > 0) | -(value < 0); + // isHalf = value % 1 === 0.5 * sgn; + isHalf = Math.abs(value % 1) >= 0.4999999999854481; + f = Math.floor(value); + if (isHalf) { + // rounds .5 away from zero + value = f + (sgn > 0); + } + return (isHalf ? value : Math.round(value)) / m; +}; /** * Returns a string representing a number in fixed point notation. diff --git a/tgui/packages/tgui/components/ProgressBar.js b/tgui/packages/tgui/components/ProgressBar.js index db3ada7023a..5cc8a88bf29 100644 --- a/tgui/packages/tgui/components/ProgressBar.js +++ b/tgui/packages/tgui/components/ProgressBar.js @@ -1,4 +1,4 @@ -import { clamp, keyOfMatchingRange, toFixed } from 'common/math'; +import { clamp01, scale, keyOfMatchingRange, toFixed } from 'common/math'; import { classes, pureComponentHooks } from 'common/react'; import { computeBoxClassName, computeBoxProps } from './Box'; @@ -13,7 +13,7 @@ export const ProgressBar = props => { children, ...rest } = props; - const scaledValue = (value - minValue) / (maxValue - minValue); + const scaledValue = scale(value, minValue, maxValue); const hasContent = children !== undefined; const effectiveColor = color || keyOfMatchingRange(value, ranges) @@ -28,9 +28,9 @@ export const ProgressBar = props => { ])} {...computeBoxProps(rest)}>
{hasContent diff --git a/tgui/packages/tgui/components/Tabs.js b/tgui/packages/tgui/components/Tabs.js index da2bfd903d5..ff42afdc149 100644 --- a/tgui/packages/tgui/components/Tabs.js +++ b/tgui/packages/tgui/components/Tabs.js @@ -1,139 +1,51 @@ -import { classes, normalizeChildren } from 'common/react'; -import { Component } from 'inferno'; -import { Box } from './Box'; +import { classes } from 'common/react'; +import { computeBoxClassName, computeBoxProps } from './Box'; import { Button } from './Button'; -// A magic value for enforcing type safety -const TAB_MAGIC_TYPE = 'Tab'; - -const validateTabs = tabs => { - for (let tab of tabs) { - if (!tab.props || tab.props.__type__ !== TAB_MAGIC_TYPE) { - const json = JSON.stringify(tab, null, 2); - throw new Error(' only accepts children of type .' - + 'This is what we received: ' + json); - } - } +export const Tabs = props => { + const { + className, + vertical, + children, + ...rest + } = props; + return ( +
+
+ {children} +
+
+ ); }; -export class Tabs extends Component { - constructor(props) { - super(props); - this.state = { - activeTabKey: null, - }; - } - - getActiveTab() { - const { state, props } = this; - const tabs = normalizeChildren(props.children); - validateTabs(tabs); - // Get active tab - let activeTabKey = props.activeTab || state.activeTabKey; - // Verify that active tab exists - let activeTab = tabs - .find(tab => { - const key = tab.key || tab.props.label; - return key === activeTabKey; - }); - // Set first tab as the active tab - if (!activeTab) { - activeTab = tabs[0]; - activeTabKey = activeTab && (activeTab.key || activeTab.props.label); - } - return { - tabs, - activeTab, - activeTabKey, - }; - } - - render() { - const { props } = this; - const { - className, - vertical, - altSelection, - children, - ...rest - } = props; - const { - tabs, - activeTab, - activeTabKey, - } = this.getActiveTab(); - // Retrieve tab content - let content = null; - if (activeTab) { - content = activeTab.props.content || activeTab.props.children; - } - // Get children by calling a wrapper function - if (typeof content === 'function') { - content = content(activeTabKey); - } - return ( - -
- {tabs.map(tab => { - const { - className, - label, - content, // ignored - children, // ignored - onClick, - highlight, - ...rest - } = tab.props; - const key = tab.key || tab.props.label; - const active = tab.active || key === activeTabKey; - const altSelectionStyle = 'Button--altSelected' - + (vertical ? '--right' : '--bottom'); - return ( - - ); - })} -
-
- {content || null} -
-
- ); - } -} - -/** - * A dummy component, which is used for carrying props for the - * tab container. - */ -export const Tab = props => null; - -Tab.defaultProps = { - __type__: TAB_MAGIC_TYPE, +const Tab = props => { + const { + className, + selected, + altSelection, + ...rest + } = props; + return ( + - +
{!requestonly && ( - + )} - +
{tab === 'catalog' && ( )} @@ -81,7 +76,10 @@ const CargoStatus = (props, context) => { title="Cargo" buttons={( - credits + formatMoney(value)} /> + {' credits'} )}> @@ -143,19 +141,16 @@ export const CargoCatalog = (props, context) => { )}> - {supplies.map(supply => ( - - ))} - - - + + {supplies.map(supply => ( + setActiveSupplyName(supply.name)}> + {supply.name} ({supply.packs.length}) + + ))} + @@ -190,9 +185,9 @@ export const CargoCatalog = (props, context) => { onClick={() => act('add', { id: pack.id, })}> - {self_paid + {formatMoney(self_paid ? Math.round(pack.cost * 1.1) - : pack.cost} + : pack.cost)} {' cr'} @@ -247,7 +242,7 @@ const CargoRequests = (props, context) => { {request.reason} - {request.cost} cr. + {formatMoney(request.cost)} cr {!requestonly && ( @@ -290,7 +285,7 @@ const CargoCartButtons = (props, context) => { {cart.length === 1 && '1 item'} {cart.length >= 2 && cart.length + ' items'} {' '} - {total > 0 && `(${total} cr)`} + {total > 0 && `(${formatMoney(total)} cr)`}