diff --git a/code/datums/achievements/_achievement_data.dm b/code/datums/achievements/_achievement_data.dm index 9ff2c4a3c1c..f353ef03614 100644 --- a/code/datums/achievements/_achievement_data.dm +++ b/code/datums/achievements/_achievement_data.dm @@ -97,7 +97,7 @@ if(!ui) var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/achievements) assets.send(user) - ui = new(user, src, ui_key, "Achievements", "Achievements Menu", 800, 1000, master_ui, state) + ui = new(user, src, ui_key, "Achievements", "Achievements Menu", 540, 680, master_ui, state) ui.open() /datum/achievement_data/ui_data(mob/user) diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index 20a550c3b83..ba3d4b48678 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -135,8 +135,7 @@ var/list/data = list() data["telecrystals"] = telecrystals data["lockable"] = lockable - data["compact_mode"] = compact_mode - + data["compactMode"] = compact_mode return data /datum/component/uplink/ui_static_data(mob/user) diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 7715c5b5e0e..fc927c15dab 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -96,7 +96,6 @@ else data["patient"] = null return data - switch(patient.stat) if(CONSCIOUS) data["patient"]["stat"] = "Conscious" @@ -118,8 +117,8 @@ data["patient"]["fireLoss"] = patient.getFireLoss() data["patient"]["toxLoss"] = patient.getToxLoss() data["patient"]["oxyLoss"] = patient.getOxyLoss() + data["procedures"] = list() if(patient.surgeries.len) - data["procedures"] = list() for(var/datum/surgery/procedure in patient.surgeries) var/datum/surgery_step/surgery_step = procedure.get_surgery_step() var/chems_needed = surgery_step.get_chem_list() diff --git a/code/game/machinery/medical_kiosk.dm b/code/game/machinery/medical_kiosk.dm index a75812eefea..ba33ab23ad5 100644 --- a/code/game/machinery/medical_kiosk.dm +++ b/code/game/machinery/medical_kiosk.dm @@ -172,7 +172,7 @@ ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "MedicalKiosk", name, 625, 550, master_ui, state) + ui = new(user, src, ui_key, "MedicalKiosk", name, 575, 420, master_ui, state) ui.open() icon_state = "kiosk_off" RefreshParts() @@ -236,29 +236,18 @@ trauma_text += trauma_desc trauma_status = "Cerebral traumas detected: patient appears to be suffering from [english_list(trauma_text)]." - var/chem_status = FALSE - var/chemical_list= list() - var/overdose_status = FALSE + var/chemical_list = list() var/overdose_list = list() - var/addict_status = FALSE var/addict_list = list() var/hallucination_status = "Patient is not hallucinating." - for(var/datum/reagent/R in altPatient.reagents.reagent_list) - if(R.overdosed) - overdose_status = TRUE - if(altPatient.reagents.reagent_list.len) //Chemical Analysis details. - chem_status = TRUE for(var/datum/reagent/R in altPatient.reagents.reagent_list) chemical_list += list(list("name" = R.name, "volume" = round(R.volume, 0.01))) if(R.overdosed == 1) overdose_list += list(list("name" = R.name)) - else - chemical_list = "Patient contains no reagents" if(altPatient.reagents.addiction_list.len) - addict_status = TRUE for(var/datum/reagent/R in altPatient.reagents.addiction_list) addict_list += list(list("name" = R.name)) if (altPatient.hallucinating()) @@ -296,7 +285,6 @@ else if (user.hallucinating()) chaos_modifier = 0.3 - data["kiosk_cost"] = active_price + (chaos_modifier * (rand(1,25))) data["patient_name"] = patient_name data["patient_health"] = round(((total_health - (chaos_modifier * (rand(1,50)))) / max_health) * 100, 0.001) @@ -316,18 +304,15 @@ data["bleed_status"] = bleed_status data["blood_levels"] = blood_percent - (chaos_modifier * (rand(1,35))) data["blood_status"] = blood_status - data["are_chems_present"] = chem_status ? TRUE : FALSE data["chemical_list"] = chemical_list - data["are_overdoses_present"] = overdose_status ? TRUE : FALSE - data["overdose_status"] = overdose_list - data["are_addictions_present"] = addict_status ? TRUE : FALSE - data["addiction_status"] = addict_list + data["overdose_list"] = overdose_list + data["addict_list"] = addict_list data["hallucinating_status"] = hallucination_status - data["active_status_1"] = scan_active_1 ? FALSE : TRUE //General Scan Check - data["active_status_2"] = scan_active_2 ? FALSE : TRUE //Symptom Scan Check - data["active_status_3"] = scan_active_3 ? FALSE : TRUE //Radio-Neuro Scan Check - data["active_status_4"] = scan_active_4 ? FALSE : TRUE //Radio-Neuro Scan Check + data["active_status_1"] = scan_active_1 // General Scan Check + data["active_status_2"] = scan_active_2 // Symptom Scan Check + data["active_status_3"] = scan_active_3 // Radio-Neuro Scan Check + data["active_status_4"] = scan_active_4 // Radio-Neuro Scan Check return data /obj/machinery/medical_kiosk/ui_act(action,active) diff --git a/code/modules/antagonists/traitor/equipment/module_picker.dm b/code/modules/antagonists/traitor/equipment/module_picker.dm index ce0062890cb..1185c0b60e0 100644 --- a/code/modules/antagonists/traitor/equipment/module_picker.dm +++ b/code/modules/antagonists/traitor/equipment/module_picker.dm @@ -39,8 +39,8 @@ /datum/module_picker/ui_data(mob/user) var/list/data = list() - data["processing_time"] = processing_time - data["compact_mode"] = compact_mode + data["processingTime"] = processing_time + data["compactMode"] = compact_mode return data /datum/module_picker/ui_static_data(mob/user) diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm index 53fc478c617..19f8bd81c5e 100644 --- a/code/modules/asset_cache/asset_list_items.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -4,10 +4,6 @@ assets = list( "tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js', "tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css', - "shim-html5shiv.js" = 'tgui/packages/tgui/public/shim-html5shiv.js', - "shim-ie8.js" = 'tgui/packages/tgui/public/shim-ie8.js', - "shim-dom4.js" = 'tgui/packages/tgui/public/shim-dom4.js', - "shim-css-om.js" = 'tgui/packages/tgui/public/shim-css-om.js', ) /datum/asset/group/tgui diff --git a/code/modules/cargo/blackmarket/blackmarket_uplink.dm b/code/modules/cargo/blackmarket/blackmarket_uplink.dm index 453294b44c2..3833b0505a5 100644 --- a/code/modules/cargo/blackmarket/blackmarket_uplink.dm +++ b/code/modules/cargo/blackmarket/blackmarket_uplink.dm @@ -4,7 +4,7 @@ icon_state = "uplink" // UI variables. - var/ui_x = 720 + var/ui_x = 600 var/ui_y = 480 var/viewing_category var/viewing_market @@ -58,7 +58,7 @@ /obj/item/blackmarket_uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "BlackmarketUplink", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, ui_key, "BlackMarketUplink", name, ui_x, ui_y, master_ui, state) ui.open() /obj/item/blackmarket_uplink/ui_data(mob/user) diff --git a/tgui/docs/component-reference.md b/tgui/docs/component-reference.md index 1ee677d6fb7..1e9f9f3f9a5 100644 --- a/tgui/docs/component-reference.md +++ b/tgui/docs/component-reference.md @@ -171,6 +171,13 @@ all available horizontal space. - `mb: number` - Bottom margin. - `ml: number` - Left margin. - `mr: number` - Right margin. +- `p: number` - Padding on all sides. +- `px: number` - Horizontal padding. +- `py: number` - Vertical padding. +- `pt: number` - Top padding. +- `pb: number` - Bottom padding. +- `pl: number` - Left padding. +- `pr: number` - Right padding. - `opacity: number` - Opacity, from 0 to 1. - `bold: boolean` - Make text bold. - `italic: boolean` - Make text italic. @@ -848,55 +855,47 @@ Here is an example of how you would construct a simple tabbed view: ```jsx - - Content for Item one. + setTabIndex(1)}> + Tab one - - Content for Item two. + setTabIndex(2)}> + Tab two + + Tab selected: {tabIndex} + ``` -This is a rather simple example. In the real world, you might be -constructing very complex tabbed views which can tax UI performance. -This is because your tabs are being rendered regardless of their -visibility status! +Notice that tabs do not contain state. It is your job to track the selected +tab, handle clicks and place tab content where you need it. In return, you get +a lot of flexibility in regards to how you can layout your tabs. -There is a simple fix however. Tabs accept functions as children, which -will be called to retrieve content only when the tab is visible: +Tabs also support a vertical configuration. This is usually paired with a +[Flex](#flex) component to render tab content to the right. ```jsx - - - {() => ( - - Content for Item one. - - )} - - - {() => ( - - Content for Item two. - - )} - - + + + + ... + + + + Tab content. + + ``` -You might not always need this, but it is highly recommended to always -use this method. Notice the `key` prop on tabs - it uniquely identifies -the tab and is used for determining which tab is currently active. It can -be either explicitly provided as a `key` prop, or if omitted, it will be -implicitly derived from the tab's `label` prop. - Props: -- `vertical: boolean` - Use a vertical configuration, where tabs will appear -stacked on the left side of the container. -- `altSelection` - Whether the tab buttons select via standard select (color -change) or by adding a white indicator to the selected tab. -Intended for usage on interfaces where tab color has relevance. +- See inherited props: [Box](#box) +- `vertical: boolean` - Use a vertical configuration, where tabs will be +stacked vertically. - `children: Tab[]` - This component only accepts tabs as its children. ### `Tabs.Tab` @@ -907,10 +906,11 @@ a lot of `Button` props. Props: - See inherited props: [Button](#button) -- `key: string` - A unique identifier for the tab. -- `label: string` - Tab label. +- `altSelection` - Whether the tab buttons select via standard select (color +change) or by adding a white indicator to the selected tab. +Intended for usage on interfaces where tab color has relevance. - `icon: string` - Tab icon. -- `content/children: any` - Content to render inside the tab. +- `children: any` - Tab text. - `onClick: function` - Called when element is clicked. ### `Tooltip` diff --git a/tgui/packages/tgui/components/Box.js b/tgui/packages/tgui/components/Box.js index 4433e10107c..ddaef96437c 100644 --- a/tgui/packages/tgui/components/Box.js +++ b/tgui/packages/tgui/components/Box.js @@ -82,13 +82,33 @@ const styleMapperByPropName = { italic: mapBooleanPropTo('font-style', 'italic'), nowrap: mapBooleanPropTo('white-space', 'nowrap'), // Margins - m: mapDirectionalUnitPropTo('margin', ['top', 'bottom', 'left', 'right']), - mx: mapDirectionalUnitPropTo('margin', ['left', 'right']), - my: mapDirectionalUnitPropTo('margin', ['top', 'bottom']), + m: mapDirectionalUnitPropTo('margin', [ + 'top', 'bottom', 'left', 'right', + ]), + mx: mapDirectionalUnitPropTo('margin', [ + 'left', 'right', + ]), + my: mapDirectionalUnitPropTo('margin', [ + 'top', 'bottom', + ]), mt: mapUnitPropTo('margin-top'), mb: mapUnitPropTo('margin-bottom'), ml: mapUnitPropTo('margin-left'), mr: mapUnitPropTo('margin-right'), + // Margins + p: mapDirectionalUnitPropTo('padding', [ + 'top', 'bottom', 'left', 'right', + ]), + px: mapDirectionalUnitPropTo('padding', [ + 'left', 'right', + ]), + py: mapDirectionalUnitPropTo('padding', [ + 'top', 'bottom', + ]), + pt: mapUnitPropTo('padding-top'), + pb: mapUnitPropTo('padding-bottom'), + pl: mapUnitPropTo('padding-left'), + pr: mapUnitPropTo('padding-right'), // Color props color: mapColorPropTo('color'), textColor: mapColorPropTo('color'), diff --git a/tgui/packages/tgui/components/ColorBox.js b/tgui/packages/tgui/components/ColorBox.js index 66866b78898..f37c4e057e4 100644 --- a/tgui/packages/tgui/components/ColorBox.js +++ b/tgui/packages/tgui/components/ColorBox.js @@ -1,19 +1,27 @@ import { classes, pureComponentHooks } from 'common/react'; -import { Box } from './Box'; +import { computeBoxClassName, computeBoxProps } from './Box'; export const ColorBox = props => { - const { color, content, className, ...rest } = props; + const { + content, + children, + className, + color, + backgroundColor, + ...rest + } = props; + rest.color = content ? null : 'transparent'; + rest.backgroundColor = color || backgroundColor; return ( - + {...computeBoxProps(rest)}> {content || '.'} - + ); }; diff --git a/tgui/packages/tgui/components/LabeledList.js b/tgui/packages/tgui/components/LabeledList.js index a7b68ddec06..e2b515014a2 100644 --- a/tgui/packages/tgui/components/LabeledList.js +++ b/tgui/packages/tgui/components/LabeledList.js @@ -1,5 +1,6 @@ import { classes, pureComponentHooks } from 'common/react'; import { Box, unit } from './Box'; +import { Divider } from './Divider'; export const LabeledList = props => { const { children } = props; @@ -62,12 +63,19 @@ export const LabeledListItem = props => { LabeledListItem.defaultHooks = pureComponentHooks; export const LabeledListDivider = props => { - const { size = 1 } = props; + const padding = props.size + ? unit(Math.max(0, props.size - 1)) + : 0; return ( - + + + ); }; diff --git a/tgui/packages/tgui/format.js b/tgui/packages/tgui/format.js index 1518d14c392..8ce1915f515 100644 --- a/tgui/packages/tgui/format.js +++ b/tgui/packages/tgui/format.js @@ -56,10 +56,28 @@ export const formatPower = (value, minBase1000 = 0) => { }; export const formatMoney = (value, precision = 0) => { - return round(value, precision) - .toLocaleString('en', { - minimumFractionDigits: precision, - }) - // Thin space - .replace(/,/g, '\u2009'); + if (!Number.isFinite(value)) { + return value; + } + // Round the number and make it fixed precision + let fixed = round(value, precision); + if (precision > 0) { + fixed = toFixed(value, precision); + } + fixed = String(fixed); + // Place thousand separators + const length = fixed.length; + let indexOfPoint = fixed.indexOf('.'); + if (indexOfPoint === -1) { + indexOfPoint = length; + } + let result = ''; + for (let i = 0; i < length; i++) { + if (i > 0 && i < indexOfPoint && (indexOfPoint - i) % 3 === 0) { + // Thin space + result += '\u2009'; + } + result += fixed.charAt(i); + } + return result; }; diff --git a/tgui/packages/tgui/index.js b/tgui/packages/tgui/index.js index 769820b9f58..59199f9edbe 100644 --- a/tgui/packages/tgui/index.js +++ b/tgui/packages/tgui/index.js @@ -1,13 +1,23 @@ +// Polyfills import 'core-js/es'; import 'core-js/web/immediate'; import 'core-js/web/queue-microtask'; import 'core-js/web/timers'; import 'regenerator-runtime/runtime'; +import './polyfills/html5shiv'; +import './polyfills/ie8'; +import './polyfills/dom4'; +import './polyfills/css-om'; +import './polyfills/inferno'; -// This one is necessary for Inferno. -if (!window.Int32Array) { - window.Int32Array = Array; -} +// Themes +import './styles/main.scss'; +import './styles/themes/cardtable.scss'; +import './styles/themes/malfunction.scss'; +import './styles/themes/ntos.scss'; +import './styles/themes/hackerman.scss'; +import './styles/themes/retro.scss'; +import './styles/themes/syndicate.scss'; import { loadCSS } from 'fg-loadcss'; import { render } from 'inferno'; diff --git a/tgui/packages/tgui/interfaces/Achievements.js b/tgui/packages/tgui/interfaces/Achievements.js index 0f6a224893f..464708d2484 100644 --- a/tgui/packages/tgui/interfaces/Achievements.js +++ b/tgui/packages/tgui/interfaces/Achievements.js @@ -1,7 +1,6 @@ import { useBackend, useLocalState } from '../backend'; -import { Box, Icon, Table, Tabs } from '../components'; +import { Box, Flex, Icon, Table, Tabs } from '../components'; import { Window } from '../layouts'; -import { Fragment } from 'inferno'; export const Achievements = (props, context) => { const { data } = useBackend(context); @@ -63,11 +62,11 @@ const Achievement = props => { score, } = achievement; return ( - - - - - + + + + +

