From 0fe61fabd4bf578b4df274a1ffdd820fb243a241 Mon Sep 17 00:00:00 2001 From: CHOMPStation2 <58959929+CHOMPStation2@users.noreply.github.com> Date: Thu, 8 Feb 2024 07:00:29 -0700 Subject: [PATCH] [MIRROR] TGUI 5.0 (#7700) Co-authored-by: Selis Co-authored-by: Selis --- tgui/.eslintignore | 4 +- tgui/.eslintrc.yml | 2 +- tgui/README.md | 7 +- tgui/babel.config.js | 40 +- tgui/docs/component-reference.md | 12 +- tgui/docs/state-usage.md | 38 + tgui/package.json | 67 +- tgui/packages/common/keys.ts | 10 +- tgui/packages/common/react.ts | 15 +- tgui/packages/common/redux.ts | 20 - tgui/packages/tgui-bench/package.json | 9 +- .../packages/tgui-bench/tests/Button.test.tsx | 23 - .../tgui-bench/tests/DisposalBin.test.tsx | 12 +- tgui/packages/tgui-dev-server/package.json | 10 +- tgui/packages/tgui-panel/Panel.tsx | 10 +- .../tgui-panel/audio/NowPlayingWidget.jsx | 16 +- tgui/packages/tgui-panel/audio/hooks.ts | 8 +- .../tgui-panel/chat/ChatPageSettings.jsx | 8 +- tgui/packages/tgui-panel/chat/ChatPanel.jsx | 8 +- tgui/packages/tgui-panel/chat/ChatTabs.jsx | 22 +- tgui/packages/tgui-panel/chat/renderer.jsx | 2 +- tgui/packages/tgui-panel/game/hooks.ts | 6 +- tgui/packages/tgui-panel/index.tsx | 8 +- tgui/packages/tgui-panel/package.json | 5 +- .../tgui-panel/ping/PingIndicator.jsx | 6 +- tgui/packages/tgui-panel/reconnect.tsx | 6 +- .../tgui-panel/settings/SettingsPanel.jsx | 50 +- tgui/packages/tgui-panel/settings/hooks.ts | 8 +- tgui/packages/tgui-polyfill/00-html5shiv.js | 336 -- tgui/packages/tgui-polyfill/01-ie8.js | 773 ---- tgui/packages/tgui-polyfill/02-dom4.js | 912 ----- tgui/packages/tgui-polyfill/03-css-om.js | 43 - tgui/packages/tgui-polyfill/1-misc.js | 48 + tgui/packages/tgui-polyfill/10-misc.js | 61 - tgui/packages/tgui-polyfill/package.json | 12 +- tgui/packages/tgui/backend.ts | 8 + .../tgui/components/AnimatedNumber.tsx | 5 +- tgui/packages/tgui/components/Autofocus.tsx | 26 +- tgui/packages/tgui/components/Blink.jsx | 6 +- .../tgui/components/BodyZoneSelector.tsx | 29 +- tgui/packages/tgui/components/Box.tsx | 195 +- tgui/packages/tgui/components/Button.jsx | 41 +- tgui/packages/tgui/components/ByondUi.jsx | 16 +- .../tgui/components/{Chart.jsx => Chart.tsx} | 116 +- tgui/packages/tgui/components/Collapsible.jsx | 2 +- tgui/packages/tgui/components/ColorBox.jsx | 4 +- .../tgui/components/DraggableControl.jsx | 8 +- tgui/packages/tgui/components/Dropdown.tsx | 48 +- .../packages/tgui/components/FakeTerminal.jsx | 2 +- tgui/packages/tgui/components/FitText.tsx | 15 +- tgui/packages/tgui/components/Flex.tsx | 81 +- tgui/packages/tgui/components/Grid.jsx | 5 - tgui/packages/tgui/components/Icon.tsx | 27 +- .../tgui/components/InfinitePlane.jsx | 30 +- tgui/packages/tgui/components/Input.jsx | 6 +- tgui/packages/tgui/components/KeyListener.tsx | 6 +- tgui/packages/tgui/components/Knob.jsx | 10 +- tgui/packages/tgui/components/LabeledList.tsx | 96 +- tgui/packages/tgui/components/MenuBar.tsx | 8 +- tgui/packages/tgui/components/NanoMap.jsx | 6 +- tgui/packages/tgui/components/NoticeBox.jsx | 4 +- tgui/packages/tgui/components/NumberInput.jsx | 34 +- tgui/packages/tgui/components/Popper.tsx | 21 +- .../{ProgressBar.jsx => ProgressBar.tsx} | 49 +- .../tgui/components/RestrictedInput.jsx | 6 +- tgui/packages/tgui/components/RoundGauge.jsx | 11 +- tgui/packages/tgui/components/Section.tsx | 169 +- tgui/packages/tgui/components/Slider.jsx | 5 - tgui/packages/tgui/components/Stack.tsx | 28 +- .../tgui/components/StyleableSection.tsx | 27 +- tgui/packages/tgui/components/Table.jsx | 8 +- .../tgui/components/{Tabs.jsx => Tabs.tsx} | 32 +- tgui/packages/tgui/components/TextArea.jsx | 7 +- tgui/packages/tgui/components/TimeDisplay.jsx | 2 +- tgui/packages/tgui/components/Tooltip.tsx | 64 +- .../tgui/components/TrackOutsideClicks.tsx | 8 +- tgui/packages/tgui/debug/hooks.js | 4 +- tgui/packages/tgui/drag.ts | 4 +- tgui/packages/tgui/interfaces/AICard.jsx | 4 +- tgui/packages/tgui/interfaces/APC.jsx | 20 +- .../interfaces/AdminShuttleController.tsx | 2 +- tgui/packages/tgui/interfaces/AiAirlock.jsx | 6 +- tgui/packages/tgui/interfaces/AiRestorer.jsx | 8 +- tgui/packages/tgui/interfaces/AirAlarm.jsx | 12 +- tgui/packages/tgui/interfaces/AlgaeFarm.jsx | 2 +- .../tgui/interfaces/AppearanceChanger.jsx | 10 +- .../packages/tgui/interfaces/ArcadeBattle.jsx | 2 +- .../tgui/interfaces/AreaScrubberControl.jsx | 2 +- .../tgui/interfaces/AtmosAlertConsole.jsx | 2 +- .../packages/tgui/interfaces/AtmosControl.jsx | 8 +- tgui/packages/tgui/interfaces/AtmosFilter.jsx | 2 +- tgui/packages/tgui/interfaces/AtmosMixer.jsx | 2 +- tgui/packages/tgui/interfaces/Batteryrack.jsx | 2 +- .../packages/tgui/interfaces/Biogenerator.jsx | 8 +- tgui/packages/tgui/interfaces/BodyScanner.jsx | 20 +- tgui/packages/tgui/interfaces/BombTester.jsx | 2 +- .../packages/tgui/interfaces/BotanyEditor.jsx | 4 +- .../tgui/interfaces/BotanyIsolator.jsx | 4 +- tgui/packages/tgui/interfaces/BrigTimer.jsx | 8 +- tgui/packages/tgui/interfaces/Canister.jsx | 2 +- tgui/packages/tgui/interfaces/Canvas.jsx | 2 +- .../tgui/interfaces/CasinoPrizeDispenser.jsx | 7 +- .../tgui/interfaces/CharacterDirectory.jsx | 10 +- .../tgui/interfaces/ChemDispenser.jsx | 8 +- tgui/packages/tgui/interfaces/ChemMaster.jsx | 12 +- .../tgui/interfaces/ChemSynthesizer.jsx | 5 +- tgui/packages/tgui/interfaces/ClawMachine.jsx | 2 +- .../tgui/interfaces/CloningConsole.jsx | 24 +- tgui/packages/tgui/interfaces/ColorMate.tsx | 8 +- .../tgui/interfaces/CommunicationsConsole.jsx | 16 +- .../packages/tgui/interfaces/Communicator.tsx | 12 +- .../tgui/interfaces/ComputerFabricator.jsx | 2 +- .../tgui/interfaces/CookingAppliance.jsx | 2 +- tgui/packages/tgui/interfaces/CrewMonitor.jsx | 8 +- tgui/packages/tgui/interfaces/Cryo.jsx | 10 +- tgui/packages/tgui/interfaces/CryoStorage.jsx | 2 +- .../tgui/interfaces/CryoStorageVr.jsx | 2 +- .../packages/tgui/interfaces/DNAForensics.jsx | 6 +- tgui/packages/tgui/interfaces/DNAModifier.jsx | 39 +- .../tgui/interfaces/DestinationTagger.jsx | 2 +- .../tgui/interfaces/DiseaseSplicer.jsx | 10 +- .../tgui/interfaces/DishIncubator.jsx | 6 +- .../packages/tgui/interfaces/DroneConsole.jsx | 8 +- .../tgui/interfaces/EmbeddedController.jsx | 44 +- .../tgui/interfaces/EntityNarrate.tsx | 2 +- tgui/packages/tgui/interfaces/ExonetNode.tsx | 2 +- .../tgui/interfaces/ExosuitFabricator.jsx | 14 +- tgui/packages/tgui/interfaces/Fax.jsx | 4 +- tgui/packages/tgui/interfaces/FileCabinet.jsx | 2 +- tgui/packages/tgui/interfaces/GasPump.jsx | 2 +- .../tgui/interfaces/GeneralAtmoControl.jsx | 16 +- .../tgui/interfaces/GeneralRecords.jsx | 18 +- tgui/packages/tgui/interfaces/Gps.jsx | 12 +- .../tgui/interfaces/GravityGenerator.jsx | 2 +- tgui/packages/tgui/interfaces/GuestPass.jsx | 2 +- .../tgui/interfaces/GyrotronControl.tsx | 2 +- tgui/packages/tgui/interfaces/Holodeck.jsx | 2 +- tgui/packages/tgui/interfaces/ICAssembly.jsx | 2 +- tgui/packages/tgui/interfaces/ICCircuit.jsx | 6 +- tgui/packages/tgui/interfaces/IDCard.jsx | 2 +- .../interfaces/IdentificationComputer.jsx | 12 +- .../tgui/interfaces/InventoryPanel.tsx | 2 +- .../tgui/interfaces/InventoryPanelHuman.jsx | 2 +- .../tgui/interfaces/IsolationCentrifuge.jsx | 10 +- tgui/packages/tgui/interfaces/Jukebox.jsx | 2 +- tgui/packages/tgui/interfaces/LawManager.jsx | 24 +- .../packages/tgui/interfaces/LookingGlass.jsx | 2 +- .../tgui/interfaces/MechaControlConsole.jsx | 8 +- .../tgui/interfaces/MedicalRecords.jsx | 30 +- .../tgui/interfaces/MessageMonitor.jsx | 12 +- tgui/packages/tgui/interfaces/Microwave.jsx | 8 +- .../interfaces/MiningOreProcessingConsole.jsx | 8 +- .../tgui/interfaces/MiningStackingConsole.jsx | 2 +- .../packages/tgui/interfaces/MiningVendor.jsx | 2 +- tgui/packages/tgui/interfaces/MobSpawner.tsx | 2 +- tgui/packages/tgui/interfaces/MuleBot.tsx | 6 +- tgui/packages/tgui/interfaces/NIF.jsx | 12 +- tgui/packages/tgui/interfaces/NTNetRelay.jsx | 5 +- tgui/packages/tgui/interfaces/Newscaster.jsx | 16 +- tgui/packages/tgui/interfaces/NoticeBoard.tsx | 6 +- .../tgui/interfaces/NtosAtmosControl.tsx | 2 +- .../tgui/interfaces/NtosCameraConsole.jsx | 2 +- .../interfaces/NtosCommunicationsConsole.tsx | 2 +- .../tgui/interfaces/NtosConfiguration.jsx | 8 +- .../tgui/interfaces/NtosCrewManifest.tsx | 2 +- .../tgui/interfaces/NtosCrewMonitor.tsx | 2 +- .../tgui/interfaces/NtosDigitalWarrant.jsx | 12 +- .../interfaces/NtosEmailAdministration.jsx | 2 +- .../tgui/interfaces/NtosEmailClient.jsx | 14 +- .../tgui/interfaces/NtosFileManager.jsx | 18 +- .../interfaces/NtosIdentificationComputer.tsx | 2 +- tgui/packages/tgui/interfaces/NtosMain.jsx | 3 +- tgui/packages/tgui/interfaces/NtosNetChat.jsx | 10 +- tgui/packages/tgui/interfaces/NtosNetDos.jsx | 6 +- .../tgui/interfaces/NtosNetDownloader.jsx | 2 +- .../tgui/interfaces/NtosNetMonitor.jsx | 16 +- .../tgui/interfaces/NtosNetTransfer.jsx | 2 +- .../tgui/interfaces/NtosNewsBrowser.jsx | 8 +- .../tgui/interfaces/NtosOvermapNavigation.tsx | 2 +- .../tgui/interfaces/NtosPowerMonitor.tsx | 2 +- tgui/packages/tgui/interfaces/NtosRCON.tsx | 2 +- .../tgui/interfaces/NtosShutoffMonitor.tsx | 2 +- .../interfaces/NtosStationAlertConsole.tsx | 2 +- .../interfaces/NtosSupermatterMonitor.tsx | 2 +- tgui/packages/tgui/interfaces/NtosUAV.jsx | 2 +- tgui/packages/tgui/interfaces/OmniFilter.tsx | 12 +- tgui/packages/tgui/interfaces/OmniMixer.tsx | 16 +- .../tgui/interfaces/OperatingComputer.jsx | 12 +- .../tgui/interfaces/OvermapDisperser.jsx | 2 +- .../tgui/interfaces/OvermapEngines.jsx | 6 +- tgui/packages/tgui/interfaces/OvermapFull.tsx | 2 +- tgui/packages/tgui/interfaces/OvermapHelm.jsx | 12 +- .../tgui/interfaces/OvermapNavigation.tsx | 8 +- .../interfaces/OvermapShieldGenerator.jsx | 12 +- .../tgui/interfaces/OvermapShipSensors.jsx | 12 +- tgui/packages/tgui/interfaces/PartsLathe.jsx | 8 +- .../tgui/interfaces/PathogenicIsolator.jsx | 12 +- tgui/packages/tgui/interfaces/Pda.jsx | 6 +- .../tgui/interfaces/PipeDispenser.jsx | 2 +- .../tgui/interfaces/PlantAnalyzer.jsx | 8 +- tgui/packages/tgui/interfaces/PlayerNotes.tsx | 3 +- .../tgui/interfaces/PlayerNotesInfo.tsx | 3 +- .../tgui/interfaces/PortableGenerator.jsx | 2 +- .../packages/tgui/interfaces/PortablePump.jsx | 2 +- .../tgui/interfaces/PortableTurret.jsx | 8 +- .../packages/tgui/interfaces/PowerMonitor.jsx | 12 +- .../tgui/interfaces/PressureRegulator.jsx | 16 +- .../tgui/interfaces/PrisonerManagement.jsx | 8 +- tgui/packages/tgui/interfaces/RCON.jsx | 8 +- tgui/packages/tgui/interfaces/RIGSuit.jsx | 16 +- .../tgui/interfaces/RequestConsole.jsx | 12 +- .../tgui/interfaces/ResearchConsole.jsx | 22 +- .../interfaces/ResearchServerController.jsx | 8 +- .../tgui/interfaces/ResleevingConsole.jsx | 8 +- .../tgui/interfaces/ResleevingPod.jsx | 10 +- .../interfaces/RoboticsControlConsole.jsx | 12 +- tgui/packages/tgui/interfaces/RogueZones.jsx | 2 +- .../tgui/interfaces/RustCoreMonitor.tsx | 2 +- .../tgui/interfaces/RustFuelControl.tsx | 2 +- .../tgui/interfaces/SecurityRecords.jsx | 22 +- tgui/packages/tgui/interfaces/SeedStorage.jsx | 2 +- .../tgui/interfaces/ShieldCapacitor.jsx | 2 +- .../tgui/interfaces/ShieldGenerator.jsx | 8 +- .../tgui/interfaces/ShutoffMonitor.jsx | 2 +- .../tgui/interfaces/ShuttleControl.jsx | 37 +- tgui/packages/tgui/interfaces/Sleeper.jsx | 20 +- tgui/packages/tgui/interfaces/SmartVend.jsx | 2 +- tgui/packages/tgui/interfaces/Smes.jsx | 2 +- tgui/packages/tgui/interfaces/SpaceHeater.tsx | 2 +- tgui/packages/tgui/interfaces/Stack.jsx | 2 +- .../tgui/interfaces/StationAlertConsole.jsx | 2 +- .../tgui/interfaces/StationBlueprints.jsx | 8 +- .../tgui/interfaces/StockExchange.jsx | 2 +- tgui/packages/tgui/interfaces/SuitCycler.jsx | 8 +- .../tgui/interfaces/SuitStorageUnit.jsx | 8 +- .../tgui/interfaces/SupermatterMonitor.jsx | 2 +- .../tgui/interfaces/SupplyConsole.jsx | 18 +- tgui/packages/tgui/interfaces/TEGenerator.jsx | 2 +- tgui/packages/tgui/interfaces/Tank.jsx | 2 +- .../tgui/interfaces/TankDispenser.tsx | 2 +- .../tgui/interfaces/TelecommsLogBrowser.jsx | 8 +- .../interfaces/TelecommsMachineBrowser.jsx | 8 +- .../interfaces/TelecommsMultitoolMenu.jsx | 8 +- tgui/packages/tgui/interfaces/Teleporter.tsx | 2 +- .../tgui/interfaces/TelesciConsole.jsx | 2 +- tgui/packages/tgui/interfaces/TimeClock.jsx | 8 +- .../tgui/interfaces/TurbineControl.jsx | 2 +- tgui/packages/tgui/interfaces/Turbolift.jsx | 8 +- tgui/packages/tgui/interfaces/Uplink.jsx | 8 +- tgui/packages/tgui/interfaces/Vending.jsx | 8 +- tgui/packages/tgui/interfaces/VorePanel.jsx | 23 +- .../tgui/interfaces/VorePanelExport.tsx | 2 +- tgui/packages/tgui/interfaces/Wires.jsx | 8 +- .../interfaces/XenoarchArtifactHarvester.jsx | 2 +- .../tgui/interfaces/XenoarchDepthScanner.tsx | 2 +- .../tgui/interfaces/XenoarchReplicator.tsx | 2 +- .../XenoarchReplicator_clothing_vr.jsx | 2 +- .../XenoarchReplicator_voremob_vr.jsx | 2 +- .../tgui/interfaces/XenoarchSpectrometer.jsx | 8 +- .../tgui/interfaces/XenoarchSuspension.tsx | 6 +- .../interfaces/chompstation/Changelog.jsx | 11 +- .../interfaces/chompstation/VorePanel.jsx | 21 +- .../chompstation/VorePanelExport.tsx | 2 +- .../tgui/interfaces/common/Mining.jsx | 6 +- .../tgui/interfaces/common/Overmap.jsx | 6 +- .../tgui/interfaces/common/PortableAtmos.jsx | 6 +- tgui/packages/tgui/interfaces/pAIAtmos.jsx | 2 +- .../tgui/interfaces/pAIDirectives.tsx | 2 +- tgui/packages/tgui/interfaces/pAIDoorjack.jsx | 2 +- .../packages/tgui/interfaces/pAIInterface.tsx | 2 +- .../tgui/interfaces/pAIMedrecords.jsx | 2 +- .../tgui/interfaces/pAISecrecords.jsx | 2 +- .../tgui/interfaces/pda/pda_main_menu.jsx | 6 +- .../packages/tgui/interfaces/pda/pda_news.jsx | 6 +- tgui/packages/tgui/layouts/Window.jsx | 206 -- tgui/packages/tgui/layouts/Window.tsx | 231 ++ tgui/packages/tgui/package.json | 16 +- tgui/packages/tgui/renderer.ts | 2 +- tgui/packages/tgui/store.ts | 15 - tgui/public/tgui-panel.bundle.css | 2 +- tgui/public/tgui-panel.bundle.js | 398 ++- tgui/public/tgui-polyfill.min.js | 2 +- tgui/public/tgui.bundle.css | 2 +- tgui/public/tgui.bundle.js | 314 +- tgui/public/tgui.html | 1 - tgui/tsconfig.json | 6 +- tgui/webpack.config.js | 5 +- tgui/yarn.lock | 3141 +++++++++-------- 288 files changed, 3840 insertions(+), 5800 deletions(-) create mode 100644 tgui/docs/state-usage.md delete mode 100644 tgui/packages/tgui-polyfill/00-html5shiv.js delete mode 100644 tgui/packages/tgui-polyfill/01-ie8.js delete mode 100644 tgui/packages/tgui-polyfill/02-dom4.js delete mode 100644 tgui/packages/tgui-polyfill/03-css-om.js create mode 100644 tgui/packages/tgui-polyfill/1-misc.js delete mode 100644 tgui/packages/tgui-polyfill/10-misc.js rename tgui/packages/tgui/components/{Chart.jsx => Chart.tsx} (53%) rename tgui/packages/tgui/components/{ProgressBar.jsx => ProgressBar.tsx} (57%) rename tgui/packages/tgui/components/{Tabs.jsx => Tabs.tsx} (67%) delete mode 100644 tgui/packages/tgui/layouts/Window.jsx create mode 100644 tgui/packages/tgui/layouts/Window.tsx diff --git a/tgui/.eslintignore b/tgui/.eslintignore index a59187b933..aa593384cc 100644 --- a/tgui/.eslintignore +++ b/tgui/.eslintignore @@ -3,4 +3,6 @@ /**/*.bundle.* /**/*.chunk.* /**/*.hot-update.* -/packages/inferno/** + +# CHOMPEdit - Until removed +/packages/tgui_ch/** diff --git a/tgui/.eslintrc.yml b/tgui/.eslintrc.yml index c5d190db91..c1bc184189 100644 --- a/tgui/.eslintrc.yml +++ b/tgui/.eslintrc.yml @@ -335,7 +335,7 @@ rules: ## Require or disallow named function expressions # func-names: error ## Enforce the consistent use of either function declarations or expressions - func-style: [error, expression] + # func-style: [error, expression] ## Enforce line breaks between arguments of a function call # function-call-argument-newline: error ## Enforce consistent line breaks inside function parentheses diff --git a/tgui/README.md b/tgui/README.md index ef8a8a35d6..686f8d0a30 100644 --- a/tgui/README.md +++ b/tgui/README.md @@ -16,10 +16,9 @@ If you are completely new to frontend and prefer to **learn by doing**, start wi ### Guides -This project uses **Inferno** - a very fast UI rendering engine with a similar API to React. Take your time to read these guides: +This project uses React. Take your time to read the guide: -- [React guide](https://reactjs.org/docs/hello-world.html) -- [Inferno documentation](https://infernojs.org/docs/guides/components) - highlights differences with React. +- [React guide](https://react.dev/learn) If you were already familiar with an older, Ractive-based tgui, and want to translate concepts between old and new tgui, read this [interface conversion guide](docs/converting-old-tgui-interfaces.md). @@ -137,7 +136,7 @@ Press `F12` or click the green bug to open the KitchenSink interface. This inter playground to test various tgui components. **Layout Debugger.** -Press `F11` to toggle the *layout debugger*. It will show outlines of +Press `F11` to toggle the _layout debugger_. It will show outlines of all tgui elements, which makes it easy to understand how everything comes together, and can reveal certain layout bugs which are not normally visible. diff --git a/tgui/babel.config.js b/tgui/babel.config.js index e702c9a711..69a5a401cc 100644 --- a/tgui/babel.config.js +++ b/tgui/babel.config.js @@ -6,28 +6,36 @@ const createBabelConfig = (options) => { const { presets = [], plugins = [], removeConsole } = options; - // prettier-ignore return { presets: [ - [require.resolve('@babel/preset-typescript'), { - allowDeclareFields: true, - }], - [require.resolve('@babel/preset-env'), { - modules: 'commonjs', - useBuiltIns: 'entry', - corejs: '3', - spec: false, - loose: true, - targets: [], - }], + [ + require.resolve('@babel/preset-typescript'), + { + allowDeclareFields: true, + }, + ], + [ + require.resolve('@babel/preset-env'), + { + modules: 'commonjs', + useBuiltIns: 'entry', + corejs: '3.3.2', + spec: false, + loose: true, + targets: [], + }, + ], + [require.resolve('@babel/preset-react'), { runtime: 'automatic' }], ...presets, ].filter(Boolean), plugins: [ - [require.resolve('@babel/plugin-proposal-class-properties'), { - loose: true, - }], + [ + require.resolve('@babel/plugin-transform-class-properties'), + { + loose: true, + }, + ], require.resolve('@babel/plugin-transform-jscript'), - require.resolve('babel-plugin-inferno'), removeConsole && require.resolve('babel-plugin-transform-remove-console'), require.resolve('common/string.babel-plugin.cjs'), ...plugins, diff --git a/tgui/docs/component-reference.md b/tgui/docs/component-reference.md index 05ec6ef56f..91462ed63f 100644 --- a/tgui/docs/component-reference.md +++ b/tgui/docs/component-reference.md @@ -65,19 +65,13 @@ it is used a lot in this framework. **Event handlers.** Event handlers are callbacks that you can attack to various element to -listen for browser events. Inferno supports camelcase (`onClick`) and -lowercase (`onclick`) event names. +listen for browser events. React supports camelcase (`onClick`) event names. - Camel case names are what's called *synthetic* events, and are the **preferred way** of handling events in React, for efficiency and performance reasons. Please read -[Inferno Event Handling](https://infernojs.org/docs/guides/event-handling) +[React Event Handling](https://react.dev/learn/responding-to-events) to understand what this is about. -- Lower case names are native browser events and should be used sparingly, -for example when you need an explicit IE8 support. **DO NOT** use -lowercase event handlers unless you really know what you are doing. -- [Button](#button) component does not support the lowercase `onclick` event. -Use the camel case `onClick` instead. ## `tgui/components` @@ -746,7 +740,7 @@ Popper lets you position elements so that they don't go out of the bounds of the **Props:** -- `popperContent: InfernoNode` - The content that will be put inside the popper. +- `popperContent: ReactNode` - The content that will be put inside the popper. - `options?: { ... }` - An object of options to pass to `createPopper`. See [https://popper.js.org/docs/v2/constructors/#options], but the one you want most is `placement`. Valid placements are "bottom", "top", "left", and "right". You can affix "-start" and "-end" to achieve something like top left or top right respectively. You can also use "auto" (with an optional "-start" or "-end"), where a best fit will be chosen. - `additionalStyles: { ... }` - A map of CSS styles to add to the element that will contain the popper. diff --git a/tgui/docs/state-usage.md b/tgui/docs/state-usage.md new file mode 100644 index 0000000000..da3162554b --- /dev/null +++ b/tgui/docs/state-usage.md @@ -0,0 +1,38 @@ +# Managing component state + +React has excellent documentation on useState and useEffect. These hooks should be the ways to manage state in TGUI (v5). +[React Hooks](https://react.dev/learn/state-a-components-memory) + +You might find usages of useLocalState. This should be considered deprecated and will be removed in the future. In older versions of TGUI, InfernoJS did not have hooks, so these were used to manage state. useSharedState is still used in some places where uis are considered "IC" and user input is shared with all persons at the console/machine/thing. + +## A Note on State + +Many beginners tend to overuse state (or hooks all together). State is effective when you want to implement user interactivity, or are handling asynchronous data, but if you are simply using state to store a value that is not changing, you should consider using a variable instead. + +In previous versions of React, each setState would trigger a re-render, which would cause poorly written components to cascade re-render on each page load. Messy! Though this is no longer the case with batch rendering, it's still worthwhile to point out that you might be overusing it. + +## Derived state + +One great way to cut back on state usage is by using props or other state as the basis for a variable. You'll see many examples of this in the TGUI codebase. What does this mean? Here's an example: + +```tsx +// Bad +const [count, setCount] = useState(0); +const [isEven, setIsEven] = useState(false); + +useEffect(() => { + setIsEven(count % 2 === 0); +}, [count]); + +// Good! +const [count, setCount] = useState(0); +const isEven = count % 2 === 0; // Derived state +``` +1 change: 1 addition & 0 deletions 1 +tgui/packages/tgui/backend.ts +Viewed +@@ -316,6 +316,7 @@ type StateWithSetter = [T, (nextState: T) => void]; + * @param context React context. + * @param key Key which uniquely identifies this state in Redux store. + * @param initialState Initializes your global variable with this value. + * diff --git a/tgui/package.json b/tgui/package.json index a3bdcb4d90..5f1b0c51b3 100644 --- a/tgui/package.json +++ b/tgui/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "tgui-workspace", - "version": "4.3.1", + "version": "5.0.0", "packageManager": "yarn@3.3.1", "workspaces": [ "packages/*" @@ -20,43 +20,44 @@ "tgui:tsc": "tsc" }, "dependencies": { - "@babel/core": "^7.18.0", - "@babel/eslint-parser": "^7.17.0", - "@babel/plugin-proposal-class-properties": "^7.17.12", - "@babel/plugin-transform-jscript": "^7.17.12", - "@babel/preset-env": "^7.18.0", - "@babel/preset-typescript": "^7.17.12", - "@types/jest": "^27.5.1", - "@types/jsdom": "^16.2.14", + "@babel/core": "^7.23.3", + "@babel/eslint-parser": "^7.23.3", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-jscript": "^7.23.3", + "@babel/preset-env": "^7.23.3", + "@babel/preset-react": "^7.23.3", + "@babel/preset-typescript": "^7.23.3", + "@types/jest": "^29.5.10", + "@types/jsdom": "^21.1.6", "@types/node": "^14.x", - "@types/webpack": "^5.28.0", - "@types/webpack-env": "^1.17.0", - "@typescript-eslint/parser": "^5.25.0", - "babel-jest": "^28.1.0", - "babel-loader": "^8.2.5", - "babel-plugin-inferno": "^6.4.0", + "@types/webpack": "^5.28.5", + "@types/webpack-env": "^1.18.4", + "@typescript-eslint/parser": "^5.62.0", + "babel-jest": "^29.7.0", + "babel-loader": "^8.3.0", "babel-plugin-transform-remove-console": "^6.9.4", "common": "workspace:*", - "css-loader": "^6.7.1", + "css-loader": "^6.8.1", "esbuild-loader": "^4.0.2", - "eslint": "^8.16.0", - "eslint-config-prettier": "^8.5.0", + "eslint": "^7.32.0", + "eslint-config-prettier": "^9.0.0", "eslint-plugin-radar": "^0.2.1", - "eslint-plugin-react": "^7.30.0", - "eslint-plugin-unused-imports": "^2.0.0", - "inferno": "^7.4.11", - "jest": "^28.1.0", - "jest-circus": "^28.1.0", - "jest-environment-jsdom": "^28.1.0", - "jsdom": "^19.0.0", - "mini-css-extract-plugin": "^2.6.0", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-unused-imports": "^1.1.5", + "file-loader": "^6.2.0", + "jest": "^29.7.0", + "jest-circus": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jsdom": "^22.1.0", + "mini-css-extract-plugin": "^2.7.6", "prettier": "npm:prettierx@0.19.0", - "sass": "^1.52.1", - "sass-loader": "^13.0.0", - "style-loader": "^3.3.1", - "typescript": "^4.6.4", - "webpack": "^5.76.0", - "webpack-bundle-analyzer": "^4.5.0", - "webpack-cli": "^4.9.2" + "sass": "^1.69.5", + "sass-loader": "^13.3.2", + "style-loader": "^3.3.3", + "typescript": "^4.9.4", + "url-loader": "^4.1.1", + "webpack": "^5.89.0", + "webpack-bundle-analyzer": "^4.10.1", + "webpack-cli": "^5.1.4" } } diff --git a/tgui/packages/common/keys.ts b/tgui/packages/common/keys.ts index 61b79992b4..34ac9e1614 100644 --- a/tgui/packages/common/keys.ts +++ b/tgui/packages/common/keys.ts @@ -22,18 +22,18 @@ export enum KEY { Backspace = 'Backspace', Control = 'Control', Delete = 'Delete', - Down = 'Down', + Down = 'ArrowDown', End = 'End', Enter = 'Enter', - Escape = 'Esc', + Escape = 'Escape', Home = 'Home', Insert = 'Insert', - Left = 'Left', + Left = 'ArrowLeft', PageDown = 'PageDown', PageUp = 'PageUp', - Right = 'Right', + Right = 'ArrowRight', Shift = 'Shift', Space = ' ', Tab = 'Tab', - Up = 'Up', + Up = 'ArrowUp', } diff --git a/tgui/packages/common/react.ts b/tgui/packages/common/react.ts index 8e42d0971a..5260ff6ae1 100644 --- a/tgui/packages/common/react.ts +++ b/tgui/packages/common/react.ts @@ -52,13 +52,10 @@ export const shallowDiffers = (a: object, b: object) => { }; /** - * Default inferno hooks for pure components. + * A common case in tgui, when you pass a value conditionally, these are + * the types that can fall through the condition. */ -export const pureComponentHooks = { - onComponentShouldUpdate: (lastProps, nextProps) => { - return shallowDiffers(lastProps, nextProps); - }, -}; +export type BooleanLike = number | boolean | null | undefined; /** * A helper to determine whether the object is renderable by React. @@ -69,9 +66,3 @@ export const canRender = (value: unknown) => { && value !== null && typeof value !== 'boolean'; }; - -/** - * A common case in tgui, when you pass a value conditionally, these are - * the types that can fall through the condition. - */ -export type BooleanLike = number | boolean | null | undefined; diff --git a/tgui/packages/common/redux.ts b/tgui/packages/common/redux.ts index 1635853c6b..7b4999d93b 100644 --- a/tgui/packages/common/redux.ts +++ b/tgui/packages/common/redux.ts @@ -194,23 +194,3 @@ export const createAction = ( return actionCreator; }; - -// Implementation specific -// -------------------------------------------------------- - -export const useDispatch = (context: { - store: Store; -}): Dispatch => { - return context?.store?.dispatch; -}; - -export const useSelector = ( - context: { store: Store }, - selector: (state: State) => Selected -): Selected => { - if (!context) { - return {} as Selected; - } - - return selector(context?.store?.getState()); -}; diff --git a/tgui/packages/tgui-bench/package.json b/tgui/packages/tgui-bench/package.json index 6e4083ba63..47cad082fb 100644 --- a/tgui/packages/tgui-bench/package.json +++ b/tgui/packages/tgui-bench/package.json @@ -1,15 +1,14 @@ { "private": true, "name": "tgui-bench", - "version": "4.3.0", + "version": "5.0.0", "dependencies": { - "@fastify/static": "^5.0.2", + "@fastify/static": "^6.12.0", "common": "workspace:*", - "fastify": "^3.29.4", - "inferno": "^7.4.8", - "inferno-vnode-flags": "^7.4.8", + "fastify": "^3.29.5", "lodash": "^4.17.21", "platform": "^1.3.6", + "react": "^18.2.0", "tgui": "workspace:*" } } diff --git a/tgui/packages/tgui-bench/tests/Button.test.tsx b/tgui/packages/tgui-bench/tests/Button.test.tsx index 6b806d720a..0549e69b62 100644 --- a/tgui/packages/tgui-bench/tests/Button.test.tsx +++ b/tgui/packages/tgui-bench/tests/Button.test.tsx @@ -1,11 +1,8 @@ -import { linkEvent } from 'inferno'; import { Button } from 'tgui/components'; import { createRenderer } from 'tgui/renderer'; const render = createRenderer(); -const handleClick = () => undefined; - export const SingleButton = () => { const node = ; render(node); @@ -16,13 +13,6 @@ export const SingleButtonWithCallback = () => { render(node); }; -export const SingleButtonWithLinkEvent = () => { - const node = ( - - ); - render(node); -}; - export const ListOfButtons = () => { const nodes: JSX.Element[] = []; for (let i = 0; i < 100; i++) { @@ -45,19 +35,6 @@ export const ListOfButtonsWithCallback = () => { render(
{nodes}
); }; -export const ListOfButtonsWithLinkEvent = () => { - const nodes: JSX.Element[] = []; - for (let i = 0; i < 100; i++) { - const node = ( - - ); - nodes.push(node); - } - render(
{nodes}
); -}; - export const ListOfButtonsWithIcons = () => { const nodes: JSX.Element[] = []; for (let i = 0; i < 100; i++) { diff --git a/tgui/packages/tgui-bench/tests/DisposalBin.test.tsx b/tgui/packages/tgui-bench/tests/DisposalBin.test.tsx index 5ac9965c76..c212ace895 100644 --- a/tgui/packages/tgui-bench/tests/DisposalBin.test.tsx +++ b/tgui/packages/tgui-bench/tests/DisposalBin.test.tsx @@ -1,22 +1,20 @@ -import { StoreProvider, configureStore } from 'tgui/store'; +import { configureStore } from 'tgui/store'; import { DisposalBin } from 'tgui/interfaces/DisposalBin'; -import { backendUpdate } from 'tgui/backend'; +import { backendUpdate, setGlobalStore } from 'tgui/backend'; import { createRenderer } from 'tgui/renderer'; const store = configureStore({ sideEffects: false }); const renderUi = createRenderer((dataJson: string) => { + setGlobalStore(store); + store.dispatch( backendUpdate({ data: Byond.parseJson(dataJson), }) ); - return ( - - - - ); + return ; }); export const data = JSON.stringify({ diff --git a/tgui/packages/tgui-dev-server/package.json b/tgui/packages/tgui-dev-server/package.json index 491f30a343..496e25c6c1 100644 --- a/tgui/packages/tgui-dev-server/package.json +++ b/tgui/packages/tgui-dev-server/package.json @@ -1,13 +1,13 @@ { "private": true, "name": "tgui-dev-server", - "version": "4.4.1", + "version": "5.0.0", "type": "module", "dependencies": { - "axios": "^1.6.0", - "glob": "^7.1.7", - "source-map": "^0.7.3", + "axios": "^1.6.2", + "glob": "^7.2.0", + "source-map": "^0.7.4", "stacktrace-parser": "^0.1.10", - "ws": "^7.5.3" + "ws": "^8.14.2" } } diff --git a/tgui/packages/tgui-panel/Panel.tsx b/tgui/packages/tgui-panel/Panel.tsx index 8171333866..0f47336cba 100644 --- a/tgui/packages/tgui-panel/Panel.tsx +++ b/tgui/packages/tgui-panel/Panel.tsx @@ -14,13 +14,13 @@ import { PingIndicator } from './ping'; import { ReconnectButton } from './reconnect'; import { SettingsPanel, useSettings } from './settings'; -export const Panel = (props, context) => { - const audio = useAudio(context); - const settings = useSettings(context); - const game = useGame(context); +export const Panel = (props) => { + const audio = useAudio(); + const settings = useSettings(); + const game = useGame(); if (process.env.NODE_ENV !== 'production') { const { useDebug, KitchenSink } = require('tgui/debug'); - const debug = useDebug(context); + const debug = useDebug(); if (debug.kitchenSink) { return ; } diff --git a/tgui/packages/tgui-panel/audio/NowPlayingWidget.jsx b/tgui/packages/tgui-panel/audio/NowPlayingWidget.jsx index 30052c3f3a..8260ee8c23 100644 --- a/tgui/packages/tgui-panel/audio/NowPlayingWidget.jsx +++ b/tgui/packages/tgui-panel/audio/NowPlayingWidget.jsx @@ -5,15 +5,15 @@ */ import { toFixed } from 'common/math'; -import { useDispatch, useSelector } from 'common/redux'; +import { useDispatch, useSelector } from 'tgui/backend'; import { Button, Collapsible, Flex, Knob, Section } from 'tgui/components'; import { useSettings } from '../settings'; import { selectAudio } from './selectors'; -export const NowPlayingWidget = (props, context) => { - const audio = useSelector(context, selectAudio), - dispatch = useDispatch(context), - settings = useSettings(context), +export const NowPlayingWidget = (props) => { + const audio = useSelector(selectAudio), + dispatch = useDispatch(), + settings = useSettings(), title = audio.meta?.title, URL = audio.meta?.link, Artist = audio.meta?.artist || 'Unknown Artist', @@ -35,9 +35,9 @@ export const NowPlayingWidget = (props, context) => { mx={0.5} grow={1} style={{ - 'white-space': 'nowrap', - 'overflow': 'hidden', - 'text-overflow': 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', }}> { diff --git a/tgui/packages/tgui-panel/audio/hooks.ts b/tgui/packages/tgui-panel/audio/hooks.ts index 504b4f5c6e..1286754a37 100644 --- a/tgui/packages/tgui-panel/audio/hooks.ts +++ b/tgui/packages/tgui-panel/audio/hooks.ts @@ -4,12 +4,12 @@ * @license MIT */ -import { useSelector, useDispatch } from 'common/redux'; +import { useSelector, useDispatch } from 'tgui/backend'; import { selectAudio } from './selectors'; -export const useAudio = (context) => { - const state = useSelector(context, selectAudio); - const dispatch = useDispatch(context); +export const useAudio = () => { + const state = useSelector(selectAudio); + const dispatch = useDispatch(); return { ...state, toggle: () => dispatch({ type: 'audio/toggle' }), diff --git a/tgui/packages/tgui-panel/chat/ChatPageSettings.jsx b/tgui/packages/tgui-panel/chat/ChatPageSettings.jsx index 2ccc491d95..b451efbe93 100644 --- a/tgui/packages/tgui-panel/chat/ChatPageSettings.jsx +++ b/tgui/packages/tgui-panel/chat/ChatPageSettings.jsx @@ -4,15 +4,15 @@ * @license MIT */ -import { useDispatch, useSelector } from 'common/redux'; +import { useDispatch, useSelector } from 'tgui/backend'; import { Button, Collapsible, Divider, Input, Section, Stack } from 'tgui/components'; import { moveChatPageLeft, moveChatPageRight, removeChatPage, toggleAcceptedType, updateChatPage } from './actions'; import { MESSAGE_TYPES } from './constants'; import { selectCurrentChatPage } from './selectors'; -export const ChatPageSettings = (props, context) => { - const page = useSelector(context, selectCurrentChatPage); - const dispatch = useDispatch(context); +export const ChatPageSettings = (props) => { + const page = useSelector(selectCurrentChatPage); + const dispatch = useDispatch(); return (
diff --git a/tgui/packages/tgui-panel/chat/ChatPanel.jsx b/tgui/packages/tgui-panel/chat/ChatPanel.jsx index 3132a66ce7..166705361f 100644 --- a/tgui/packages/tgui-panel/chat/ChatPanel.jsx +++ b/tgui/packages/tgui-panel/chat/ChatPanel.jsx @@ -5,13 +5,13 @@ */ import { shallowDiffers } from 'common/react'; -import { Component, createRef } from 'inferno'; +import { Component, createRef } from 'react'; import { Button } from 'tgui/components'; import { chatRenderer } from './renderer'; export class ChatPanel extends Component { - constructor() { - super(); + constructor(props) { + super(props); this.ref = createRef(); this.state = { scrollTracking: true, @@ -46,7 +46,7 @@ export class ChatPanel extends Component { !prevProps || shallowDiffers(this.props, prevProps); if (shouldUpdateStyle) { chatRenderer.assignStyle({ - 'width': '100%', + width: '100%', 'white-space': 'pre-wrap', 'font-size': this.props.fontSize, 'line-height': this.props.lineHeight, diff --git a/tgui/packages/tgui-panel/chat/ChatTabs.jsx b/tgui/packages/tgui-panel/chat/ChatTabs.jsx index 1d4f6f65ed..04d5f25b4b 100644 --- a/tgui/packages/tgui-panel/chat/ChatTabs.jsx +++ b/tgui/packages/tgui-panel/chat/ChatTabs.jsx @@ -4,7 +4,7 @@ * @license MIT */ -import { useDispatch, useSelector } from 'common/redux'; +import { useDispatch, useSelector } from 'tgui/backend'; import { Box, Tabs, Flex, Button } from 'tgui/components'; import { changeChatPage, addChatPage } from './actions'; import { selectChatPages, selectCurrentChatPage } from './selectors'; @@ -13,21 +13,21 @@ import { openChatSettings } from '../settings/actions'; const UnreadCountWidget = ({ value }) => ( {Math.min(value, 99)} ); -export const ChatTabs = (props, context) => { - const pages = useSelector(context, selectChatPages); - const currentPage = useSelector(context, selectCurrentChatPage); - const dispatch = useDispatch(context); +export const ChatTabs = (props) => { + const pages = useSelector(selectChatPages); + const currentPage = useSelector(selectCurrentChatPage); + const dispatch = useDispatch(); return ( diff --git a/tgui/packages/tgui-panel/chat/renderer.jsx b/tgui/packages/tgui-panel/chat/renderer.jsx index 3b060548bb..a2bfba6d2e 100644 --- a/tgui/packages/tgui-panel/chat/renderer.jsx +++ b/tgui/packages/tgui-panel/chat/renderer.jsx @@ -8,7 +8,7 @@ import { EventEmitter } from 'common/events'; import { classes } from 'common/react'; import { createLogger } from 'tgui/logging'; import { IMAGE_RETRY_DELAY, IMAGE_RETRY_LIMIT, IMAGE_RETRY_MESSAGE_AGE, MESSAGE_PRUNE_INTERVAL, MESSAGE_TYPES, MESSAGE_TYPE_INTERNAL, MESSAGE_TYPE_UNKNOWN } from './constants'; -import { render } from 'inferno'; +import { render } from 'react-dom'; import { canPageAcceptType, createMessage, isSameMessage, serializeMessage } from './model'; import { highlightNode, linkifyNode } from './replaceInTextNode'; import { Tooltip } from '../../tgui/components'; diff --git a/tgui/packages/tgui-panel/game/hooks.ts b/tgui/packages/tgui-panel/game/hooks.ts index 859aaa09a4..c3e7c06284 100644 --- a/tgui/packages/tgui-panel/game/hooks.ts +++ b/tgui/packages/tgui-panel/game/hooks.ts @@ -4,9 +4,9 @@ * @license MIT */ -import { useSelector } from 'common/redux'; +import { useSelector } from 'tgui/backend'; import { selectGame } from './selectors'; -export const useGame = (context) => { - return useSelector(context, selectGame); +export const useGame = () => { + return useSelector(selectGame); }; diff --git a/tgui/packages/tgui-panel/index.tsx b/tgui/packages/tgui-panel/index.tsx index 2c5ef175a8..e2f3794fff 100644 --- a/tgui/packages/tgui-panel/index.tsx +++ b/tgui/packages/tgui-panel/index.tsx @@ -15,7 +15,7 @@ import { setupHotReloading } from 'tgui-dev-server/link/client.cjs'; import { setupGlobalEvents } from 'tgui/events'; import { captureExternalLinks } from 'tgui/links'; import { createRenderer } from 'tgui/renderer'; -import { configureStore, StoreProvider } from 'tgui/store'; +import { configureStore } from 'tgui/store'; import { audioMiddleware, audioReducer } from './audio'; import { chatMiddleware, chatReducer } from './chat'; import { gameMiddleware, gameReducer } from './game'; @@ -52,11 +52,7 @@ const renderApp = createRenderer(() => { setGlobalStore(store); const { Panel } = require('./Panel'); - return ( - - - - ); + return ; }); const setupApp = () => { diff --git a/tgui/packages/tgui-panel/package.json b/tgui/packages/tgui-panel/package.json index 7aab57e169..f020764a31 100644 --- a/tgui/packages/tgui-panel/package.json +++ b/tgui/packages/tgui-panel/package.json @@ -6,8 +6,9 @@ "@types/node": "^14.x", "@types/react": "^18.2.42", "common": "workspace:*", - "dompurify": "^2.3.1", - "inferno": "^7.4.8", + "dompurify": "^2.4.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", "tgui": "workspace:*", "tgui-dev-server": "workspace:*", "tgui-polyfill": "workspace:*" diff --git a/tgui/packages/tgui-panel/ping/PingIndicator.jsx b/tgui/packages/tgui-panel/ping/PingIndicator.jsx index aadbd1c134..b2355820e5 100644 --- a/tgui/packages/tgui-panel/ping/PingIndicator.jsx +++ b/tgui/packages/tgui-panel/ping/PingIndicator.jsx @@ -6,12 +6,12 @@ import { Color } from 'common/color'; import { toFixed } from 'common/math'; -import { useSelector } from 'common/redux'; +import { useSelector } from 'tgui/backend'; import { Box } from 'tgui/components'; import { selectPing } from './selectors'; -export const PingIndicator = (props, context) => { - const ping = useSelector(context, selectPing); +export const PingIndicator = (props) => { + const ping = useSelector(selectPing); const color = Color.lookup(ping.networkQuality, [ new Color(220, 40, 40), new Color(220, 200, 40), diff --git a/tgui/packages/tgui-panel/reconnect.tsx b/tgui/packages/tgui-panel/reconnect.tsx index 589bc7f110..6793125be2 100644 --- a/tgui/packages/tgui-panel/reconnect.tsx +++ b/tgui/packages/tgui-panel/reconnect.tsx @@ -1,5 +1,5 @@ import { Button } from 'tgui/components'; -import { useDispatch } from 'common/redux'; +import { useDispatch } from 'tgui/backend'; import { dismissWarning } from './game/actions'; let url: string | null = null; @@ -13,11 +13,11 @@ setInterval(() => { }); }, 5000); -export const ReconnectButton = (props, context) => { +export const ReconnectButton = (props) => { if (!url) { return null; } - const dispatch = useDispatch(context); + const dispatch = useDispatch(); return ( <>
- + ); }; diff --git a/tgui/packages/tgui/interfaces/AdminShuttleController.tsx b/tgui/packages/tgui/interfaces/AdminShuttleController.tsx index 167e1ddf92..eda0459404 100644 --- a/tgui/packages/tgui/interfaces/AdminShuttleController.tsx +++ b/tgui/packages/tgui/interfaces/AdminShuttleController.tsx @@ -22,7 +22,7 @@ type OvermapShip = { export const AdminShuttleController = () => { return ( - + diff --git a/tgui/packages/tgui/interfaces/AiAirlock.jsx b/tgui/packages/tgui/interfaces/AiAirlock.jsx index 11a5e11380..4d9fc3a70f 100644 --- a/tgui/packages/tgui/interfaces/AiAirlock.jsx +++ b/tgui/packages/tgui/interfaces/AiAirlock.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; @@ -66,7 +66,7 @@ export const AiAirlock = (props) => { label="Electrify" color={statusElectrify.color} buttons={ - + <> - + }> {occupant.name} @@ -211,7 +211,7 @@ const BodyScannerMainReagents = (props) => { const { occupant } = props; return ( - + <>
{occupant.reagents ? ( @@ -254,7 +254,7 @@ const BodyScannerMainReagents = (props) => { No Stomach Reagents Detected )} - + ); }; @@ -305,7 +305,7 @@ const BodyScannerMainDamage = (props) => {
{mapTwoByTwo(damages, (d1, d2, i) => ( - + <> {d1[0]}: {!!d2 && d2[0] + ':'} @@ -321,7 +321,7 @@ const BodyScannerMainDamage = (props) => { {!!d2 && } - + ))}
diff --git a/tgui/packages/tgui/interfaces/BombTester.jsx b/tgui/packages/tgui/interfaces/BombTester.jsx index 0d7c7c81b9..b67f0d141e 100644 --- a/tgui/packages/tgui/interfaces/BombTester.jsx +++ b/tgui/packages/tgui/interfaces/BombTester.jsx @@ -1,4 +1,4 @@ -import { Component } from 'inferno'; +import { Component } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Icon, LabeledList, Section, Slider } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/BotanyEditor.jsx b/tgui/packages/tgui/interfaces/BotanyEditor.jsx index 89ce6f8741..0b148e155a 100644 --- a/tgui/packages/tgui/interfaces/BotanyEditor.jsx +++ b/tgui/packages/tgui/interfaces/BotanyEditor.jsx @@ -9,7 +9,7 @@ export const BotanyEditor = (props) => { if (activity) { return ( - + Scanning... @@ -18,7 +18,7 @@ export const BotanyEditor = (props) => { } return ( - +
{(disk && ( diff --git a/tgui/packages/tgui/interfaces/BotanyIsolator.jsx b/tgui/packages/tgui/interfaces/BotanyIsolator.jsx index e1020b6153..6eb865e33f 100644 --- a/tgui/packages/tgui/interfaces/BotanyIsolator.jsx +++ b/tgui/packages/tgui/interfaces/BotanyIsolator.jsx @@ -17,7 +17,7 @@ export const BotanyIsolator = (props) => { if (activity) { return ( - + Scanning... @@ -26,7 +26,7 @@ export const BotanyIsolator = (props) => { } return ( - +
{(hasGenetics && ( diff --git a/tgui/packages/tgui/interfaces/BrigTimer.jsx b/tgui/packages/tgui/interfaces/BrigTimer.jsx index 7ef7910cf9..0dd4a4a82e 100644 --- a/tgui/packages/tgui/interfaces/BrigTimer.jsx +++ b/tgui/packages/tgui/interfaces/BrigTimer.jsx @@ -1,5 +1,5 @@ import { round } from 'common/math'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Button, Section, NumberInput, Flex } from '../components'; import { Window } from '../layouts'; @@ -8,12 +8,12 @@ import { formatTime } from '../format'; export const BrigTimer = (props) => { const { act, data } = useBackend(); return ( - +
+ <>
diff --git a/tgui/packages/tgui/interfaces/ChemMaster.jsx b/tgui/packages/tgui/interfaces/ChemMaster.jsx index 65d716fdd2..588e6a3526 100644 --- a/tgui/packages/tgui/interfaces/ChemMaster.jsx +++ b/tgui/packages/tgui/interfaces/ChemMaster.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Flex, Icon, LabeledList, Section } from '../components'; import { Window } from '../layouts'; @@ -30,7 +30,7 @@ const analyzeModalBodyOverride = (modal) => { {(result.desc || '').length > 0 ? result.desc : 'N/A'} {result.blood_type && ( - + <> {result.blood_type} @@ -39,7 +39,7 @@ const analyzeModalBodyOverride = (modal) => { className="LabeledList__breakContents"> {result.blood_dna} - + )} {!data.condi && ( - + }> diff --git a/tgui/packages/tgui/interfaces/DNAModifier.jsx b/tgui/packages/tgui/interfaces/DNAModifier.jsx index 85955c8ada..eaa4a94d84 100644 --- a/tgui/packages/tgui/interfaces/DNAModifier.jsx +++ b/tgui/packages/tgui/interfaces/DNAModifier.jsx @@ -1,4 +1,3 @@ -import { Fragment } from 'inferno'; import { useBackend } from '../backend'; import { Box, Button, Dimmer, Flex, Icon, Knob, LabeledList, ProgressBar, Section, Tabs } from '../components'; import { Window } from '../layouts'; @@ -32,7 +31,7 @@ export const DNAModifier = (props) => { radiatingModal = ; } return ( - + {radiatingModal} @@ -50,7 +49,7 @@ const DNAModifierOccupant = (props) => {
+ <> Door Lock: @@ -67,10 +66,10 @@ const DNAModifierOccupant = (props) => { content="Eject" onClick={() => act('ejectOccupant')} /> - + }> {hasOccupant ? ( - + <> {occupant.name} @@ -120,7 +119,7 @@ const DNAModifierOccupant = (props) => { )} - + ) : ( Cell unoccupied. )} @@ -159,17 +158,17 @@ const DNAModifierMain = (props) => { let body; if (selectedMenuKey === 'ui') { body = ( - + <> - + ); } else if (selectedMenuKey === 'se') { body = ( - + <> - + ); } else if (selectedMenuKey === 'buffer') { body = ; @@ -305,12 +304,12 @@ const DNAModifierMainBuffers = (props) => { /> )); return ( - + <>
{bufferElements}
-
+ ); }; @@ -327,7 +326,7 @@ const DNAModifierMainBuffersElement = (props) => { mx="0" lineHeight="18px" buttons={ - + <> { }) } /> - + }> @@ -413,8 +412,8 @@ const DNAModifierMainBuffersElement = (props) => { } /> - {buffer.data ? ( - + {!!buffer.data && ( + <> {buffer.owner || Unknown} @@ -464,8 +463,8 @@ const DNAModifierMainBuffersElement = (props) => { } /> - - ) : null} + + )} {!buffer.data && ( @@ -485,7 +484,7 @@ const DNAModifierMainBuffersDisk = (props) => { title="Data Disk" level="2" buttons={ - + <> { content="Eject" onClick={() => act('ejectDisk')} /> - + }> {hasDisk ? ( disk.data ? ( diff --git a/tgui/packages/tgui/interfaces/DestinationTagger.jsx b/tgui/packages/tgui/interfaces/DestinationTagger.jsx index 50e189aefb..f52357d263 100644 --- a/tgui/packages/tgui/interfaces/DestinationTagger.jsx +++ b/tgui/packages/tgui/interfaces/DestinationTagger.jsx @@ -8,7 +8,7 @@ export const DestinationTagger = (props) => { const { currTag, taggerLocs } = data; return ( - +
diff --git a/tgui/packages/tgui/interfaces/DiseaseSplicer.jsx b/tgui/packages/tgui/interfaces/DiseaseSplicer.jsx index 6a7c33c644..92e2c997ad 100644 --- a/tgui/packages/tgui/interfaces/DiseaseSplicer.jsx +++ b/tgui/packages/tgui/interfaces/DiseaseSplicer.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; @@ -18,10 +18,10 @@ export const DiseaseSplicer = (props) => {
) : ( - + <> - + )}
@@ -63,7 +63,7 @@ const DiseaseSplicerVirusDish = (props) => { {info}
) : ( - + <>
{(effects && effects.map((effect) => ( @@ -95,7 +95,7 @@ const DiseaseSplicerVirusDish = (props) => { onClick={() => act('affected_species')} />
-
+ )}
); diff --git a/tgui/packages/tgui/interfaces/DishIncubator.jsx b/tgui/packages/tgui/interfaces/DishIncubator.jsx index 4f2770ae91..b7d79c6c65 100644 --- a/tgui/packages/tgui/interfaces/DishIncubator.jsx +++ b/tgui/packages/tgui/interfaces/DishIncubator.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { formatCommaNumber } from '../format'; import { useBackend } from '../backend'; import { Box, Button, Flex, LabeledList, ProgressBar, Section } from '../components'; @@ -100,7 +100,7 @@ export const DishIncubator = (props) => {
+ <>
- + ); }; primaryRoutes['DockingConsoleMulti'] = DockingConsoleMulti; @@ -646,7 +646,7 @@ const DoorAccessConsole = (props) => {
+ <> {/* Interior Button */}
); diff --git a/tgui/packages/tgui/interfaces/GeneralRecords.jsx b/tgui/packages/tgui/interfaces/GeneralRecords.jsx index f11cc72688..863e8b05a9 100644 --- a/tgui/packages/tgui/interfaces/GeneralRecords.jsx +++ b/tgui/packages/tgui/interfaces/GeneralRecords.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend, useLocalState } from '../backend'; import { Box, Button, Icon, Input, LabeledList, Section, Tabs } from '../components'; import { ComplexModal, modalOpen } from './common/ComplexModal'; @@ -22,7 +22,7 @@ export const GeneralRecords = (_properties) => { const { authenticated, screen } = data; if (!authenticated) { return ( - + @@ -43,7 +43,7 @@ export const GeneralRecords = (_properties) => { } return ( - + @@ -83,7 +83,7 @@ const GeneralRecordsList = (_properties) => { const records = selectRecords(data.records, searchText); return ( - + <>
-
+ ); }; @@ -171,7 +171,7 @@ const GeneralRecordsViewGeneral = (_properties) => { ); } return ( - + <> {general.fields.map((field, i) => ( @@ -240,7 +240,7 @@ const GeneralRecordsViewGeneral = (_properties) => { ))} - + ); }; diff --git a/tgui/packages/tgui/interfaces/Gps.jsx b/tgui/packages/tgui/interfaces/Gps.jsx index b2f4c2c401..491e4018b8 100644 --- a/tgui/packages/tgui/interfaces/Gps.jsx +++ b/tgui/packages/tgui/interfaces/Gps.jsx @@ -2,7 +2,7 @@ import { map, sortBy } from 'common/collections'; import { flow } from 'common/fp'; import { clamp } from 'common/math'; import { vecLength, vecSubtract } from 'common/vector'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Icon, LabeledList, Section, Table } from '../components'; import { Window } from '../layouts'; @@ -37,11 +37,7 @@ export const Gps = (props) => { ), ])(data.signals || []); return ( - +
{
{!!power && ( - + <>
{currentArea} ({currentCoordsText}) @@ -121,7 +117,7 @@ export const Gps = (props) => { ))}
-
+ )}
diff --git a/tgui/packages/tgui/interfaces/GravityGenerator.jsx b/tgui/packages/tgui/interfaces/GravityGenerator.jsx index a0023627c8..f901542ffc 100644 --- a/tgui/packages/tgui/interfaces/GravityGenerator.jsx +++ b/tgui/packages/tgui/interfaces/GravityGenerator.jsx @@ -17,7 +17,7 @@ export const GravityGenerator = (props) => { } return ( - +
{ data; return ( - + {(mode === 1 && (
( - + diff --git a/tgui/packages/tgui/interfaces/Holodeck.jsx b/tgui/packages/tgui/interfaces/Holodeck.jsx index 2b36e0602f..81738cefe6 100644 --- a/tgui/packages/tgui/interfaces/Holodeck.jsx +++ b/tgui/packages/tgui/interfaces/Holodeck.jsx @@ -22,7 +22,7 @@ export const Holodeck = (props) => { } return ( - +
{programsToShow.map((prog) => ( diff --git a/tgui/packages/tgui/interfaces/ICAssembly.jsx b/tgui/packages/tgui/interfaces/ICAssembly.jsx index 8ed2a364f3..402b6b542d 100644 --- a/tgui/packages/tgui/interfaces/ICAssembly.jsx +++ b/tgui/packages/tgui/interfaces/ICAssembly.jsx @@ -20,7 +20,7 @@ export const ICAssembly = (props) => { } = data; return ( - +
diff --git a/tgui/packages/tgui/interfaces/ICCircuit.jsx b/tgui/packages/tgui/interfaces/ICCircuit.jsx index 2fba659237..1e43c42ae1 100644 --- a/tgui/packages/tgui/interfaces/ICCircuit.jsx +++ b/tgui/packages/tgui/interfaces/ICCircuit.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Flex, LabeledList, Section } from '../components'; import { Window } from '../layouts'; @@ -28,11 +28,11 @@ export const ICCircuit = (props) => {
+ <> - + }> {complexity} diff --git a/tgui/packages/tgui/interfaces/IDCard.jsx b/tgui/packages/tgui/interfaces/IDCard.jsx index 2b9dfbb9dc..a6a122eb56 100644 --- a/tgui/packages/tgui/interfaces/IDCard.jsx +++ b/tgui/packages/tgui/interfaces/IDCard.jsx @@ -28,7 +28,7 @@ export const IDCard = (props) => { ]; return ( - +
diff --git a/tgui/packages/tgui/interfaces/IdentificationComputer.jsx b/tgui/packages/tgui/interfaces/IdentificationComputer.jsx index bb33accea7..c81122848f 100644 --- a/tgui/packages/tgui/interfaces/IdentificationComputer.jsx +++ b/tgui/packages/tgui/interfaces/IdentificationComputer.jsx @@ -1,5 +1,5 @@ import { sortBy } from 'common/collections'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Flex, Input, LabeledList, Section, Table, Tabs } from '../components'; import { Window } from '../layouts'; @@ -9,7 +9,7 @@ import { CrewManifestContent } from './CrewManifest'; export const IdentificationComputer = () => { return ( - + @@ -33,7 +33,7 @@ export const IdentificationComputerContent = (props) => { } return ( - + <> {(!ntos || !!data.have_id_slot) && ( { ))} {body} - + ); }; @@ -118,7 +118,7 @@ export const IdentificationComputerAccessModification = (props) => { )} {!!authenticated && !!has_modify && ( - + <>
@@ -213,7 +213,7 @@ export const IdentificationComputerAccessModification = (props) => {
)} -
+ )}
); diff --git a/tgui/packages/tgui/interfaces/InventoryPanel.tsx b/tgui/packages/tgui/interfaces/InventoryPanel.tsx index b5dddeb430..1918a6a8df 100644 --- a/tgui/packages/tgui/interfaces/InventoryPanel.tsx +++ b/tgui/packages/tgui/interfaces/InventoryPanel.tsx @@ -14,7 +14,7 @@ export const InventoryPanel = (props) => { const { slots, internalsValid } = data; return ( - +
diff --git a/tgui/packages/tgui/interfaces/InventoryPanelHuman.jsx b/tgui/packages/tgui/interfaces/InventoryPanelHuman.jsx index 8672888459..13f9042e65 100644 --- a/tgui/packages/tgui/interfaces/InventoryPanelHuman.jsx +++ b/tgui/packages/tgui/interfaces/InventoryPanelHuman.jsx @@ -19,7 +19,7 @@ export const InventoryPanelHuman = (props) => { } = data; return ( - +
diff --git a/tgui/packages/tgui/interfaces/IsolationCentrifuge.jsx b/tgui/packages/tgui/interfaces/IsolationCentrifuge.jsx index bcbed18bf8..ac1eb9006f 100644 --- a/tgui/packages/tgui/interfaces/IsolationCentrifuge.jsx +++ b/tgui/packages/tgui/interfaces/IsolationCentrifuge.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Flex, LabeledList, Section } from '../components'; import { Window } from '../layouts'; @@ -18,7 +18,7 @@ export const IsolationCentrifuge = (props) => { ); } else { blood_sample = ( - + <> {antibodies ? (
{antibodies}
) : null} @@ -33,7 +33,7 @@ export const IsolationCentrifuge = (props) => {
) : null} - + ); } } @@ -48,7 +48,7 @@ export const IsolationCentrifuge = (props) => {
) : ( - + <>
@@ -102,7 +102,7 @@ export const IsolationCentrifuge = (props) => {
) : null} -
+ )}
diff --git a/tgui/packages/tgui/interfaces/Jukebox.jsx b/tgui/packages/tgui/interfaces/Jukebox.jsx index 6cbf58cd88..f305152cc1 100644 --- a/tgui/packages/tgui/interfaces/Jukebox.jsx +++ b/tgui/packages/tgui/interfaces/Jukebox.jsx @@ -31,7 +31,7 @@ export const Jukebox = (props) => { let true_genre = playing && (current_genre || 'Uncategorized'); return ( - +
diff --git a/tgui/packages/tgui/interfaces/LawManager.jsx b/tgui/packages/tgui/interfaces/LawManager.jsx index abc0d2bfd8..2416195e1e 100644 --- a/tgui/packages/tgui/interfaces/LawManager.jsx +++ b/tgui/packages/tgui/interfaces/LawManager.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend, useSharedState } from '../backend'; import { Button, LabeledList, Section, Tabs, NoticeBox, Table, Input } from '../components'; import { Window } from '../layouts'; @@ -9,7 +9,7 @@ export const LawManager = (props) => { const { isSlaved } = data; return ( - + {(isSlaved && Law-synced to {isSlaved}) || null} @@ -23,7 +23,7 @@ const LawManagerContent = (props) => { const [tabIndex, setTabIndex] = useSharedState('lawsTabIndex', 0); return ( - + <> setTabIndex(0)}> Law Management @@ -34,7 +34,7 @@ const LawManagerContent = (props) => { {(tabIndex === 0 && ) || null} {(tabIndex === 1 && ) || null} - + ); }; @@ -224,10 +224,10 @@ const LawsTable = (props) => { Law {(!noButtons && State) || null} {(isMalf && !noButtons && ( - + <> Edit Delete - + )) || null} @@ -250,7 +250,7 @@ const LawsTable = (props) => { )) || null} {(isMalf && !noButtons && ( - + <> - + )) || null} @@ -284,7 +284,7 @@ const LawManagerLawSets = (props) => { const { isMalf, law_sets } = data; return ( - + <> Remember: Stating laws other than those currently loaded may be grounds for decommissioning! - NanoTrasen @@ -295,7 +295,7 @@ const LawManagerLawSets = (props) => { key={laws.name} title={laws.name} buttons={ - + <> - + }> {(laws.laws.has_ion_laws && ( {
))) || null} - + ); }; diff --git a/tgui/packages/tgui/interfaces/LookingGlass.jsx b/tgui/packages/tgui/interfaces/LookingGlass.jsx index 279a857de3..36d685cb09 100644 --- a/tgui/packages/tgui/interfaces/LookingGlass.jsx +++ b/tgui/packages/tgui/interfaces/LookingGlass.jsx @@ -10,7 +10,7 @@ export const LookingGlass = (props) => { let height = Math.min(180 + supportedPrograms.length * 23, 600); return ( - +
{supportedPrograms.map((program) => ( diff --git a/tgui/packages/tgui/interfaces/MechaControlConsole.jsx b/tgui/packages/tgui/interfaces/MechaControlConsole.jsx index 4e6f2e104c..afb0fa0c86 100644 --- a/tgui/packages/tgui/interfaces/MechaControlConsole.jsx +++ b/tgui/packages/tgui/interfaces/MechaControlConsole.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Modal, LabeledList, ProgressBar, Section, NoticeBox } from '../components'; import { Window } from '../layouts'; @@ -8,7 +8,7 @@ export const MechaControlConsole = (props) => { const { act, data } = useBackend(); const { beacons, stored_data } = data; return ( - + {(stored_data.length && ( @@ -37,7 +37,7 @@ export const MechaControlConsole = (props) => { key={beacon.name} title={beacon.name} buttons={ - + <>
- + ); }; @@ -211,7 +211,7 @@ const MedicalRecordsViewGeneral = (_properties) => { return General records lost!; } return ( - + <> {general.fields.map((field, i) => ( @@ -247,7 +247,7 @@ const MedicalRecordsViewGeneral = (_properties) => { ))} - + ); }; @@ -268,7 +268,7 @@ const MedicalRecordsViewMedical = (_properties) => { ); } return ( - + <> {medical.fields.map((field, i) => ( @@ -314,7 +314,7 @@ const MedicalRecordsViewMedical = (_properties) => { onClick={() => modalOpen('add_c')} />
- + ); }; @@ -350,7 +350,7 @@ const MedicalRecordsMedbots = (_properties) => { {medbot.on ? ( - + <> Online {medbot.use_beaker @@ -360,7 +360,7 @@ const MedicalRecordsMedbots = (_properties) => { medbot.maximum_volume : 'Using internal synthesizer.'} - + ) : ( Offline )} diff --git a/tgui/packages/tgui/interfaces/MessageMonitor.jsx b/tgui/packages/tgui/interfaces/MessageMonitor.jsx index 9570a7b9c0..14b0ceda24 100644 --- a/tgui/packages/tgui/interfaces/MessageMonitor.jsx +++ b/tgui/packages/tgui/interfaces/MessageMonitor.jsx @@ -1,5 +1,5 @@ import { decodeHtmlEntities } from 'common/string'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend, useLocalState } from '../backend'; import { Box, Button, Dropdown, Flex, Icon, Input, LabeledList, Section, Tabs } from '../components'; import { Window } from '../layouts'; @@ -23,7 +23,7 @@ export const MessageMonitor = (props) => { } return ( - + {body} @@ -176,7 +176,7 @@ const MessageMonitorContent = (props) => { } return ( - + <> { {body} - + ); }; @@ -226,7 +226,7 @@ const MessageMonitorMain = (props) => {
+ <> - + }> {items.map((item) => ( diff --git a/tgui/packages/tgui/interfaces/MiningOreProcessingConsole.jsx b/tgui/packages/tgui/interfaces/MiningOreProcessingConsole.jsx index 154bbcd0aa..05b63cb651 100644 --- a/tgui/packages/tgui/interfaces/MiningOreProcessingConsole.jsx +++ b/tgui/packages/tgui/interfaces/MiningOreProcessingConsole.jsx @@ -1,5 +1,5 @@ import { toTitleCase } from 'common/string'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Dropdown, Section, LabeledList, AnimatedNumber } from '../components'; import { Window } from '../layouts'; @@ -11,7 +11,7 @@ export const MiningOreProcessingConsole = (props) => { const { unclaimedPoints, ores, showAllOres, power, speed } = data; return ( - + {
+ <> - + }> { const { stacktypes, stackingAmt } = data; return ( - +
diff --git a/tgui/packages/tgui/interfaces/MiningVendor.jsx b/tgui/packages/tgui/interfaces/MiningVendor.jsx index b230fdb7e9..5f826deeb6 100644 --- a/tgui/packages/tgui/interfaces/MiningVendor.jsx +++ b/tgui/packages/tgui/interfaces/MiningVendor.jsx @@ -12,7 +12,7 @@ const sortTypes = { export const MiningVendor = (props) => { return ( - + diff --git a/tgui/packages/tgui/interfaces/MobSpawner.tsx b/tgui/packages/tgui/interfaces/MobSpawner.tsx index eb3c079fb6..177be52f27 100644 --- a/tgui/packages/tgui/interfaces/MobSpawner.tsx +++ b/tgui/packages/tgui/interfaces/MobSpawner.tsx @@ -43,7 +43,7 @@ export const MobSpawner = (props) => { tabs[1] = ; return ( - + setTabIndex(0)}> diff --git a/tgui/packages/tgui/interfaces/MuleBot.tsx b/tgui/packages/tgui/interfaces/MuleBot.tsx index cbad770c2e..45aabb8efe 100644 --- a/tgui/packages/tgui/interfaces/MuleBot.tsx +++ b/tgui/packages/tgui/interfaces/MuleBot.tsx @@ -1,5 +1,5 @@ import { BooleanLike } from 'common/react'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; @@ -64,7 +64,7 @@ const MuleBotClosed = (props) => { {locked && !issilicon ? ( This interface is currently locked. ) : ( - + <>
); diff --git a/tgui/packages/tgui/interfaces/NIF.jsx b/tgui/packages/tgui/interfaces/NIF.jsx index a9c308450d..0d6b32a3d7 100644 --- a/tgui/packages/tgui/interfaces/NIF.jsx +++ b/tgui/packages/tgui/interfaces/NIF.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend, useLocalState } from '../backend'; import { Box, Button, LabeledList, ProgressBar, Modal, Section, Dropdown, AnimatedNumber, NoticeBox, Table } from '../components'; import { Window } from '../layouts'; @@ -29,7 +29,7 @@ export const NIF = (props) => { const [viewingModule, setViewing] = useLocalState('viewingModule', null); return ( - + {!!last_notification && ( @@ -57,7 +57,7 @@ export const NIF = (props) => { m={0} title={viewingModule.name} buttons={ - + <> { icon="window-close" onClick={() => setViewing(null)} /> - + }> {viewingModule.desc} @@ -220,7 +220,7 @@ const NIFMain = (props) => { label={module.name} key={module.ref} buttons={ - + <> { tooltip="View Information" tooltipPosition="left" /> - + }> {(module.activates && (
)} - + ); }; @@ -478,7 +478,7 @@ const NewscasterViewSelected = (props) => {
+ <> {!!securityCaster && ( { onClick={() => setScreen(NEWSCASTER_SCREEN_VIEWLIST)}> Back - + }> @@ -536,7 +536,7 @@ const NewscasterViewSelected = (props) => { {message.timestamp}] {!!securityCaster && ( - + <> { act('censor_channel_story_author', { ref: message.ref }) } /> - + )}
))) || diff --git a/tgui/packages/tgui/interfaces/NoticeBoard.tsx b/tgui/packages/tgui/interfaces/NoticeBoard.tsx index 99d3b1997e..3df50546fe 100644 --- a/tgui/packages/tgui/interfaces/NoticeBoard.tsx +++ b/tgui/packages/tgui/interfaces/NoticeBoard.tsx @@ -1,5 +1,5 @@ import { BooleanLike } from 'common/react'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; @@ -34,7 +34,7 @@ export const NoticeBoard = (props) => { /> )) || (notice.ispaper && ( - + <> @@ -107,20 +107,20 @@ const ActiveWarrant = (props) => { - + }> + <>
@@ -188,7 +188,7 @@ export const NtosEmailClientViewMessage = (props) => { administrator ? (
)) || ( - + <>
{ New Text File
-
+ )} {error && ( @@ -133,7 +133,7 @@ const FileTable = (props) => { {!file.undeletable ? ( - + <> { onCommit={(e, value) => onRename(file.uid, value)} />
{!!idsalarm && ( - + <> NETWORK INCURSION DETECTED Abnormal activity has been detected in the network. Check system logs for more information - + )} + <> - + }> {banned_nids.join(', ') || 'None'} + <> - + }> {!!cover && } {/* News articles are written in premade .html files and cannot be edited by players, so it should be diff --git a/tgui/packages/tgui/interfaces/NtosOvermapNavigation.tsx b/tgui/packages/tgui/interfaces/NtosOvermapNavigation.tsx index ce14970818..c0abea4745 100644 --- a/tgui/packages/tgui/interfaces/NtosOvermapNavigation.tsx +++ b/tgui/packages/tgui/interfaces/NtosOvermapNavigation.tsx @@ -3,7 +3,7 @@ import { OvermapNavigationContent } from './OvermapNavigation'; export const NtosOvermapNavigation = () => { return ( - + diff --git a/tgui/packages/tgui/interfaces/NtosPowerMonitor.tsx b/tgui/packages/tgui/interfaces/NtosPowerMonitor.tsx index b00a83a0f5..39b36f03b7 100644 --- a/tgui/packages/tgui/interfaces/NtosPowerMonitor.tsx +++ b/tgui/packages/tgui/interfaces/NtosPowerMonitor.tsx @@ -3,7 +3,7 @@ import { PowerMonitorContent } from './PowerMonitor'; export const NtosPowerMonitor = () => { return ( - + diff --git a/tgui/packages/tgui/interfaces/NtosRCON.tsx b/tgui/packages/tgui/interfaces/NtosRCON.tsx index 0f14e7f94d..d0728330e7 100644 --- a/tgui/packages/tgui/interfaces/NtosRCON.tsx +++ b/tgui/packages/tgui/interfaces/NtosRCON.tsx @@ -3,7 +3,7 @@ import { RCONContent } from './RCON'; export const NtosRCON = () => { return ( - + diff --git a/tgui/packages/tgui/interfaces/NtosShutoffMonitor.tsx b/tgui/packages/tgui/interfaces/NtosShutoffMonitor.tsx index c7b0731e5f..e9a4d30bf1 100644 --- a/tgui/packages/tgui/interfaces/NtosShutoffMonitor.tsx +++ b/tgui/packages/tgui/interfaces/NtosShutoffMonitor.tsx @@ -3,7 +3,7 @@ import { ShutoffMonitorContent } from './ShutoffMonitor'; export const NtosShutoffMonitor = () => { return ( - + diff --git a/tgui/packages/tgui/interfaces/NtosStationAlertConsole.tsx b/tgui/packages/tgui/interfaces/NtosStationAlertConsole.tsx index de258df01e..229b96597c 100644 --- a/tgui/packages/tgui/interfaces/NtosStationAlertConsole.tsx +++ b/tgui/packages/tgui/interfaces/NtosStationAlertConsole.tsx @@ -3,7 +3,7 @@ import { StationAlertConsoleContent } from './StationAlertConsole'; export const NtosStationAlertConsole = () => { return ( - + diff --git a/tgui/packages/tgui/interfaces/NtosSupermatterMonitor.tsx b/tgui/packages/tgui/interfaces/NtosSupermatterMonitor.tsx index b9067fc78d..4dba8bbf16 100644 --- a/tgui/packages/tgui/interfaces/NtosSupermatterMonitor.tsx +++ b/tgui/packages/tgui/interfaces/NtosSupermatterMonitor.tsx @@ -3,7 +3,7 @@ import { SupermatterMonitorContent } from './SupermatterMonitor'; export const NtosSupermatterMonitor = () => { return ( - + diff --git a/tgui/packages/tgui/interfaces/NtosUAV.jsx b/tgui/packages/tgui/interfaces/NtosUAV.jsx index 24bcb44bd3..6e46cab314 100644 --- a/tgui/packages/tgui/interfaces/NtosUAV.jsx +++ b/tgui/packages/tgui/interfaces/NtosUAV.jsx @@ -8,7 +8,7 @@ export const NtosUAV = (props) => { const { current_uav, signal_strength, in_use, paired_uavs } = data; return ( - +
diff --git a/tgui/packages/tgui/interfaces/OmniFilter.tsx b/tgui/packages/tgui/interfaces/OmniFilter.tsx index 2bf84ea828..e094472b86 100644 --- a/tgui/packages/tgui/interfaces/OmniFilter.tsx +++ b/tgui/packages/tgui/interfaces/OmniFilter.tsx @@ -1,5 +1,5 @@ import { useBackend } from '../backend'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { Box, Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; import { BooleanLike } from 'common/react'; @@ -31,12 +31,12 @@ export const OmniFilter = (props) => { const { power, config, ports, set_flow_rate, last_flow_rate } = data; return ( - +
+ <>
- + ); }; export const AreaCharge = (props) => { const { charging, charge } = props; return ( - + <> { {toFixed(charge) + '%'} - + ); }; diff --git a/tgui/packages/tgui/interfaces/PressureRegulator.jsx b/tgui/packages/tgui/interfaces/PressureRegulator.jsx index 7cf21c8a70..80e1574c6e 100644 --- a/tgui/packages/tgui/interfaces/PressureRegulator.jsx +++ b/tgui/packages/tgui/interfaces/PressureRegulator.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Button, LabeledList, Section, AnimatedNumber } from '../components'; import { Window } from '../layouts'; @@ -18,7 +18,7 @@ export const PressureRegulator = (props) => { } = data; return ( - +
@@ -47,7 +47,7 @@ export const PressureRegulator = (props) => { + <> - + } /> )) || @@ -215,7 +215,7 @@ const RequestConsoleAnnounce = (props) => { return (
{(announceAuth && ( - + <> ID Verified. Authentication Accepted. @@ -234,7 +234,7 @@ const RequestConsoleAnnounce = (props) => { }> {message || 'No Message'}
- + )) || ( Swipe your ID card to authenticate yourself. @@ -273,7 +273,7 @@ export const RequestConsole = (props) => { let BodyElement = screenToTemplate[screen]; return ( - + { const { target } = props; return ( - + <> { || null} - + }> { } buttons={ - + <> - + }> {mat.amount} cm³
@@ -687,14 +687,14 @@ const ResearchConsoleSettings = (props) => { {(settingsTab === 0 && ( {(sync && ( - + <> - + )) || (
- + ); }; @@ -221,7 +221,7 @@ const SecurityRecordsViewSecurity = (_properties) => { ); } return ( - + <> {security.fields.map((field, i) => ( @@ -267,7 +267,7 @@ const SecurityRecordsViewSecurity = (_properties) => { onClick={() => modalOpen('add_c')} />
- + ); }; diff --git a/tgui/packages/tgui/interfaces/SeedStorage.jsx b/tgui/packages/tgui/interfaces/SeedStorage.jsx index 3580524ba2..dd7e87c9e4 100644 --- a/tgui/packages/tgui/interfaces/SeedStorage.jsx +++ b/tgui/packages/tgui/interfaces/SeedStorage.jsx @@ -12,7 +12,7 @@ export const SeedStorage = (props) => { const sortedSeeds = sortBy((seed) => seed.name.toLowerCase())(seeds); return ( - +
{sortedSeeds.map((seed) => ( diff --git a/tgui/packages/tgui/interfaces/ShieldCapacitor.jsx b/tgui/packages/tgui/interfaces/ShieldCapacitor.jsx index 973b908f9b..0c718abc54 100644 --- a/tgui/packages/tgui/interfaces/ShieldCapacitor.jsx +++ b/tgui/packages/tgui/interfaces/ShieldCapacitor.jsx @@ -17,7 +17,7 @@ export const ShieldCapacitor = (props) => { } = data; return ( - +
{ const { locked } = data; return ( - + {locked ? : } @@ -59,7 +59,7 @@ const ShieldGeneratorContent = (props) => { const capacitorLen = (capacitors || []).length; return ( - + <>
@@ -182,6 +182,6 @@ const ShieldGeneratorContent = (props) => {
-
+ ); }; diff --git a/tgui/packages/tgui/interfaces/ShutoffMonitor.jsx b/tgui/packages/tgui/interfaces/ShutoffMonitor.jsx index f09705e188..59fd98f51c 100644 --- a/tgui/packages/tgui/interfaces/ShutoffMonitor.jsx +++ b/tgui/packages/tgui/interfaces/ShutoffMonitor.jsx @@ -3,7 +3,7 @@ import { Window } from '../layouts'; import { Button, Section, Table } from '../components'; export const ShutoffMonitor = (props) => ( - + diff --git a/tgui/packages/tgui/interfaces/ShuttleControl.jsx b/tgui/packages/tgui/interfaces/ShuttleControl.jsx index 908e65fd0a..4104a4b6e4 100644 --- a/tgui/packages/tgui/interfaces/ShuttleControl.jsx +++ b/tgui/packages/tgui/interfaces/ShuttleControl.jsx @@ -1,5 +1,5 @@ import { toTitleCase } from 'common/string'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Flex, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; @@ -64,7 +64,7 @@ const ShuttleControlSharedShuttleStatus = (props) => { )) || ERROR} {(has_docking && ( - + <> {getDockingStatus(docking_status, docking_override)} @@ -73,7 +73,7 @@ const ShuttleControlSharedShuttleStatus = (props) => { {docking_codes || 'Not Set'} - + )) || null} @@ -125,10 +125,10 @@ const ShuttleControlSharedShuttleControls = (props) => { const ShuttleControlConsoleDefault = (props) => { const { act, data } = useBackend(); return ( - + <> - + ); }; @@ -136,7 +136,7 @@ const ShuttleControlConsoleMulti = (props) => { const { act, data } = useBackend(); const { can_cloak, can_pick, legit, cloaked, destination_name } = data; return ( - + <>
@@ -162,7 +162,7 @@ const ShuttleControlConsoleMulti = (props) => {
-
+ ); }; @@ -171,7 +171,7 @@ const ShuttleControlConsoleExploration = (props) => { const { can_pick, destination_name, fuel_usage, fuel_span, remaining_fuel } = data; return ( - + <>
@@ -184,20 +184,20 @@ const ShuttleControlConsoleExploration = (props) => { {(fuel_usage && ( - + <> {remaining_fuel} m/s {fuel_usage} m/s - + )) || null}
-
+ ); }; @@ -226,7 +226,7 @@ const ShuttleControlConsoleWeb = (props) => { } = data; return ( - + <> {(autopilot && (
@@ -263,7 +263,7 @@ const ShuttleControlConsoleWeb = (props) => { )) || ERROR} {(!is_moving && ( - + <> {toTitleCase(shuttle_location)} @@ -271,7 +271,7 @@ const ShuttleControlConsoleWeb = (props) => { + <> - + }> {getDockingStatus(docking_status, docking_override)} @@ -320,7 +320,7 @@ const ShuttleControlConsoleWeb = (props) => { )) || null} - + )) || null} @@ -444,7 +444,7 @@ const ShuttleControlConsoleWeb = (props) => {
)) || null} -
+ ); }; @@ -463,8 +463,7 @@ export const ShuttleControl = (props) => { return ( + height={subtemplate === 'ShuttleControlConsoleWeb' ? 560 : 370}> {SubtemplateList[subtemplate]} ); diff --git a/tgui/packages/tgui/interfaces/Sleeper.jsx b/tgui/packages/tgui/interfaces/Sleeper.jsx index c8af39a608..3f4cbbd38f 100644 --- a/tgui/packages/tgui/interfaces/Sleeper.jsx +++ b/tgui/packages/tgui/interfaces/Sleeper.jsx @@ -1,5 +1,5 @@ import { round } from 'common/math'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; @@ -37,7 +37,7 @@ export const Sleeper = (props) => { const { hasOccupant } = data; const body = hasOccupant ? : ; return ( - + {body} @@ -49,7 +49,7 @@ const SleeperMain = (props) => { const { act, data } = useBackend(); const { occupant, dialysis, stomachpumping } = data; return ( - + <> { actToDo="togglepump" /> - + ); }; @@ -74,7 +74,7 @@ const SleeperOccupant = (props) => {
+ <> Auto-eject if dead:  @@ -92,7 +92,7 @@ const SleeperOccupant = (props) => { onClick={() => act('ejectify')} />
@@ -179,7 +179,7 @@ const SleeperDialysisPump = (props) => {
+ <>
))} @@ -413,7 +413,7 @@ const SupplyConsoleMenuHistoryExport = (props) => { key={i} buttons={ order_auth ? ( - + <>
))} diff --git a/tgui/packages/tgui/interfaces/TEGenerator.jsx b/tgui/packages/tgui/interfaces/TEGenerator.jsx index 5534ff6251..31499c94c4 100644 --- a/tgui/packages/tgui/interfaces/TEGenerator.jsx +++ b/tgui/packages/tgui/interfaces/TEGenerator.jsx @@ -11,7 +11,7 @@ export const TEGenerator = (props) => { data; return ( - +
diff --git a/tgui/packages/tgui/interfaces/Tank.jsx b/tgui/packages/tgui/interfaces/Tank.jsx index b40860bf20..eea20aa82e 100644 --- a/tgui/packages/tgui/interfaces/Tank.jsx +++ b/tgui/packages/tgui/interfaces/Tank.jsx @@ -17,7 +17,7 @@ export const Tank = (props) => { } = data; return ( - +
{ const { act, data } = useBackend(); const { plasma, oxygen } = data; return ( - +
diff --git a/tgui/packages/tgui/interfaces/TelecommsLogBrowser.jsx b/tgui/packages/tgui/interfaces/TelecommsLogBrowser.jsx index fb598fb5c7..f26cf05e30 100644 --- a/tgui/packages/tgui/interfaces/TelecommsLogBrowser.jsx +++ b/tgui/packages/tgui/interfaces/TelecommsLogBrowser.jsx @@ -1,5 +1,5 @@ import { round } from 'common/math'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Flex, NoticeBox, LabeledList, Section } from '../components'; import { Window } from '../layouts'; @@ -10,7 +10,7 @@ export const TelecommsLogBrowser = (props) => { const { universal_translate, network, temp, servers, selectedServer } = data; return ( - + {temp ? ( { + <> {!!job_datum && ( - + <> @@ -85,7 +85,7 @@ export const TimeClock = (props) => { Requires PTO - {job_datum.pto_department} )) || Neutral} - + )}
diff --git a/tgui/packages/tgui/interfaces/TurbineControl.jsx b/tgui/packages/tgui/interfaces/TurbineControl.jsx index 565c8f01a2..53d35ff9cb 100644 --- a/tgui/packages/tgui/interfaces/TurbineControl.jsx +++ b/tgui/packages/tgui/interfaces/TurbineControl.jsx @@ -19,7 +19,7 @@ export const TurbineControl = (props) => { } = data; return ( - +
diff --git a/tgui/packages/tgui/interfaces/Turbolift.jsx b/tgui/packages/tgui/interfaces/Turbolift.jsx index e58972da54..5a03c9f235 100644 --- a/tgui/packages/tgui/interfaces/Turbolift.jsx +++ b/tgui/packages/tgui/interfaces/Turbolift.jsx @@ -1,4 +1,4 @@ -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Button, Flex, Section } from '../components'; import { Window } from '../layouts'; @@ -9,13 +9,13 @@ export const Turbolift = (props) => { const { floors, doors_open, fire_mode } = data; return ( - +
+ <>
- + ); }; @@ -1645,7 +1644,7 @@ const VoreContentsPanel = (props) => { const { contents, belly, outside = false } = props; return ( - + <> {(outside && ( - + }> diff --git a/tgui/packages/tgui/interfaces/XenoarchSuspension.tsx b/tgui/packages/tgui/interfaces/XenoarchSuspension.tsx index be3b282079..6e16f97de3 100644 --- a/tgui/packages/tgui/interfaces/XenoarchSuspension.tsx +++ b/tgui/packages/tgui/interfaces/XenoarchSuspension.tsx @@ -1,5 +1,5 @@ import { BooleanLike } from 'common/react'; -import { Fragment } from 'inferno'; +import { Fragment } from 'react'; import { useBackend } from '../backend'; import { Box, Button, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; @@ -35,7 +35,7 @@ export const XenoarchSuspension = (props) => { This interface is locked. Swipe an ID card to unlock it. )) || ( - + <> {(cell && ( @@ -61,7 +61,7 @@ export const XenoarchSuspension = (props) => { ? 'Disengage Suspension Field' : 'Engage Suspension Field'} - + )}
diff --git a/tgui/packages/tgui/interfaces/chompstation/Changelog.jsx b/tgui/packages/tgui/interfaces/chompstation/Changelog.jsx index bc81e97cb2..d95b15dc20 100644 --- a/tgui/packages/tgui/interfaces/chompstation/Changelog.jsx +++ b/tgui/packages/tgui/interfaces/chompstation/Changelog.jsx @@ -1,11 +1,12 @@ import { classes } from 'common/react'; -import { useBackend } from '../../backend'; -import { Component, Fragment } from 'inferno'; -import { Box, Button, Dropdown, Icon, Section, Stack, Table } from '../../components'; -import { Window } from '../../layouts'; -import { resolveAsset } from '../../assets'; import dateformat from 'dateformat'; import yaml from 'js-yaml'; +import { Component, Fragment } from 'react'; + +import { resolveAsset } from '../../assets'; +import { useBackend } from '../../backend'; +import { Box, Button, Dropdown, Icon, Section, Stack, Table } from '../../components'; +import { Window } from '../../layouts'; const icons = { add: { icon: 'check-circle', color: 'green' }, diff --git a/tgui/packages/tgui/interfaces/chompstation/VorePanel.jsx b/tgui/packages/tgui/interfaces/chompstation/VorePanel.jsx index 065994720b..871433c229 100644 --- a/tgui/packages/tgui/interfaces/chompstation/VorePanel.jsx +++ b/tgui/packages/tgui/interfaces/chompstation/VorePanel.jsx @@ -1,5 +1,4 @@ import { capitalize } from 'common/string'; -import { Fragment } from 'inferno'; import { useBackend, useLocalState } from '../../backend'; import { Box, Button, Flex, Collapsible, Icon, LabeledList, NoticeBox, Section, Tabs, Divider, Stack } from '../../components'; import { Window } from '../../layouts'; @@ -395,7 +394,7 @@ const VoreSelectedBelly = (props) => { tabs[8] = ; return ( - + <> setTabIndex(0)}> Controls @@ -426,7 +425,7 @@ const VoreSelectedBelly = (props) => { {tabs[tabIndex] || 'Error'} - + ); }; @@ -441,7 +440,7 @@ const VoreSelectedBellyControls = (props) => { + <>
- + ); }; @@ -1978,7 +1977,7 @@ const VoreContentsPanel = (props) => { const { contents, belly, outside = false } = props; return ( - + <> {(outside && (