tgui-core 5.7.2 → 5.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import type { DOMAttributes } from 'react';
2
2
  import type { BoxProps } from '../components/Box';
3
- import { type BooleanLike } from './react';
3
+ import { type BooleanLike } from './react.ts';
4
4
  type UnitMapper = (value: unknown) => string | undefined;
5
5
  /**
6
6
  * Coverts our rem-like spacing unit into a CSS unit.
@@ -1,6 +1,7 @@
1
1
  import { type RefObject } from 'react';
2
2
  import type { BoxProps } from './Box';
3
- export type BaseInputProps<TElement = HTMLInputElement> = Partial<{
3
+ /** Takes two optional params: The dom element type & the input type */
4
+ export type BaseInputProps<TElement = HTMLInputElement, TInput = string> = Partial<{
4
5
  /** Automatically focuses the input on mount */
5
6
  autoFocus: boolean;
6
7
  /** Automatically selects the input value on focus */
@@ -22,24 +23,24 @@ export type BaseInputProps<TElement = HTMLInputElement> = Partial<{
22
23
  fluid: boolean;
23
24
  /** Mark this if you want to use a monospace font */
24
25
  monospace: boolean;
25
- /** Allows to toggle on spellcheck on inputs */
26
- spellcheck: boolean;
27
- }> & BoxProps<TElement>;
28
- export type TextInputProps<TElement = HTMLInputElement> = Partial<{
29
- /** The maximum length of the input value */
30
- maxLength: number;
31
26
  /** Fires each time focus leaves the input, including if Esc or Enter are pressed */
32
- onBlur: (value: string) => void;
33
- /** Fires each time the input has been changed */
34
- onChange: (value: string) => void;
27
+ onBlur: (value: TInput) => void;
28
+ /**
29
+ * Fires each time the input has been changed. You do not need to enter the second param unless you're using it. All of these are valid:
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * <Input onChange={(value) => console.log(value)} />
34
+ * <Input onChange={(value, event) => console.log(value, event)} />
35
+ * <Input onChange={console.log} /> // This will log the value and the event
36
+ * <Input onChange={setValue} /> // This will just change the value state
37
+ * ```
38
+ */
39
+ onChange: (value: TInput, event?: React.ChangeEvent<TElement>) => void;
35
40
  /** Fires once the enter key is pressed */
36
- onEnter: (value: string) => void;
41
+ onEnter: (value: TInput, event?: React.KeyboardEvent<TElement>) => void;
37
42
  /** Fires once the escape key is pressed */
38
- onEscape: (value: string) => void;
39
- /** The placeholder text when everything is cleared */
40
- placeholder: string;
41
- /** Clears the input value on enter */
42
- selfClear: boolean;
43
+ onEscape: (value: TInput, event?: React.KeyboardEvent<TElement>) => void;
43
44
  /**
44
45
  * Generally, input can handle its own state value. You might not NEED this.
45
46
  *
@@ -80,12 +81,20 @@ export type TextInputProps<TElement = HTMLInputElement> = Partial<{
80
81
  * )
81
82
  * ```
82
83
  */
83
- value: string;
84
- }> & BaseInputProps<TElement>;
85
- type Props = Partial<{
84
+ value: TInput;
85
+ }> & BoxProps<TElement>;
86
+ export type TextInputProps<TElement = HTMLInputElement> = Partial<{
87
+ /** The maximum length of the input value */
88
+ maxLength: number;
89
+ /** The placeholder text when everything is cleared */
90
+ placeholder: string;
86
91
  /** Ref of the input element */
87
- ref: RefObject<HTMLInputElement | null>;
88
- }> & BaseInputProps & TextInputProps;
92
+ ref: RefObject<TElement | null>;
93
+ /** Clears the input value on enter */
94
+ selfClear: boolean;
95
+ /** Allows to toggle on spellcheck on inputs */
96
+ spellcheck: boolean;
97
+ }> & BaseInputProps<TElement>;
89
98
  /**
90
99
  * ## Input
91
100
  *
@@ -94,5 +103,4 @@ type Props = Partial<{
94
103
  * - [View documentation on tgui core](https://tgstation.github.io/tgui-core/?path=/docs/components-input--docs)
95
104
  * - [View inherited Box props](https://tgstation.github.io/tgui-core/?path=/docs/components-box--docs)
96
105
  */
