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 (