11import { mdiMinus , mdiMinusBox , mdiPlus , mdiPlusBox } from "@mdi/js"
2- import { type JSX } from "solid-js"
2+ import { type ComponentProps , type JSX , splitProps } from "solid-js"
3+ import { Input } from "~ui/input/input/Input"
34import type { NumberInputText } from "~ui/input/number/NumberInputTexts"
45import { numberInputTextDefault } from "~ui/input/number/NumberInputTexts"
5- import { Input } from "~ui/input/input/Input"
66import { buttonVariant , type ButtonVariant } from "~ui/interactive/button/buttonCva"
77import { ButtonIconOnly } from "~ui/interactive/button/ButtonIconOnly"
88import { classMerge } from "~ui/utils/classMerge"
99import type { SignalObject } from "~ui/utils/createSignalObject"
1010import { safeParseInt } from "~utils/int/safeParseInt"
1111
12- export type NumberInputSProps = {
12+ export interface NumberInputSProps extends ComponentProps < "input" > {
1313 valueSignal : SignalObject < number >
1414 min ?: number
1515 max ?: number
@@ -22,101 +22,116 @@ export type NumberInputSProps = {
2222 buttonClass ?: string
2323 onChanged ?: ( v : number ) => void
2424 id ?: string
25- translate ?: ( en : string , x1 ?: string | number ) => string
2625 texts ?: NumberInputText
2726}
2827
2928export function NumberInputS ( p : NumberInputSProps ) {
30- const hasMajor = p . incrDecrAmountMajor !== undefined
29+ const [ s , rest ] = splitProps ( p , [
30+ "valueSignal" ,
31+ "min" ,
32+ "max" ,
33+ "incrDecrAmount" ,
34+ "incrDecrAmountMajor" ,
35+ "disabled" ,
36+ "class" ,
37+ "inputClass" ,
38+ "variant" ,
39+ "buttonClass" ,
40+ "onChanged" ,
41+ "id" ,
42+ "texts" ,
43+ ] )
44+ const hasMajor = s . incrDecrAmountMajor !== undefined
3145 const onChange : JSX . InputEventHandlerUnion < HTMLInputElement , InputEvent > | undefined = ( e ) => {
32- const n = p . valueSignal . get ( )
46+ const n = s . valueSignal . get ( )
3347 let newN = safeParseInt ( e . target . value , n )
34- if ( p . min !== undefined ) newN = Math . max ( p . min , newN )
35- if ( p . max !== undefined ) newN = Math . min ( p . max , newN )
36- p . valueSignal . set ( newN )
37- if ( p . onChanged ) p . onChanged ( newN )
48+ if ( s . min !== undefined ) newN = Math . max ( s . min , newN )
49+ if ( s . max !== undefined ) newN = Math . min ( s . max , newN )
50+ s . valueSignal . set ( newN )
51+ if ( s . onChanged ) s . onChanged ( newN )
3852 }
3953 const decrementMajor : JSX . EventHandlerUnion < HTMLButtonElement , MouseEvent > | undefined = ( e ) => {
40- const n = p . valueSignal . get ( )
41- let newN = n - ( p . incrDecrAmountMajor ?? 10 ) * ( e . ctrlKey ? 100 : 1 )
42- if ( p . min !== undefined ) newN = Math . max ( p . min , newN )
43- p . valueSignal . set ( newN )
44- if ( p . onChanged ) p . onChanged ( newN )
54+ const n = s . valueSignal . get ( )
55+ let newN = n - ( s . incrDecrAmountMajor ?? 10 ) * ( e . ctrlKey ? 100 : 1 )
56+ if ( s . min !== undefined ) newN = Math . max ( s . min , newN )
57+ s . valueSignal . set ( newN )
58+ if ( s . onChanged ) s . onChanged ( newN )
4559 }
4660 const decrement : JSX . EventHandlerUnion < HTMLButtonElement , MouseEvent > | undefined = ( e ) => {
47- const n = p . valueSignal . get ( )
48- let newN = n - ( p . incrDecrAmount ?? 1 ) * ( e . ctrlKey ? 100 : 1 )
49- if ( p . min !== undefined ) newN = Math . max ( p . min , newN )
50- p . valueSignal . set ( newN )
51- if ( p . onChanged ) p . onChanged ( newN )
61+ const n = s . valueSignal . get ( )
62+ let newN = n - ( s . incrDecrAmount ?? 1 ) * ( e . ctrlKey ? 100 : 1 )
63+ if ( s . min !== undefined ) newN = Math . max ( s . min , newN )
64+ s . valueSignal . set ( newN )
65+ if ( s . onChanged ) s . onChanged ( newN )
5266 }
5367 const increment : JSX . EventHandlerUnion < HTMLButtonElement , MouseEvent > | undefined = ( e ) => {
54- const n = p . valueSignal . get ( )
55- let newN = n + ( p . incrDecrAmount ?? 1 ) * ( e . ctrlKey ? 100 : 1 )
56- if ( p . max !== undefined ) newN = Math . min ( p . max , newN )
57- p . valueSignal . set ( newN )
58- if ( p . onChanged ) p . onChanged ( newN )
68+ const n = s . valueSignal . get ( )
69+ let newN = n + ( s . incrDecrAmount ?? 1 ) * ( e . ctrlKey ? 100 : 1 )
70+ if ( s . max !== undefined ) newN = Math . min ( s . max , newN )
71+ s . valueSignal . set ( newN )
72+ if ( s . onChanged ) s . onChanged ( newN )
5973 }
6074 const incrementMajor : JSX . EventHandlerUnion < HTMLButtonElement , MouseEvent > | undefined = ( e ) => {
61- const n = p . valueSignal . get ( )
62- let newN = n + ( p . incrDecrAmountMajor ?? 10 ) * ( e . ctrlKey ? 100 : 1 )
63- if ( p . max !== undefined ) newN = Math . min ( p . max , newN )
64- p . valueSignal . set ( newN )
65- if ( p . onChanged ) p . onChanged ( newN )
75+ const n = s . valueSignal . get ( )
76+ let newN = n + ( s . incrDecrAmountMajor ?? 10 ) * ( e . ctrlKey ? 100 : 1 )
77+ if ( s . max !== undefined ) newN = Math . min ( s . max , newN )
78+ s . valueSignal . set ( newN )
79+ if ( s . onChanged ) s . onChanged ( newN )
6680 }
6781 const defaultVariant = buttonVariant . ghost
6882
69- const texts = p . texts ?? numberInputTextDefault
83+ const texts = s . texts ?? numberInputTextDefault
7084
7185 return (
72- < div class = { classMerge ( "flex flex-row flex-nowrap items-center" , p . class ) } >
73- { p . incrDecrAmountMajor && (
86+ < div class = { classMerge ( "flex flex-row flex-nowrap items-center" , s . class ) } >
87+ { s . incrDecrAmountMajor && (
7488 < ButtonIconOnly
7589 icon = { mdiMinusBox }
76- title = { texts . decreaseByX ( p . incrDecrAmountMajor ) }
90+ title = { texts . decreaseByX ( s . incrDecrAmountMajor ) }
7791 onClick = { decrementMajor }
78- variant = { p . variant ?? defaultVariant }
79- class = { classMerge ( "rounded-r-none" , p . buttonClass ) }
80- disabled = { p . disabled || ( p . min !== undefined && p . valueSignal . get ( ) <= p . min ) }
92+ variant = { s . variant ?? defaultVariant }
93+ class = { classMerge ( "rounded-r-none" , s . buttonClass ) }
94+ disabled = { s . disabled || ( s . min !== undefined && s . valueSignal . get ( ) <= s . min ) }
8195 type = { "button" }
8296 />
8397 ) }
8498 < ButtonIconOnly
8599 icon = { mdiMinus }
86- title = { texts . decreaseByX ( p . incrDecrAmount ?? 1 ) }
100+ title = { texts . decreaseByX ( s . incrDecrAmount ?? 1 ) }
87101 onClick = { decrement }
88- variant = { p . variant ?? defaultVariant }
89- class = { classMerge ( hasMajor ? "rounded-none" : "rounded-r-none" , p . buttonClass ) }
90- disabled = { p . disabled || ( p . min !== undefined && p . valueSignal . get ( ) <= p . min ) }
102+ variant = { s . variant ?? defaultVariant }
103+ class = { classMerge ( hasMajor ? "rounded-none" : "rounded-r-none" , s . buttonClass ) }
104+ disabled = { s . disabled || ( s . min !== undefined && s . valueSignal . get ( ) <= s . min ) }
91105 type = { "button" }
92106 />
93107 < Input
94108 type = "number"
95- value = { p . valueSignal . get ( ) }
109+ value = { s . valueSignal . get ( ) }
96110 onInput = { onChange }
97- id = { p . id }
98- class = { classMerge ( "w-14 rounded-none text-center outline-0 focus:z-10" , p . inputClass ) }
99- disabled = { p . disabled }
100- min = { p . min }
101- max = { p . max }
111+ id = { s . id }
112+ class = { classMerge ( "w-14 rounded-none text-center outline-0 focus:z-10" , s . inputClass ) }
113+ disabled = { s . disabled }
114+ min = { s . min }
115+ max = { s . max }
116+ { ...rest }
102117 />
103118 < ButtonIconOnly
104119 icon = { mdiPlus }
105- title = { texts . increaseByX ( p . incrDecrAmount ?? 1 ) }
120+ title = { texts . increaseByX ( s . incrDecrAmount ?? 1 ) }
106121 onClick = { increment }
107- variant = { p . variant ?? defaultVariant }
108- class = { classMerge ( hasMajor ? "rounded-none" : "rounded-l-none" , p . buttonClass ) }
109- disabled = { p . disabled || ( p . max !== undefined && p . valueSignal . get ( ) >= p . max ) }
122+ variant = { s . variant ?? defaultVariant }
123+ class = { classMerge ( hasMajor ? "rounded-none" : "rounded-l-none" , s . buttonClass ) }
124+ disabled = { s . disabled || ( s . max !== undefined && s . valueSignal . get ( ) >= s . max ) }
110125 type = { "button" }
111126 />
112- { p . incrDecrAmountMajor && (
127+ { s . incrDecrAmountMajor && (
113128 < ButtonIconOnly
114129 icon = { mdiPlusBox }
115- title = { texts . increaseByX ( p . incrDecrAmountMajor ) }
130+ title = { texts . increaseByX ( s . incrDecrAmountMajor ) }
116131 onClick = { incrementMajor }
117- variant = { p . variant ?? defaultVariant }
118- class = { classMerge ( "rounded-l-none" , p . buttonClass ) }
119- disabled = { p . disabled || ( p . max !== undefined && p . valueSignal . get ( ) >= p . max ) }
132+ variant = { s . variant ?? defaultVariant }
133+ class = { classMerge ( "rounded-l-none" , s . buttonClass ) }
134+ disabled = { s . disabled || ( s . max !== undefined && s . valueSignal . get ( ) >= s . max ) }
120135 type = { "button" }
121136 />
122137 ) }
0 commit comments