tgui-core 3.1.3 → 3.1.5

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.
package/README.md CHANGED
@@ -74,3 +74,9 @@ This project uses [pnpm](https://pnpm.io/installation) for its package manager.
74
74
 
75
75
  To set up the repository:
76
76
  `pnpm install`
77
+
78
+ To test your changes using [Storybook](https://storybook.js.org/docs) run:
79
+ `pnpm run storybook`
80
+
81
+ To run unit tests run
82
+ `pnpm test`
@@ -1 +1 @@
1
- class t{r;g;b;a;constructor(t=0,r=0,e=0,s=1){this.r=t,this.g=r,this.b=e,this.a=s}toString(){let t=this.a;return"string"==typeof t&&(t=Number.parseFloat(this.a)),Number.isNaN(t)&&(t=1),`rgba(${0|this.r}, ${0|this.g}, ${0|this.b}, ${t})`}darken(r){let e=r/100;return new t(this.r-this.r*e,this.g-this.g*e,this.b-this.b*e,this.a)}lighten(t){return this.darken(-t)}static fromHex(r){return new t(Number.parseInt(r.slice(1,3),16),Number.parseInt(r.slice(3,5),16),Number.parseInt(r.slice(5,7),16))}static lerp(r,e,s){return new t((e.r-r.r)*s+r.r,(e.g-r.g)*s+r.g,(e.b-r.b)*s+r.b,(e.a-r.a)*s+r.a)}static lookup(r,e){let s=e.length;if(s<2)throw Error("Needs at least two colors!");let i=r*(s-1);if(r<1e-4)return e[0];if(r>=.9999)return e[s-1];let a=0|i;return t.lerp(e[a],e[a+1],i%1)}}export{t as Color};
1
+ class r{r;g;b;a;constructor(r=0,t=0,e=0,s=1){this.r=r,this.g=t,this.b=e,this.a=s}toString(){let r=this.a;return"string"==typeof r&&(r=Number.parseFloat(this.a)),Number.isNaN(r)&&(r=1),`rgba(${0|this.r}, ${0|this.g}, ${0|this.b}, ${r})`}darken(t){let e=t/100;return new r(this.r-this.r*e,this.g-this.g*e,this.b-this.b*e,this.a)}lighten(r){return this.darken(-r)}static fromHex(t){if(7===t.length)return new r(Number.parseInt(t.slice(1,3),16),Number.parseInt(t.slice(3,5),16),Number.parseInt(t.slice(5,7),16));if(9===t.length)return new r(Number.parseInt(t.slice(1,3),16),Number.parseInt(t.slice(3,5),16),Number.parseInt(t.slice(5,7),16),Number.parseInt(t.slice(7,9),16)/256);throw Error("Invalid hex color format. Expected #RRGGBB or #RRGGBBAA.")}static lerp(t,e,s){return new r((e.r-t.r)*s+t.r,(e.g-t.g)*s+t.g,(e.b-t.b)*s+t.b,(e.a-t.a)*s+t.a)}static lookup(t,e){let s=e.length;if(s<2)throw Error("Needs at least two colors!");let i=t*(s-1);if(t<1e-4)return e[0];if(t>=.9999)return e[s-1];let n=0|i;return r.lerp(e[n],e[n+1],i%1)}}export{r as Color};
@@ -101,6 +101,6 @@ export declare const getGasFromId: (gasId: string) => Gas | undefined;
101
101
  export declare const getGasFromPath: (gasPath: string) => Gas | undefined;
102
102
  export declare const COMPONENT_COLORS: {
103
103
  readonly states: readonly ["", "good", "average", "bad", "black", "white"];
104
- readonly spectrum: readonly ["red", "orange", "yellow", "olive", "green", "teal", "blue", "violet", "purple", "pink", "brown", "grey"];
104
+ readonly spectrum: readonly ["red", "orange", "yellow", "olive", "green", "teal", "blue", "violet", "purple", "pink", "brown", "grey", "gold"];
105
105
  };
106
106
  export {};
@@ -1 +1 @@
1
- let e=2,a=1,o=0,r=-1,l={department:{captain:"#c06616",security:"#e74c3c",medbay:"#3498db",science:"#9b59b6",engineering:"#f1c40f",cargo:"#f39c12",service:"#7cc46a",centcom:"#00c100",other:"#c38312"},damageType:{oxy:"#3498db",toxin:"#2ecc71",burn:"#e67e22",brute:"#e74c3c"},reagent:{acidicbuffer:"#fbc314",basicbuffer:"#3853a4"}},t=["average","bad","black","blue","brown","good","green","grey","label","olive","orange","pink","purple","red","teal","transparent","violet","white","yellow"],i=[{name:"Syndicate",freq:1213,color:"#8f4a4b"},{name:"Red Team",freq:1215,color:"#ff4444"},{name:"Blue Team",freq:1217,color:"#3434fd"},{name:"Green Team",freq:1219,color:"#34fd34"},{name:"Yellow Team",freq:1221,color:"#fdfd34"},{name:"CentCom",freq:1337,color:"#2681a5"},{name:"Supply",freq:1347,color:"#b88646"},{name:"Service",freq:1349,color:"#6ca729"},{name:"Science",freq:1351,color:"#c68cfa"},{name:"Command",freq:1353,color:"#fcdf03"},{name:"Medical",freq:1355,color:"#57b8f0"},{name:"Engineering",freq:1357,color:"#f37746"},{name:"Security",freq:1359,color:"#dd3535"},{name:"AI Private",freq:1447,color:"#d65d95"},{name:"Common",freq:1459,color:"#1ecc43"}],n=[{id:"o2",path:"/datum/gas/oxygen",name:"Oxygen",label:"O₂",color:"blue"},{id:"n2",path:"/datum/gas/nitrogen",name:"Nitrogen",label:"N₂",color:"yellow"},{id:"co2",path:"/datum/gas/carbon_dioxide",name:"Carbon Dioxide",label:"CO₂",color:"grey"},{id:"plasma",path:"/datum/gas/plasma",name:"Plasma",label:"Plasma",color:"pink"},{id:"water_vapor",path:"/datum/gas/water_vapor",name:"Water Vapor",label:"H₂O",color:"lightsteelblue"},{id:"hypernoblium",path:"/datum/gas/hypernoblium",name:"Hyper-noblium",label:"Hyper-nob",color:"teal"},{id:"n2o",path:"/datum/gas/nitrous_oxide",name:"Nitrous Oxide",label:"N₂O",color:"bisque"},{id:"no2",path:"/datum/gas/nitrium",name:"Nitrium",label:"Nitrium",color:"brown"},{id:"tritium",path:"/datum/gas/tritium",name:"Tritium",label:"Tritium",color:"limegreen"},{id:"bz",path:"/datum/gas/bz",name:"BZ",label:"BZ",color:"mediumpurple"},{id:"pluoxium",path:"/datum/gas/pluoxium",name:"Pluoxium",label:"Pluoxium",color:"mediumslateblue"},{id:"miasma",path:"/datum/gas/miasma",name:"Miasma",label:"Miasma",color:"olive"},{id:"freon",path:"/datum/gas/freon",name:"Freon",label:"Freon",color:"paleturquoise"},{id:"hydrogen",path:"/datum/gas/hydrogen",name:"Hydrogen",label:"H₂",color:"white"},{id:"healium",path:"/datum/gas/healium",name:"Healium",label:"Healium",color:"salmon"},{id:"proto_nitrate",path:"/datum/gas/proto_nitrate",name:"Proto Nitrate",label:"Proto-Nitrate",color:"greenyellow"},{id:"zauker",path:"/datum/gas/zauker",name:"Zauker",label:"Zauker",color:"darkgreen"},{id:"halon",path:"/datum/gas/halon",name:"Halon",label:"Halon",color:"purple"},{id:"helium",path:"/datum/gas/helium",name:"Helium",label:"He",color:"aliceblue"},{id:"antinoblium",path:"/datum/gas/antinoblium",name:"Antinoblium",label:"Anti-Noblium",color:"maroon"},{id:"nitrium",path:"/datum/gas/nitrium",name:"Nitrium",label:"Nitrium",color:"brown"}];function m(e,a){if(!e)return a||"None";let o=e.toLowerCase();for(let e=0;e<n.length;e++)if(n[e].id===o)return n[e].label;return a||"None"}function u(e){if(!e)return"black";let a=e.toLowerCase();for(let e=0;e<n.length;e++)if(n[e].id===a)return n[e].color;return"black"}let c=e=>{if(!e)return;let a=e.toLowerCase();for(let e=0;e<n.length;e++)if(n[e].id===a)return n[e]},d=e=>{if(e){for(let a=0;a<n.length;a++)if(n[a].path===e)return n[a]}},b={states:["","good","average","bad","black","white"],spectrum:["red","orange","yellow","olive","green","teal","blue","violet","purple","pink","brown","grey"]};export{l as COLORS,b as COMPONENT_COLORS,t as CSS_COLORS,i as RADIO_CHANNELS,r as UI_CLOSE,o as UI_DISABLED,e as UI_INTERACTIVE,a as UI_UPDATE,u as getGasColor,c as getGasFromId,d as getGasFromPath,m as getGasLabel};
1
+ let e=2,a=1,o=0,r=-1,l={department:{captain:"#c06616",security:"#e74c3c",medbay:"#3498db",science:"#9b59b6",engineering:"#f1c40f",cargo:"#f39c12",service:"#7cc46a",centcom:"#00c100",other:"#c38312"},damageType:{oxy:"#3498db",toxin:"#2ecc71",burn:"#e67e22",brute:"#e74c3c"},reagent:{acidicbuffer:"#fbc314",basicbuffer:"#3853a4"}},t=["average","bad","black","blue","brown","good","green","grey","label","olive","orange","pink","purple","red","teal","transparent","violet","white","yellow"],i=[{name:"Syndicate",freq:1213,color:"#8f4a4b"},{name:"Red Team",freq:1215,color:"#ff4444"},{name:"Blue Team",freq:1217,color:"#3434fd"},{name:"Green Team",freq:1219,color:"#34fd34"},{name:"Yellow Team",freq:1221,color:"#fdfd34"},{name:"CentCom",freq:1337,color:"#2681a5"},{name:"Supply",freq:1347,color:"#b88646"},{name:"Service",freq:1349,color:"#6ca729"},{name:"Science",freq:1351,color:"#c68cfa"},{name:"Command",freq:1353,color:"#fcdf03"},{name:"Medical",freq:1355,color:"#57b8f0"},{name:"Engineering",freq:1357,color:"#f37746"},{name:"Security",freq:1359,color:"#dd3535"},{name:"AI Private",freq:1447,color:"#d65d95"},{name:"Common",freq:1459,color:"#1ecc43"}],n=[{id:"o2",path:"/datum/gas/oxygen",name:"Oxygen",label:"O₂",color:"blue"},{id:"n2",path:"/datum/gas/nitrogen",name:"Nitrogen",label:"N₂",color:"yellow"},{id:"co2",path:"/datum/gas/carbon_dioxide",name:"Carbon Dioxide",label:"CO₂",color:"grey"},{id:"plasma",path:"/datum/gas/plasma",name:"Plasma",label:"Plasma",color:"pink"},{id:"water_vapor",path:"/datum/gas/water_vapor",name:"Water Vapor",label:"H₂O",color:"lightsteelblue"},{id:"hypernoblium",path:"/datum/gas/hypernoblium",name:"Hyper-noblium",label:"Hyper-nob",color:"teal"},{id:"n2o",path:"/datum/gas/nitrous_oxide",name:"Nitrous Oxide",label:"N₂O",color:"bisque"},{id:"no2",path:"/datum/gas/nitrium",name:"Nitrium",label:"Nitrium",color:"brown"},{id:"tritium",path:"/datum/gas/tritium",name:"Tritium",label:"Tritium",color:"limegreen"},{id:"bz",path:"/datum/gas/bz",name:"BZ",label:"BZ",color:"mediumpurple"},{id:"pluoxium",path:"/datum/gas/pluoxium",name:"Pluoxium",label:"Pluoxium",color:"mediumslateblue"},{id:"miasma",path:"/datum/gas/miasma",name:"Miasma",label:"Miasma",color:"olive"},{id:"freon",path:"/datum/gas/freon",name:"Freon",label:"Freon",color:"paleturquoise"},{id:"hydrogen",path:"/datum/gas/hydrogen",name:"Hydrogen",label:"H₂",color:"white"},{id:"healium",path:"/datum/gas/healium",name:"Healium",label:"Healium",color:"salmon"},{id:"proto_nitrate",path:"/datum/gas/proto_nitrate",name:"Proto Nitrate",label:"Proto-Nitrate",color:"greenyellow"},{id:"zauker",path:"/datum/gas/zauker",name:"Zauker",label:"Zauker",color:"darkgreen"},{id:"halon",path:"/datum/gas/halon",name:"Halon",label:"Halon",color:"purple"},{id:"helium",path:"/datum/gas/helium",name:"Helium",label:"He",color:"aliceblue"},{id:"antinoblium",path:"/datum/gas/antinoblium",name:"Antinoblium",label:"Anti-Noblium",color:"maroon"},{id:"nitrium",path:"/datum/gas/nitrium",name:"Nitrium",label:"Nitrium",color:"brown"}];function m(e,a){if(!e)return a||"None";let o=e.toLowerCase();for(let e=0;e<n.length;e++)if(n[e].id===o)return n[e].label;return a||"None"}function u(e){if(!e)return"black";let a=e.toLowerCase();for(let e=0;e<n.length;e++)if(n[e].id===a)return n[e].color;return"black"}let c=e=>{if(!e)return;let a=e.toLowerCase();for(let e=0;e<n.length;e++)if(n[e].id===a)return n[e]},d=e=>{if(e){for(let a=0;a<n.length;a++)if(n[a].path===e)return n[a]}},b={states:["","good","average","bad","black","white"],spectrum:["red","orange","yellow","olive","green","teal","blue","violet","purple","pink","brown","grey","gold"]};export{l as COLORS,b as COMPONENT_COLORS,t as CSS_COLORS,i as RADIO_CHANNELS,r as UI_CLOSE,o as UI_DISABLED,e as UI_INTERACTIVE,a as UI_UPDATE,u as getGasColor,c as getGasFromId,d as getGasFromPath,m as getGasLabel};
@@ -10,6 +10,8 @@ export declare function acquireHotKey(keyCode: number): void;
10
10
  export declare function releaseHotKey(keyCode: number): void;
11
11
  export declare function releaseHeldKeys(): void;
12
12
  export declare function setupHotKeys(): void;
13
+ export declare function startKeyPassthrough(): void;
14
+ export declare function stopKeyPassthrough(): void;
13
15
  /**
14
16
  * Registers for any key events, such as key down or key up.
15
17
  * This should be preferred over directly connecting to keydown/keyup
@@ -1 +1 @@
1
- import*as e from"./events.js";import*as t from"./keycodes.js";let o={},n=[t.KEY_ESCAPE,t.KEY_ENTER,t.KEY_SPACE,t.KEY_TAB,t.KEY_CTRL,t.KEY_SHIFT,t.KEY_UP,t.KEY_DOWN,t.KEY_LEFT,t.KEY_RIGHT,t.KEY_F5],l={},r=[];function i(e){n.push(e)}function s(e){let t=n.indexOf(e);t>=0&&n.splice(t,1)}function d(){for(let e in l)l[e]&&(l[e]=!1,Byond.command(`${globalThis.ByondKeyUp} "${e}"`))}function a(){globalThis.ByondKeyUp||(globalThis.ByondKeyUp="KeyUp",globalThis.ByondKeyDown="KeyDown"),Byond.winget("default.*").then(e=>{let t={};for(let o in e){let n=o.split("."),l=n[1],r=n[2];l&&r&&(t[l]||(t[l]={}),t[l][r]=e[o])}let n=/\\"/g;function l(e){return e.substring(1,e.length-1).replace(n,'"')}for(let e in t){let n=t[e];o[l(n.name)]=l(n.command)}}),e.globalEvents.on("window-blur",()=>{d()}),e.globalEvents.on("key",e=>{for(let t of r)t(e);!function(e){var t;let r=String(e);if("Ctrl+F5"===r||"Ctrl+R"===r)return location.reload();if("Ctrl+F"===r||e.event.defaultPrevented||e.isModifierKey()||n.includes(e.code))return;let i=16===(t=e.code)?"Shift":17===t?"Ctrl":18===t?"Alt":33===t?"Northeast":34===t?"Southeast":35===t?"Southwest":36===t?"Northwest":37===t?"West":38===t?"North":39===t?"East":40===t?"South":45===t?"Insert":46===t?"Delete":t>=48&&t<=57||t>=65&&t<=90?String.fromCharCode(t):t>=96&&t<=105?`Numpad${t-96}`:t>=112&&t<=123?`F${t-111}`:188===t?",":189===t?"-":190===t?".":void 0;if(!i)return;let s=o[i];if(s)return Byond.command(s);if(e.isDown()&&!l[i]){l[i]=!0;let e=`${globalThis.ByondKeyDown} "${i}"`;return Byond.command(e)}if(e.isUp()&&l[i]){l[i]=!1;let e=`${globalThis.ByondKeyUp} "${i}"`;Byond.command(e)}}(e)})}function f(e){r.push(e);let t=!1;return()=>{t||(t=!0,r.splice(r.indexOf(e),1))}}export{i as acquireHotKey,f as listenForKeyEvents,d as releaseHeldKeys,s as releaseHotKey,a as setupHotKeys};
1
+ import*as e from"./events.js";import*as t from"./keycodes.js";let o={},n=[t.KEY_ESCAPE,t.KEY_ENTER,t.KEY_SPACE,t.KEY_TAB,t.KEY_CTRL,t.KEY_SHIFT,t.KEY_UP,t.KEY_DOWN,t.KEY_LEFT,t.KEY_RIGHT,t.KEY_F5],l={},r=[];function i(e){n.push(e)}function s(e){let t=n.indexOf(e);t>=0&&n.splice(t,1)}function a(){for(let e in l)l[e]&&(l[e]=!1,Byond.command(`${globalThis.ByondKeyUp} "${e}"`))}function d(){globalThis.ByondKeyUp||(globalThis.ByondKeyUp="KeyUp",globalThis.ByondKeyDown="KeyDown"),Byond.winget("default.*").then(e=>{let t={};for(let o in e){let n=o.split("."),l=n[1],r=n[2];l&&r&&(t[l]||(t[l]={}),t[l][r]=e[o])}let n=/\\"/g;function l(e){return e.substring(1,e.length-1).replace(n,'"')}for(let e in t){let n=t[e];o[l(n.name)]=l(n.command)}}),e.globalEvents.on("window-blur",()=>{a()}),f()}function f(){e.globalEvents.on("key",y)}function u(){e.globalEvents.off("key",y)}function y(e){for(let t of r)t(e);!function(e){var t;let r=String(e);if("Ctrl+F5"===r||"Ctrl+R"===r)return location.reload();if("Ctrl+F"===r||e.event.defaultPrevented||e.isModifierKey()||n.includes(e.code))return;let i=16===(t=e.code)?"Shift":17===t?"Ctrl":18===t?"Alt":33===t?"Northeast":34===t?"Southeast":35===t?"Southwest":36===t?"Northwest":37===t?"West":38===t?"North":39===t?"East":40===t?"South":45===t?"Insert":46===t?"Delete":t>=48&&t<=57||t>=65&&t<=90?String.fromCharCode(t):t>=96&&t<=105?`Numpad${t-96}`:t>=112&&t<=123?`F${t-111}`:188===t?",":189===t?"-":190===t?".":void 0;if(!i)return;let s=o[i];if(s)return Byond.command(s);if(e.isDown()&&!l[i]){l[i]=!0;let e=`${globalThis.ByondKeyDown} "${i}"`;return Byond.command(e)}if(e.isUp()&&l[i]){l[i]=!1;let e=`${globalThis.ByondKeyUp} "${i}"`;Byond.command(e)}}(e)}function K(e){r.push(e);let t=!1;return()=>{t||(t=!0,r.splice(r.indexOf(e),1))}}export{i as acquireHotKey,K as listenForKeyEvents,a as releaseHeldKeys,s as releaseHotKey,d as setupHotKeys,f as startKeyPassthrough,u as stopKeyPassthrough};
@@ -61,6 +61,16 @@ export declare const KEY_W = 87;
61
61
  export declare const KEY_X = 88;
62
62
  export declare const KEY_Y = 89;
63
63
  export declare const KEY_Z = 90;
64
+ export declare const KEY_NUMPAD_0 = 96;
65
+ export declare const KEY_NUMPAD_1 = 97;
66
+ export declare const KEY_NUMPAD_2 = 98;
67
+ export declare const KEY_NUMPAD_3 = 99;
68
+ export declare const KEY_NUMPAD_4 = 100;
69
+ export declare const KEY_NUMPAD_5 = 101;
70
+ export declare const KEY_NUMPAD_6 = 102;
71
+ export declare const KEY_NUMPAD_7 = 103;
72
+ export declare const KEY_NUMPAD_8 = 104;
73
+ export declare const KEY_NUMPAD_9 = 105;
64
74
  export declare const KEY_F1 = 112;
65
75
  export declare const KEY_F2 = 113;
66
76
  export declare const KEY_F3 = 114;
@@ -1 +1 @@
1
- let E=8,K=9,_=13,Y=16,A=17,F=18,T=19,S=20,C=27,L=32,P=33,O=34,R=35,I=36,N=37,H=38,U=39,B=40,D=45,M=46,G=48,Q=49,W=50,e=51,t=52,l=53,o=54,p=55,r=56,x=57,J=65,V=66,X=67,Z=68,a=69,b=70,c=71,d=72,f=73,g=74,h=75,i=76,j=77,k=78,m=79,n=80,q=81,s=82,u=83,v=84,w=85,y=86,z=87,$=88,EE=89,EK=90,E_=112,EY=113,EA=114,EF=115,ET=116,ES=117,EC=118,EL=119,EP=120,EO=121,ER=122,EI=123,EN=186,EH=187,EU=188,EB=189,ED=190,EM=191,EG=219,EQ=220,EW=221,Ee=222;export{G as KEY_0,Q as KEY_1,W as KEY_2,e as KEY_3,t as KEY_4,l as KEY_5,o as KEY_6,p as KEY_7,r as KEY_8,x as KEY_9,J as KEY_A,F as KEY_ALT,V as KEY_B,EQ as KEY_BACKSLASH,E as KEY_BACKSPACE,X as KEY_C,S as KEY_CAPSLOCK,EU as KEY_COMMA,A as KEY_CTRL,Z as KEY_D,M as KEY_DELETE,B as KEY_DOWN,a as KEY_E,R as KEY_END,_ as KEY_ENTER,EH as KEY_EQUAL,C as KEY_ESCAPE,b as KEY_F,E_ as KEY_F1,EO as KEY_F10,ER as KEY_F11,EI as KEY_F12,EY as KEY_F2,EA as KEY_F3,EF as KEY_F4,ET as KEY_F5,ES as KEY_F6,EC as KEY_F7,EL as KEY_F8,EP as KEY_F9,c as KEY_G,d as KEY_H,I as KEY_HOME,f as KEY_I,D as KEY_INSERT,g as KEY_J,h as KEY_K,i as KEY_L,N as KEY_LEFT,EG as KEY_LEFT_BRACKET,j as KEY_M,EB as KEY_MINUS,k as KEY_N,m as KEY_O,n as KEY_P,O as KEY_PAGEDOWN,P as KEY_PAGEUP,T as KEY_PAUSE,ED as KEY_PERIOD,q as KEY_Q,Ee as KEY_QUOTE,s as KEY_R,U as KEY_RIGHT,EW as KEY_RIGHT_BRACKET,u as KEY_S,EN as KEY_SEMICOLON,Y as KEY_SHIFT,EM as KEY_SLASH,L as KEY_SPACE,v as KEY_T,K as KEY_TAB,w as KEY_U,H as KEY_UP,y as KEY_V,z as KEY_W,$ as KEY_X,EE as KEY_Y,EK as KEY_Z};
1
+ let E=8,_=9,K=13,Y=16,A=17,P=18,N=19,U=20,D=27,F=32,M=33,T=34,S=35,C=36,L=37,O=38,R=39,I=40,H=45,B=46,G=48,Q=49,W=50,e=51,t=52,l=53,o=54,p=55,r=56,x=57,J=65,V=66,X=67,Z=68,a=69,b=70,c=71,d=72,f=73,g=74,h=75,i=76,j=77,k=78,m=79,n=80,q=81,s=82,u=83,v=84,w=85,y=86,z=87,$=88,EE=89,E_=90,EK=96,EY=97,EA=98,EP=99,EN=100,EU=101,ED=102,EF=103,EM=104,ET=105,ES=112,EC=113,EL=114,EO=115,ER=116,EI=117,EH=118,EB=119,EG=120,EQ=121,EW=122,Ee=123,Et=186,El=187,Eo=188,Ep=189,Er=190,Ex=191,EJ=219,EV=220,EX=221,EZ=222;export{G as KEY_0,Q as KEY_1,W as KEY_2,e as KEY_3,t as KEY_4,l as KEY_5,o as KEY_6,p as KEY_7,r as KEY_8,x as KEY_9,J as KEY_A,P as KEY_ALT,V as KEY_B,EV as KEY_BACKSLASH,E as KEY_BACKSPACE,X as KEY_C,U as KEY_CAPSLOCK,Eo as KEY_COMMA,A as KEY_CTRL,Z as KEY_D,B as KEY_DELETE,I as KEY_DOWN,a as KEY_E,S as KEY_END,K as KEY_ENTER,El as KEY_EQUAL,D as KEY_ESCAPE,b as KEY_F,ES as KEY_F1,EQ as KEY_F10,EW as KEY_F11,Ee as KEY_F12,EC as KEY_F2,EL as KEY_F3,EO as KEY_F4,ER as KEY_F5,EI as KEY_F6,EH as KEY_F7,EB as KEY_F8,EG as KEY_F9,c as KEY_G,d as KEY_H,C as KEY_HOME,f as KEY_I,H as KEY_INSERT,g as KEY_J,h as KEY_K,i as KEY_L,L as KEY_LEFT,EJ as KEY_LEFT_BRACKET,j as KEY_M,Ep as KEY_MINUS,k as KEY_N,EK as KEY_NUMPAD_0,EY as KEY_NUMPAD_1,EA as KEY_NUMPAD_2,EP as KEY_NUMPAD_3,EN as KEY_NUMPAD_4,EU as KEY_NUMPAD_5,ED as KEY_NUMPAD_6,EF as KEY_NUMPAD_7,EM as KEY_NUMPAD_8,ET as KEY_NUMPAD_9,m as KEY_O,n as KEY_P,T as KEY_PAGEDOWN,M as KEY_PAGEUP,N as KEY_PAUSE,Er as KEY_PERIOD,q as KEY_Q,EZ as KEY_QUOTE,s as KEY_R,R as KEY_RIGHT,EX as KEY_RIGHT_BRACKET,u as KEY_S,Et as KEY_SEMICOLON,Y as KEY_SHIFT,Ex as KEY_SLASH,F as KEY_SPACE,v as KEY_T,_ as KEY_TAB,w as KEY_U,O as KEY_UP,y as KEY_V,z as KEY_W,$ as KEY_X,EE as KEY_Y,E_ as KEY_Z};
@@ -41,3 +41,7 @@ export declare function numberOfDecimalDigits(value: number): number;
41
41
  * Ensures the number is valid and not infinite/NaN.
42
42
  */
43
43
  export declare function isSafeNumber(value: number): boolean;
44
+ /**
45
+ * Converts a value in radians to degrees.
46
+ */
47
+ export declare function rad2deg(rad: number): number;
@@ -1 +1 @@
1
- function n(n,t,e){return n<t?t:n>e?e:n}function t(n){return n<0?0:n>1?1:n}function e(n,t=0,r=100){return(n-t)/(r-t)}function r(n,t){return Number.parseFloat((Math.round(n*10**t+1e-4*(n>=0?1:-1))/10**t).toFixed(t))}function u(n,t=0){return Number(n).toFixed(Math.max(t,0))}function i(n,t){return t&&n>=t[0]&&n<=t[1]}function o(n,t){for(let e of Object.keys(t))if(i(n,t[e]))return e}function f(n){return Math.floor(n)!==n&&n.toString().split(".")[1].length||0}function a(n){return"number"==typeof n&&Number.isFinite(n)&&!Number.isNaN(n)}export{n as clamp,t as clamp01,i as inRange,a as isSafeNumber,o as keyOfMatchingRange,f as numberOfDecimalDigits,r as round,e as scale,u as toFixed};
1
+ function n(n,t,e){return n<t?t:n>e?e:n}function t(n){return n<0?0:n>1?1:n}function e(n,t=0,r=100){return(n-t)/(r-t)}function r(n,t){return Number.parseFloat((Math.round(n*10**t+1e-4*(n>=0?1:-1))/10**t).toFixed(t))}function u(n,t=0){return Number(n).toFixed(Math.max(t,0))}function i(n,t){return t&&n>=t[0]&&n<=t[1]}function o(n,t){for(let e of Object.keys(t))if(i(n,t[e]))return e}function f(n){return Math.floor(n)!==n&&n.toString().split(".")[1].length||0}function a(n){return"number"==typeof n&&Number.isFinite(n)&&!Number.isNaN(n)}function c(n){return 180/Math.PI*n}export{n as clamp,t as clamp01,i as inRange,a as isSafeNumber,o as keyOfMatchingRange,f as numberOfDecimalDigits,c as rad2deg,r as round,e as scale,u as toFixed};
@@ -112,7 +112,7 @@ export type BooleanStyleMap = {
112
112
  };
113
113
  export declare const booleanStyleMap: Record<keyof BooleanStyleMap, any>;
114
114
  export declare function computeBoxProps(props: any): Record<string, any>;
115
- export declare function computeBoxClassName(props: BoxProps): string;
115
+ export declare function computeBoxClassName<TElement = HTMLDivElement>(props: BoxProps<TElement>): string;
116
116
  type StyleMap = StringStyleMap & BooleanStyleMap;
117
117
  /** Super light implementation of tailwind-like class names. */
118
118
  export declare function computeTwClass(input: string | undefined): StyleMap;
@@ -1,18 +1,18 @@
1
1
  import { type CSSProperties, type KeyboardEventHandler, type MouseEventHandler, type ReactNode, type UIEventHandler } from 'react';
2
2
  import type { BooleanLike } from '../common/react';
3
3
  import { type BooleanStyleMap, type StringStyleMap } from '../common/ui';
4
- type EventHandlers = {
5
- onClick: MouseEventHandler<HTMLDivElement>;
6
- onContextMenu: MouseEventHandler<HTMLDivElement>;
7
- onDoubleClick: MouseEventHandler<HTMLDivElement>;
8
- onKeyDown: KeyboardEventHandler<HTMLDivElement>;
9
- onKeyUp: KeyboardEventHandler<HTMLDivElement>;
10
- onMouseDown: MouseEventHandler<HTMLDivElement>;
11
- onMouseLeave: MouseEventHandler<HTMLDivElement>;
12
- onMouseMove: MouseEventHandler<HTMLDivElement>;
13
- onMouseOver: MouseEventHandler<HTMLDivElement>;
14
- onMouseUp: MouseEventHandler<HTMLDivElement>;
15
- onScroll: UIEventHandler<HTMLDivElement | HTMLTextAreaElement>;
4
+ type EventHandlers<TElement = HTMLDivElement> = {
5
+ onClick: MouseEventHandler<TElement>;
6
+ onContextMenu: MouseEventHandler<TElement>;
7
+ onDoubleClick: MouseEventHandler<TElement>;
8
+ onKeyDown: KeyboardEventHandler<TElement>;
9
+ onKeyUp: KeyboardEventHandler<TElement>;
10
+ onMouseDown: MouseEventHandler<TElement>;
11
+ onMouseLeave: MouseEventHandler<TElement>;
12
+ onMouseMove: MouseEventHandler<TElement>;
13
+ onMouseOver: MouseEventHandler<TElement>;
14
+ onMouseUp: MouseEventHandler<TElement>;
15
+ onScroll: UIEventHandler<TElement>;
16
16
  };
17
17
  type InternalProps = {
18
18
  /** The component used for the root node. */
@@ -49,7 +49,7 @@ type InternalProps = {
49
49
  */
50
50
  tw: string;
51
51
  };
52
- export type BoxProps = Partial<InternalProps & BooleanStyleMap & StringStyleMap & EventHandlers>;
52
+ export type BoxProps<TElement = HTMLDivElement> = Partial<InternalProps & BooleanStyleMap & StringStyleMap & EventHandlers<TElement>>;
53
53
  type DangerDoNotUse = {
54
54
  dangerouslySetInnerHTML?: {
55
55
  __html: any;
@@ -97,7 +97,7 @@ type DangerDoNotUse = {
97
97
  *
98
98
  * Default font size (`1rem`) is equal to `12px`.
99
99
  */
100
- export declare function Box(props: BoxProps & DangerDoNotUse): import("react").ReactElement<{
100
+ export declare function Box<TElement = HTMLDivElement>(props: BoxProps<TElement> & DangerDoNotUse): import("react").ReactElement<{
101
101
  className: string;
102
102
  }, string | import("react").JSXElementConstructor<any>>;
103
103
  export {};
@@ -33,6 +33,8 @@ type Props = {
33
33
  * @default 200
34
34
  */
35
35
  animationDuration: number;
36
+ /** Direct content open state control. */
37
+ handleOpen: boolean;
36
38
  /** Content will open when you hover over children. */
37
39
  hoverOpen: boolean;
38
40
  /**
@@ -48,6 +50,8 @@ type Props = {
48
50
  * - Classes must be sent like this: `".class1, .class2"`
49
51
  */
50
52
  allowedOutsideClasses: string;
53
+ /** Do not wrap content in FloatingPortal, thus preventing it from moving into the body */
54
+ preventPortal: true;
51
55
  /** Stops event propagation on children. */
52
56
  stopChildPropagation: boolean;
53
57
  /** Close the content after interaction with it. */
@@ -1 +1 @@
1
- import*as e from"react/jsx-runtime";import*as t from"@floating-ui/react";import*as n from"react";import*as a from"../common/react.js";function s(s){let o,{allowedOutsideClasses:i,animationDuration:r,children:l,closeAfterInteract:c,content:m,contentAutoWidth:d,contentClasses:p,contentOffset:f=6,contentStyles:u,disabled:g,hoverDelay:h,hoverOpen:x,onMounted:F,placement:j,stopChildPropagation:C,onOpenChange:v}=s,[w,E]=(0,n.useState)(!1),{refs:S,floatingStyles:b,context:k}=(0,t.useFloating)({open:w,onOpenChange(e){E(e),v?.(e)},whileElementsMounted:(e,n,a)=>(void 0!==F&&F(),(0,t.autoUpdate)(e,n,a,{elementResize:!1,ancestorResize:!1,ancestorScroll:!1})),placement:j||"bottom",transform:!1,middleware:[(0,t.offset)(f),(0,t.flip)({padding:6}),d&&(0,t.size)({apply({rects:e,elements:t}){t.floating.style.width=`${e.reference.width}px`}})]}),{isMounted:y,status:z}=(0,t.useTransitionStatus)(k,{duration:r||200}),P=(0,t.useDismiss)(k,{ancestorScroll:!0,outsidePress:e=>!i||e.target instanceof Element&&!e.target.closest(i)}),R=(0,t.useClick)(k,{enabled:!g}),M=(0,t.useHover)(k,{enabled:!g,restMs:h||200}),{getReferenceProps:O,getFloatingProps:D}=(0,t.useInteractions)([P,x?M:R]),H=O({ref:S.setReference,...C&&{onClick:e=>e.stopPropagation()}}),I=D({onClick:()=>{c&&k.onOpenChange(!1)}});return o=(0,n.isValidElement)(l)?(0,n.cloneElement)(l,H):(0,e.jsx)("div",{...H,children:l}),(0,e.jsxs)(e.Fragment,{children:[o,y&&!!m&&(0,e.jsx)(t.FloatingPortal,{children:(0,e.jsx)("div",{ref:S.setFloating,className:(0,a.classes)(["Floating",!r&&"Floating--animated",p]),"data-position":k.placement,"data-transition":z,style:{...b,...u},...I,children:m})})]})}export{s as Floating};
1
+ import*as e from"react/jsx-runtime";import*as t from"@floating-ui/react";import*as n from"react";import*as s from"../common/react.js";function a(a){let o,{allowedOutsideClasses:i,animationDuration:r,children:l,closeAfterInteract:c,content:m,contentAutoWidth:d,contentClasses:p,contentOffset:f=6,contentStyles:u,disabled:g,hoverDelay:h,hoverOpen:x,handleOpen:F,onMounted:j,placement:C,preventPortal:v,stopChildPropagation:E,onOpenChange:w}=a,[S,b]=(0,n.useState)(!1),{refs:k,floatingStyles:y,context:z}=(0,t.useFloating)({open:S,onOpenChange(e){b(e),w?.(e)},whileElementsMounted:(e,n,s)=>(void 0!==j&&j(),(0,t.autoUpdate)(e,n,s,{ancestorResize:!1,ancestorScroll:!1,elementResize:!d})),placement:C||"bottom",transform:!1,middleware:[(0,t.offset)(f),(0,t.flip)({padding:6}),(0,t.shift)(),d&&(0,t.size)({apply({rects:e,elements:t}){t.floating.style.width=`${e.reference.width}px`}})]}),{isMounted:O,status:P}=(0,t.useTransitionStatus)(z,{duration:r||200}),R=(0,t.useDismiss)(z,{ancestorScroll:!0,outsidePress:e=>!i||e.target instanceof Element&&!e.target.closest(i)}),M=(0,t.useClick)(z,{enabled:!g}),D=(0,t.useHover)(z,{enabled:!g,restMs:h||200}),H=void 0!==F,{getReferenceProps:I,getFloatingProps:N}=(0,t.useInteractions)(H?[]:[R,x?D:M]),T=I({ref:k.setReference,...E&&{onClick:e=>e.stopPropagation()}}),U=N({ref:k.setFloating,onClick:()=>{c&&z.onOpenChange(!1)}});(0,n.useEffect)(()=>{H&&z.onOpenChange(F)},[F]),o=(0,n.isValidElement)(l)?(0,n.cloneElement)(l,T):(0,e.jsx)("div",{...T,children:l});let V=(0,e.jsx)("div",{className:(0,s.classes)(["Floating",!r&&"Floating--animated",p]),"data-transition":P,"data-position":z.placement,style:{...y,...u},...U,children:m});return(0,e.jsxs)(e.Fragment,{children:[o,O&&!!m&&(v?V:(0,e.jsx)(t.FloatingPortal,{children:V}))]})}export{a as Floating};
@@ -1,6 +1,6 @@
1
1
  import { type RefObject } from 'react';
2
2
  import type { BoxProps } from './Box';
3
- export type BaseInputProps = Partial<{
3
+ export type BaseInputProps<TElement = HTMLInputElement> = Partial<{
4
4
  /** Automatically focuses the input on mount */
5
5
  autoFocus: boolean;
6
6
  /** Automatically selects the input value on focus */
@@ -22,10 +22,12 @@ export type BaseInputProps = Partial<{
22
22
  fluid: boolean;
23
23
  /** Mark this if you want to use a monospace font */
24
24
  monospace: boolean;
25
- }> & BoxProps;
26
- export type TextInputProps = Partial<{
25
+ }> & BoxProps<TElement>;
26
+ export type TextInputProps<TElement = HTMLInputElement> = Partial<{
27
27
  /** The maximum length of the input value */
28
28
  maxLength: number;
29
+ /** Fires each time focus leaves the input, including if Esc or Enter are pressed */
30
+ onBlur: (value: string) => void;
29
31
  /** Fires each time the input has been changed */
30
32
  onChange: (value: string) => void;
31
33
  /** Fires once the enter key is pressed */
@@ -75,7 +77,7 @@ export type TextInputProps = Partial<{
75
77
  * ```
76
78
  */
77
79
  value: string;
78
- }> & BaseInputProps;
80
+ }> & BaseInputProps<TElement>;
79
81
  type Props = Partial<{
80
82
  /** Ref of the input element */
81
83
  ref: RefObject<HTMLInputElement | null>;
@@ -1 +1 @@
1
- import*as e from"react/jsx-runtime";import*as t from"react";import*as r from"../common/keys.js";import*as u from"../common/react.js";import*as o from"../common/timer.js";import*as n from"../common/ui.js";let a=(0,o.debounce)(e=>e(),250);function c(o){let{autoFocus:c,autoSelect:s,className:m,disabled:l,expensive:p,fluid:f,maxLength:i,monospace:d,onChange:g,onEnter:v,onEscape:x,placeholder:T,ref:j,selfClear:E,value:b,...y}=o,I=(0,t.useRef)(null),h=j??I,[k,C]=(0,t.useState)(b);(0,t.useEffect)(()=>{let e;return(c||s)&&(e=setTimeout(()=>{h.current?.focus(),s&&h.current?.select()},1)),()=>clearTimeout(e)},[]),(0,t.useEffect)(()=>{h.current&&document.activeElement!==h.current&&b!==k&&C(b??"")},[b]);let D=(0,n.computeBoxProps)(y),B=(0,u.classes)(["Input",l&&"Input--disabled",f&&"Input--fluid",d&&"Input--monospace",(0,n.computeBoxClassName)(y),m]);return(0,e.jsx)("input",{...D,autoComplete:"off",className:B,disabled:l,maxLength:i,onChange:function(e){let t=e.currentTarget.value;C(t),p?a(()=>g?.(t)):g?.(t)},onKeyDown:function(e){if(e.key===r.KEY.Enter){e.preventDefault(),v?.(e.currentTarget.value),E&&C(""),e.currentTarget.blur();return}(0,r.isEscape)(e.key)&&(e.preventDefault(),x?.(e.currentTarget.value),e.currentTarget.blur())},placeholder:T,ref:h,spellCheck:!1,type:"text",value:k})}export{c as Input};
1
+ import*as e from"react/jsx-runtime";import*as t from"react";import*as r from"../common/keys.js";import*as u from"../common/react.js";import*as n from"../common/timer.js";import*as o from"../common/ui.js";let a=(0,n.debounce)(e=>e(),250);function c(n){let{autoFocus:c,autoSelect:s,className:m,disabled:l,expensive:p,fluid:f,maxLength:i,monospace:d,onBlur:g,onChange:v,onEnter:x,onEscape:T,onKeyDown:j,placeholder:E,ref:b,selfClear:y,value:I,...h}=n,k=(0,t.useRef)(null),C=b??k,[B,D]=(0,t.useState)(I??"");(0,t.useEffect)(()=>{let e;return(c||s)&&(e=setTimeout(()=>{C.current?.focus(),s&&C.current?.select()},1)),()=>clearTimeout(e)},[]),(0,t.useEffect)(()=>{C.current&&document.activeElement!==C.current&&I!==B&&D(I??"")},[I]);let K=(0,o.computeBoxProps)(h),N=(0,u.classes)(["Input",l&&"Input--disabled",f&&"Input--fluid",d&&"Input--monospace",(0,o.computeBoxClassName)(h),m]);return(0,e.jsx)("input",{...K,autoComplete:"off",className:N,disabled:l,maxLength:i,onBlur:function(e){g?.(B)},onChange:function(e){let t=e.currentTarget.value;D(t),p?a(()=>v?.(t)):v?.(t)},onKeyDown:function(e){if(j?.(e),e.key===r.KEY.Enter){e.preventDefault(),x?.(e.currentTarget.value),y&&D(""),e.currentTarget.blur();return}(0,r.isEscape)(e.key)&&(e.preventDefault(),T?.(e.currentTarget.value),e.currentTarget.blur())},placeholder:E,ref:C,spellCheck:!1,type:"text",value:B})}export{c as Input};
@@ -1,3 +1,4 @@
1
+ import type { Placement } from '@floating-ui/react';
1
2
  import { type BooleanLike } from '../common/react';
2
3
  import type { BoxProps } from './Box';
3
4
  type Props = {
@@ -46,6 +47,8 @@ type Props = {
46
47
  unclamped: boolean;
47
48
  /** Unit to display to the right of value. */
48
49
  unit: string;
50
+ /** Value popup placement, like on tooltips. */
51
+ popupPosition: Placement;
49
52
  }> & BoxProps;
50
53
  /**
51
54
  * ## Knob
@@ -1 +1 @@
1
- import*as s from"react/jsx-runtime";import*as o from"../common/math.js";import*as r from"../common/react.js";import*as e from"../common/ui.js";import*as a from"./DraggableControl.js";function c(c){let{animated:l,format:n,maxValue:i,minValue:t,onChange:m,onDrag:x,step:_,stepPixelSize:b,unclamped:d,unit:j,value:g,bipolar:h,className:K,color:f,fillValue:p,ranges:u={},size:v=1,style:N,...y}=c;return(0,s.jsx)(a.DraggableControl,{dragMatrix:[0,-1],animated:l,format:n,maxValue:i,minValue:t,onChange:m,onDrag:x,step:_,stepPixelSize:b,unclamped:d,unit:j,value:g,children:a=>{let{displayElement:c,displayValue:l,dragging:n,handleDragStart:m,inputElement:x}=a,_=(0,o.scale)(p??l,t,i),b=(0,o.scale)(l,t,i),d=f||(0,o.keyOfMatchingRange)(p??g,u)||"default",j=Math.min((b-.5)*270,225);return(0,s.jsxs)("div",{className:(0,r.classes)(["Knob",`Knob--color--${d}`,h&&"Knob--bipolar",K,(0,e.computeBoxClassName)(y)]),...(0,e.computeBoxProps)({style:{fontSize:`${v}em`,...N},...y}),onMouseDown:m,children:[(0,s.jsx)("div",{className:"Knob__circle",children:(0,s.jsx)("div",{className:"Knob__cursorBox",style:{transform:`rotate(${j}deg)`},children:(0,s.jsx)("div",{className:"Knob__cursor"})})}),n&&(0,s.jsx)("div",{className:"Knob__popupValue",children:c}),(0,s.jsxs)("svg",{className:"Knob__ring Knob__ringTrackPivot",viewBox:"0 0 100 100",children:[(0,s.jsx)("circle",{className:"Knob__ringTrack",cx:"50",cy:"50",r:"50"}),(0,s.jsx)("title",{children:"track"})]}),(0,s.jsxs)("svg",{className:"Knob__ring Knob__ringFillPivot",viewBox:"0 0 100 100",children:[(0,s.jsx)("title",{children:"fill"}),(0,s.jsx)("circle",{className:"Knob__ringFill",style:{strokeDashoffset:Math.max(((h?2.75:2)-1.5*_)*Math.PI*50,0)},cx:"50",cy:"50",r:"50"})]}),x]})}})}export{c as Knob};
1
+ import*as o from"react/jsx-runtime";import*as s from"../common/math.js";import*as e from"../common/react.js";import*as r from"../common/ui.js";import*as a from"./DraggableControl.js";import*as n from"./Floating.js";function t(t){let{animated:l,format:c,maxValue:i,minValue:m,onChange:x,onDrag:_,step:g,stepPixelSize:j,unclamped:p,unit:b,value:d,bipolar:h,popupPosition:f,className:K,color:u,fillValue:v,ranges:N={},size:y=1,style:M,...k}=t;return(0,o.jsx)(a.DraggableControl,{dragMatrix:[0,-1],animated:l,format:c,maxValue:i,minValue:m,onChange:x,onDrag:_,step:g,stepPixelSize:j,unclamped:p,unit:b,value:d,children:a=>{let{displayElement:t,displayValue:l,dragging:c,handleDragStart:x,inputElement:_}=a,g=(0,s.scale)(v??l,m,i),j=(0,s.scale)(l,m,i),p=u||(0,s.keyOfMatchingRange)(v??d,N)||"default",b=Math.min((j-.5)*270,225);return(0,o.jsx)(n.Floating,{preventPortal:!0,handleOpen:c,contentClasses:"Knob__popupValue",content:t,placement:f||"top",children:(0,o.jsxs)("div",{className:(0,e.classes)(["Knob",`Knob--color--${p}`,h&&"Knob--bipolar",K,(0,r.computeBoxClassName)(k)]),...(0,r.computeBoxProps)({style:{fontSize:`${y}em`,...M},...k}),onMouseDown:x,children:[(0,o.jsx)("div",{className:"Knob__circle",children:(0,o.jsx)("div",{className:"Knob__cursorBox",style:{transform:`rotate(${b}deg)`},children:(0,o.jsx)("div",{className:"Knob__cursor"})})}),(0,o.jsxs)("svg",{className:"Knob__ring Knob__ringTrackPivot",viewBox:"0 0 100 100",children:[(0,o.jsx)("circle",{className:"Knob__ringTrack",cx:"50",cy:"50",r:"50"}),(0,o.jsx)("title",{children:"track"})]}),(0,o.jsxs)("svg",{className:"Knob__ring Knob__ringFillPivot",viewBox:"0 0 100 100",children:[(0,o.jsx)("title",{children:"fill"}),(0,o.jsx)("circle",{className:"Knob__ringFill",style:{strokeDashoffset:Math.max(((h?2.75:2)-1.5*g)*Math.PI*50,0)},cx:"50",cy:"50",r:"50"})]}),_]})})}})}export{t as Knob};
@@ -1,3 +1,4 @@
1
+ import type { Placement } from '@floating-ui/react';
1
2
  import type { PropsWithChildren, ReactNode } from 'react';
2
3
  import { type BooleanLike } from '../common/react';
3
4
  export declare function LabeledList(props: PropsWithChildren): import("react/jsx-runtime").JSX.Element;
@@ -33,6 +34,8 @@ type LabeledListItemProps = Partial<{
33
34
  textAlign: string;
34
35
  /** Tooltip text. */
35
36
  tooltip: string;
37
+ /** Tooltip position. See Tooltip for valid values. */
38
+ tooltipPosition: Placement;
36
39
  /**
37
40
  * Align both the label and the content vertically.
38
41
  *
@@ -42,6 +45,8 @@ type LabeledListItemProps = Partial<{
42
45
  * - `bottom`
43
46
  */
44
47
  verticalAlign: string;
48
+ /** Preserves line-breaks and spacing in Labeled.Item text. */
49
+ preserveWhitespace: boolean;
45
50
  }>;
46
51
  declare function LabeledListItem(props: LabeledListItemProps): import("react/jsx-runtime").JSX.Element;
47
52
  type LabeledListDividerProps = {
@@ -1 +1 @@
1
- var e;import*as s from"react/jsx-runtime";import*as t from"../common/react.js";import*as l from"../common/ui.js";import*as i from"./Box.js";import*as a from"./Divider.js";import*as o from"./Tooltip.js";function r(e){let{children:t}=e;return(0,s.jsx)("table",{className:"LabeledList",children:(0,s.jsx)("tbody",{children:t})})}(e=r||(r={})).Divider=function(e){let t=e.size?(0,l.unit)(Math.max(0,e.size-1)):0;return(0,s.jsx)("tr",{className:"LabeledList__row",children:(0,s.jsx)("td",{colSpan:3,style:{paddingTop:t,paddingBottom:t},children:(0,s.jsx)(a.Divider,{})})})},e.Item=function(e){let l,{className:a,label:r,labelColor:d="label",labelWrap:n,color:c,textAlign:m,buttons:L,content:x,children:b,verticalAlign:p="baseline",tooltip:j}=e;r&&(l=r,"string"==typeof r&&(l+=":")),void 0!==j&&(l=(0,s.jsx)(o.Tooltip,{content:j,children:(0,s.jsx)(i.Box,{as:"span",style:{borderBottom:"2px dotted rgba(255, 255, 255, 0.8)"},children:l})}));let _=(0,s.jsx)(i.Box,{as:"td",color:d,className:(0,t.classes)(["LabeledList__cell",!n&&"LabeledList__label--nowrap"]),verticalAlign:p,children:l});return(0,s.jsxs)("tr",{className:(0,t.classes)(["LabeledList__row",a]),children:[_,(0,s.jsxs)(i.Box,{as:"td",color:c,textAlign:m,className:"LabeledList__cell",colSpan:L?void 0:2,verticalAlign:p,children:[x,b]}),L&&(0,s.jsx)("td",{className:"LabeledList__cell LabeledList__buttons",children:L})]})};export{r as LabeledList};
1
+ var e;import*as s from"react/jsx-runtime";import*as t from"../common/react.js";import*as l from"../common/ui.js";import*as i from"./Box.js";import*as a from"./Divider.js";import*as o from"./Tooltip.js";function r(e){let{children:t}=e;return(0,s.jsx)("table",{className:"LabeledList",children:(0,s.jsx)("tbody",{children:t})})}(e=r||(r={})).Divider=function(e){let t=e.size?(0,l.unit)(Math.max(0,e.size-1)):0;return(0,s.jsx)("tr",{className:"LabeledList__row",children:(0,s.jsx)("td",{colSpan:3,style:{paddingTop:t,paddingBottom:t},children:(0,s.jsx)(a.Divider,{})})})},e.Item=function(e){let l,{className:a,label:r,labelColor:d="label",labelWrap:n,color:c,textAlign:m,buttons:L,content:p,children:x,verticalAlign:b="baseline",preserveWhitespace:j,tooltip:_,tooltipPosition:h}=e;r&&(l=r,"string"==typeof r&&(l+=":")),void 0!==_&&(l=(0,s.jsx)(o.Tooltip,{content:_,position:h,children:(0,s.jsx)(i.Box,{as:"span",style:{borderBottom:"2px dotted rgba(255, 255, 255, 0.8)"},children:l})}));let f=(0,s.jsx)(i.Box,{as:"td",color:d,className:(0,t.classes)(["LabeledList__cell",!n&&"LabeledList__label--nowrap"]),verticalAlign:b,preserveWhitespace:j,children:l});return(0,s.jsxs)("tr",{className:(0,t.classes)(["LabeledList__row",a]),children:[f,(0,s.jsxs)(i.Box,{as:"td",color:c,textAlign:m,className:"LabeledList__cell",colSpan:L?void 0:2,verticalAlign:b,children:[p,x]}),L&&(0,s.jsx)("td",{className:"LabeledList__cell LabeledList__buttons",children:L})]})};export{r as LabeledList};
@@ -6,6 +6,8 @@ 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;
9
11
  /** Fires each time the input has been changed */
10
12
  onChange: (value: number) => void;
11
13
  /** Fires once the enter key is pressed */
@@ -1 +1 @@
1
- import*as e from"react/jsx-runtime";import*as t from"../common/react.js";import*as r from"../common/timer.js";import*as u from"../common/ui.js";import*as n from"react";import*as o from"../common/keys.js";let s=(0,r.debounce)(e=>e(),250);function c(r){let{allowFloats:c,autoFocus:m,autoSelect:a,className:i,disabled:l,expensive:f,fluid:p,maxValue:d=1e4,minValue:v=0,monospace:y,onChange:E,onEnter:b,onEscape:I,onValidationChange:j,value:x,...k}=r,C=(0,n.useRef)(null),[D,R]=(0,n.useState)(x??v),[K,N]=(0,n.useState)(!0);function g(e){E&&(f?s(()=>E(e)):E(e))}(0,n.useEffect)(()=>{let e;return(m||a)&&(e=setTimeout(()=>{C.current?.focus(),a&&C.current?.select()},1)),()=>clearTimeout(e)},[]),(0,n.useEffect)(()=>{if(C.current){let e=C.current.validity.valid;K!==e&&(N(e),j?.(e))}},[D]),(0,n.useEffect)(()=>{C.current&&document.activeElement!==C.current&&x!==D&&R(x??v)},[x]);let h=(0,u.computeBoxProps)(k),B=(0,t.classes)(["Input","RestrictedInput",l&&"Input--disabled",p&&"Input--fluid",y&&"Input--monospace",(0,u.computeBoxClassName)(k),i,!K&&"RestrictedInput--invalid"]);return(0,e.jsx)("input",{...h,autoComplete:"off",className:B,disabled:l,max:d,min:v,onChange:function(e){let t=Number(e.target.value);R(t),g(t)},onKeyDown:function(e){if(e.key===o.KEY.Enter){e.preventDefault(),b?.(D),C.current?.blur();return}if((0,o.isEscape)(e.key)){e.preventDefault(),I?.(D),C.current?.blur();return}if(e.key===o.KEY.Minus){e.preventDefault(),R(-1*D),g(D);return}},ref:C,spellCheck:!1,step:c?"any":"1",type:"number",value:D})}export{c as RestrictedInput};
1
+ import*as e from"react/jsx-runtime";import*as t from"../common/react.js";import*as r from"../common/timer.js";import*as n from"../common/ui.js";import*as u from"react";import*as o from"../common/keys.js";let s=(0,r.debounce)(e=>e(),250);function c(r){let{allowFloats:c,autoFocus:i,autoSelect:m,className:a,disabled:l,expensive:f,fluid:p,maxValue:d=1e4,minValue:v=0,monospace:y,onBlur:E,onChange:b,onEnter:I,onEscape:j,onKeyDown:x,onValidationChange:k,value:C,...D}=r,R=(0,u.useRef)(null),[B,K]=(0,u.useState)(C??v),[N,g]=(0,u.useState)(!0);function h(e){b&&(f?s(()=>b(e)):b(e))}(0,u.useEffect)(()=>{let e;return(i||m)&&(e=setTimeout(()=>{R.current?.focus(),m&&R.current?.select()},1)),()=>clearTimeout(e)},[]),(0,u.useEffect)(()=>{if(R.current){let e=R.current.validity.valid;N!==e&&(g(e),k?.(e))}},[B]),(0,u.useEffect)(()=>{R.current&&document.activeElement!==R.current&&C!==B&&K(C??v)},[C]);let S=(0,n.computeBoxProps)(D),T=(0,t.classes)(["Input","RestrictedInput",l&&"Input--disabled",p&&"Input--fluid",y&&"Input--monospace",(0,n.computeBoxClassName)(D),a,!N&&"RestrictedInput--invalid"]);return(0,e.jsx)("input",{...S,autoComplete:"off",className:T,disabled:l,max:d,min:v,onBlur:function(e){E?.(B)},onChange:function(e){let t=Number(e.target.value);K(t),h(t)},onKeyDown:function(e){if(x?.(e),e.key===o.KEY.Enter){e.preventDefault(),I?.(B),R.current?.blur();return}if((0,o.isEscape)(e.key)){e.preventDefault(),j?.(B),R.current?.blur();return}if(e.key===o.KEY.Minus){e.preventDefault();let t=-1*B;K(t),h(t);return}},ref:R,spellCheck:!1,step:c?"any":"1",type:"number",value:B})}export{c as RestrictedInput};
@@ -11,7 +11,7 @@ type Props = Partial<{
11
11
  * character
12
12
  */
13
13
  userMarkup: Record<string, string>;
14
- }> & TextInputProps;
14
+ }> & TextInputProps<HTMLTextAreaElement>;
15
15
  /**
16
16
  * ## Textarea
17
17
  *
@@ -1 +1 @@
1
- import*as e from"react/jsx-runtime";import*as t from"../common/timer.js";import*as r from"react";import*as n from"../common/keys.js";import*as u from"../common/react.js";import*as a from"../common/ui.js";let s=(0,t.debounce)(e=>e(),250);function o(t){let{autoFocus:o,autoSelect:c,className:l,disabled:m,dontUseTabForIndent:i,expensive:f,fluid:p,maxLength:g,monospace:T,onChange:b,onEnter:v,onEscape:y,placeholder:x,ref:E,selfClear:d,userMarkup:k,value:$,...h}=t,j=(0,r.useRef)(null),K=E??j,[C,D]=(0,r.useState)($??"");(0,r.useEffect)(()=>{(o||c)&&setTimeout(()=>{K.current?.focus(),c&&K.current?.select()},1)},[]),(0,r.useEffect)(()=>{K.current&&document.activeElement!==K.current&&$!==C&&D($??"")},[$]);let I=(0,a.computeBoxProps)(h),A=(0,u.classes)(["Input","TextArea",p&&"Input--fluid",T&&"Input--monospace",m&&"Input--disabled",(0,a.computeBoxClassName)(h),l]);return(0,e.jsx)("textarea",{...I,autoComplete:"off",className:A,maxLength:g,onChange:function(e){let t=e.currentTarget.value;D(t),b&&(f?s(()=>b(t)):b(t))},onKeyDown:function(e){if(e.key===n.KEY.Enter&&!e.shiftKey){e.preventDefault(),v?.(e.currentTarget.value),d&&D(""),e.currentTarget.blur();return}if((0,n.isEscape)(e.key)){y?.(e.currentTarget.value),e.currentTarget.blur();return}if(!i&&e.key===n.KEY.Tab){e.preventDefault();let{value:t,selectionStart:r,selectionEnd:n}=e.currentTarget;D(`${t.substring(0,r)} ${t.substring(n)}`),e.currentTarget.selectionEnd=r+1,b?.(e.currentTarget.value);return}if(k&&(e.ctrlKey||e.metaKey)&&k[e.key]){e.preventDefault();let{selectionStart:t,selectionEnd:r,value:n}=e.currentTarget,u=k[e.key];D(`${n.substring(0,t)}${u}${n.substring(t,r)}${u}${n.substring(r)}`),e.currentTarget.selectionEnd=r+2*u.length,b?.(e.currentTarget.value);return}},placeholder:x,ref:K,spellCheck:!1,value:C})}export{o as TextArea};
1
+ import*as e from"react/jsx-runtime";import*as t from"../common/timer.js";import*as r from"react";import*as n from"../common/keys.js";import*as u from"../common/react.js";import*as a from"../common/ui.js";let o=(0,t.debounce)(e=>e(),250);function s(t){let{autoFocus:s,autoSelect:c,className:l,disabled:m,dontUseTabForIndent:i,expensive:f,fluid:p,maxLength:g,monospace:T,onBlur:b,onChange:v,onEnter:y,onEscape:x,onKeyDown:E,placeholder:d,ref:k,selfClear:$,userMarkup:h,value:j,...K}=t,C=(0,r.useRef)(null),D=k??C,[I,B]=(0,r.useState)(j??"");(0,r.useEffect)(()=>{(s||c)&&setTimeout(()=>{D.current?.focus(),c&&D.current?.select()},1)},[]),(0,r.useEffect)(()=>{D.current&&document.activeElement!==D.current&&j!==I&&B(j??"")},[j]);let A=(0,a.computeBoxProps)(K),N=(0,u.classes)(["Input","TextArea",p&&"Input--fluid",T&&"Input--monospace",m&&"Input--disabled",(0,a.computeBoxClassName)(K),l]);return(0,e.jsx)("textarea",{...A,autoComplete:"off",className:N,maxLength:g,onBlur:function(e){b?.(I)},onChange:function(e){let t=e.currentTarget.value;B(t),v&&(f?o(()=>v(t)):v(t))},onKeyDown:function(e){if(E?.(e),e.key===n.KEY.Enter&&!e.shiftKey){e.preventDefault(),y?.(e.currentTarget.value),$&&B(""),e.currentTarget.blur();return}if((0,n.isEscape)(e.key)){x?.(e.currentTarget.value),e.currentTarget.blur();return}if(!i&&e.key===n.KEY.Tab){e.preventDefault();let{value:t,selectionStart:r,selectionEnd:n}=e.currentTarget;B(`${t.substring(0,r)} ${t.substring(n)}`),e.currentTarget.selectionEnd=r+1,v?.(e.currentTarget.value);return}if(h&&(e.ctrlKey||e.metaKey)&&h[e.key]){e.preventDefault();let{selectionStart:t,selectionEnd:r,value:n}=e.currentTarget,u=h[e.key];B(`${n.substring(0,t)}${u}${n.substring(t,r)}${u}${n.substring(r)}`),e.currentTarget.selectionEnd=r+2*u.length,v?.(e.currentTarget.value);return}},placeholder:d,ref:D,spellCheck:!1,value:I})}export{s as TextArea};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tgui-core",
3
- "version": "3.1.3",
3
+ "version": "3.1.5",
4
4
  "description": "TGUI core component library",
5
5
  "keywords": ["TGUI", "library", "typescript"],
6
6
  "files": ["dist", "styles"],
@@ -34,9 +34,10 @@ $label: var(--color-label) !default;
34
34
 
35
35
  // Mappings of color names
36
36
  $color-map: ();
37
+
38
+ // prettier-ignore
37
39
  $_gen_map: (
38
- "black": var(--color-black),
39
- "white": var(--color-white),
40
+ /* Base colors */
40
41
  "red": var(--color-red),
41
42
  "orange": var(--color-orange),
42
43
  "yellow": var(--color-yellow),
@@ -48,10 +49,20 @@ $_gen_map: (
48
49
  "purple": var(--color-purple),
49
50
  "pink": var(--color-pink),
50
51
  "brown": var(--color-brown),
52
+
53
+ /* Additional colors */
54
+ "gold": var(--color-gold),
55
+
56
+ /* Grayscale colors */
57
+ "black": var(--color-black),
58
+ "white": var(--color-white),
51
59
  "grey": var(--color-grey),
52
60
  "gray": var(--color-grey),
53
61
  "light-grey": var(--color-light-grey),
54
62
  "light-gray": var(--color-light-grey),
63
+
64
+ /* Semantic colors */
65
+ "primary": var(--color-primary),
55
66
  "good": var(--color-good),
56
67
  "average": var(--color-average),
57
68
  "bad": var(--color-bad),
@@ -148,14 +148,19 @@ $border-radius: 0 !default;
148
148
  &:not(.Button--disabled) {
149
149
  &:hover {
150
150
  background-color: var(--color-hover);
151
- color: var(--color-text);
151
+ color: hsl(from var(--button-color-transparent) h s l / 1);
152
152
  }
153
153
 
154
154
  &:active {
155
155
  background-color: var(--color-active);
156
- color: var(--color-text);
156
+ color: hsl(from var(--button-color-transparent) h s l / 1);
157
157
  }
158
158
  }
159
+
160
+ &.Button--disabled {
161
+ --button-color-transparent: var(--color-text-translucent-light);
162
+ background-color: hsl(from var(--color-bad) h s l / 0.33) !important;
163
+ }
159
164
  }
160
165
 
161
166
  .Button--color--default {
@@ -53,6 +53,12 @@ $bg-map: colors.$color-map !default;
53
53
 
54
54
  @each $color-name, $color-value in $bg-map {
55
55
  .ImageButton__color--#{$color-name} {
56
+ @each $color in colors.$low-contrast-color-map {
57
+ @if $color-name == $color {
58
+ --color-text-fixed-white: var(--color-black);
59
+ }
60
+ }
61
+
56
62
  @include button-style($color-value);
57
63
  }
58
64
  }
@@ -1,4 +1,5 @@
1
1
  .Input {
2
+ font-size: 1rem;
2
3
  background-color: var(--input-background);
3
4
  border-radius: var(--input-border-radius);
4
5
  border: var(--border-thickness-tiny) solid var(--input-border-color);
@@ -56,6 +56,9 @@
56
56
  --color-pink: hsl(325, 70%, 50%);
57
57
  --color-brown: hsl(25, 47.5%, 45%);
58
58
 
59
+ /* Additional colors */
60
+ --color-gold: hsl(40, 90%, 50%);
61
+
59
62
  /* Grayscale colors */
60
63
  --color-black: hsl(0, 0%, 0%);
61
64
  --color-white: hsl(0, 0%, 100%);