{name}

{desc} {score && ( @@ -79,8 +78,8 @@ const Achievement = props => { {value ? 'Unlocked' : 'Locked'}
)} - - + + ); }; @@ -105,54 +104,58 @@ const HighScoreTable = (props, context) => { value: highscore.scores[key], })); return ( - - - {highscores.map((highscore, i) => ( - setHighScoreIndex(i)}> - {highscore.name} - - ))} - - - - - # - - - Key - - - Score - - - {scores.map((score, i) => ( - - - {i + 1} - - - {i === 0 && ( - - )} - {score.ckey} - {i === 0 && ( - - )} + + + + {highscores.map((highscore, i) => ( + setHighScoreIndex(i)}> + {highscore.name} + + ))} + + + +
+ + + # - {score.value} + Key + + + Score - ))} -
-
+ {scores.map((score, i) => ( + + + {i + 1} + + + {i === 0 && ( + + )} + {score.ckey} + {i === 0 && ( + + )} + + + {score.value} + + + ))} + + + ); }; diff --git a/tgui/packages/tgui/interfaces/BlackmarketUplink.js b/tgui/packages/tgui/interfaces/BlackmarketUplink.js index 1a0e17a8e0b..a2e2f0b7adf 100644 --- a/tgui/packages/tgui/interfaces/BlackmarketUplink.js +++ b/tgui/packages/tgui/interfaces/BlackmarketUplink.js @@ -1,45 +1,145 @@ -import { map } from 'common/collections'; import { useBackend } from '../backend'; import { AnimatedNumber, Box, Button, Flex, Modal, Section, Table, Tabs } from '../components'; +import { formatMoney } from '../format'; import { Window } from '../layouts'; -export const BlackmarketUplink = (props, context) => { +export const BlackMarketUplink = (props, context) => { const { act, data } = useBackend(context); - const categories = data.categories || []; - const deliveryMethods = data.delivery_methods || []; - const deliveryMethodDesc = data.delivery_method_description || []; - const markets = data.markets || {}; - const items = data.items || {}; + const { + categories = [], + markets = [], + items = [], + money, + viewing_market, + viewing_category, + } = data; + return ( + + + +
+ formatMoney(value) + ' cr'} /> + + )} /> + + {markets.map(market => ( + act('set_market', { + market: market.id, + })}> + {market.name} + + ))} + + + + + {categories.map(category => ( + act('set_category', { + category: category, + })}> + {category} + + ))} + + + + {items.map(item => ( + + + + {item.name} + + + {item.amount + ? item.amount + " in stock" + : "Out of stock"} + + + {formatMoney(item.cost) + ' cr'} + + +
+
); }; - -const ItemList = props => { - const { - items, - hoveredItem, - processing_time, - compact, - onBuy, - onBuyMouseOver, - onBuyMouseOut, - } = props; - const hoveredCost = hoveredItem && hoveredItem.cost || 0; - if (compact) { - return ( - - {items.map(item => { - const notSameItem = hoveredItem && hoveredItem.name !== item.name; - const notEnoughHovered = processing_time - hoveredCost < item.cost; - const disabledDueToHovered = notSameItem && notEnoughHovered; - return ( - - - {decodeHtmlEntities(item.name)} - - -
- ); - } - return items.map(item => { - const notSameItem = hoveredItem && hoveredItem.name !== item.name; - const notEnoughHovered = processing_time - hoveredCost < item.cost; - const disabledDueToHovered = notSameItem && notEnoughHovered; - return ( -
onBuyMouseOver(item)} - onmouseout={() => onBuyMouseOut(item)} - onClick={() => onBuy(item)} /> - )}> - {decodeHtmlEntities(item.desc)} -
- ); - }); -}; diff --git a/tgui/packages/tgui/interfaces/MedicalKiosk.js b/tgui/packages/tgui/interfaces/MedicalKiosk.js index 60a0cdc8bb9..3b475e78e75 100644 --- a/tgui/packages/tgui/interfaces/MedicalKiosk.js +++ b/tgui/packages/tgui/interfaces/MedicalKiosk.js @@ -1,302 +1,358 @@ import { multiline } from 'common/string'; -import { useBackend } from '../backend'; -import { AnimatedNumber, Box, Button, LabeledList, ProgressBar, Section, Tabs } from '../components'; +import { useBackend, useSharedState } from '../backend'; +import { AnimatedNumber, Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; export const MedicalKiosk = (props, context) => { const { act, data } = useBackend(context); + const [scanIndex] = useSharedState(context, 'scanIndex'); + const { + active_status_1, + active_status_2, + active_status_3, + active_status_4, + } = data; return ( -
- - Greetings Valued Employee. Please select your desired diagnosis. - Diagnosis costs {data.kiosk_cost} credits. - - - Current patient targeted for scanning: {data.patient_name} | - - -
- - - {() => ( - - {data.active_status_1 === 0 && ( -
- - - - % - - - - - - - - - - - - - - - - - - - - - - - - -
- )} -
- )} -
- - {() => ( - - {data.active_status_2 === 0 && ( -
- - - {data.patient_status} - - - - {data.patient_illness} - - - {data.illness_info} - - - - {data.bleed_status} - - - - - - - {data.blood_status} - - -
- )} -
- )} -
- - {() => ( - - {data.active_status_3 === 0 && ( -
- - - - - - - - - - - - {data.brain_health} - - - {data.rad_status} - - - {data.rad_value}% - - - {data.trauma_status} - -
- )} -
- )} -
- - {() => ( - - {data.active_status_4 === 0 && ( -
- - {data.are_chems_present ? ( - data.chemical_list.length ? ( - data.chemical_list.map(specificChem => ( - - {specificChem.volume} units of {specificChem.name} - - )) - ) : ( - - No reagents detected. - - ) - ) : ( - - No reagents detected. - - )} - - - {data.are_overdoses_present ? ( - data.overdose_status.length ? ( - data.overdose_status.map(specificOD => ( - - Overdosing on {specificOD.name} - - )) - ) : ( - - No reagents detected. - - ) - ) : ( - - Patient is not overdosing. - - )} - - - {data.are_addictions_present ? ( - data.addiction_status.length ? ( - data.addiction_status.map(specificAddict => ( - - Addicted to {specificAddict.name} - - )) - ) : ( - - Patient has no addictions. - - ) - ) : ( - - Patient has no addictions detected. - - )} - - - {data.hallucinating_status} - -
- )} -
- )} -
-
+ + +
+ + + + +
+
+ + + +
+ {!!active_status_1 && scanIndex === 1 && ( + + )} + {!!active_status_2 && scanIndex === 2 && ( + + )} + {!!active_status_3 && scanIndex === 3 && ( + + )} + {!!active_status_4 && scanIndex === 4 && ( + + )}
); }; + +const MedicalKioskScanButton = (props, context) => { + const { + index, + name, + description, + icon, + } = props; + const { act, data } = useBackend(context); + const [scanIndex, setScanIndex] = useSharedState(context, 'scanIndex'); + const paid = data[`active_status_${index}`]; + return ( + + +