tgui-core 4.3.4 → 5.1.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.
- package/dist/common/ui.d.ts +1 -1
- package/dist/common/ui.js +1 -1
- package/dist/components/Box.d.ts +8 -2
- package/dist/components/DraggableControl.d.ts +3 -3
- package/dist/components/DraggableControl.js +1 -1
- package/dist/components/Input.d.ts +2 -0
- package/dist/components/Input.js +1 -1
- package/dist/components/Knob.d.ts +2 -2
- package/dist/components/Knob.js +1 -1
- package/dist/components/NumberInput.d.ts +2 -2
- package/dist/components/NumberInput.js +1 -1
- package/dist/components/ProgressBar.d.ts +3 -1
- package/dist/components/ProgressBar.js +1 -1
- package/dist/components/Slider.d.ts +2 -2
- package/dist/components/Slider.js +1 -1
- package/dist/components/TextArea.js +1 -1
- package/package.json +11 -11
- package/styles/atomic/candystripe.scss +3 -2
- package/styles/colors.scss +1 -1
- package/styles/components/Button.scss +0 -1
- package/styles/components/Section.scss +4 -4
package/dist/common/ui.d.ts
CHANGED
|
@@ -118,6 +118,6 @@ type StyleMap = StringStyleMap & BooleanStyleMap;
|
|
|
118
118
|
/** Super light implementation of tailwind-like class names. */
|
|
119
119
|
export declare function computeTwClass(input: string | undefined): StyleMap;
|
|
120
120
|
/** Short list of accepted DOM event handlers */
|
|
121
|
-
export declare const eventHandlers:
|
|
121
|
+
export declare const eventHandlers: ["onClick", "onContextMenu", "onDoubleClick", "onKeyDown", "onKeyUp", "onMouseDown", "onMouseLeave", "onMouseMove", "onMouseOver", "onMouseUp", "onScroll", "onDrag", "onDragEnd", "onDragEnter", "onDragExit", "onDragLeave", "onDragOver", "onDragStart", "onDrop"];
|
|
122
122
|
export type EventHandlers<TElement = HTMLDivElement> = Pick<DOMAttributes<TElement>, (typeof eventHandlers)[number]>;
|
|
123
123
|
export {};
|
package/dist/common/ui.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CSS_COLORS as t}from"./constants.js";import{classes as o}from"./react.js";let e=t=>"string"==typeof t?t.endsWith("px")?`${Number.parseFloat(t)/12}rem`:t:"number"==typeof t?`${t}rem`:void 0,
|
|
1
|
+
import{CSS_COLORS as t}from"./constants.js";import{classes as o}from"./react.js";let e=t=>"string"==typeof t?t.endsWith("px")?`${Number.parseFloat(t)/12}rem`:t:"number"==typeof t?`${t}rem`:void 0,n=t=>"string"==typeof t?e(t):"number"==typeof t?e(.5*t):void 0;function i(o){return"string"==typeof o&&t.includes(o)}let r=t=>(o,e)=>{("number"==typeof e||"string"==typeof e)&&(o[t]=e)},l=(t,o)=>(e,n)=>{("number"==typeof n||"string"==typeof n)&&(e[t]=o(n))},p=(t,o)=>(e,n)=>{n&&(e[t]=o)},a=(t,o,e)=>(n,i)=>{if("number"==typeof i||"string"==typeof i)for(let r=0;r<e.length;r++)n[t+e[r]]=o(i)},g=t=>(o,e)=>{i(e)||(o[t]=e)},f={align:r("textAlign"),backgroundColor:g("backgroundColor"),bottom:l("bottom",e),color:g("color"),fontFamily:r("fontFamily"),fontSize:l("fontSize",e),fontWeight:r("fontWeight"),g:l("gap",n),gc:l("columnGap",n),gr:l("rowGap",n),height:l("height",e),left:l("left",e),lineHeight:(t,o)=>{"number"==typeof o?t.lineHeight=o:"string"==typeof o&&(t.lineHeight=e(o))},m:a("margin",n,["Top","Bottom","Left","Right"]),maxHeight:l("maxHeight",e),maxWidth:l("maxWidth",e),mb:l("marginBottom",n),minHeight:l("minHeight",e),minWidth:l("minWidth",e),ml:l("marginLeft",n),mr:l("marginRight",n),mt:l("marginTop",n),mx:a("margin",n,["Left","Right"]),my:a("margin",n,["Top","Bottom"]),opacity:r("opacity"),overflow:r("overflow"),overflowX:r("overflowX"),overflowY:r("overflowY"),p:a("padding",n,["Top","Bottom","Left","Right"]),pb:l("paddingBottom",n),pl:l("paddingLeft",n),position:r("position"),pr:l("paddingRight",n),pt:l("paddingTop",n),px:a("padding",n,["Left","Right"]),py:a("padding",n,["Top","Bottom"]),right:l("right",e),textAlign:r("textAlign"),textColor:g("color"),top:l("top",e),verticalAlign:r("verticalAlign"),width:l("width",e)},m={bold:p("fontWeight","bold"),fillPositionedParent:(t,o)=>{o&&(t.position="absolute",t.top=0,t.bottom=0,t.left=0,t.right=0)},inline:p("display","inline-block"),italic:p("fontStyle","italic"),nowrap:p("whiteSpace","nowrap"),preserveWhitespace:p("whiteSpace","pre-wrap")};function s(t){let o={},e={};for(let n in t){if("style"===n)continue;let i=t[n],r=f[n]||m[n];r?r(e,i):o[n]=i}return o.style={...e,...t.style},o}function u(t){let e=t.textColor||t.color,{backgroundColor:n}=t;return o([i(e)&&`color-${e}`,i(n)&&`color-bg-${n}`])}function c(t){let o={};if(!t)return o;for(let e of t.split(" ")){let[t,n]=e.split("-");if(t)if(t in f){if(""===n)continue;let e=Number(n);!Number.isNaN(e)&&Number.isFinite(e)?o[t]=e:o[t]=n}else t in m?o[t]=!0:console.warn(`Unknown prop ${t}`)}return o}let h=["onClick","onContextMenu","onDoubleClick","onKeyDown","onKeyUp","onMouseDown","onMouseLeave","onMouseMove","onMouseOver","onMouseUp","onScroll","onDrag","onDragEnd","onDragEnter","onDragExit","onDragLeave","onDragOver","onDragStart","onDrop"];export{m as booleanStyleMap,u as computeBoxClassName,s as computeBoxProps,c as computeTwClass,h as eventHandlers,n as halfUnit,f as stringStyleMap,e as unit};
|
package/dist/components/Box.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BooleanLike } from '../common/react.ts';
|
|
2
2
|
import { type BooleanStyleMap, type EventHandlers, type StringStyleMap } from '../common/ui.ts';
|
|
3
|
-
import { type CSSProperties, type ReactNode } from 'react';
|
|
3
|
+
import { type CSSProperties, type HTMLAttributes, type ReactNode } from 'react';
|
|
4
4
|
export type BoxInternalProps = Partial<{
|
|
5
5
|
/**
|
|
6
6
|
* The component used for the root node.
|
|
@@ -38,7 +38,13 @@ export type BoxInternalProps = Partial<{
|
|
|
38
38
|
*/
|
|
39
39
|
tw: string;
|
|
40
40
|
}>;
|
|
41
|
-
|
|
41
|
+
type LiftedHTMLAttributes<TElement> = {
|
|
42
|
+
/** Whether this element is draggable.
|
|
43
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/draggable
|
|
44
|
+
*/
|
|
45
|
+
draggable?: HTMLAttributes<TElement>['draggable'];
|
|
46
|
+
};
|
|
47
|
+
export interface BoxProps<TElement = HTMLDivElement> extends BoxInternalProps, BooleanStyleMap, StringStyleMap, LiftedHTMLAttributes<TElement>, EventHandlers<TElement> {
|
|
42
48
|
}
|
|
43
49
|
type DangerDoNotUse = {
|
|
44
50
|
dangerouslySetInnerHTML?: {
|
|
@@ -23,6 +23,8 @@ type Props = {
|
|
|
23
23
|
animated: boolean;
|
|
24
24
|
/** The matrix to use for the drag. */
|
|
25
25
|
dragMatrix: [number, number];
|
|
26
|
+
/** onChange also fires when you drag the input. */
|
|
27
|
+
tickWhileDragging: boolean;
|
|
26
28
|
/** Format the value using this function before displaying it. */
|
|
27
29
|
format: (value: number) => string;
|
|
28
30
|
/** The maximum value. */
|
|
@@ -34,12 +36,10 @@ type Props = {
|
|
|
34
36
|
* number. This is the default value event for controls.
|
|
35
37
|
*/
|
|
36
38
|
onChange: (event: Event, value: number) => void;
|
|
37
|
-
/** An event which fires when you drag the input. */
|
|
38
|
-
onDrag: (event: MouseEvent, value: number) => void;
|
|
39
39
|
/** The step size. */
|
|
40
40
|
step: number;
|
|
41
41
|
/** The step size in pixels. */
|
|
42
|
-
stepPixelSize: number;
|
|
42
|
+
stepPixelSize: number | ((defaultStepPixelSize: number) => number);
|
|
43
43
|
/** Whether to unclamp the value. */
|
|
44
44
|
unclamped: boolean;
|
|
45
45
|
/** The unit of the value. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Fragment as e,jsx as r,jsxs as t}from"react/jsx-runtime";import{KEY as n,isEscape as u}from"../common/keys.js";import{clamp as
|
|
1
|
+
import{Fragment as e,jsx as r,jsxs as t}from"react/jsx-runtime";import{KEY as n,isEscape as u}from"../common/keys.js";import{clamp as o}from"../common/math.js";import{useEffect as l,useRef as c,useState as i}from"react";import{AnimatedNumber as a}from"./AnimatedNumber.js";function s(e,r){return e.screenX*r[0]+e.screenY*r[1]}function m(m){let{animated:v,children:f,dragMatrix:p=[1,0],tickWhileDragging:d,format:h,maxValue:y=1/0,minValue:g=-1/0,onChange:E,step:b=1,stepPixelSize:N,unclamped:w,unit:T,updateRate:j=400,fontSize:x,height:L,lineHeight:S}=m,[k,z]=i(m.value),[D,I]=i(!1),F=c(!1),M=c(m.value),O=c(0),$=c(0),_=c(null),A=c(null),B=c(null),C=c(null);function H(e){let r=$.current;if(null===r)throw Error("Origin is unset.");let t=s(e,p),n=_.current;if(null===n)throw Error("Final step pixel size has not been computed.");let u=O.current;if(null===u)throw Error("Original value is unset.");let l=o(Math.floor(u/b)*b+Math.trunc((t-r)/n)*b,g,y);M.current=l,z(l)}function K(e){document.body.style["pointer-events"]="auto",B.current&&clearInterval(B.current),$.current=null,_.current=null,O.current=null,document.removeEventListener("mousemove",H),document.removeEventListener("mouseup",K),F.current&&(E?.(e,M.current),F.current=!1)}l(()=>{m.value!==M.current&&(M.current=m.value,z(m.value))},[m.value]);let P=m.value;F.current&&(P=M.current);let U=t(e,{children:[v&&!F.current?r(a,{format:h,value:P}):h?h(P):P,T?` ${T}`:""]}),W=r("input",{className:"NumberInput__input",onBlur:function(e){let r=Number.parseFloat(e.currentTarget.value);if(w||(r=o(r,g,y)),Number.isNaN(r))return void I(!1);M.current=r,z(r),E?.(e.nativeEvent,r),D&&I(!1)},onKeyDown:function(e){(e.key===n.Enter||u(e.key))&&I(!1)},ref:A,style:{display:D?void 0:"none",fontSize:x,height:L,lineHeight:S}});return f({displayElement:U,displayValue:P,dragging:F.current,editing:D,handleDragStart:function(e){if(!D){if("number"!=typeof N){let r=e.currentTarget.offsetWidth/((y-g)/b);if(void 0===N)_.current=r;else if("function"==typeof N)_.current=N(r);else throw Error(`Unsupported value for stepPixelSize of type ${typeof N}`)}else _.current=N;document.body.style["pointer-events"]="none",$.current=s(e.nativeEvent,p),O.current=m.value,F.current=!0,document.addEventListener("mouseup",K),C.current=setTimeout(()=>{var r=e.nativeEvent;if(F.current)document.addEventListener("mousemove",H),B.current=setInterval(()=>{F.current&&d&&E?.(r,m.value)},j);else if(I(!0),A.current){let e=A.current;e.value=M.current.toString(),setTimeout(()=>{e.focus(),e.select()},10)}C.current&&clearTimeout(C.current)},100)}},inputElement:W})}export{m as DraggableControl};
|
|
@@ -22,6 +22,8 @@ export type BaseInputProps<TElement = HTMLInputElement> = Partial<{
|
|
|
22
22
|
fluid: boolean;
|
|
23
23
|
/** Mark this if you want to use a monospace font */
|
|
24
24
|
monospace: boolean;
|
|
25
|
+
/** Allows to toggle on spellcheck on inputs */
|
|
26
|
+
spellcheck: boolean;
|
|
25
27
|
}> & BoxProps<TElement>;
|
|
26
28
|
export type TextInputProps<TElement = HTMLInputElement> = Partial<{
|
|
27
29
|
/** The maximum length of the input value */
|
package/dist/components/Input.js
CHANGED
|
@@ -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,value:
|
|
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};
|
|
@@ -11,6 +11,8 @@ type Props = {
|
|
|
11
11
|
bipolar: boolean;
|
|
12
12
|
/** Color of the outer ring around the knob. */
|
|
13
13
|
color: string | BooleanLike;
|
|
14
|
+
/** onChange also fires every 500ms while dragging the input. */
|
|
15
|
+
tickWhileDragging: boolean;
|
|
14
16
|
/**
|
|
15
17
|
* If set, this value will be used to set the fill percentage of the outer
|
|
16
18
|
* ring independently of the main value.
|
|
@@ -27,8 +29,6 @@ type Props = {
|
|
|
27
29
|
* default value event for controls.
|
|
28
30
|
*/
|
|
29
31
|
onChange: (event: Event, value: number) => void;
|
|
30
|
-
/** An event which fires about every 500ms while dragging the input */
|
|
31
|
-
onDrag: (event: Event, value: number) => void;
|
|
32
32
|
/**
|
|
33
33
|
* Applies a `color` to the outer ring around the knob based on whether the
|
|
34
34
|
* value lands in the range between `from` and `to`.
|
package/dist/components/Knob.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as o,jsxs as r}from"react/jsx-runtime";import{keyOfMatchingRange as e,scale as n}from"../common/math.js";import{classes as t}from"../common/react.js";import{computeBoxClassName as i,computeBoxProps as l}from"../common/ui.js";import{DraggableControl as c}from"./DraggableControl.js";import{Floating as a}from"./Floating.js";function s(s){let{animated:m,
|
|
1
|
+
import{jsx as o,jsxs as r}from"react/jsx-runtime";import{keyOfMatchingRange as e,scale as n}from"../common/math.js";import{classes as t}from"../common/react.js";import{computeBoxClassName as i,computeBoxProps as l}from"../common/ui.js";import{DraggableControl as c}from"./DraggableControl.js";import{Floating as a}from"./Floating.js";function s(s){let{animated:m,tickWhileDragging:_,format:d,maxValue:b,minValue:h,onChange:p,step:K,stepPixelSize:f,unclamped:g,unit:u,value:v,bipolar:x,popupPosition:N,className:j,color:y,fillValue:M,ranges:k={},size:P=1,style:w,...B}=s;return o(c,{dragMatrix:[0,-1],animated:m,tickWhileDragging:_,format:d,maxValue:b,minValue:h,onChange:p,step:K,stepPixelSize:f,unclamped:g,unit:u,value:v,children:c=>{let{displayElement:s,displayValue:m,dragging:_,handleDragStart:d,inputElement:p}=c,K=n(M??m,h,b),f=n(m,h,b),g=y||e(M??v,k)||"default",u=Math.min((f-.5)*270,225);return o(a,{content:s,contentClasses:"Knob__popupValue",handleOpen:_,placement:N||"top",preventPortal:!0,children:r("div",{className:t(["Knob",`Knob--color--${g}`,x&&"Knob--bipolar",j,i(B)]),...l({style:{fontSize:`${P}em`,...w},...B}),onMouseDown:d,children:[o("div",{className:"Knob__circle",children:o("div",{className:"Knob__cursorBox",style:{transform:`rotate(${u}deg)`},children:o("div",{className:"Knob__cursor"})})}),r("svg",{className:"Knob__ring Knob__ringTrackPivot",viewBox:"0 0 100 100",children:[o("circle",{className:"Knob__ringTrack",cx:"50",cy:"50",r:"50"}),o("title",{children:"track"})]}),r("svg",{className:"Knob__ring Knob__ringFillPivot",viewBox:"0 0 100 100",children:[o("title",{children:"fill"}),o("circle",{className:"Knob__ringFill",cx:"50",cy:"50",r:"50",style:{strokeDashoffset:Math.max(((x?2.75:2)-1.5*K)*Math.PI*50,0)}})]}),p]})})}})}export{s as Knob};
|
|
@@ -15,14 +15,14 @@ type Props = Required<{
|
|
|
15
15
|
animated: boolean;
|
|
16
16
|
/** Makes the input field uneditable & non draggable to prevent user changes */
|
|
17
17
|
disabled: boolean;
|
|
18
|
+
/** onChange also fires about every 500ms when you drag the input up and down. */
|
|
19
|
+
tickWhileDragging: boolean;
|
|
18
20
|
/** Format value using this function before displaying it. */
|
|
19
21
|
format: (value: number) => string;
|
|
20
22
|
/** Adjusts the width to 100% of its parent container */
|
|
21
23
|
fluid: boolean;
|
|
22
24
|
/** An event which fires when you release the input or successfully enter a number. */
|
|
23
25
|
onChange: (value: number) => void;
|
|
24
|
-
/** An event which fires about every 500ms when you drag the input up and down, on release and on manual editing. */
|
|
25
|
-
onDrag: (value: number) => void;
|
|
26
26
|
/** Screen distance mouse needs to travel to adjust value by one `step`. */
|
|
27
27
|
stepPixelSize: number;
|
|
28
28
|
/** Unit to display to the right of value. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{KEY as r,isEscape as i}from"../common/keys.js";import{clamp as n,round as s}from"../common/math.js";import{classes as a}from"../common/react.js";import{Component as o,createRef as u}from"react";import{AnimatedNumber as l}from"./AnimatedNumber.js";import{Box as m}from"./Box.js";class h extends o{inputRef=u();dragTimeout;dragInterval;state={currentValue:0,dragging:!1,editing:!1,origin:0,previousValue:0};componentDidMount(){let e=Number.parseFloat(this.props.value.toString());this.setState({currentValue:e,previousValue:e})}handleDragStart=e=>{let{value:t,disabled:r}=this.props,{editing:i}=this.state;if(r||i)return;document.body.style["pointer-events"]="none";let n=Number.parseFloat(t.toString());this.setState({currentValue:n,dragging:!1,origin:e.screenY,previousValue:n}),this.dragTimeout=setTimeout(()=>{this.setState({dragging:!0})},250),this.dragInterval=setInterval(()=>{let{dragging:e,currentValue:t,previousValue:r}=this.state,{
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{KEY as r,isEscape as i}from"../common/keys.js";import{clamp as n,round as s}from"../common/math.js";import{classes as a}from"../common/react.js";import{Component as o,createRef as u}from"react";import{AnimatedNumber as l}from"./AnimatedNumber.js";import{Box as m}from"./Box.js";class h extends o{inputRef=u();dragTimeout;dragInterval;state={currentValue:0,dragging:!1,editing:!1,origin:0,previousValue:0};componentDidMount(){let e=Number.parseFloat(this.props.value.toString());this.setState({currentValue:e,previousValue:e})}handleDragStart=e=>{let{value:t,disabled:r}=this.props,{editing:i}=this.state;if(r||i)return;document.body.style["pointer-events"]="none";let n=Number.parseFloat(t.toString());this.setState({currentValue:n,dragging:!1,origin:e.screenY,previousValue:n}),this.dragTimeout=setTimeout(()=>{this.setState({dragging:!0})},250),this.dragInterval=setInterval(()=>{let{dragging:e,currentValue:t,previousValue:r}=this.state,{onChange:i,tickWhileDragging:n}=this.props;e&&n&&t!==r&&(this.setState({previousValue:t}),i?.(t))},400),document.addEventListener("mousemove",this.handleDragMove),document.addEventListener("mouseup",this.handleDragEnd)};handleDragMove=e=>{let{minValue:t,maxValue:r,step:i,stepPixelSize:a,disabled:o}=this.props;o||this.setState(o=>{let u={...o},l=u.origin-e.screenY;if(o.dragging){let o=a||1,m=n(u.currentValue+l*i/o,t-i,r+i);Math.abs(m-u.currentValue)>=i?(u.currentValue=n(s(m/i,0)*i,t,r),u.origin=e.screenY):Math.abs(l)>o&&(u.origin=e.screenY)}else Math.abs(l)>4&&(u.dragging=!0);return u})};handleDragEnd=e=>{let{dragging:t,currentValue:r}=this.state,{onChange:i,disabled:n}=this.props;if(!n){if(document.body.style["pointer-events"]="auto",clearInterval(this.dragInterval),clearTimeout(this.dragTimeout),this.setState({dragging:!1,editing:!t,previousValue:r}),t)i?.(r);else if(this.inputRef){let e=this.inputRef.current;e&&(e.value=`${r}`,setTimeout(()=>{e.focus(),e.select()},10))}document.removeEventListener("mousemove",this.handleDragMove),document.removeEventListener("mouseup",this.handleDragEnd)}};handleBlur=e=>{let{editing:t,previousValue:r}=this.state,{minValue:i,maxValue:s,onChange:a,disabled:o}=this.props;if(o||!t)return;let u=n(Number.parseFloat(e.target.value),i,s);if(Number.isNaN(u))return void this.setState({editing:!1});this.setState({currentValue:u,editing:!1,previousValue:u}),r!==u&&a?.(u)};handleKeyDown=e=>{let{minValue:t,maxValue:s,onChange:a,disabled:o}=this.props;if(o)return;let{previousValue:u}=this.state;if(e.key===r.Enter){let r=n(Number.parseFloat(e.currentTarget.value),t,s);if(Number.isNaN(r))return void this.setState({editing:!1});this.setState({currentValue:r,editing:!1,previousValue:r}),u!==r&&a?.(r)}else i(e.key)&&this.setState({editing:!1})};render(){let{dragging:r,editing:i,currentValue:s}=this.state,{className:o,fluid:u,animated:h,unit:d,value:p,minValue:g,maxValue:c,height:v,width:f,lineHeight:N,fontSize:b,format:S}=this.props,V=Number.parseFloat(p.toString());r&&(V=s);let y=t("div",{className:"NumberInput__content",children:[h&&!r?e(l,{format:S,value:V}):S?S(V):V,d?` ${d}`:""]});return t(m,{className:a(["NumberInput",u&&"NumberInput--fluid",o]),fontSize:b,lineHeight:N,minHeight:v,minWidth:f,onMouseDown:this.handleDragStart,children:[e("div",{className:"NumberInput__barContainer",children:e("div",{className:"NumberInput__bar",style:{height:`${n((V-g)/(c-g)*100,0,100)}%`}})}),y,e("input",{className:"NumberInput__input",onBlur:this.handleBlur,onKeyDown:this.handleKeyDown,ref:this.inputRef,style:{display:i?"inline":"none",fontSize:b,height:v,lineHeight:N}})]})}}export{h as NumberInput};
|
|
@@ -39,9 +39,11 @@ type Props = {
|
|
|
39
39
|
* ```
|
|
40
40
|
*
|
|
41
41
|
*/
|
|
42
|
-
ranges: Record<string, [number, number]
|
|
42
|
+
ranges: Readonly<Record<string, Readonly<[number, number]>>>;
|
|
43
43
|
/** Removes progress percentage text, makes no sense if children are present */
|
|
44
44
|
empty: boolean;
|
|
45
|
+
/** The number of digits to appear after the percent's decimal point. */
|
|
46
|
+
fractionDigits: number;
|
|
45
47
|
}> & BoxProps & PropsWithChildren;
|
|
46
48
|
/**
|
|
47
49
|
* ## ProgressBar
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as r,jsxs as o}from"react/jsx-runtime";import{CSS_COLORS as s}from"../common/constants.js";import{clamp01 as e,keyOfMatchingRange as
|
|
1
|
+
import{jsx as r,jsxs as o}from"react/jsx-runtime";import{CSS_COLORS as s}from"../common/constants.js";import{clamp01 as e,keyOfMatchingRange as t,scale as m}from"../common/math.js";import{classes as a}from"../common/react.js";import{computeBoxClassName as i,computeBoxProps as l}from"../common/ui.js";function c(c){let{className:n,value:d,minValue:f=0,maxValue:u=1,color:g,ranges:p={},empty:B,children:P,fractionDigits:_=0,...h}=c,j=m(d,f,u),v=void 0!==P,x=g||t(d,p)||"default",y=l(h),N=["ProgressBar",n,i(h)],$={width:`${100*e(j)}%`};return s.includes(x)||"default"===x?N.push(`ProgressBar--color--${x}`):(y.style={...y.style,borderColor:x},$.backgroundColor=x),o("div",{className:a(N),...y,children:[r("div",{className:"ProgressBar__fill ProgressBar__fill--animated",style:$}),r("div",{className:"ProgressBar__content",children:v?P:!B&&`${(100*j).toFixed(_)}%`})]})}export{c as ProgressBar};
|
|
@@ -16,6 +16,8 @@ type Props = {
|
|
|
16
16
|
color: string;
|
|
17
17
|
/** Disables the slider. */
|
|
18
18
|
disabled: boolean;
|
|
19
|
+
/** onChange also fires when you drag the input. */
|
|
20
|
+
tickWhileDragging: boolean;
|
|
19
21
|
/**
|
|
20
22
|
* If set, this value will be used to set the fill percentage of the
|
|
21
23
|
* progress bar filler independently of the main value.
|
|
@@ -28,8 +30,6 @@ type Props = {
|
|
|
28
30
|
* the default value event for controls.
|
|
29
31
|
*/
|
|
30
32
|
onChange: (event: Event, value: number) => void;
|
|
31
|
-
/** An event which fires only while dragging the slider. */
|
|
32
|
-
onDrag: (event: Event, value: number) => void;
|
|
33
33
|
/**
|
|
34
34
|
* Applies a `color` to the slider based on whether the value lands in the
|
|
35
35
|
* range between `from` and `to`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as r,jsxs as e}from"react/jsx-runtime";import{clamp01 as i,keyOfMatchingRange as s,scale as l}from"../common/math.js";import{classes as a}from"../common/react.js";import{computeBoxClassName as o,computeBoxProps as t}from"../common/ui.js";import{DraggableControl as m}from"./DraggableControl.js";function d(d){let{animated:c,
|
|
1
|
+
import{jsx as r,jsxs as e}from"react/jsx-runtime";import{clamp01 as i,keyOfMatchingRange as s,scale as l}from"../common/math.js";import{classes as a}from"../common/react.js";import{computeBoxClassName as o,computeBoxProps as t}from"../common/ui.js";import{DraggableControl as m}from"./DraggableControl.js";function d(d){let{animated:c,tickWhileDragging:n,format:_,maxValue:f,minValue:h,onChange:u,step:g,stepPixelSize:p,unit:v,value:B,className:N,fillValue:P,color:S,ranges:j={},children:w,...x}=d,y=void 0!==w;return r(m,{dragMatrix:[1,0],animated:c,tickWhileDragging:n,format:_,maxValue:f,minValue:h,onChange:u,step:g,stepPixelSize:p,unit:v,value:B,children:m=>{let{displayElement:d,displayValue:c,dragging:n,editing:_,handleDragStart:u,inputElement:g}=m,p=null!=P,v=i(l(P??c,h,f)),M=i(l(c,h,f)),$=S||s(P??B,j)||"default";return e("div",{className:a(["Slider",_&&"Slider--editing","ProgressBar",`ProgressBar--color--${$}`,N,o(x)]),...t(x),onMouseDown:u,children:[r("div",{className:a(["ProgressBar__fill",p&&!n&&"ProgressBar__fill--animated"]),style:{opacity:.4,width:`${100*Math.max(v,M)}%`}}),r("div",{className:a(["ProgressBar__fill",!n&&"ProgressBar__fill--animated"]),style:{width:`${100*Math.min(v,M)}%`}}),r("div",{className:"Slider__cursorOffset",style:{width:`${100*M}%`},children:r("div",{className:"Slider__cursor",children:n&&r("div",{className:"Slider__popupValue",children:d})})}),r("div",{className:"ProgressBar__content",children:y?w:d}),g]})}})}export{d as Slider};
|
|
@@ -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,
|
|
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};
|
package/package.json
CHANGED
|
@@ -6,18 +6,18 @@
|
|
|
6
6
|
},
|
|
7
7
|
"description": "TGUI core component library",
|
|
8
8
|
"devDependencies": {
|
|
9
|
-
"@biomejs/biome": "^2.
|
|
10
|
-
"@rsbuild/core": "^1.4.
|
|
11
|
-
"@rsbuild/plugin-react": "^1.3.
|
|
12
|
-
"@rsbuild/plugin-sass": "^1.3.
|
|
13
|
-
"@rslib/core": "^0.10.
|
|
14
|
-
"@storybook/addon-docs": "^9.0.
|
|
15
|
-
"@types/bun": "
|
|
16
|
-
"@types/react": "
|
|
17
|
-
"@types/react-dom": "
|
|
9
|
+
"@biomejs/biome": "^2.1.1",
|
|
10
|
+
"@rsbuild/core": "^1.4.7",
|
|
11
|
+
"@rsbuild/plugin-react": "^1.3.4",
|
|
12
|
+
"@rsbuild/plugin-sass": "^1.3.3",
|
|
13
|
+
"@rslib/core": "^0.10.6",
|
|
14
|
+
"@storybook/addon-docs": "^9.0.17",
|
|
15
|
+
"@types/bun": "latest",
|
|
16
|
+
"@types/react": "latest",
|
|
17
|
+
"@types/react-dom": "latest",
|
|
18
18
|
"prettier": "^3.6.2",
|
|
19
19
|
"sass": "^1.89.2",
|
|
20
|
-
"storybook": "^9.0.
|
|
20
|
+
"storybook": "^9.0.17",
|
|
21
21
|
"storybook-addon-sass-postcss": "^0.3.2",
|
|
22
22
|
"storybook-react-rsbuild": "^2.0.2",
|
|
23
23
|
"typescript": "^5.8.3"
|
|
@@ -69,5 +69,5 @@
|
|
|
69
69
|
"test": "bun test"
|
|
70
70
|
},
|
|
71
71
|
"type": "module",
|
|
72
|
-
"version": "
|
|
72
|
+
"version": "5.1.0"
|
|
73
73
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* Using :where for 0 specificity - https://developer.mozilla.org/en-US/docs/Web/CSS/:where */
|
|
2
2
|
:where(.candystripe:nth-child(odd)) {
|
|
3
|
-
background-color
|
|
3
|
+
/* background-color is usually overridden. So we use linear "gradient" */
|
|
4
|
+
background: linear-gradient(var(--candystripe-odd));
|
|
4
5
|
}
|
|
5
6
|
|
|
6
7
|
:where(.candystripe:nth-child(even)) {
|
|
7
|
-
background
|
|
8
|
+
background: linear-gradient(var(--candystripe-even));
|
|
8
9
|
}
|
package/styles/colors.scss
CHANGED
|
@@ -68,7 +68,7 @@ $_gen_map: (
|
|
|
68
68
|
"bad": var(--color-bad),
|
|
69
69
|
"label": var(--color-label),
|
|
70
70
|
);
|
|
71
|
-
$low-contrast-color-map: ("yellow", "white");
|
|
71
|
+
$low-contrast-color-map: ("yellow", "white") !default;
|
|
72
72
|
|
|
73
73
|
// Color names for which to generate a color map
|
|
74
74
|
$color-map-keys: map.keys($_gen_map) !default;
|
|
@@ -142,7 +142,6 @@
|
|
|
142
142
|
@each $color-name, $color-value in colors.$color-map {
|
|
143
143
|
.Button--color--#{$color-name} {
|
|
144
144
|
--color: #{$color-value};
|
|
145
|
-
--button-color: var(--color-white);
|
|
146
145
|
|
|
147
146
|
@each $color in colors.$low-contrast-color-map {
|
|
148
147
|
@if $color-name == $color {
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
overflow-y: hidden;
|
|
70
70
|
|
|
71
71
|
& > .Section__rest > .Section__content {
|
|
72
|
-
overflow-y:
|
|
72
|
+
overflow-y: auto;
|
|
73
73
|
overflow-x: hidden;
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
|
|
81
81
|
& > .Section__rest > .Section__content {
|
|
82
82
|
overflow-y: hidden;
|
|
83
|
-
overflow-x:
|
|
83
|
+
overflow-x: auto;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
overflow-y: hidden;
|
|
90
90
|
|
|
91
91
|
& > .Section__rest > .Section__content {
|
|
92
|
-
overflow-y:
|
|
93
|
-
overflow-x:
|
|
92
|
+
overflow-y: auto;
|
|
93
|
+
overflow-x: auto;
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
|