97
- export declare function Input(props: Props): import("react/jsx-runtime").JSX.Element;
98
- export {};
106
+ export declare function Input(props: TextInputProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- import{jsx as e}from"react/jsx-runtime";import{KEY as t,isEscape as r}from"../common/keys.js";import{classes as n}from"../common/react.js";import{debounce as u}from"../common/timer.js";import{computeBoxClassName as o,computeBoxProps as m}from"../common/ui.js";import{useEffect as c,useRef as l,useState as a}from"react";let i=u(e=>e(),250);function p(u){let{autoFocus:p,autoSelect:f,className:s,disabled:d,expensive:g,fluid:v,maxLength:T,monospace:j,onBlur:y,onChange:I,onEnter:b,onEscape:h,onKeyDown:k,placeholder:x,ref:C,selfClear:D,spellcheck:E=!1,value:w,...B}=u,K=l(null),L=C??K,[N,q]=a(w??"");c(()=>{let e;return(p||f)&&(e=setTimeout(()=>{L.current?.focus(),f&&L.current?.select()},1)),()=>clearTimeout(e)},[]),c(()=>{L.current&&document.activeElement!==L.current&&w!==N&&q(w??"")},[w]);let z=m(B),A=n(["Input",d&&"Input--disabled",v&&"Input--fluid",j&&"Input--monospace",o(B),s]);return e("input",{...z,autoComplete:"off",className:A,disabled:d,maxLength:T,onBlur:()=>y?.(N),onChange:function(e){let t=e.currentTarget.value;q(t),g?i(()=>I?.(t)):I?.(t)},onKeyDown:function(e){if(k?.(e),e.key===t.Enter){e.preventDefault(),b?.(e.currentTarget.value),D&&q(""),e.currentTarget.blur();return}r(e.key)&&(e.preventDefault(),h?.(e.currentTarget.value),e.currentTarget.blur())},placeholder:x,ref:L,spellCheck:E,type:"text",value:N})}export{p as Input};
1
+ import{jsx as e}from"react/jsx-runtime";import{KEY as t,isEscape as r}from"../common/keys.js";import{classes as n}from"../common/react.js";import{debounce as u}from"../common/timer.js";import{computeBoxClassName as o,computeBoxProps as m}from"../common/ui.js";import{useEffect as c,useRef as l,useState as a}from"react";let i=u(e=>e(),250);function p(u){let{autoFocus:p,autoSelect:f,className:s,disabled:d,expensive:g,fluid:v,maxLength:T,monospace:j,onBlur:y,onChange:I,onEnter:b,onEscape:h,onKeyDown:k,placeholder:x,ref:C,selfClear:D,spellcheck:E=!1,value:w,...B}=u,K=l(null),L=C??K,[N,q]=a(w??"");c(()=>{let e;return(p||f)&&(e=setTimeout(()=>{L.current?.focus(),f&&L.current?.select()},1)),()=>clearTimeout(e)},[]),c(()=>{L.current&&document.activeElement!==L.current&&w!==N&&q(w??"")},[w]);let z=m(B),A=n(["Input",d&&"Input--disabled",v&&"Input--fluid",j&&"Input--monospace",o(B),s]);return e("input",{...z,autoComplete:"off",className:A,disabled:d,maxLength:T,onBlur:()=>y?.(N),onChange:function(e){let t=e.currentTarget.value;q(t),g?i(()=>I?.(t,e)):I?.(t,e)},onKeyDown:function(e){if(k?.(e),e.key===t.Enter){e.preventDefault(),b?.(e.currentTarget.value,e),D&&q(""),e.currentTarget.blur();return}r(e.key)&&(e.preventDefault(),h?.(e.currentTarget.value,e),e.currentTarget.blur())},placeholder:x,ref:L,spellCheck:E,type:"text",value:N})}export{p as Input};
@@ -6,58 +6,9 @@ type Props = Partial<{
6
6
  maxValue: number;
7
7
  /** Min value. 0 by default. */
8
8
  minValue: number;
9
- /** Fires each time focus leaves the input, including if Esc or Enter are pressed */
10
- onBlur: (value: number) => void;
11
- /** Fires each time the input has been changed */
12
- onChange: (value: number) => void;
13
- /** Fires once the enter key is pressed */
14
- onEnter: (value: number) => void;
15
- /** Fires once the escape key is pressed */
16
- onEscape: (value: number) => void;
17
9
  /** Fires on input validation change */
18
10
  onValidationChange: (isValid: boolean) => void;
19
- /**
20
- * Generally, input can handle its own state value. You might not NEED this.
21
- *
22
- * Use this if you want to hold the value in the parent for external
23
- * manipulation. For instance:
24
- *
25
- * Clearing the input
26
- *
27
- * ```tsx
28
- * const [value, setValue] = useState(1);
29
- *
30
- * return (
31
- * <>
32
- * <Button onClick={() => act('inputVal', {inputVal: value})}>
33
- * Submit
34
- * </Button>
35
- * <RestrictedInput
36
- * value={value}
37
- * onChange={setValue} />
38
- * <Button onClick={() => setValue(1)}>
39
- * Clear
40
- * </Button>
41
- * </>
42
- * )
43
- * ```
44
- *
45
- * Updating the value from the backend
46
- *
47
- * ```tsx
48
- * const { data } = useBackend<Data>();
49
- * const { valveSetting } = data;
50
- *
51
- * return (
52
- * <RestrictedInput
53
- * value={valveSetting}
54
- * onEnter={(value) => act('submit', { valveSetting: value })}
55
- * />
56
- * )
57
- * ```
58
- */
59
- value: number;
60
- }> & BaseInputProps;
11
+ }> & BaseInputProps<HTMLInputElement, number>;
61
12
  /**
62
13
  * ## RestrictedInput
63
14
  *
@@ -1 +1 @@
1
- import{jsx as e}from"react/jsx-runtime";import{KEY as t,isEscape as r}from"../common/keys.js";import{classes as n}from"../common/react.js";import{debounce as u}from"../common/timer.js";import{computeBoxClassName as o,computeBoxProps as i}from"../common/ui.js";import{useEffect as m,useRef as c,useState as l}from"react";let a=u(e=>e(),250);function f(u){let{allowFloats:f,autoFocus:p,autoSelect:s,className:d,disabled:v,expensive:y,fluid:I,maxValue:b=1e4,minValue:j=0,monospace:k,onBlur:D,onChange:x,onEnter:C,onEscape:R,onKeyDown:g,onValidationChange:h,value:E,...N}=u,T=c(null),[w,B]=l(E??j),[K,M]=l(!0);function q(e){x&&(y?a(()=>x(e)):x(e))}m(()=>{let e;return(p||s)&&(e=setTimeout(()=>{T.current?.focus(),s&&T.current?.select()},1)),()=>clearTimeout(e)},[]),m(()=>{if(T.current){let e=T.current.validity.valid;K!==e&&(M(e),h?.(e))}},[w]),m(()=>{T.current&&document.activeElement!==T.current&&E!==w&&B(E??j)},[E]);let z=i(N),A=n(["Input","RestrictedInput",v&&"Input--disabled",I&&"Input--fluid",k&&"Input--monospace",o(N),d,!K&&"RestrictedInput--invalid"]);return e("input",{...z,autoComplete:"off",className:A,disabled:v,max:b,min:j,onBlur:function(e){D?.(w)},onChange:function(e){let t=Number(e.target.value);B(t),q(t)},onKeyDown:function(e){if(g?.(e),e.key===t.Enter){e.preventDefault(),C?.(w),T.current?.blur();return}if(r(e.key)){e.preventDefault(),R?.(w),T.current?.blur();return}if(e.key===t.Minus){e.preventDefault();let t=-1*w;B(t),q(t);return}},ref:T,spellCheck:!1,step:f?"any":"1",type:"number",value:w})}export{f as RestrictedInput};
1
+ import{jsx as e}from"react/jsx-runtime";import{KEY as t,isEscape as r}from"../common/keys.js";import{classes as n}from"../common/react.js";import{debounce as u}from"../common/timer.js";import{computeBoxClassName as o,computeBoxProps as i}from"../common/ui.js";import{useEffect as m,useRef as c,useState as l}from"react";let a=u(e=>e(),250);function f(u){let{allowFloats:f,autoFocus:p,autoSelect:s,className:d,disabled:v,expensive:y,fluid:I,maxValue:b=1e4,minValue:j=0,monospace:k,onBlur:D,onChange:x,onEnter:C,onEscape:R,onKeyDown:g,onValidationChange:h,value:E,...N}=u,T=c(null),[w,B]=l(E??j),[K,M]=l(!0);function q(e,t){x&&(y?a(()=>x?.(e,t)):x(e,t))}m(()=>{let e;return(p||s)&&(e=setTimeout(()=>{T.current?.focus(),s&&T.current?.select()},1)),()=>clearTimeout(e)},[]),m(()=>{if(T.current){let e=T.current.validity.valid;K!==e&&(M(e),h?.(e))}},[w]),m(()=>{T.current&&document.activeElement!==T.current&&E!==w&&B(E??j)},[E]);let z=i(N),A=n(["Input","RestrictedInput",v&&"Input--disabled",I&&"Input--fluid",k&&"Input--monospace",o(N),d,!K&&"RestrictedInput--invalid"]);return e("input",{...z,autoComplete:"off",className:A,disabled:v,max:b,min:j,onBlur:function(e){D?.(w)},onChange:function(e){let t=Number(e.target.value);B(t),q(t,e)},onKeyDown:function(e){if(g?.(e),e.key===t.Enter){e.preventDefault(),C?.(w,e),T.current?.blur();return}if(r(e.key)){e.preventDefault(),R?.(w,e),T.current?.blur();return}if(e.key===t.Minus){e.preventDefault();let t=-1*w;B(t),q(t,e);return}},ref:T,spellCheck:!1,step:f?"any":"1",type:"number",value:w})}export{f as RestrictedInput};
@@ -1,10 +1,7 @@
1
- import type { RefObject } from 'react';
2
1
  import type { TextInputProps } from './Input';
3
2
  type Props = Partial<{
4
3
  /** Don't use tab for indent */
