Browse Source

REMOVES TGUI (#49330)

* Removes tgui

* Make tgui script executable again

* Set version of packages to 2.0.0

* Update copypasta docs to match the current best practice

* Rebuild tgui

* Update .github/CONTRIBUTING.md

Co-Authored-By: BadSS13Player <58376109+BadSS13Player@users.noreply.github.com>

* Remove holy bible by Arcane

* rebuild

Co-authored-by: BadSS13Player <58376109+BadSS13Player@users.noreply.github.com>
Co-authored-by: Rob Bailey <actioninja@gmail.com>
pride
Aleksej Komarov 5 months ago
committed by GitHub
parent
commit
baf9bd2f95
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
100 changed files with 899 additions and 11996 deletions
  1. +1
    -1
      .dockerignore
  2. +0
    -4
      .editorconfig
  3. +0
    -1
      .github/CODEOWNERS
  4. +6
    -6
      .github/CONTRIBUTING.md
  5. +3
    -3
      .github/workflows/autobuild_tgui.yml
  6. +1
    -1
      .travis.yml
  7. +5
    -7
      README.md
  8. +1
    -1
      code/controllers/subsystem/tgui.dm
  9. +6
    -12
      code/modules/client/asset_cache.dm
  10. +0
    -10
      tgui-next/.gitattributes
  11. +0
    -7
      tgui-next/.gitignore
  12. +0
    -855
      tgui-next/README.md
  13. +0
    -19
      tgui-next/package.json
  14. +0
    -68
      tgui-next/packages/tgui/public/tgui-fallback.html
  15. +0
    -3
      tgui-next/packages/tgui/public/tgui.bundle.js
  16. +0
    -5
      tgui/.babelrc
  17. +0
    -0
      tgui/.editorconfig
  18. +0
    -0
      tgui/.eslintignore
  19. +0
    -0
      tgui/.eslintrc-harder.yml
  20. +0
    -0
      tgui/.eslintrc.yml
  21. +10
    -1
      tgui/.gitattributes
  22. +7
    -2
      tgui/.gitignore
  23. +0
    -20
      tgui/LICENSE.md
  24. +832
    -101
      tgui/README.md
  25. +0
    -1
      tgui/assets/tgui.css
  26. +0
    -22
      tgui/assets/tgui.js
  27. +0
    -0
      tgui/bin/tgui
  28. +0
    -0
      tgui/bin/tgui-build.bat
  29. +0
    -0
      tgui/bin/tgui-dev-server.bat
  30. +0
    -12
      tgui/build.sh
  31. +0
    -6
      tgui/build_assets.bat
  32. +0
    -0
      tgui/docs/converting-old-tgui-interfaces.md
  33. +13
    -16
      tgui/docs/tutorial-and-examples.md
  34. +0
    -31
      tgui/gulp/css.js
  35. +0
    -7
      tgui/gulp/flags.js
  36. +0
    -68
      tgui/gulp/js.js
  37. +0
    -21
      tgui/gulp/plugins.js
  38. +0
    -10
      tgui/gulp/reload.js
  39. +0
    -9
      tgui/gulp/size.js
  40. +0
    -12
      tgui/gulpfile.babel.js
  41. +0
    -8
      tgui/install_dependencies.bat
  42. +0
    -10545
      tgui/package-lock.json
  43. +12
    -60
      tgui/package.json
  44. +0
    -0
      tgui/packages/common/collections.js
  45. +0
    -0
      tgui/packages/common/fp.js
  46. +0
    -0
      tgui/packages/common/logging.js
  47. +0
    -0
      tgui/packages/common/math.js
  48. +1
    -1
      tgui/packages/common/package.json
  49. +0
    -0
      tgui/packages/common/react.js
  50. +0
    -0
      tgui/packages/common/redux.js
  51. +0
    -0
      tgui/packages/common/string.babel-plugin.cjs
  52. +0
    -0
      tgui/packages/common/string.js
  53. +0
    -0
      tgui/packages/common/vector.js
  54. +0
    -0
      tgui/packages/tgui-dev-server/index.js
  55. +0
    -0
      tgui/packages/tgui-dev-server/link/client.js
  56. +0
    -0
      tgui/packages/tgui-dev-server/link/retrace.js
  57. +0
    -0
      tgui/packages/tgui-dev-server/link/server.js
  58. +1
    -1
      tgui/packages/tgui-dev-server/package.json
  59. +0
    -0
      tgui/packages/tgui-dev-server/reloader.js
  60. +0
    -0
      tgui/packages/tgui-dev-server/util.js
  61. +0
    -0
      tgui/packages/tgui-dev-server/webpack.js
  62. +0
    -0
      tgui/packages/tgui/assets/bg-nanotrasen.svg
  63. +0
    -0
      tgui/packages/tgui/assets/bg-syndicate.svg
  64. +0
    -0
      tgui/packages/tgui/backend.js
  65. +0
    -0
      tgui/packages/tgui/byond.js
  66. +0
    -0
      tgui/packages/tgui/components/AnimatedNumber.js
  67. +0
    -0
      tgui/packages/tgui/components/BlockQuote.js
  68. +0
    -0
      tgui/packages/tgui/components/Box.js
  69. +0
    -0
      tgui/packages/tgui/components/Button.js
  70. +0
    -0
      tgui/packages/tgui/components/Chart.js
  71. +0
    -0
      tgui/packages/tgui/components/Collapsible.js
  72. +0
    -0
      tgui/packages/tgui/components/ColorBox.js
  73. +0
    -0
      tgui/packages/tgui/components/Dimmer.js
  74. +0
    -0
      tgui/packages/tgui/components/Dropdown.js
  75. +0
    -0
      tgui/packages/tgui/components/Flex.js
  76. +0
    -0
      tgui/packages/tgui/components/Grid.js
  77. +0
    -0
      tgui/packages/tgui/components/Icon.js
  78. +0
    -0
      tgui/packages/tgui/components/Input.js
  79. +0
    -0
      tgui/packages/tgui/components/LabeledList.js
  80. +0
    -0
      tgui/packages/tgui/components/NoticeBox.js
  81. +0
    -0
      tgui/packages/tgui/components/NumberInput.js
  82. +0
    -0
      tgui/packages/tgui/components/ProgressBar.js
  83. +0
    -0
      tgui/packages/tgui/components/Section.js
  84. +0
    -0
      tgui/packages/tgui/components/Table.js
  85. +0
    -0
      tgui/packages/tgui/components/Tabs.js
  86. +0
    -0
      tgui/packages/tgui/components/TitleBar.js
  87. +0
    -0
      tgui/packages/tgui/components/Toast.js
  88. +0
    -0
      tgui/packages/tgui/components/Tooltip.js
  89. +0
    -0
      tgui/packages/tgui/components/index.js
  90. +0
    -0
      tgui/packages/tgui/constants.js
  91. +0
    -0
      tgui/packages/tgui/drag.js
  92. +0
    -0
      tgui/packages/tgui/hotkeys.js
  93. +0
    -39
      tgui/packages/tgui/index.js
  94. +0
    -0
      tgui/packages/tgui/interfaces/Achievements.js
  95. +0
    -0
      tgui/packages/tgui/interfaces/AiAirlock.js
  96. +0
    -0
      tgui/packages/tgui/interfaces/AirAlarm.js
  97. +0
    -0
      tgui/packages/tgui/interfaces/AirlockElectronics.js
  98. +0
    -0
      tgui/packages/tgui/interfaces/Apc.js
  99. +0
    -0
      tgui/packages/tgui/interfaces/AtmosAlertConsole.js
  100. +0
    -0
      tgui/packages/tgui/interfaces/AtmosControlConsole.js

+ 1
- 1
.dockerignore View File

@@ -17,7 +17,7 @@ TGS3.json
cfg
data
SQL
tgui/node_modules
node_modules
tgstation.dmb
tgstation.int
tgstation.rsc


+ 0
- 4
.editorconfig View File

@@ -11,7 +11,3 @@ indent_size = 2

[*.py]
indent_style = space

[/tgui/**/*.{js,styl,ract,json,html}]
indent_style = space
indent_size = 2

+ 0
- 1
.github/CODEOWNERS View File

@@ -78,7 +78,6 @@
# stylemistake

/tgui @stylemistake
/tgui-next @stylemistake

# Qustinnus
/code/datums/components/mood.dm @Qustinnus


+ 6
- 6
.github/CONTRIBUTING.md View File

@@ -258,11 +258,11 @@ This prevents nesting levels from getting deeper then they need to be.
* Areas should not be var-edited on a map to change it's name or attributes. All areas of a single type and it's altered instances are considered the same area within the code, and editing their variables on a map can lead to issues with powernets and event subsystems which are difficult to debug.

### User Interfaces
* All new player-facing user interfaces must use TGUI-next; TGUI is deprecated.
* All new player-facing user interfaces must use TGUI.
* Raw HTML is permitted for admin and debug UIs.
* Documentation for TGUI-next can be found at:
* [tgui-next/README.md](../tgui-next/README.md)
* [tgui-next/tutorial-and-examples.md](../tgui-next/docs/tutorial-and-examples.md)
* Documentation for TGUI can be found at:
* [tgui/README.md](../tgui/README.md)
* [tgui/tutorial-and-examples.md](../tgui/docs/tutorial-and-examples.md)

### Other Notes
* Code should be modular where possible; if you are working on a new addition, then strongly consider putting it in its own file unless it makes sense to put it with similar ones (i.e. a new tool would go in the "tools.dm" file)
@@ -343,7 +343,7 @@ for(var/obj/item/sword/S in bag_of_swords)
if(!best_sword || S.damage > best_sword.damage)
best_sword = S
```
specifies a type for DM to filter by.
specifies a type for DM to filter by.

With the previous example that's perfectly fine, we only want swords, but here the bag only contains swords? Is DM still going to try to filter because we gave it a type to filter by? YES, and here comes the inefficiency. Wherever a list (or other container, such as an atom (in which case you're technically accessing their special contents list, but that's irrelevant)) contains datums of the same datatype or subtypes of the datatype you require for your loop's body,
you can circumvent DM's filtering and automatic ```istype()``` checks by writing the loop as such:
@@ -380,7 +380,7 @@ mob
```
This does NOT mean that you can access it everywhere like a global var. Instead, it means that that var will only exist once for all instances of its type, in this case that var will only exist once for all mobs - it's shared across everything in its type. (Much more like the keyword `static` in other languages like PHP/C++/C#/Java)

Isn't that confusing?
Isn't that confusing?

There is also an undocumented keyword called `static` that has the same behaviour as global but more correctly describes BYOND's behaviour. Therefore, we always use static instead of global where we need it, as it reduces suprise when reading BYOND code.



+ 3
- 3
.github/workflows/autobuild_tgui.yml View File

@@ -5,8 +5,8 @@ on:
branches:
- 'master'
paths:
- 'tgui-next/**.js'
- 'tgui-next/**.scss'
- 'tgui/**.js'
- 'tgui/**.scss'

jobs:
build:
@@ -23,7 +23,7 @@ jobs:
node-version: '>=12.13'
- name: Build TGUI
run: bin/tgui --ci
working-directory: ./tgui-next
working-directory: ./tgui
- name: Commit Artifacts
run: |
git config --local user.email "action@github.com"


+ 1
- 1
.travis.yml View File

@@ -24,7 +24,7 @@ matrix:
- tools/travis/check_filedirs.sh tgstation.dme
- tools/travis/check_changelogs.sh
- find . -name "*.php" -print0 | xargs -0 -n1 php -l
- find . -name "*.json" -not -path "./tgui/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py
- find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py
- tools/travis/build_tgui.sh
- tools/travis/check_grep.sh
- ~/dreamchecker


+ 5
- 7
README.md View File

@@ -1,7 +1,7 @@
## /tg/station codebase
[![Build Status](https://travis-ci.org/tgstation/tgstation.png)](https://travis-ci.org/tgstation/tgstation) [![Krihelimeter](https://www.krihelinator.xyz/badge/tgstation/tgstation)](https://www.krihelinator.xyz)
[![Percentage of issues still open](https://isitmaintained.com/badge/open/tgstation/tgstation.svg)](https://isitmaintained.com/project/tgstation/tgstation "Percentage of issues still open") [![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/tgstation/tgstation.svg)](https://isitmaintained.com/project/tgstation/tgstation "Average time to resolve an issue") ![Coverage](https://img.shields.io/badge/coverage---2%25-red.svg)
[![Build Status](https://travis-ci.org/tgstation/tgstation.png)](https://travis-ci.org/tgstation/tgstation) [![Krihelimeter](https://www.krihelinator.xyz/badge/tgstation/tgstation)](https://www.krihelinator.xyz)
[![Percentage of issues still open](https://isitmaintained.com/badge/open/tgstation/tgstation.svg)](https://isitmaintained.com/project/tgstation/tgstation "Percentage of issues still open") [![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/tgstation/tgstation.svg)](https://isitmaintained.com/project/tgstation/tgstation "Average time to resolve an issue") ![Coverage](https://img.shields.io/badge/coverage---2%25-red.svg)
[![forthebadge](https://forthebadge.com/images/badges/built-with-resentment.svg)](https://forthebadge.com) [![forthebadge](https://forthebadge.com/images/badges/contains-technical-debt.svg)](https://user-images.githubusercontent.com/8171642/50290880-ffef5500-043a-11e9-8270-a2e5b697c86c.png) [![forinfinityandbyond](https://user-images.githubusercontent.com/5211576/29499758-4efff304-85e6-11e7-8267-62919c3688a9.gif)](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a)
* **Website:** https://www.tgstation13.org
@@ -9,7 +9,7 @@
* **Wiki** https://tgstation13.org/wiki/Main_Page
* **Codedocs:** https://codedocs.tgstation13.org/
* **IRC:** irc://irc.rizon.net/coderbus or if you dont have an IRC client, you can click [here](https://kiwiirc.com/client/irc.rizon.net:6667/?&theme=cli#coderbus)
## DOWNLOADING
There are a number of ways to download the source code. Some are described here, an alternative all-inclusive guide is also located at https://www.tgstation13.org/wiki/Downloading_the_source_code
@@ -95,7 +95,7 @@ the new version.
## HOSTING
If you'd like a more robust server hosting option for tgstation and its
derivatives. Check out our server tools suite at
derivatives. Check out our server tools suite at
https://github.com/tgstation/tgstation-server
## MAPS
@@ -131,7 +131,7 @@ The SQL backend requires a Mariadb server running 10.2 or later. Mysql is not su
If you are hosting a testing server on windows you can use a standalone version of MariaDB pre load with a blank (but initialized) tgdb database. Find them here: https://tgstation13.download/database/ Just unzip and run for a working (but insecure) database server. Includes a zipped copy of the data folder for easy resetting back to square one.
## WEB/CDN RESOURCE DELIVERY
## WEB/CDN RESOURCE DELIVERY
Web delivery of game resources makes it quicker for players to join and reduces some of the stress on the game server.
@@ -163,8 +163,6 @@ Font Awesome font files, used by tgui, are licensed under the SIL Open Font Lice
tgui assets are licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/).
The TGS3 API is licensed as a subproject under the MIT license.
See tgui/LICENSE.md for the MIT license.
See tgui/assets/fonts/SIL-OFL-1.1-LICENSE.md for the SIL Open Font License.
See the footers of code/\_\_DEFINES/server\_tools.dm, code/modules/server\_tools/st\_commands.dm, and code/modules/server\_tools/st\_inteface.dm for the MIT license.
All assets including icons and sound are under a [Creative Commons 3.0 BY-SA license](https://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated.

+ 1
- 1
code/controllers/subsystem/tgui.dm View File

@@ -11,7 +11,7 @@ SUBSYSTEM_DEF(tgui)
var/basehtml // The HTML base used for all UIs.

/datum/controller/subsystem/tgui/PreInit()
basehtml = file2text('tgui-next/packages/tgui/public/tgui-main.html')
basehtml = file2text('tgui/packages/tgui/public/tgui.html')

/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()


+ 6
- 12
code/modules/client/asset_cache.dm View File

@@ -388,18 +388,12 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset/simple/tgui
assets = list(
// tgui
"tgui.css" = 'tgui/assets/tgui.css',
"tgui.js" = 'tgui/assets/tgui.js',
// tgui-next
"tgui-main.html" = 'tgui-next/packages/tgui/public/tgui-main.html',
"tgui-fallback.html" = 'tgui-next/packages/tgui/public/tgui-fallback.html',
"tgui.bundle.js" = 'tgui-next/packages/tgui/public/tgui.bundle.js',
"tgui.bundle.css" = 'tgui-next/packages/tgui/public/tgui.bundle.css',
"shim-html5shiv.js" = 'tgui-next/packages/tgui/public/shim-html5shiv.js',
"shim-ie8.js" = 'tgui-next/packages/tgui/public/shim-ie8.js',
"shim-dom4.js" = 'tgui-next/packages/tgui/public/shim-dom4.js',
"shim-css-om.js" = 'tgui-next/packages/tgui/public/shim-css-om.js',
"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


+ 0
- 10
tgui-next/.gitattributes View File

@@ -1,10 +0,0 @@
* text=auto

## Enforce text mode and LF line breaks
*.js text eol=lf
*.css text eol=lf
*.html text eol=lf
*.json text eol=lf

## Treat bundles as binary and ignore them during conflicts
*.bundle.* binary merge=tgui-merge-bundle

+ 0
- 7
tgui-next/.gitignore View File

@@ -1,7 +0,0 @@
node_modules
*.log
package-lock.json

/packages/tgui/public/.tmp/**/*
/packages/tgui/public/**/*.hot-update.*
/packages/tgui/public/**/*.map

+ 0
- 855
tgui-next/README.md View File

@@ -1,855 +0,0 @@
# tgui

## Introduction

tgui is a robust user interface framework of /tg/station.

tgui is very different from most UIs you will encounter in BYOND programming.
It is heavily reliant on Javascript and web technologies as opposed to DM.
If you are familiar with NanoUI (a library which can be found on almost
every other SS13 codebase), tgui should be fairly easy to pick up.

## Learn tgui

People come to tgui from different backgrounds and with different
learning styles. Whether you prefer a more theoretical or a practical
approach, we hope you’ll find this section helpful.

### Practical tutorial

If you are completely new to frontend and prefer to **learn by doing**,
start with our [practical tutorial](docs/tutorial-and-examples.md).

### Guides

This project uses **Inferno** - a very fast UI rendering engine with a similar
API to React. Take your time to read these guides:

- [React guide](https://reactjs.org/docs/hello-world.html)
- [Inferno documentation](https://infernojs.org/docs/guides/components) -
highlights differences with React.

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).

## Pre-requisites

You will need these programs to start developing in tgui:

- [Node v12.13+](https://nodejs.org/en/download/)
- [Yarn v1.19+](https://yarnpkg.com/en/docs/install)
- [MSys2](https://www.msys2.org/) (optional)

> MSys2 closely replicates a unix-like environment which is necessary for
> the `bin/tgui` script to run. It comes with a robust "mintty" terminal
> emulator which is better than any standard Windows shell, it supports
> "git" out of the box (almost like Git for Windows, but better), has
> a "pacman" package manager, and you can install a text editor like "vim"
> for a full boomer experience.

## Usage

**For MSys2, Git Bash, WSL, Linux or macOS users:**

First and foremost, change your directory to `tgui-next`.

Run `bin/tgui --install-git-hooks` (optional) to install merge drivers
which will assist you in conflict resolution when rebasing your branches.

Run one of the following:

- `bin/tgui` - build the project in production mode.
- `bin/tgui --dev` - launch a development server.
- tgui development server provides you with incremental compilation,
hot module replacement and logging facilities in all running instances
of tgui. In short, this means that you will instantly see changes in the
game as you code it. Very useful, highly recommended.
In order to use, you should start the game server first, connect to it so dreamseeker is
open, then start the dev server. You'll know if it's hooked correctly if data gets dumped
to the log when tgui windows are opened.
- `bin/tgui --dev --reload` - reload byond cache once.
- `bin/tgui --dev --debug` - run server with debug logging enabled.
- `bin/tgui --dev --no-hot` - disable hot module replacement (helps when
doing development on IE8).
- `bin/tgui --lint` - show problems with the code.
- `bin/tgui --lint --fix` - auto-fix problems with the code.
- `bin/tgui --analyze` - run a bundle analyzer.
- `bin/tgui --clean` - clean up project repo.
- `bin/tgui [webpack options]` - build the project with custom webpack
options.

**For everyone else:**

If you haven't opened the console already, you can do that by holding
Shift and right clicking on the `tgui-next` folder, then pressing
either `Open command window here` or `Open PowerShell window here`.

Run `yarn install` to install npm dependencies, then one of the following:

- `yarn run build` - build the project in production mode.
- `yarn run watch` - launch a development server.
- `yarn run lint` - show problems with the code.
- `yarn run lint --fix` - auto-fix problems with the code.
- `yarn run analyze` - run a bundle analyzer.

We also got some batch files in store, for those who don't like fiddling
with the console:

- `bin/tgui-build.bat` - build the project in production mode.
- `bin/tgui-dev-server.bat` - launch a development server.

> Remember to always run a full build before submitting a PR. It creates
> a compressed javascript bundle which is then referenced from DM code.
> We prefer to keep it version controlled, so that people could build the
> game just by using Dream Maker.

## Project structure

- `/packages` - Each folder here represents a self-contained Node module.
- `/packages/common` - Helper functions
- `/packages/tgui/index.js` - Application entry point.
- `/packages/tgui/components` - Basic UI building blocks.
- `/packages/tgui/interfaces` - Actual in-game interfaces.
Interface takes data via the `state` prop and outputs an html-like stucture,
which you can build using existing UI components.
- `/packages/tgui/routes.js` - This is where you want to register new
interfaces, otherwise they simply won't load.
- `/packages/tgui/layout.js` - A root-level component, holding the
window elements, like the titlebar, buttons, resize handlers. Calls
`routes.js` to decide which component to render.
- `/packages/tgui/styles/main.scss` - CSS entry point.
- `/packages/tgui/styles/atomic.scss` - Atomic CSS classes.
These are very simple, tiny, reusable CSS classes which you can use and
combine to change appearance of your elements. Keep them small.
- `/packages/tgui/styles/components.scss` - CSS classes which are used
in UI components, and most of the stylesheets referenced here are located
in `/packages/tgui/components`. These stylesheets closely follow the
[BEM](https://en.bem.info/methodology/) methodology.
- `/packages/tgui/styles/functions.scss` - Useful SASS functions.
Stuff like `lighten`, `darken`, `luminance` are defined here.

## Component reference

> Notice: This documentation might be out of date, so always check the source
> code to see the most up-to-date information.

These are the components which you can use for interface construction.
If you have trouble finding the exact prop you need on a component,
please note, that most of these components inherit from other basic
components, such as `Box`. This component in particular provides a lot
of styling options for all components, e.g. `color` and `opacity`, thus
it is used a lot in this framework.

There are a few important semantics you need to know about:

- `content` prop is a synonym to a `children` prop.
- `content` is better used when your element is a self-closing tag
(like `<Button content="Hello" />`), and when content is small and simple
enough to fit in a prop. Keep in mind, that this prop is **not** native
to React, and is a feature of this component system.
- `children` is better used when your element is a full tag (like
`<Button>Hello</Button>`), and when content is long and complex. This is
a native React prop (unlike `content`), and contains all elements you
defined between the opening and the closing tag of an element.
- You should never use both on a same element.
- You should never use `children` explicitly as a prop on an element.
- Inferno supports both camelcase (`onClick`) and lowercase (`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)
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 straight up does not support lowercase event
handlers. Use the camel case `onClick` instead.

### `AnimatedNumber`

This component provides animations for numeric values.

Props:

- `value: number` - Value to animate.
- `initial: number` - Initial value to use in animation when element
first appears. If you set initial to `0` for example, number will always
animate starting from `0`, and if omitted, it will not play an initial
animation.
- `format: value => value` - Output formatter.
- Example: `value => Math.round(value)`.
- `children: (formattedValue, rawValue) => any` - Pull the animated number to
animate more complex things deeper in the DOM tree.
- Example: `(_, value) => <Icon rotation={value} />`

### `BlockQuote`

Just a block quote, just like this example in markdown:

> Here's an example of a block quote.

Props:

- See inherited props: [Box](#box)

### `Box`

The Box component serves as a wrapper component for most of the CSS utility
needs. It creates a new DOM element, a `<div>` by default that can be changed
with the `as` property. Let's say you want to use a `<span>` instead:

```jsx
<Box as="span" m={1}>
<Button />
</Box>
```

This works great when the changes can be isolated to a new DOM element.
For instance, you can change the margin this way.

However, sometimes you have to target the underlying DOM element.
For instance, you want to change the text color of the button. The Button
component defines its own color. CSS inheritance doesn't help.

To workaround this problem, the Box children accept a render props function.
This way, `Button` can pull out the `className` generated by the `Box`.

```jsx
<Box color="primary">
{props => <Button {...props} />}
</Box>
```

`Box` units, like width, height and margins can be defined in two ways:
- By plain numbers (1 unit equals `0.5em`);
- In absolute measures, by providing a full unit string (e.g. `100px`).

Units which are used in `Box` are `0.5em`, which are half font-size.
Default font size is `12px`, so each unit is effectively `6px` in size.
If you need more precision, you can always use fractional numbers.

Props:

- `as: string` - The component used for the root node.
- `color: string` - Applies an atomic `color-<name>` class to the element.
- See `styles/atomic/color.scss`.
- `width: number` - Box width.
- `minWidth: number` - Box minimum width.
- `maxWidth: number` - Box maximum width.
- `height: number` - Box height.
- `minHeight: number` - Box minimum height.
- `maxHeight: number` - Box maximum height.
- `fontSize: number` - Font size.
- `fontFamily: string` - Font family.
- `lineHeight: number` - Directly affects the height of text lines.
Useful for adjusting button height.
- `inline: boolean` - Forces the `Box` to appear as an `inline-block`,
or in other words, makes the `Box` flow with the text instead of taking
all available horizontal space.
- `m: number` - Margin on all sides.
- `mx: number` - Horizontal margin.
- `my: number` - Vertical margin.
- `mt: number` - Top margin.
- `mb: number` - Bottom margin.
- `ml: number` - Left margin.
- `mr: number` - Right margin.
- `opacity: number` - Opacity, from 0 to 1.
- `bold: boolean` - Make text bold.
- `italic: boolean` - Make text italic.
- `nowrap: boolean` - Stops text from wrapping.
- `textAlign: string` - Align text inside the box.
- `left` (default)
- `center`
- `right`
- `position: string` - A direct mapping to `position` CSS property.
- `relative` - Relative positioning.
- `absolute` - Absolute positioning.
- `fixed` - Fixed positioning.
- `color: string` - An alias to `textColor`.
- `textColor: string` - Sets text color.
- `#ffffff` - Hex format
- `rgba(255, 255, 255, 1)` - RGB format
- `purple` - Applies an atomic `color-<name>` class to the element.
See `styles/color-map.scss`.
- `backgroundColor: string` - Sets background color.
- `#ffffff` - Hex format
- `rgba(255, 255, 255, 1)` - RGB format

### `Button`

Buttons allow users to take actions, and make choices, with a single click.

Props:

- See inherited props: [Box](#box)
- `fluid: boolean` - Fill all available horizontal space.
- `icon: string` - Adds an icon to the button.
- `color: string` - Button color, as defined in `variables.scss`.
- There is also a special color `transparent` - makes the button
transparent and slightly dim when inactive.
- `disabled: boolean` - Disables and greys out the button.
- `selected: boolean` - Activates the button (gives it a green color).
- `tooltip: string` - A fancy, boxy tooltip, which appears when hovering
over the button.
- `tooltipPosition: string` - Position of the tooltip.
- `top` - Show tooltip above the button.
- `bottom` (default) - Show tooltip below the button.
- `left` - Show tooltip on the left of the button.
- `right` - Show tooltip on the right of the button.
- `ellipsis: boolean` - If button width is constrained, button text will
be truncated with an ellipsis. Be careful however, because this prop breaks
the baseline alignment.
- `title: string` - A native browser tooltip, which appears when hovering
over the button.
- `content/children: any` - Content to render inside the button.
- `onClick: function` - Called when element is clicked.

### `Button.Checkbox`

A ghetto checkbox, made entirely using existing Button API.

Props:

- See inherited props: [Button](#button)
- `checked: boolean` - Boolean value, which marks the checkbox as checked.

### `Button.Confirm`

A button with a an extra confirmation step, using native button component.

Props:

- See inherited props: [Button](#button)
- `confirmMessage: string` - Text to display after first click; defaults to "Confirm?"
- `confirmColor: string` - Color to display after first click; default to "bad"

### `Button.Input`

A button that turns into an input box after the first click. Turns back into a button after the user hits enter, defocuses, or hits escape. Enter and defocus commit, while escape cancels.

Props:
- See inherited props: [Box](#box)
- `fluid`: fill availible horizontal space
- `onCommit: (e, value) => void`: function that is called after the user defocuses the input or presses enter
- `currentValue: string`: default string to display when the input is shown
- `defaultValue: string`: default value emitted if the user leaves the box blank when hitting enter or defocusing. If left undefined, will cancel the change on a blank defocus/enter

### `Collapsible`

Displays contents when open, acts as a fluid button when closed. Click to toggle, closed by default.

Props:
- See inherited props: [Box](#box)
- `children: any` - What is collapsed when closed
- `title: string` - Text to display on the button for collapsing
- `color: string` - Color of the button; see [Button](#button)
- `buttons: any` - Buttons or other content to render inline with the button

### `ColorBox`

Displays a 1-character wide colored square. Can be used as a status indicator,
or for visually representing a color.

If you want to set a background color on an element, use a plain
[Box](#box) instead.

Props:

- See inherited props: [Box](#box)
- `color: string` - Color of the box.

### `Dimmer`

Dims surrounding area to emphasize content placed inside.

Props:

- See inherited props: [Box](#box)

### `Dropdown`

A simple dropdown box component. Lets the user select from a list of options and displays selected entry.

Props:

- See inherited props: [Box](#box)
- `options: string[]` - An array of strings which will be displayed in the dropdown when open
- `selected: string` - Currently selected entry
- `width: number` - Width of dropdown button and resulting menu
- `over: boolean` - dropdown renders over instead of below
- `color: string` - color of dropdown button
- `onClick: (e) => void` - Called when dropdown button is clicked
- `onSelected: (value) => void` - Called when a value is picked from the list, `value` is the value that was picked

### `Flex`

Quickly manage the layout, alignment, and sizing of grid columns, navigation, components, and more with a full suite of responsive flexbox utilities.

If you are new to or unfamiliar with flexbox, we encourage you to read this
[CSS-Tricks flexbox guide](https://css-tricks.com/snippets/css/a-guide-to-flexbox/).

Consists of two elements: `<Flex>` and `<Flex.Item>`. Both of them provide
the most straight-forward mapping to flex CSS properties as possible.

One of the most basic usage of flex, is to align certain elements
to the left, and certain elements to the right:

```jsx
<Flex>
<Flex.Item>
Button description
</Flex.Item>
<Flex.Item grow={1} />
<Flex.Item>
<Button content="Perform an action" />
</Flex.Item>
</Flex>
```

Flex item with `grow` property serves as a "filler", to separate the other
two flex items as far as possible from each other.

Props:

- See inherited props: [Box](#box)
- `spacing: number` - Spacing between flex items, in integer units
(1 unit - 0.5em). Does not directly relate to a flex css property
(adds a modifier class under the hood), and only integer numbers are
supported.
- `direction: string` - This establishes the main-axis, thus defining the
direction flex items are placed in the flex container.
- `row` (default) - left to right.
- `row-reverse` - right to left.
- `column` - top to bottom.
- `column-reverse` - bottom to top.
- `wrap: string` - By default, flex items will all try to fit onto one line.
You can change that and allow the items to wrap as needed with this property.
- `nowrap` (default) - all flex items will be on one line
- `wrap` - flex items will wrap onto multiple lines, from top to bottom.
- `wrap-reverse` - flex items will wrap onto multiple lines from bottom to top.
- `align: string` - Default alignment of all children.
- `stretch` (default) - stretch to fill the container.
- `start` - items are placed at the start of the cross axis.
- `end` - items are placed at the end of the cross axis.
- `center` - items are centered on the cross axis.
- `baseline` - items are aligned such as their baselines align.
- `justify: string` - This defines the alignment along the main axis.
It helps distribute extra free space leftover when either all the flex
items on a line are inflexible, or are flexible but have reached their
maximum size. It also exerts some control over the alignment of items
when they overflow the line.
- `flex-start` (default) - items are packed toward the start of the
flex-direction.
- `flex-end` - items are packed toward the end of the flex-direction.
- `space-between` - items are evenly distributed in the line; first item is
on the start line, last item on the end line
- `space-around` - items are evenly distributed in the line with equal space
around them. Note that visually the spaces aren't equal, since all the items
have equal space on both sides. The first item will have one unit of space
against the container edge, but two units of space between the next item
because that next item has its own spacing that applies.
- `space-evenly` - items are distributed so that the spacing between any two
items (and the space to the edges) is equal.
- TBD (not all properties are supported in IE11).

### `Flex.Item`

Props:

- See inherited props: [Box](#box)
- `order: number` - By default, flex items are laid out in the source order.
However, the order property controls the order in which they appear in the
flex container.
- `grow: number` - This defines the ability for a flex item to grow if
necessary. It accepts a unitless value that serves as a proportion. It
dictates what amount of the available space inside the flex container the
item should take up. This number is unit-less and is relative to other
siblings.
- `shrink: number` - This defines the ability for a flex item to shrink
if necessary. Inverse of `grow`.
- `basis: string` - This defines the default size of an element before the
remaining space is distributed. It can be a length (e.g. `20%`, `5rem`, etc.),
an `auto` or `content` keyword.
- `align: string` - This allows the default alignment (or the one specified by align-items) to be overridden for individual flex items. See: [Flex](#flex).


### `Grid`

Helps you to divide horizontal space into two or more equal sections.
It is essentially a single-row `Table`, but with some extra features.

Example:

```jsx
<Grid>
<Grid.Column>
<Section title="Section 1" content="Hello world!" />
</Grid.Column>
<Grid.Column size={2}>
<Section title="Section 2" content="Hello world!" />
</Grid.Column>
</Grid>
```

Props:

- See inherited props: [Table](#table)

### `Grid.Column`

Props:

- See inherited props: [Table.Cell](#tablecell)
- `size: number` (default: 1) - Size of the column relative to other columns.

### `Icon`

Renders one of the FontAwesome icons of your choice.

```jsx
<Icon name="plus" />
```

To smoothen the transition from v4 to v5, we have added a v4 semantic to
transform names with `-o` suffixes to FA Regular icons. For example:
- `square` will get transformed to `fas square`
- `square-o` will get transformed to `far square`

Props:

- See inherited props: [Box](#box)
- `name: string` - Icon name.
- `size: number` - Icon size. `1` is normal size, `2` is two times bigger.
Fractional numbers are supported.
- `rotation: number` - Icon rotation, in degrees.
- `spin: boolean` - Whether an icon should be spinning. Good for load
indicators.

### `Input`

A basic text input, which allow users to enter text into a UI.

> Input does not support custom font size and height due to the way
> it's implemented in CSS. Eventually, this needs to be fixed.

Props:

- See inherited props: [Box](#box)
- `value: string` - Value of an input.
- `placeholder: string` - Text placed into Input box when value is otherwise nothing. Clears automatically when focused.
- `fluid: boolean` - Fill all available horizontal space.
- `selfClear: boolean` - Clear after hitting enter, as well as remain focused when this happens. Useful for things like chat inputs
- `onChange: (e, value) => void` - An event, which fires when you commit
the text by either unfocusing the input box, or by pressing the Enter key.
- `onInput: (e, value) => void` - An event, which fires on every keypress.

### `LabeledList`

LabeledList is a continuous, vertical list of text and other content, where
every item is labeled. It works just like a two column table, where first
column is labels, and second column is content.

```jsx
<LabeledList>
<LabeledList.Item label="Item">
Content
</LabeledList.Item>
</LabeledList>
```

If you want to have a button on the right side of an item (for example,
to perform some sort of action), there is a way to do that:

```jsx
<LabeledList>
<LabeledList.Item
label="Item"
buttons={(
<Button content="Click me!" />
)}>
Content
</LabeledList.Item>
</LabeledList>
```

Props:

- `children: LabeledList.Item` - Items to render.

### `LabeledList.Item`

Props:

- `label: string` - Item label.
- `color: string` - Sets the color of the text.
- `buttons: any` - Buttons to render aside the content.
- `content/children: any` - Content of this labeled item.

### `LabeledList.Divider`

Adds some empty space between LabeledList items.

Example:

```jsx
<LabeledList>
<LabeledList.Item label="Foo">
Content
</LabeledList.Item>
<LabeledList.Divider size={1} />
</LabeledList>
```

Props:

- `size: number` - Size of the divider.

### `NoticeBox`

A notice box, which warns you about something very important.

Props:

- See inherited props: [Box](#box)

### `NumberInput`

A fancy, interactive number input, which you can either drag up and down
to fine tune the value, or single click it to manually type a number.

Props:

- `animated: boolean` - Animates the value if it was changed externally.
- `fluid: boolean` - Fill all available horizontal space.
- `value: number` - Value itself.
- `unit: string` - Unit to display to the right of value.
- `minValue: number` - Lowest possible value.
- `maxValue: number` - Highest possible value.
- `step: number` (default: 1) - Adjust value by this amount when
dragging the input.
- `stepPixelSize: number` (default: 1) - Screen distance mouse needs
to travel to adjust value by one `step`.
- `width: string|number` - Width of the element, in `Box` units or pixels.
- `height: string|numer` - Height of the element, in `Box` units or pixels.
- `lineHeight: string|number` - lineHeight of the element, in `Box` units or pixels.
- `fontSize: string|number` - fontSize of the element, in `Box` units or pixels.
- `format: value => value` - Format value using this function before
displaying it.
- `suppressFlicker: number` - A number in milliseconds, for which the input
will hold off from updating while events propagate through the backend.
Default is about 250ms, increase it if you still see flickering.
- `onChange: (e, value) => void` - An event, which fires when you release
the input, or successfully enter a number.
- `onDrag: (e, value) => void` - An event, which fires about every 500ms
when you drag the input up and down, on release and on manual editing.

### `ProgressBar`

Progress indicators inform users about the status of ongoing processes.

```jsx
<ProgressBar value={0.6} />
```

Usage of `ranges` prop:

```jsx
<ProgressBar
ranges={{
good: [0.5, Infinity],
average: [0.25, 0.5],
bad: [-Infinity, 0.25],
}}
value={0.6} />
```

Props:

- `value: number` - Current progress as a floating point number between
`minValue` (default: 0) and `maxValue` (default: 1). Determines the
percentage and how filled the bar is.
- `minValue: number` - Lowest possible value.
- `maxValue: number` - Highest possible value.
- `ranges: { color: [from, to] }` - Applies a `color` to the progress bar
based on whether the value lands in the range between `from` and `to`.
- `color: string` - Color of the progress bar.
- `content/children: any` - Content to render inside the progress bar.

### `Section`

Section is a surface that displays content and actions on a single topic.

They should be easy to scan for relevant and actionable information.
Elements, like text and images, should be placed in them in a way that
clearly indicates hierarchy.

Section can also be titled to clearly define its purpose.

```jsx
<Section title="Cargo">
Here you can order supply crates.
</Section>
```

If you want to have a button on the right side of an section title
(for example, to perform some sort of action), there is a way to do that:

```jsx
<Section
title="Cargo"
buttons={(
<Button content="Send shuttle" />
)}>
Here you can order supply crates.
</Section>
```

- See inherited props: [Box](#box)
- `title: string` - Title of the section.
- `level: number` - Section level in hierarchy. Default is 1, higher number
means deeper level of nesting. Must be an integer number.
- `buttons: any` - Buttons to render aside the section title.
- `content/children: any` - Content of this section.

### `Table`

A straight forward mapping to a standard html table, which is slightly
simplified (does not need a `<tbody>` tag) and with sane default styles
(e.g. table width is 100% by default).

Example:

```jsx
<Table>
<Table.Row>
<Table.Cell bold>
Hello world!
</Table.Cell>
<Table.Cell collapsing color="label">
Label
</Table.Cell>
</Table.Row>
</Table>
```

Props:

- See inherited props: [Box](#box)
- `collapsing: boolean` - Collapses table to the smallest possible size.

### `Table.Row`

A straight forward mapping to `<tr>` element.

Props:

- See inherited props: [Box](#box)

### `Table.Cell`

A straight forward mapping to `<td>` element.

Props:

- See inherited props: [Box](#box)
- `collapsing: boolean` - Collapses table cell to the smallest possible size,
and stops any text inside from wrapping.

### `Tabs`

Tabs make it easy to explore and switch between different views.

Here is an example of how you would construct a simple tabbed view:

```jsx
<Tabs>
<Tabs.Tab label="Item one">
Content for Item one.
</Tabs.Tab>
<Tabs.Tab label="Item two">
Content for Item two.
</Tabs.Tab>
</Tabs>
```

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!

There is a simple fix however. Tabs accept functions as children, which
will be called to retrieve content only when the tab is visible:

```jsx
<Tabs>
<Tabs.Tab key="tab_1" label="Item one">
{() => (
<Fragment>
Content for Item one.
</Fragment>
)}
</Tabs.Tab>
<Tabs.Tab key="tab_2" label="Item two">
{() => (
<Fragment>
Content for Item two.
</Fragment>
)}
</Tabs.Tab>
</Tabs>
```

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.
- `children: Tab[]` - This component only accepts tabs as its children.

### `Tabs.Tab`

An individual tab element. Tabs function like buttons, so they inherit
a lot of `Button` props.

Props:

- See inherited props: [Button](#button)
- `key: string` - A unique identifier for the tab.
- `label: string` - Tab label.
- `icon: string` - Tab icon.
- `content/children: any` - Content to render inside the tab.
- `onClick: function` - Called when element is clicked.

### `Tooltip`

A boxy tooltip from tgui 1. It is very hacky in its current state, and
requires setting `position: relative` on the container.

Please note, that [Button](#button) component has a `tooltip` prop, and
it is recommended to use that prop instead.

Usage:

```jsx
<Box position="relative">
Sample text.
<Tooltip
position="bottom"
content="Box tooltip" />
</Box>
```

Props:

- `position: string` - Tooltip position.
- `content/children: string` - Content of the tooltip. Must be a plain string.
Fragments or other elements are **not** supported.

+ 0
- 19
tgui-next/package.json View File

@@ -1,19 +0,0 @@
{
"private": true,
"name": "tgui-next",
"version": "0.1.0",
"workspaces": [
"packages/*"
],
"scripts": {
"build": "eslint packages && cd packages/tgui && npx webpack --mode=production",
"watch": "cd packages/tgui-dev-server && node --experimental-modules index.js",
"analyze": "cd packages/tgui && npx webpack --mode=production --env.analyze=1",
"lint": "eslint packages"
},
"dependencies": {
"babel-eslint": "^10.0.3",
"eslint": "^6.7.2",
"eslint-plugin-react": "^7.17.0"
}
}

+ 0
- 68
tgui-next/packages/tgui/public/tgui-fallback.html View File

@@ -1,68 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">

<!-- Styles -->
<link rel="stylesheet" type="text/css" href="tgui.css">

<!-- This is processed in byond, so interfaces can override the
html head if needed, for custom sheets of style etc. -->
<!--customheadhtml-->
<script id="data" type="application/json" data-ref="[ref]">{}</script>

</head>
<body class="">

<!-- Old TGUI container -->
<div id="container" class="container">
<div class="notice">
<span>Loading...</span><br>
</div>
</div>

<!-- Scripts -->
<script type="text/javascript">
// Explicitly state to the script this is a fallback html document
window.tguiFallback = true;
// Retrieve and save ref to a global variable
// Since this is a fallback html, we get the ref from the querystring
var ref = location.search.replace('?ref=', '');
document.getElementById('data').setAttribute('data-ref', ref);
// Early global error handling
window.onerror = function (msg, url, line, col, error) {
// Proper stacktrace
var stack = error && error.stack;
// Ghetto stacktrace
if (!stack) {
stack = msg + '\n at ' + url + ':' + line;
if (col) {
stack += ':' + col;
}
}
// Append user agent info
stack += '\n\nUser Agent: ' + navigator.userAgent;
// Print error to the page
document.write(stack);
// Send to the backend
location.href = 'byond://?src=' + ref
+ '&action=tgui:log&fatal=1'
+ '&log=' + encodeURIComponent(stack);
// Short-circuit further updates
window.update = window.initialize = function () {};
// Prevent default action
return true;
};
</script>
<script defer src='tgui.js'></script>

<noscript>
<div class="notice">
<div>Javascript is required in order to use this interface.</div>
<div>Please enable Javascript and restart the game.</div>
</div>
</noscript>

</body>
</html>

+ 0
- 3
tgui-next/packages/tgui/public/tgui.bundle.js
File diff suppressed because it is too large
View File


+ 0
- 5
tgui/.babelrc View File

@@ -1,5 +0,0 @@
{
"presets": [
"es2015"
]
}

tgui-next/.editorconfig → tgui/.editorconfig View File


tgui-next/.eslintignore → tgui/.eslintignore View File


tgui-next/.eslintrc-harder.yml → tgui/.eslintrc-harder.yml View File


tgui-next/.eslintrc.yml → tgui/.eslintrc.yml View File


+ 10
- 1
tgui/.gitattributes View File

@@ -1 +1,10 @@
assets/* binary
* text=auto

## Enforce text mode and LF line breaks
*.js text eol=lf
*.css text eol=lf
*.html text eol=lf
*.json text eol=lf

## Treat bundles as binary and ignore them during conflicts
*.bundle.* binary merge=tgui-merge-bundle

+ 7
- 2
tgui/.gitignore View File

@@ -1,2 +1,7 @@
npm-debug.log
node_modules/
node_modules
*.log
package-lock.json

/packages/tgui/public/.tmp/**/*
/packages/tgui/public/**/*.hot-update.*
/packages/tgui/public/**/*.map

+ 0
- 20
tgui/LICENSE.md View File

@@ -1,20 +0,0 @@
MIT license
Copyright (c) 2016 Bjorn Neergaard (neersighted), tgui contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 832
- 101
tgui/README.md View File

@@ -1,139 +1,870 @@
<!-- TOC depthFrom:1 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 -->
- [tgui](#tgui)
- [Concepts](#concepts)
- [Using It](#using-it)
- [Copypasta](#copypasta)
<!-- /TOC -->

# tgui
tgui is the user interface library of /tg/station. It is rendered clientside, based on JSON data sent from the server. Clicks are processed on the server, in a similar method to native BYOND `Topic()`.

Basic tgui consists of defining a few procs. In these procs you will handle a request to open or update a UI (typically by updating a UI if it exists or setting up and opening it if it does not), a request for data, in which you build a list to be passed as JSON to the UI, and an action handler, which handles any user input. In addition, you will write a HTML template file which renders your data and provides actionable inputs.
## Introduction

tgui is a robust user interface framework of /tg/station.

tgui is very different from most UIs you will encounter in BYOND programming.
It is heavily reliant on Javascript and web technologies as opposed to DM.
If you are familiar with NanoUI (a library which can be found on almost
every other SS13 codebase), tgui should be fairly easy to pick up.

## Learn tgui

People come to tgui from different backgrounds and with different
learning styles. Whether you prefer a more theoretical or a practical
approach, we hope you’ll find this section helpful.

### Practical tutorial

If you are completely new to frontend and prefer to **learn by doing**,
start with our [practical tutorial](docs/tutorial-and-examples.md).

### Guides

This project uses **Inferno** - a very fast UI rendering engine with a similar
API to React. Take your time to read these guides:

- [React guide](https://reactjs.org/docs/hello-world.html)
- [Inferno documentation](https://infernojs.org/docs/guides/components) -
highlights differences with React.

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).

## Pre-requisites

You will need these programs to start developing in tgui:

- [Node v12.13+](https://nodejs.org/en/download/)
- [Yarn v1.19+](https://yarnpkg.com/en/docs/install)
- [MSys2](https://www.msys2.org/) (optional)

> MSys2 closely replicates a unix-like environment which is necessary for
> the `bin/tgui` script to run. It comes with a robust "mintty" terminal
> emulator which is better than any standard Windows shell, it supports
> "git" out of the box (almost like Git for Windows, but better), has
> a "pacman" package manager, and you can install a text editor like "vim"
> for a full boomer experience.

## Usage

**For MSys2, Git Bash, WSL, Linux or macOS users:**

First and foremost, change your directory to `tgui`.

Run `bin/tgui --install-git-hooks` (optional) to install merge drivers
which will assist you in conflict resolution when rebasing your branches.

Run one of the following:

- `bin/tgui` - build the project in production mode.
- `bin/tgui --dev` - launch a development server.
- tgui development server provides you with incremental compilation,
hot module replacement and logging facilities in all running instances
of tgui. In short, this means that you will instantly see changes in the
game as you code it. Very useful, highly recommended.
- In order to use it, you should start the game server first, connect to it
and wait until the world has been properly loaded and you are no longer
in the lobby. Start tgui dev server. You'll know that it's hooked correctly
if data gets dumped to the log when tgui windows are opened.
- `bin/tgui --dev --reload` - reload byond cache once.
- `bin/tgui --dev --debug` - run server with debug logging enabled.
- `bin/tgui --dev --no-hot` - disable hot module replacement (helps when
doing development on IE8).
- `bin/tgui --lint` - show problems with the code.
- `bin/tgui --lint --fix` - auto-fix problems with the code.
- `bin/tgui --analyze` - run a bundle analyzer.
- `bin/tgui --clean` - clean up project repo.
- `bin/tgui [webpack options]` - build the project with custom webpack
options.

**For everyone else:**

If you haven't opened the console already, you can do that by holding
Shift and right clicking on the `tgui` folder, then pressing
either `Open command window here` or `Open PowerShell window here`.

Run `yarn install` to install npm dependencies, then one of the following:

- `yarn run build` - build the project in production mode.
- `yarn run watch` - launch a development server.
- `yarn run lint` - show problems with the code.
- `yarn run lint --fix` - auto-fix problems with the code.
- `yarn run analyze` - run a bundle analyzer.

We also got some batch files in store, for those who don't like fiddling
with the console:

- `bin/tgui-build.bat` - build the project in production mode.
- `bin/tgui-dev-server.bat` - launch a development server.

> Remember to always run a full build before submitting a PR. It creates
> a compressed javascript bundle which is then referenced from DM code.
> We prefer to keep it version controlled, so that people could build the
> game just by using Dream Maker.

## Project structure

- `/packages` - Each folder here represents a self-contained Node module.
- `/packages/common` - Helper functions
- `/packages/tgui/index.js` - Application entry point.
- `/packages/tgui/components` - Basic UI building blocks.
- `/packages/tgui/interfaces` - Actual in-game interfaces.
Interface takes data via the `state` prop and outputs an html-like stucture,
which you can build using existing UI components.
- `/packages/tgui/routes.js` - This is where you want to register new
interfaces, otherwise they simply won't load.
- `/packages/tgui/layout.js` - A root-level component, holding the
window elements, like the titlebar, buttons, resize handlers. Calls
`routes.js` to decide which component to render.
- `/packages/tgui/styles/main.scss` - CSS entry point.
- `/packages/tgui/styles/atomic.scss` - Atomic CSS classes.
These are very simple, tiny, reusable CSS classes which you can use and
combine to change appearance of your elements. Keep them small.
- `/packages/tgui/styles/components.scss` - CSS classes which are used
in UI components, and most of the stylesheets referenced here are located
in `/packages/tgui/components`. These stylesheets closely follow the
[BEM](https://en.bem.info/methodology/) methodology.
- `/packages/tgui/styles/functions.scss` - Useful SASS functions.
Stuff like `lighten`, `darken`, `luminance` are defined here.

## Component reference

> Notice: This documentation might be out of date, so always check the source
> code to see the most up-to-date information.

These are the components which you can use for interface construction.
If you have trouble finding the exact prop you need on a component,
please note, that most of these components inherit from other basic
components, such as `Box`. This component in particular provides a lot
of styling options for all components, e.g. `color` and `opacity`, thus
it is used a lot in this framework.

There are a few important semantics you need to know about:

- `content` prop is a synonym to a `children` prop.
- `content` is better used when your element is a self-closing tag
(like `<Button content="Hello" />`), and when content is small and simple
enough to fit in a prop. Keep in mind, that this prop is **not** native
to React, and is a feature of this component system.
- `children` is better used when your element is a full tag (like
`<Button>Hello</Button>`), and when content is long and complex. This is
a native React prop (unlike `content`), and contains all elements you
defined between the opening and the closing tag of an element.
- You should never use both on a same element.
- You should never use `children` explicitly as a prop on an element.
- Inferno supports both camelcase (`onClick`) and lowercase (`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)
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 straight up does not support lowercase event
handlers. Use the camel case `onClick` instead.

### `AnimatedNumber`

This component provides animations for numeric values.

Props:

- `value: number` - Value to animate.
- `initial: number` - Initial value to use in animation when element
first appears. If you set initial to `0` for example, number will always
animate starting from `0`, and if omitted, it will not play an initial
animation.
- `format: value => value` - Output formatter.
- Example: `value => Math.round(value)`.
- `children: (formattedValue, rawValue) => any` - Pull the animated number to
animate more complex things deeper in the DOM tree.
- Example: `(_, value) => <Icon rotation={value} />`

### `BlockQuote`

Just a block quote, just like this example in markdown:

> Here's an example of a block quote.

Props:

- See inherited props: [Box](#box)

### `Box`

The Box component serves as a wrapper component for most of the CSS utility
needs. It creates a new DOM element, a `<div>` by default that can be changed
with the `as` property. Let's say you want to use a `<span>` instead:

```jsx
<Box as="span" m={1}>
<Button />
</Box>
```

This works great when the changes can be isolated to a new DOM element.
For instance, you can change the margin this way.

However, sometimes you have to target the underlying DOM element.
For instance, you want to change the text color of the button. The Button
component defines its own color. CSS inheritance doesn't help.

To workaround this problem, the Box children accept a render props function.
This way, `Button` can pull out the `className` generated by the `Box`.

```jsx
<Box color="primary">
{props => <Button {...props} />}
</Box>
```

`Box` units, like width, height and margins can be defined in two ways:
- By plain numbers (1 unit equals `0.5em`);
- In absolute measures, by providing a full unit string (e.g. `100px`).

Units which are used in `Box` are `0.5em`, which are half font-size.
Default font size is `12px`, so each unit is effectively `6px` in size.
If you need more precision, you can always use fractional numbers.

Props:

- `as: string` - The component used for the root node.
- `color: string` - Applies an atomic `color-<name>` class to the element.
- See `styles/atomic/color.scss`.
- `width: number` - Box width.
- `minWidth: number` - Box minimum width.
- `maxWidth: number` - Box maximum width.
- `height: number` - Box height.
- `minHeight: number` - Box minimum height.
- `maxHeight: number` - Box maximum height.
- `fontSize: number` - Font size.
- `fontFamily: string` - Font family.
- `lineHeight: number` - Directly affects the height of text lines.
Useful for adjusting button height.
- `inline: boolean` - Forces the `Box` to appear as an `inline-block`,
or in other words, makes the `Box` flow with the text instead of taking
all available horizontal space.
- `m: number` - Margin on all sides.
- `mx: number` - Horizontal margin.
- `my: number` - Vertical margin.
- `mt: number` - Top margin.
- `mb: number` - Bottom margin.
- `ml: number` - Left margin.
- `mr: number` - Right margin.
- `opacity: number` - Opacity, from 0 to 1.
- `bold: boolean` - Make text bold.
- `italic: boolean` - Make text italic.
- `nowrap: boolean` - Stops text from wrapping.
- `textAlign: string` - Align text inside the box.
- `left` (default)
- `center`
- `right`
- `position: string` - A direct mapping to `position` CSS property.
- `relative` - Relative positioning.
- `absolute` - Absolute positioning.
- `fixed` - Fixed positioning.
- `color: string` - An alias to `textColor`.
- `textColor: string` - Sets text color.
- `#ffffff` - Hex format
- `rgba(255, 255, 255, 1)` - RGB format
- `purple` - Applies an atomic `color-<name>` class to the element.
See `styles/color-map.scss`.
- `backgroundColor: string` - Sets background color.
- `#ffffff` - Hex format
- `rgba(255, 255, 255, 1)` - RGB format

### `Button`

Buttons allow users to take actions, and make choices, with a single click.

Props:

- See inherited props: [Box](#box)
- `fluid: boolean` - Fill all available horizontal space.
- `icon: string` - Adds an icon to the button.
- `color: string` - Button color, as defined in `variables.scss`.
- There is also a special color `transparent` - makes the button
transparent and slightly dim when inactive.
- `disabled: boolean` - Disables and greys out the button.
- `selected: boolean` - Activates the button (gives it a green color).
- `tooltip: string` - A fancy, boxy tooltip, which appears when hovering
over the button.
- `tooltipPosition: string` - Position of the tooltip.
- `top` - Show tooltip above the button.
- `bottom` (default) - Show tooltip below the button.
- `left` - Show tooltip on the left of the button.
- `right` - Show tooltip on the right of the button.
- `ellipsis: boolean` - If button width is constrained, button text will
be truncated with an ellipsis. Be careful however, because this prop breaks
the baseline alignment.
- `title: string` - A native browser tooltip, which appears when hovering
over the button.
- `content/children: any` - Content to render inside the button.
- `onClick: function` - Called when element is clicked.

### `Button.Checkbox`

A ghetto checkbox, made entirely using existing Button API.

Props:

- See inherited props: [Button](#button)
- `checked: boolean` - Boolean value, which marks the checkbox as checked.

### `Button.Confirm`

A button with a an extra confirmation step, using native button component.

Props:

- See inherited props: [Button](#button)
- `confirmMessage: string` - Text to display after first click; defaults to "Confirm?"
- `confirmColor: string` - Color to display after first click; defaults to "bad"

### `Button.Input`

A button that turns into an input box after the first click. Turns back into a
button after the user hits enter, defocuses, or hits escape. Enter and defocus
commit, while escape cancels.

Props:

- See inherited props: [Box](#box)
- `fluid`: fill availible horizontal space
- `onCommit: (e, value) => void`: function that is called after the user
defocuses the input or presses enter
- `currentValue: string`: default string to display when the input is shown
- `defaultValue: string`: default value emitted if the user leaves the box
blank when hitting enter or defocusing. If left undefined, will cancel the
change on a blank defocus/enter

### `Collapsible`

Displays contents when open, acts as a fluid button when closed. Click to
toggle, closed by default.

Props:

- See inherited props: [Box](#box)
- `children: any` - What is collapsed when closed
- `title: string` - Text to display on the button for collapsing
- `color: string` - Color of the button; see [Button](#button)
- `buttons: any` - Buttons or other content to render inline with the button

### `ColorBox`

Displays a 1-character wide colored square. Can be used as a status indicator,
or for visually representing a color.

If you want to set a background color on an element, use a plain
[Box](#box) instead.

Props:

- See inherited props: [Box](#box)
- `color: string` - Color of the box.

### `Dimmer`

Dims surrounding area to emphasize content placed inside.

tgui is very different from most UIs you will encounter in BYOND programming, and is heavily reliant of Javascript and web technologies as opposed to DM. However, if you are familiar with NanoUI (a library which can be found on almost every other SS13 codebase), tgui should be fairly easy to pick up.
Props:

tgui is a fork of NanoUI. The server-side code (DM) is similar and derived from NanoUI, while the clientside is a wholly new project with no code in common.
- See inherited props: [Box](#box)

## Concepts
tgui is loosely based a MVVM architecture. MVVM stands for model, view, view model.
- A model is the object that a UI represents. This is the atom a UI corresponds to in the game world in most cases, and is known as the `src_object` in tgui.
- The view model is how data is represented in terms of the view. In tgui, this is the `ui_data` proc which munges whatever complex data your `src_object` has into a list.
- The view is how the data is rendered. This is the template, a HTML (plus mustaches and other goodies) file which is compiled into the tgui blob that the browser executes.
### `Dropdown`

Not included in the MVVM model are other important concepts:
- The action/topic handler, `ui_act`, is what recieves input from the user and acts on it.
- The request/update proc, `ui_interact` is where you open your UI and set options like title, size, autoupdate, theme, and more.
- Finally, `ui_state`s (set in `ui_interact`) dictate under what conditions a UI may be interacted with. This may be the standard checks that check if you are in range and conscious, or more.
A simple dropdown box component. Lets the user select from a list of options
and displays selected entry.

States are easy to write and extend, and what make tgui interactions so powerful. Because states can over overridden from other procs, you can build powerful interactions for embedded objects or remote access.
Props:

## Using It
All these examples and abstracts sound great, you might say. But you also might say, "How do I use it?"
- See inherited props: [Box](#box)
- `options: string[]` - An array of strings which will be displayed in the
dropdown when open
- `selected: string` - Currently selected entry
- `width: number` - Width of dropdown button and resulting menu
- `over: boolean` - dropdown renders over instead of below
- `color: string` - color of dropdown button
- `onClick: (e) => void` - Called when dropdown button is clicked
- `onSelected: (value) => void` - Called when a value is picked from the list, `value` is the value that was picked

Examples can be as simple or as complex as you would like. Let's start with a very basic hello world.
### `Flex`

```DM
/obj/machinery/my_machine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "my_machine", name, 300, 300, master_ui, state)
ui.open()
Quickly manage the layout, alignment, and sizing of grid columns, navigation,
components, and more with a full suite of responsive flexbox utilities.

If you are new to or unfamiliar with flexbox, we encourage you to read this
[CSS-Tricks flexbox guide](https://css-tricks.com/snippets/css/a-guide-to-flexbox/).

Consists of two elements: `<Flex>` and `<Flex.Item>`. Both of them provide
the most straight-forward mapping to flex CSS properties as possible.

One of the most basic usage of flex, is to align certain elements
to the left, and certain elements to the right:

```jsx
<Flex>
<Flex.Item>
Button description
</Flex.Item>
<Flex.Item grow={1} />
<Flex.Item>
<Button content="Perform an action" />
</Flex.Item>
</Flex>
```

Flex item with `grow` property serves as a "filler", to separate the other
two flex items as far as possible from each other.

Props:

- See inherited props: [Box](#box)
- `spacing: number` - Spacing between flex items, in integer units
(1 unit - 0.5em). Does not directly relate to a flex css property
(adds a modifier class under the hood), and only integer numbers are
supported.
- `direction: string` - This establishes the main-axis, thus defining the
direction flex items are placed in the flex container.
- `row` (default) - left to right.
- `row-reverse` - right to left.
- `column` - top to bottom.
- `column-reverse` - bottom to top.
- `wrap: string` - By default, flex items will all try to fit onto one line.
You can change that and allow the items to wrap as needed with this property.
- `nowrap` (default) - all flex items will be on one line
- `wrap` - flex items will wrap onto multiple lines, from top to bottom.
- `wrap-reverse` - flex items will wrap onto multiple lines from bottom to top.
- `align: string` - Default alignment of all children.
- `stretch` (default) - stretch to fill the container.
- `start` - items are placed at the start of the cross axis.
- `end` - items are placed at the end of the cross axis.
- `center` - items are centered on the cross axis.
- `baseline` - items are aligned such as their baselines align.
- `justify: string` - This defines the alignment along the main axis.
It helps distribute extra free space leftover when either all the flex
items on a line are inflexible, or are flexible but have reached their
maximum size. It also exerts some control over the alignment of items
when they overflow the line.
- `flex-start` (default) - items are packed toward the start of the
flex-direction.
- `flex-end` - items are packed toward the end of the flex-direction.
- `space-between` - items are evenly distributed in the line; first item is
on the start line, last item on the end line
- `space-around` - items are evenly distributed in the line with equal space
around them. Note that visually the spaces aren't equal, since all the items
have equal space on both sides. The first item will have one unit of space
against the container edge, but two units of space between the next item
because that next item has its own spacing that applies.
- `space-evenly` - items are distributed so that the spacing between any two
items (and the space to the edges) is equal.
- TBD (not all properties are supported in IE11).

### `Flex.Item`

Props:

- See inherited props: [Box](#box)
- `order: number` - By default, flex items are laid out in the source order.
However, the order property controls the order in which they appear in the
flex container.
- `grow: number` - This defines the ability for a flex item to grow if
necessary. It accepts a unitless value that serves as a proportion. It
dictates what amount of the available space inside the flex container the
item should take up. This number is unit-less and is relative to other
siblings.
- `shrink: number` - This defines the ability for a flex item to shrink
if necessary. Inverse of `grow`.
- `basis: string` - This defines the default size of an element before the
remaining space is distributed. It can be a length (e.g. `20%`, `5rem`, etc.),
an `auto` or `content` keyword.
- `align: string` - This allows the default alignment (or the one specified by
align-items) to be overridden for individual flex items. See: [Flex](#flex).

### `Grid`

Helps you to divide horizontal space into two or more equal sections.
It is essentially a single-row `Table`, but with some extra features.

Example:

```jsx
<Grid>
<Grid.Column>
<Section title="Section 1" content="Hello world!" />
</Grid.Column>
<Grid.Column size={2}>
<Section title="Section 2" content="Hello world!" />
</Grid.Column>
</Grid>
```

This is the proc that defines our interface. There's a bit going on here, so let's break it down. First, we override the ui_interact proc on our object. This will be called by `interact` for you, which is in turn called by `attack_hand` (or `attack_self` for items). `ui_interact` is also called to update a UI (hence the `try_update_ui`), so we accept an existing UI to update. The `state` is a default argument so that a caller can overload it with named arguments (`ui_interact(state = overloaded_state)`) if needed.
Props:

- See inherited props: [Table](#table)

### `Grid.Column`

Props:

- See inherited props: [Table.Cell](#tablecell)
- `size: number` (default: 1) - Size of the column relative to other columns.

### `Icon`

Renders one of the FontAwesome icons of your choice.

```jsx
<Icon name="plus" />
```

To smoothen the transition from v4 to v5, we have added a v4 semantic to
transform names with `-o` suffixes to FA Regular icons. For example:
- `square` will get transformed to `fas square`
- `square-o` will get transformed to `far square`

Props:

- See inherited props: [Box](#box)
- `name: string` - Icon name.
- `size: number` - Icon size. `1` is normal size, `2` is two times bigger.
Fractional numbers are supported.
- `rotation: number` - Icon rotation, in degrees.
- `spin: boolean` - Whether an icon should be spinning. Good for load
indicators.

### `Input`

A basic text input, which allow users to enter text into a UI.

> Input does not support custom font size and height due to the way
> it's implemented in CSS. Eventually, this needs to be fixed.

Props:

- See inherited props: [Box](#box)
- `value: string` - Value of an input.
- `placeholder: string` - Text placed into Input box when it's empty,
otherwise nothing. Clears automatically when focused.
- `fluid: boolean` - Fill all available horizontal space.
- `selfClear: boolean` - Clear after hitting enter, as well as remain focused
when this happens. Useful for things like chat inputs.
- `onChange: (e, value) => void` - An event, which fires when you commit
the text by either unfocusing the input box, or by pressing the Enter key.
- `onInput: (e, value) => void` - An event, which fires on every keypress.

### `LabeledList`

LabeledList is a continuous, vertical list of text and other content, where
every item is labeled. It works just like a two column table, where first
column is labels, and second column is content.

```jsx
<LabeledList>
<LabeledList.Item label="Item">
Content
</LabeledList.Item>
</LabeledList>
```

If you want to have a button on the right side of an item (for example,
to perform some sort of action), there is a way to do that:

```jsx
<LabeledList>
<LabeledList.Item
label="Item"
buttons={(
<Button content="Click me!" />
)}>
Content
</LabeledList.Item>
</LabeledList>
```

Props:

- `children: LabeledList.Item` - Items to render.

### `LabeledList.Item`

Inside the `if(!ui)` block (which means we are creating a new UI), we choose our template, title, and size; we can also set various options like `style` (for themes), or autoupdate. These options will be elaborated on later (as will `ui_state`s).
Props:

After `ui_interact`, we need to define `ui_data`. This just returns a list of data for our object to use. Let's imagine our object has a few vars:
- `label: string` - Item label.
- `color: string` - Sets the color of the text.
- `buttons: any` - Buttons to render aside the content.
- `content/children: any` - Content of this labeled item.

```DM
/obj/machinery/my_machine/ui_data(mob/user)
var/list/data = list()
data["health"] = health
data["color"] = color
### `LabeledList.Divider`

return data
Adds some empty space between LabeledList items.

Example:

```jsx
<LabeledList>
<LabeledList.Item label="Foo">
Content
</LabeledList.Item>
<LabeledList.Divider size={1} />
</LabeledList>
```

The `ui_data` proc is what people often find the hardest about tgui, but its really quite simple! You just need to represent your object as numbers, strings, and lists, instead of atoms and datums.
Props:

- `size: number` - Size of the divider.

### `NoticeBox`

A notice box, which warns you about something very important.

Props:

- See inherited props: [Box](#box)

### `NumberInput`

A fancy, interactive number input, which you can either drag up and down
to fine tune the value, or single click it to manually type a number.

Props:

- `animated: boolean` - Animates the value if it was changed externally.
- `fluid: boolean` - Fill all available horizontal space.
- `value: number` - Value itself.
- `unit: string` - Unit to display to the right of value.
- `minValue: number` - Lowest possible value.
- `maxValue: number` - Highest possible value.
- `step: number` (default: 1) - Adjust value by this amount when
dragging the input.
- `stepPixelSize: number` (default: 1) - Screen distance mouse needs
to travel to adjust value by one `step`.
- `width: string|number` - Width of the element, in `Box` units or pixels.
- `height: string|numer` - Height of the element, in `Box` units or pixels.
- `lineHeight: string|number` - lineHeight of the element, in `Box` units or pixels.
- `fontSize: string|number` - fontSize of the element, in `Box` units or pixels.
- `format: value => value` - Format value using this function before
displaying it.
- `suppressFlicker: number` - A number in milliseconds, for which the input
will hold off from updating while events propagate through the backend.
Default is about 250ms, increase it if you still see flickering.
- `onChange: (e, value) => void` - An event, which fires when you release
the input, or successfully enter a number.
- `onDrag: (e, value) => void` - An event, which fires about every 500ms
when you drag the input up and down, on release and on manual editing.

Finally, the `ui_act` proc is called by the interface whenever the user used an input. The input's `action` and `params` are passed to the proc.
### `ProgressBar`

```DM
/obj/machinery/my_machine/ui_act(action, params)
if(..())
return
switch(action)
if("change_color")
var/new_color = params["color"]
if(!(color in allowed_coors))
return
color = new_color
. = TRUE
update_icon()
Progress indicators inform users about the status of ongoing processes.

```jsx
<ProgressBar value={0.6} />
```

The `..()` (parent call) is very important here, as it is how we check that the user is allowed to use this interface (to avoid so-called href exploits). It is also very important to clamp and sanitize all input here. Always assume the user is attempting to exploit the game.
Usage of `ranges` prop:

```jsx
<ProgressBar
ranges={{
good: [0.5, Infinity],
average: [0.25, 0.5],
bad: [-Infinity, 0.25],
}}
value={0.6} />
```