diff --git a/code/modules/client/preference_setup/global/01_ui.dm b/code/modules/client/preference_setup/global/01_ui.dm
index 7f96fca3d0..221b89fcc2 100644
--- a/code/modules/client/preference_setup/global/01_ui.dm
+++ b/code/modules/client/preference_setup/global/01_ui.dm
@@ -14,7 +14,6 @@
S["tgui_fancy"] >> pref.tgui_fancy
S["tgui_lock"] >> pref.tgui_lock
S["tgui_input_mode"] >> pref.tgui_input_mode
- S["tgui_input_lock"] >> pref.tgui_input_lock
S["tgui_large_buttons"] >> pref.tgui_large_buttons
S["tgui_swapped_buttons"] >> pref.tgui_swapped_buttons
S["obfuscate_key"] >> pref.obfuscate_key
@@ -34,7 +33,6 @@
S["tgui_fancy"] << pref.tgui_fancy
S["tgui_lock"] << pref.tgui_lock
S["tgui_input_mode"] << pref.tgui_input_mode
- S["tgui_input_lock"] << pref.tgui_input_lock
S["tgui_large_buttons"] << pref.tgui_large_buttons
S["tgui_swapped_buttons"] << pref.tgui_swapped_buttons
S["obfuscate_key"] << pref.obfuscate_key
@@ -54,7 +52,6 @@
pref.tgui_fancy = sanitize_integer(pref.tgui_fancy, 0, 1, initial(pref.tgui_fancy))
pref.tgui_lock = sanitize_integer(pref.tgui_lock, 0, 1, initial(pref.tgui_lock))
pref.tgui_input_mode = sanitize_integer(pref.tgui_input_mode, 0, 1, initial(pref.tgui_input_mode))
- pref.tgui_input_lock = sanitize_integer(pref.tgui_input_lock, 0, 1, initial(pref.tgui_input_lock))
pref.tgui_large_buttons = sanitize_integer(pref.tgui_large_buttons, 0, 1, initial(pref.tgui_large_buttons))
pref.tgui_swapped_buttons = sanitize_integer(pref.tgui_swapped_buttons, 0, 1, initial(pref.tgui_swapped_buttons))
pref.obfuscate_key = sanitize_integer(pref.obfuscate_key, 0, 1, initial(pref.obfuscate_key))
@@ -74,7 +71,6 @@
. += "TGUI Window Mode: [(pref.tgui_fancy) ? "Fancy (default)" : "Compatible (slower)"]
"
. += "TGUI Window Placement: [(pref.tgui_lock) ? "Primary Monitor" : "Free (default)"]
"
. += "TGUI Input Framework: [(pref.tgui_input_mode) ? "Enabled" : "Disabled (default)"]
"
- . += "TGUI Input Lock: [(pref.tgui_input_lock) ? "Enabled" : "Disabled (default)"]
"
. += "TGUI Large Buttons: [(pref.tgui_large_buttons) ? "Enabled (default)" : "Disabled"]
"
. += "TGUI Swapped Buttons: [(pref.tgui_swapped_buttons) ? "Enabled" : "Disabled (default)"]
"
. += "Obfuscate Ckey: [(pref.obfuscate_key) ? "Enabled" : "Disabled (default)"]
"
@@ -154,10 +150,6 @@
pref.tgui_input_mode = !pref.tgui_input_mode
return TOPIC_REFRESH
- else if(href_list["tgui_input_lock"])
- pref.tgui_input_lock = !pref.tgui_input_lock
- return TOPIC_REFRESH
-
else if(href_list["tgui_large_buttons"])
pref.tgui_large_buttons = !pref.tgui_large_buttons
return TOPIC_REFRESH
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 810dab44bf..21c3ced2ac 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -29,7 +29,6 @@ var/list/preferences_datums = list()
var/tgui_fancy = TRUE
var/tgui_lock = FALSE
var/tgui_input_mode = FALSE // All the Input Boxes (Text,Number,List,Alert)
- var/tgui_input_lock = FALSE
var/tgui_large_buttons = TRUE
var/tgui_swapped_buttons = FALSE
var/obfuscate_key = FALSE
diff --git a/code/modules/client/preferences_toggle_procs.dm b/code/modules/client/preferences_toggle_procs.dm
index fb5f3d70c5..9e9f00c659 100644
--- a/code/modules/client/preferences_toggle_procs.dm
+++ b/code/modules/client/preferences_toggle_procs.dm
@@ -379,17 +379,6 @@
You will have to reload TGChat and/or reconnect to the server for these changes to take place. \
TGChat message persistence is not guaranteed if you change this again before the start of the next round.")
-/client/verb/toggle_tgui_inputlock()
- set name = "Toggle TGUI Input Lock"
- set category = "Preferences"
- set desc = "Toggles whether or not pressing the 'Enter' key in TGUI input sends the message or creates a new line."
-
- prefs.tgui_input_lock = !prefs.tgui_input_lock //There is no preference datum for tgui input lock, nor for any TGUI prefs.
- SScharacter_setup.queue_preferences_save(prefs)
-
- to_chat(src, span_notice("You have toggled TGUI input lock: [prefs.tgui_input_lock ? "ON" : "OFF"] \n \
- This setting determines whether pressing enter on TGUI input sends the input, or creates a newline."))
-
/client/verb/toggle_chat_timestamps()
set name = "Toggle Chat Timestamps"
set category = "Preferences"
diff --git a/code/modules/tgui_input/checkboxes.dm b/code/modules/tgui_input/checkboxes.dm
index 0b1d653955..adac0d0d22 100644
--- a/code/modules/tgui_input/checkboxes.dm
+++ b/code/modules/tgui_input/checkboxes.dm
@@ -14,13 +14,17 @@
if (!user)
user = usr
if(!length(items))
- return
+ return null
if (!istype(user))
if (istype(user, /client))
var/client/client = user
user = client.mob
else
- return
+ return null
+
+ if(isnull(user.client))
+ return null
+
if(!user.client.prefs.tgui_input_mode)
return input(user, message, title) as null|anything in items
var/datum/tgui_checkbox_input/input = new(user, message, title, items, min_checked, max_checked, timeout, ui_state)
@@ -66,7 +70,7 @@
start_time = world.time
QDEL_IN(src, timeout)
-/datum/tgui_checkbox_input/Destroy(force, ...)
+/datum/tgui_checkbox_input/Destroy(force)
SStgui.close_uis(src)
state = null
QDEL_NULL(items)
diff --git a/code/modules/tgui_input/list.dm b/code/modules/tgui_input/list.dm
index c079f0be74..bd51aee060 100644
--- a/code/modules/tgui_input/list.dm
+++ b/code/modules/tgui_input/list.dm
@@ -7,28 +7,31 @@
* * message - The content of the input box, shown in the body of the TGUI window.
* * title - The title of the input box, shown on the top of the TGUI window.
* * items - The options that can be chosen by the user, each string is assigned a button on the UI.
- * * default - The option with this value will be selected on first paint of the TGUI window.
- * * timeout - The timeout of the input box, after which the input box will close and qdel itself. Set to zero for no timeout.
- * * strict_modern - Disabled the preference check of the input box, only allowing the TGUI window to show.
+ * * default - If an option is already preselected on the UI. Current values, etc.
+ * * timeout - The timeout of the input box, after which the menu will close and qdel itself. Set to zero for no timeout.
*/
-/proc/tgui_input_list(mob/user, message, title = "Select", list/items, default, timeout = 0, strict_modern = FALSE)
- if (istext(user))
- stack_trace("tgui_alert() received text for user instead of mob")
- return
+/proc/tgui_input_list(mob/user, message, title = "Select", list/items, default, timeout = 0, strict_modern = FALSE, ui_state = GLOB.tgui_always_state)
if (!user)
user = usr
if(!length(items))
- return
+ return null
if (!istype(user))
if (istype(user, /client))
var/client/client = user
user = client.mob
else
- return
+ return null
+
+ if(isnull(user.client))
+ return null
+
/// Client does NOT have tgui_input on: Returns regular input
if(!user.client.prefs.tgui_input_mode && !strict_modern)
return input(user, message, title, default) as null|anything in items
- var/datum/tgui_list_input/input = new(user, message, title, items, default, timeout)
+ var/datum/tgui_list_input/input = new(user, message, title, items, default, timeout, ui_state)
+ if(input.invalid)
+ qdel(input)
+ return
input.tgui_interact(user)
input.wait()
if (input)
@@ -48,11 +51,11 @@
var/message
/// The list of items (responses) provided on the TGUI window
var/list/items
- /// Items (strings specifically) mapped to the actual value (e.g. a mob or a verb)
+ /// Buttons (strings specifically) mapped to the actual value (e.g. a mob or a verb)
var/list/items_map
/// The button that the user has pressed, null if no selection has been made
var/choice
- /// The default item to be selected
+ /// The default button to be selected
var/default
/// The time at which the tgui_list_input was created, for displaying timeout progress.
var/start_time
@@ -60,41 +63,42 @@
var/timeout
/// Boolean field describing if the tgui_list_input was closed by the user.
var/closed
+ /// The TGUI UI state that will be returned in ui_state(). Default: always_state
+ var/datum/tgui_state/state
+ /// Whether the tgui list input is invalid or not (i.e. due to all list entries being null)
+ var/invalid = FALSE
-/datum/tgui_list_input/New(mob/user, message, title, list/items, default, timeout)
+/datum/tgui_list_input/New(mob/user, message, title, list/items, default, timeout, ui_state)
src.title = title
src.message = message
src.items = list()
src.items_map = list()
src.default = default
+ src.state = ui_state
var/list/repeat_items = list()
-
// Gets rid of illegal characters
var/static/regex/whitelistedWords = regex(@{"([^\u0020-\u8000]+)"})
-
for(var/i in items)
- if(isnull(i))
- stack_trace("Null in a tgui_input_list() items")
+ if(!i)
continue
-
var/string_key = whitelistedWords.Replace("[i]", "")
-
//avoids duplicated keys E.g: when areas have the same name
string_key = avoid_assoc_duplicate_keys(string_key, repeat_items)
-
src.items += string_key
src.items_map[string_key] = i
-
+ if(length(src.items) == 0)
+ invalid = TRUE
if (timeout)
src.timeout = timeout
start_time = world.time
QDEL_IN(src, timeout)
-/datum/tgui_list_input/Destroy(force, ...)
+/datum/tgui_list_input/Destroy(force)
SStgui.close_uis(src)
+ state = null
QDEL_NULL(items)
- . = ..()
+ return ..()
/**
* Waits for a user's response to the tgui_list_input's prompt before returning. Returns early if
@@ -115,7 +119,7 @@
closed = TRUE
/datum/tgui_list_input/tgui_state(mob/user)
- return GLOB.tgui_always_state
+ return state
/datum/tgui_list_input/tgui_static_data(mob/user)
var/list/data = list()
@@ -146,68 +150,9 @@
SStgui.close_uis(src)
return TRUE
if("cancel")
- SStgui.close_uis(src)
closed = TRUE
+ SStgui.close_uis(src)
return TRUE
/datum/tgui_list_input/proc/set_choice(choice)
src.choice = choice
-
-/**
- * Creates an asynchronous TGUI input list window with an associated callback.
- *
- * This proc should be used to create inputs that invoke a callback with the user's chosen option.
- * Arguments:
- * * user - The user to show the input box to.
- * * message - The content of the input box, shown in the body of the TGUI window.
- * * title - The title of the input box, shown on the top of the TGUI window.
- * * items - The options that can be chosen by the user, each string is assigned a button on the UI.
- * * default - The option with this value will be selected on first paint of the TGUI window.
- * * callback - The callback to be invoked when a choice is made.
- * * timeout - The timeout of the input box, after which the menu will close and qdel itself. Set to zero for no timeout.
- */
-/proc/tgui_input_list_async(mob/user, message, title, list/items, default, datum/callback/callback, timeout = 60 SECONDS)
- if (istext(user))
- stack_trace("tgui_alert() received text for user instead of mob")
- return
- if (!user)
- user = usr
- if(!length(items))
- return
- if (!istype(user))
- if (istype(user, /client))
- var/client/client = user
- user = client.mob
- else
- return
- var/datum/tgui_list_input/async/input = new(user, message, title, items, default, callback, timeout)
- input.tgui_interact(user)
-
-/**
- * # async tgui_list_input
- *
- * An asynchronous version of tgui_list_input to be used with callbacks instead of waiting on user responses.
- */
-/datum/tgui_list_input/async
- /// The callback to be invoked by the tgui_list_input upon having a choice made.
- var/datum/callback/callback
-
-/datum/tgui_list_input/async/New(mob/user, message, title, list/items, default, callback, timeout)
- ..(user, title, message, items, default, timeout)
- src.callback = callback
-
-/datum/tgui_list_input/async/Destroy(force, ...)
- QDEL_NULL(callback)
- . = ..()
-
-/datum/tgui_list_input/async/tgui_close(mob/user)
- . = ..()
- qdel(src)
-
-/datum/tgui_list_input/async/set_choice(choice)
- . = ..()
- if(!isnull(src.choice))
- callback?.InvokeAsync(src.choice)
-
-/datum/tgui_list_input/async/wait()
- return
diff --git a/code/modules/tgui_input/number.dm b/code/modules/tgui_input/number.dm
index 4aadb5edc1..dfcfc73570 100644
--- a/code/modules/tgui_input/number.dm
+++ b/code/modules/tgui_input/number.dm
@@ -152,60 +152,3 @@
/datum/tgui_input_number/proc/set_entry(entry)
src.entry = entry
-
-/**
- * Creates an asynchronous TGUI input num window with an associated callback.
- *
- * This proc should be used to create inputs that invoke a callback with the user's chosen option.
- * Arguments:
- * * user - The user to show the input box to.
- * * message - The content of the input box, shown in the body of the TGUI window.
- * * title - The title of the input box, shown on the top of the TGUI window.
- * * default - The default value pre-populated in the input box.
- * * callback - The callback to be invoked when a choice is made.
- * * timeout - The timeout of the input box, after which the menu will close and qdel itself. Set to zero for no timeout.
- * * round_value - whether the inputted number is rounded down into an integer.
- */
-/proc/tgui_input_number_async(mob/user, message, title, default, datum/callback/callback, timeout = 60 SECONDS, round_value = FALSE)
- if (istext(user))
- stack_trace("tgui_input_num_async() received text for user instead of mob")
- return
- if (!user)
- user = usr
- if (!istype(user))
- if (istype(user, /client))
- var/client/client = user
- user = client.mob
- else
- return
- var/datum/tgui_input_number/async/input = new(user, message, title, default, callback, timeout, round_value)
- input.tgui_interact(user)
-
-/**
- * # async tgui_text_input
- *
- * An asynchronous version of tgui_text_input to be used with callbacks instead of waiting on user responses.
- */
-/datum/tgui_input_number/async
- /// The callback to be invoked by the tgui_text_input upon having a choice made.
- var/datum/callback/callback
-
-/datum/tgui_input_number/async/New(mob/user, message, title, default, callback, timeout, round_value)
- ..(user, title, message, default, timeout, round_value)
- src.callback = callback
-
-/datum/tgui_input_number/async/Destroy(force, ...)
- QDEL_NULL(callback)
- . = ..()
-
-/datum/tgui_input_number/async/tgui_close(mob/user)
- . = ..()
- qdel(src)
-
-/datum/tgui_input_number/async/set_entry(entry)
- . = ..()
- if(!isnull(src.entry))
- callback?.InvokeAsync(src.entry)
-
-/datum/tgui_input_number/async/wait()
- return
\ No newline at end of file
diff --git a/code/modules/tgui_input/text.dm b/code/modules/tgui_input/text.dm
index 614f9e142e..8dc1e5a6c4 100644
--- a/code/modules/tgui_input/text.dm
+++ b/code/modules/tgui_input/text.dm
@@ -16,9 +16,6 @@
* * timeout - The timeout of the textbox, after which the modal will close and qdel itself. Set to zero for no timeout.
*/
/proc/tgui_input_text(mob/user, message = "", title = "Text Input", default, max_length = INFINITY, multiline = FALSE, encode = FALSE, timeout = 0, prevent_enter = FALSE)
- if (istext(user))
- stack_trace("tgui_input_text() received text for user instead of mob")
- return
if (!user)
user = usr
if (!istype(user))
@@ -27,6 +24,10 @@
user = client.mob
else
return
+
+ if(isnull(user.client))
+ return null
+
// Client does NOT have tgui_input on: Returns regular input
if(!user.client.prefs.tgui_input_mode)
if(encode)
@@ -40,11 +41,7 @@
else
return input(user, message, title, default) as text|null
- //Client has TGUI input lock on; override whatever prevent_enter was specified beforehand
- if(user.client.prefs.tgui_input_lock)
- prevent_enter = TRUE
-
- var/datum/tgui_input_text/text_input = new(user, message, title, default, max_length, multiline, encode, timeout, prevent_enter)
+ var/datum/tgui_input_text/text_input = new(user, message, title, default, max_length, multiline, encode, timeout)
text_input.tgui_interact(user)
text_input.wait()
if (text_input)
@@ -79,9 +76,7 @@
/// The title of the TGUI window
var/title
- var/prevent_enter
-
-/datum/tgui_input_text/New(mob/user, message, title, default, max_length, multiline, encode, timeout, prevent_enter)
+/datum/tgui_input_text/New(mob/user, message, title, default, max_length, multiline, encode, timeout)
src.default = default
src.encode = encode
src.max_length = max_length
@@ -92,18 +87,17 @@
src.timeout = timeout
start_time = world.time
QDEL_IN(src, timeout)
- src.prevent_enter = prevent_enter
-/datum/tgui_input_text/Destroy(force, ...)
+/datum/tgui_input_text/Destroy(force)
SStgui.close_uis(src)
- . = ..()
+ return ..()
/**
* Waits for a user's response to the tgui_text_input's prompt before returning. Returns early if
* the window was closed by the user.
*/
/datum/tgui_input_text/proc/wait()
- while (!entry && !closed)
+ while (!entry && !closed && !QDELETED(src))
stoplag(1)
/datum/tgui_input_text/tgui_interact(mob/user, datum/tgui/ui)
@@ -128,7 +122,6 @@
data["placeholder"] = default // Default is a reserved keyword
data["swapped_buttons"] = !user.client.prefs.tgui_swapped_buttons
data["title"] = title
- data["prevent_enter"] = prevent_enter
return data
/datum/tgui_input_text/tgui_data(mob/user)
@@ -143,77 +136,27 @@
return
switch(action)
if("submit")
- if(length(params["entry"]) > max_length)
- return
- if(encode && (length(html_encode(params["entry"])) > max_length))
- to_chat(usr, span_notice("Your message was clipped due to special character usage."))
+ if(max_length)
+ if(length(params["entry"]) > max_length)
+ CRASH("[usr] typed a text string longer than the max length")
+ if(encode && (length(html_encode(params["entry"])) > max_length))
+ to_chat(usr, span_notice("Your message was clipped due to special character usage."))
set_entry(params["entry"])
closed = TRUE
SStgui.close_uis(src)
return TRUE
if("cancel")
- SStgui.close_uis(src)
closed = TRUE
+ SStgui.close_uis(src)
return TRUE
+/**
+ * Sets the return value for the tgui text proc.
+ * If html encoding is enabled, the text will be encoded.
+ * This can sometimes result in a string that is longer than the max length.
+ * If the string is longer than the max length, it will be clipped.
+ */
/datum/tgui_input_text/proc/set_entry(entry)
if(!isnull(entry))
var/converted_entry = encode ? html_encode(entry) : entry
- //converted_entry = readd_quotes(converted_entry)
src.entry = trim(converted_entry, max_length)
-
-/**
- * Creates an asynchronous TGUI input text window with an associated callback.
- *
- * This proc should be used to create inputs that invoke a callback with the user's chosen option.
- * Arguments:
- * * user - The user to show the input box to.
- * * message - The content of the input box, shown in the body of the TGUI window.
- * * title - The title of the input box, shown on the top of the TGUI window.
- * * default - The default value pre-populated in the input box.
- * * callback - The callback to be invoked when a choice is made.
- * * timeout - The timeout of the input box, after which the menu will close and qdel itself. Set to zero for no timeout.
- */
-/proc/tgui_input_text_async(mob/user, message, title, default, datum/callback/callback, max_length, multiline, encode, timeout = 60 SECONDS)
- if (istext(user))
- stack_trace("tgui_input_text_async() received text for user instead of mob")
- return
- if (!user)
- user = usr
- if (!istype(user))
- if (istype(user, /client))
- var/client/client = user
- user = client.mob
- else
- return
- var/datum/tgui_input_text/async/input = new(user, message, title, default, callback, max_length, multiline, encode, timeout)
- input.tgui_interact(user)
-
-/**
- * # async tgui_text_input
- *
- * An asynchronous version of tgui_text_input to be used with callbacks instead of waiting on user responses.
- */
-/datum/tgui_input_text/async
- /// The callback to be invoked by the tgui_text_input upon having a choice made.
- var/datum/callback/callback
-
-/datum/tgui_input_text/async/New(mob/user, message, title, default, callback, max_length, multiline, encode, timeout)
- ..(user, title, message, default, max_length, multiline, encode, timeout)
- src.callback = callback
-
-/datum/tgui_input_text/async/Destroy(force, ...)
- QDEL_NULL(callback)
- . = ..()
-
-/datum/tgui_input_text/async/tgui_close(mob/user)
- . = ..()
- qdel(src)
-
-/datum/tgui_input_text/async/set_entry(entry)
- . = ..()
- if(!isnull(src.entry))
- callback?.InvokeAsync(src.entry)
-
-/datum/tgui_input_text/async/wait()
- return
diff --git a/tgui/packages/tgui/components/Box.tsx b/tgui/packages/tgui/components/Box.tsx
index 5c5acb63b3..2ee476fddd 100644
--- a/tgui/packages/tgui/components/Box.tsx
+++ b/tgui/packages/tgui/components/Box.tsx
@@ -5,72 +5,56 @@
*/
import { BooleanLike, classes } from 'common/react';
-import { createElement, ReactNode } from 'react';
+import {
+ createElement,
+ KeyboardEventHandler,
+ MouseEventHandler,
+ ReactNode,
+ UIEventHandler,
+} from 'react';
import { CSS_COLORS } from '../constants';
+import { logger } from '../logging';
-export type BoxProps = {
- [key: string]: any;
- as?: string;
- className?: string | BooleanLike;
- children?: ReactNode;
- position?: string | BooleanLike;
- overflow?: string | BooleanLike;
- overflowX?: string | BooleanLike;
- overflowY?: string | BooleanLike;
- top?: string | BooleanLike;
- bottom?: string | BooleanLike;
- left?: string | BooleanLike;
- right?: string | BooleanLike;
- width?: string | BooleanLike;
- minWidth?: string | BooleanLike;
- maxWidth?: string | BooleanLike;
- height?: string | BooleanLike;
- minHeight?: string | BooleanLike;
- maxHeight?: string | BooleanLike;
- fontSize?: string | BooleanLike;
- fontFamily?: string;
- lineHeight?: string | BooleanLike;
- opacity?: number;
- textAlign?: string | BooleanLike;
- verticalAlign?: string | BooleanLike;
- textTransform?: string | BooleanLike; // VOREStation Addition
- inline?: BooleanLike;
- bold?: BooleanLike;
- italic?: BooleanLike;
- nowrap?: BooleanLike;
- preserveWhitespace?: BooleanLike;
- m?: string | BooleanLike;
- mx?: string | BooleanLike;
- my?: string | BooleanLike;
- mt?: string | BooleanLike;
- mb?: string | BooleanLike;
- ml?: string | BooleanLike;
- mr?: string | BooleanLike;
- p?: string | BooleanLike;
- px?: string | BooleanLike;
- py?: string | BooleanLike;
- pt?: string | BooleanLike;
- pb?: string | BooleanLike;
- pl?: string | BooleanLike;
- pr?: string | BooleanLike;
- color?: string | BooleanLike;
- textColor?: string | BooleanLike;
- backgroundColor?: string | BooleanLike;
- // VOREStation Addition Start
- // Flex props
- flexGrow?: string | BooleanLike;
- flexWrap?: string | BooleanLike;
- flexBasis?: string | BooleanLike;
- flex?: string | BooleanLike;
- // VOREStation Addition End
- fillPositionedParent?: boolean;
+type BooleanProps = Partial>;
+type StringProps = Partial<
+ Record
+>;
+
+export type EventHandlers = Partial<{
+ onClick: MouseEventHandler;
+ onContextMenu: MouseEventHandler;
+ onDoubleClick: MouseEventHandler;
+ onKeyDown: KeyboardEventHandler;
+ onKeyUp: KeyboardEventHandler;
+ onMouseDown: MouseEventHandler;
+ onMouseMove: MouseEventHandler;
+ onMouseOver: MouseEventHandler;
+ onMouseUp: MouseEventHandler;
+ onScroll: UIEventHandler;
+}>;
+
+export type BoxProps = Partial<{
+ as: string;
+ children: ReactNode;
+ className: string | BooleanLike;
+ style: Partial;
+}> &
+ BooleanProps &
+ StringProps &
+ EventHandlers;
+
+// Don't you dare put this elsewhere
+type DangerDoNotUse = {
+ dangerouslySetInnerHTML?: {
+ __html: any;
+ };
};
/**
* Coverts our rem-like spacing unit into a CSS unit.
*/
-export const unit = (value: unknown): string | undefined => {
+export const unit = (value: unknown) => {
if (typeof value === 'string') {
// Transparently convert pixels into rem units
if (value.endsWith('px')) {
@@ -86,7 +70,7 @@ export const unit = (value: unknown): string | undefined => {
/**
* Same as `unit`, but half the size for integers numbers.
*/
-export const halfUnit = (value: unknown): string | undefined => {
+export const halfUnit = (value: unknown) => {
if (typeof value === 'string') {
return unit(value);
}
@@ -98,7 +82,7 @@ export const halfUnit = (value: unknown): string | undefined => {
const isColorCode = (str: unknown) => !isColorClass(str);
const isColorClass = (str: unknown): boolean => {
- return typeof str === 'string' && CSS_COLORS.includes(str);
+ return typeof str === 'string' && CSS_COLORS.includes(str as any);
};
const mapRawPropTo = (attrName) => (style, value) => {
@@ -135,9 +119,12 @@ const mapColorPropTo = (attrName) => (style, value) => {
// String / number props
const stringStyleMap = {
+ align: mapRawPropTo('textAlign'),
bottom: mapUnitPropTo('bottom', unit),
+ colSpan: mapRawPropTo('colSpan'),
fontFamily: mapRawPropTo('fontFamily'),
fontSize: mapUnitPropTo('fontSize', unit),
+ fontWeight: mapRawPropTo('fontWeight'),
height: mapUnitPropTo('height', unit),
left: mapUnitPropTo('left', unit),
maxHeight: mapUnitPropTo('maxHeight', unit),
@@ -162,22 +149,19 @@ const stringStyleMap = {
style['lineHeight'] = unit(value);
}
},
-
- textTransform: mapRawPropTo('text-transform'), // VOREStation Addition
-
- // Margins
+ // Margin
m: mapDirectionalUnitPropTo('margin', halfUnit, [
'Top',
'Bottom',
'Left',
'Right',
]),
- mx: mapDirectionalUnitPropTo('margin', halfUnit, ['Left', 'Right']),
- my: mapDirectionalUnitPropTo('margin', halfUnit, ['Top', 'Bottom']),
- mt: mapUnitPropTo('marginTop', halfUnit),
mb: mapUnitPropTo('marginBottom', halfUnit),
ml: mapUnitPropTo('marginLeft', halfUnit),
mr: mapUnitPropTo('marginRight', halfUnit),
+ mt: mapUnitPropTo('marginTop', halfUnit),
+ mx: mapDirectionalUnitPropTo('margin', halfUnit, ['Left', 'Right']),
+ my: mapDirectionalUnitPropTo('margin', halfUnit, ['Top', 'Bottom']),
// Padding
p: mapDirectionalUnitPropTo('padding', halfUnit, [
'Top',
@@ -185,12 +169,12 @@ const stringStyleMap = {
'Left',
'Right',
]),
- px: mapDirectionalUnitPropTo('padding', halfUnit, ['Left', 'Right']),
- py: mapDirectionalUnitPropTo('padding', halfUnit, ['Top', 'Bottom']),
- pt: mapUnitPropTo('paddingTop', halfUnit),
pb: mapUnitPropTo('paddingBottom', halfUnit),
pl: mapUnitPropTo('paddingLeft', halfUnit),
pr: mapUnitPropTo('paddingRight', halfUnit),
+ pt: mapUnitPropTo('paddingTop', halfUnit),
+ px: mapDirectionalUnitPropTo('padding', halfUnit, ['Left', 'Right']),
+ py: mapDirectionalUnitPropTo('padding', halfUnit, ['Top', 'Bottom']),
// Color props
color: mapColorPropTo('color'),
textColor: mapColorPropTo('color'),
@@ -203,8 +187,11 @@ const stringStyleMap = {
flexBasis: mapRawPropTo('flex-basis'),
flex: mapRawPropTo('flex'),
// VOREStation Addition End
+} as const;
- // Utility props
+// Boolean props
+const booleanStyleMap = {
+ bold: mapBooleanPropTo('fontWeight', 'bold'),
fillPositionedParent: (style, value) => {
if (value) {
style['position'] = 'absolute';
@@ -214,11 +201,6 @@ const stringStyleMap = {
style['right'] = 0;
}
},
-} as const;
-
-// Boolean props
-const booleanStyleMap = {
- bold: mapBooleanPropTo('fontWeight', 'bold'),
inline: mapBooleanPropTo('display', 'inline-block'),
italic: mapBooleanPropTo('fontStyle', 'italic'),
nowrap: mapBooleanPropTo('whiteSpace', 'nowrap'),
@@ -262,7 +244,7 @@ export const computeBoxClassName = (props: BoxProps) => {
]);
};
-export const Box = (props: BoxProps) => {
+export const Box = (props: BoxProps & DangerDoNotUse) => {
const { as = 'div', className, children, ...rest } = props;
// Compute class name and styles
@@ -270,8 +252,11 @@ export const Box = (props: BoxProps) => {
? `${className} ${computeBoxClassName(rest)}`
: computeBoxClassName(rest);
const computedProps = computeBoxProps(rest);
+
if (as === 'img') {
- computedProps.style['-ms-interpolation-mode'] = 'nearest-neighbor';
+ logger.error(
+ 'Box component cannot be used as an image. Use Image component instead.',
+ );
}
// Render the component
diff --git a/tgui/packages/tgui/interfaces/BodyScanner.jsx b/tgui/packages/tgui/interfaces/BodyScanner.jsx
index c4684bd739..9afdb71823 100644
--- a/tgui/packages/tgui/interfaces/BodyScanner.jsx
+++ b/tgui/packages/tgui/interfaces/BodyScanner.jsx
@@ -373,7 +373,7 @@ const BodyScannerMainOrgansExternal = (props) => {
Injuries
{props.organs.map((o, i) => (
-
+
{o.name}
{
Injuries
{props.organs.map((o, i) => (
-
+
{o.name}
{
height="88%"
mb={1}
style={{
- 'overflow-y': 'auto',
+ overflowY: 'auto',
}}
>
{TabToTemplate[currentTab] || }
@@ -154,7 +154,7 @@ const VideoComm = (props) => {
position: 'absolute',
right: '5px',
bottom: '50px',
- 'z-index': 1,
+ zIndex: '1',
}}
>
@@ -843,8 +843,8 @@ const MessagingThreadTab = (props) => {
@@ -870,7 +870,7 @@ const MessagingThreadTab = (props) => {
{imList.map(
@@ -905,8 +905,8 @@ const MessagingThreadTab = (props) => {
@@ -932,7 +932,7 @@ const MessagingThreadTab = (props) => {
{imList.map(
@@ -1126,8 +1126,8 @@ const NoteTab = (props) => {
width="100%"
height="100%"
style={{
- 'word-break': 'break-all',
- 'overflow-y': 'auto',
+ wordBreak: 'break-all',
+ overflowY: 'auto',
}}
>
{note}
diff --git a/tgui/packages/tgui/interfaces/ListInputModal.tsx b/tgui/packages/tgui/interfaces/ListInputModal.tsx
index b555f795d1..8695ac842f 100644
--- a/tgui/packages/tgui/interfaces/ListInputModal.tsx
+++ b/tgui/packages/tgui/interfaces/ListInputModal.tsx
@@ -9,7 +9,7 @@ import {
KEY_Z,
} from '../../common/keycodes';
import { useBackend } from '../backend';
-import { Button, Input, Section, Stack } from '../components';
+import { Autofocus, Button, Input, Section, Stack } from '../components';
import { Window } from '../layouts';
import { InputButtons } from './common/InputButtons';
import { Loader } from './common/Loader';
@@ -188,16 +188,16 @@ const ListDisplay = (props) => {
props;
return (
-
+
+
{filteredItems.map((item, index) => {
return (