5
4
  dontUseTabForIndent: boolean;
6
- /** Ref to the textarea element. */
7
- ref: RefObject<HTMLTextAreaElement | null>;
8
5
  /**
9
6
  * Provides a Record with key: markupChar entries which can be used for
10
7
  * ctrl + key combinations to surround a selected text with the markup
@@ -1 +1 @@
1
- import{jsx as e}from"react/jsx-runtime";import{KEY as t,isEscape as r}from"../common/keys.js";import{classes as n}from"../common/react.js";import{computeBoxClassName as u,computeBoxProps as o}from"../common/ui.js";import{debounce as a}from"../common/timer.js";import{useEffect as c,useRef as l,useState as m}from"react";let i=a(e=>e(),250);function s(a){let{autoFocus:s,autoSelect:f,className:g,disabled:p,dontUseTabForIndent:T,expensive:v,fluid:y,maxLength:b,monospace:d,onBlur:k,onChange:$,onEnter:h,onEscape:x,onKeyDown:j,placeholder:D,ref:E,selfClear:I,spellcheck:K=!1,userMarkup:C,value:A,...w}=a,B=l(null),L=E??B,[N,q]=m(A??"");c(()=>{(s||f)&&setTimeout(()=>{L.current?.focus(),f&&L.current?.select()},1)},[]),c(()=>{L.current&&document.activeElement!==L.current&&A!==N&&q(A??"")},[A]);let z=o(w),F=n(["Input","TextArea",y&&"Input--fluid",d&&"Input--monospace",p&&"Input--disabled",u(w),g]);return e("textarea",{...z,autoComplete:"off",className:F,maxLength:b,onBlur:function(e){k?.(N)},onChange:function(e){let t=e.currentTarget.value;q(t),$&&(v?i(()=>$(t)):$(t))},onKeyDown:function(e){if(j?.(e),e.key===t.Enter&&!e.shiftKey){e.preventDefault(),h?.(e.currentTarget.value),I&&q(""),e.currentTarget.blur();return}if(r(e.key)){x?.(e.currentTarget.value),e.currentTarget.blur();return}if(!T&&e.key===t.Tab){e.preventDefault();let{value:t,selectionStart:r,selectionEnd:n}=e.currentTarget;q(`${t.substring(0,r)} ${t.substring(n)}`),e.currentTarget.selectionEnd=r+1,$?.(e.currentTarget.value);return}if(C&&(e.ctrlKey||e.metaKey)&&C[e.key]){e.preventDefault();let{selectionStart:t,selectionEnd:r,value:n}=e.currentTarget,u=C[e.key];q(`${n.substring(0,t)}${u}${n.substring(t,r)}${u}${n.substring(r)}`),e.currentTarget.selectionEnd=r+2*u.length,$?.(e.currentTarget.value);return}},placeholder:D,ref:L,spellCheck:K,value:N})}export{s as TextArea};
1
+ import{jsx as e}from"react/jsx-runtime";import{KEY as t,isEscape as r}from"../common/keys.js";import{classes as n}from"../common/react.js";import{computeBoxClassName as u,computeBoxProps as o}from"../common/ui.js";import{debounce as a}from"../common/timer.js";import{useEffect as c,useRef as l,useState as m}from"react";let i=a(e=>e(),250);function s(a){let{autoFocus:s,autoSelect:f,className:g,disabled:p,dontUseTabForIndent:T,expensive:v,fluid:y,maxLength:b,monospace:d,onBlur:k,onChange:$,onEnter:h,onEscape:x,onKeyDown:j,placeholder:D,ref:E,selfClear:I,spellcheck:K=!1,userMarkup:C,value:A,...w}=a,B=l(null),L=E??B,[N,q]=m(A??"");c(()=>{(s||f)&&setTimeout(()=>{L.current?.focus(),f&&L.current?.select()},1)},[]),c(()=>{L.current&&document.activeElement!==L.current&&A!==N&&q(A??"")},[A]);let z=o(w),F=n(["Input","TextArea",y&&"Input--fluid",d&&"Input--monospace",p&&"Input--disabled",u(w),g]);return e("textarea",{...z,autoComplete:"off",className:F,maxLength:b,onBlur:function(e){k?.(N)},onChange:function(e){let t=e.currentTarget.value;q(t),$&&(v?i(()=>$?.(t,e)):$(t,e))},onKeyDown:function(e){if(j?.(e),e.key===t.Enter&&!e.shiftKey){e.preventDefault(),h?.(e.currentTarget.value,e),I&&q(""),e.currentTarget.blur();return}if(r(e.key)){x?.(e.currentTarget.value,e),e.currentTarget.blur();return}if(!T&&e.key===t.Tab){e.preventDefault();let{value:t,selectionStart:r,selectionEnd:n}=e.currentTarget;q(`${t.substring(0,r)} ${t.substring(n)}`),e.currentTarget.selectionEnd=r+1,$?.(e.currentTarget.value,e);return}if(C&&(e.ctrlKey||e.metaKey)&&C[e.key]){e.preventDefault();let{selectionStart:t,selectionEnd:r,value:n}=e.currentTarget,u=C[e.key];q(`${n.substring(0,t)}${u}${n.substring(t,r)}${u}${n.substring(r)}`),e.currentTarget.selectionEnd=r+2*u.length,$?.(e.currentTarget.value,e);return}},placeholder:D,ref:L,spellCheck:K,value:N})}export{s as TextArea};
package/package.json CHANGED
@@ -71,5 +71,5 @@
71
71
  "test": "bun test"
72
72
  },
73
73
  "type": "module",
74
- "version": "5.7.2"
74
+ "version": "5.8.0"
75
75
  }