@@ -218,63 +218,6 @@ const useScrub = ({
218218export const isNumericString = ( input : string ) =>
219219 String ( input ) . trim ( ) . length !== 0 && Number . isNaN ( Number ( input ) ) === false ;
220220
221- const useHandleKeyDown =
222- ( {
223- ignoreEnter,
224- ignoreUpDownNumeric,
225- value,
226- onChange,
227- onKeyDown,
228- } : {
229- ignoreEnter : boolean ;
230- ignoreUpDownNumeric : boolean ;
231- value : CssValueInputValue ;
232- onChange : ( event : {
233- value : CssValueInputValue ;
234- altKey : boolean ;
235- shiftKey : boolean ;
236- } ) => void ;
237- onKeyDown : KeyboardEventHandler < HTMLInputElement > ;
238- } ) =>
239- ( event : KeyboardEvent < HTMLInputElement > ) => {
240- if ( event . defaultPrevented ) {
241- // Underlying select like `unitSelect` can already prevent an event like up/down buttons
242- return ;
243- }
244- const meta = { altKey : event . altKey , shiftKey : event . shiftKey } ;
245-
246- // Do not prevent downshift behaviour on item select
247- if ( ignoreEnter === false ) {
248- if ( event . key === "Enter" ) {
249- onChange ( { value, ...meta } ) ;
250- }
251- }
252-
253- if (
254- ignoreUpDownNumeric === false &&
255- ( value . type === "unit" ||
256- ( value . type === "intermediate" && isNumericString ( value . value ) ) ) &&
257- value . unit !== undefined &&
258- ( event . key === "ArrowUp" || event . key === "ArrowDown" )
259- ) {
260- const inputValue =
261- value . type === "unit" ? value . value : Number ( value . value . trim ( ) ) ;
262-
263- onChange ( {
264- value : {
265- type : "unit" ,
266- value : handleNumericInputArrowKeys ( inputValue , event ) ,
267- unit : value . unit ,
268- } ,
269- ...meta ,
270- } ) ;
271- // Prevent Downshift from opening menu on arrow up/down
272- return ;
273- }
274-
275- onKeyDown ( event ) ;
276- } ;
277-
278221export type IntermediateStyleValue = {
279222 type : "intermediate" ;
280223 value : string ;
@@ -289,7 +232,13 @@ type Modifiers = {
289232} ;
290233
291234type ChangeCompleteEvent = {
292- type : "enter" | "blur" | "scrub-end" | "unit-select" | "keyword-select" ;
235+ type :
236+ | "enter"
237+ | "blur"
238+ | "scrub-end"
239+ | "unit-select"
240+ | "keyword-select"
241+ | "delta" ;
293242 value : StyleValue ;
294243} & Modifiers ;
295244
@@ -355,6 +304,7 @@ const Description = styled(Box, { width: theme.spacing[27] });
355304 * - shift key modifier increases/decreases value by 10
356305 * - option/alt key modifier increases/decreases value by 0.1
357306 * - no modifier increases/decreases value by 1
307+ * - does not open the combobox when the input is a number (CSS root variables can include numbers in their names)
358308 * - Scrub interaction
359309 * - Click outside, unit selection or escape when list is open should unfocus the unit select trigger
360310 *
@@ -612,18 +562,6 @@ export const CssValueInput = ({
612562 onChangeComplete ( { value, type : "blur" } ) ;
613563 } ;
614564
615- const handleKeyDown = useHandleKeyDown ( {
616- // In case of the menu is really open and the selection is inside it
617- // we do not prevent the default downshift Enter key behavior
618- ignoreEnter :
619- isUnitsOpen || ( isOpen && ! menuProps . empty && highlightedIndex !== - 1 ) ,
620- // Do not change the number value on the arrow up/down if any menu is opened
621- ignoreUpDownNumeric : isUnitsOpen || isOpen ,
622- onChange : ( event ) => onChangeComplete ( { ...event , type : "enter" } ) ,
623- value,
624- onKeyDown : inputProps . onKeyDown ,
625- } ) ;
626-
627565 const finalPrefix =
628566 prefix ||
629567 ( icon && (
@@ -692,9 +630,67 @@ export const CssValueInput = ({
692630 . filter ( Boolean )
693631 . map ( ( descr ) => < Description > { descr } </ Description > ) ;
694632
633+ const handleUpDownNumeric = ( event : KeyboardEvent < HTMLInputElement > ) => {
634+ const isComboOpen = isOpen && ! menuProps . empty ;
635+
636+ if ( isUnitsOpen || isComboOpen ) {
637+ return ;
638+ }
639+
640+ if (
641+ ( value . type === "unit" ||
642+ ( value . type === "intermediate" && isNumericString ( value . value ) ) ) &&
643+ value . unit !== undefined &&
644+ ( event . key === "ArrowUp" || event . key === "ArrowDown" )
645+ ) {
646+ const inputValue =
647+ value . type === "unit" ? value . value : Number ( value . value . trim ( ) ) ;
648+
649+ const meta = { altKey : event . altKey , shiftKey : event . shiftKey } ;
650+ const hasMeta = meta . altKey || meta . shiftKey ;
651+
652+ if ( hasMeta ) {
653+ // @todo switch to using props.onChange instead of props.onChangeComplete
654+ // this will require modifying input-popover.tsx
655+ const newValue = {
656+ type : "unit" as const ,
657+ value : handleNumericInputArrowKeys ( inputValue , event ) ,
658+ unit : value . unit ,
659+ } ;
660+
661+ onChangeComplete ( { value : newValue , ...meta , type : "delta" } ) ;
662+ } else {
663+ props . onChange ( {
664+ type : "unit" ,
665+ value : handleNumericInputArrowKeys ( inputValue , event ) ,
666+ unit : value . unit ,
667+ } ) ;
668+ }
669+ event . preventDefault ( ) ;
670+ }
671+ } ;
672+
673+ const handleMetaEnter = ( event : KeyboardEvent < HTMLInputElement > ) => {
674+ if (
675+ isUnitsOpen ||
676+ ( isOpen && ! menuProps . empty && highlightedIndex !== - 1 )
677+ ) {
678+ return ;
679+ }
680+
681+ const meta = { altKey : event . altKey , shiftKey : event . shiftKey } ;
682+
683+ if ( event . key === "Enter" ) {
684+ onChangeComplete ( { type : "enter" , value, ...meta } ) ;
685+ }
686+ } ;
687+
695688 const inputPropsHandleKeyDown = composeEventHandlers (
696- inputProps . onKeyDown ,
697- handleKeyDown
689+ composeEventHandlers ( handleUpDownNumeric , inputProps . onKeyDown , {
690+ // Pass prevented events to the combobox (e.g., the Escape key doesn't work otherwise, as it's blocked by Radix)
691+ checkForDefaultPrevented : false ,
692+ } ) ,
693+ handleMetaEnter
698694 ) ;
699695
700696 return (
0 commit comments