@@ -53,7 +53,7 @@ import {
53
53
FieldLabel ,
54
54
HelpText
55
55
} from './Field' ;
56
- import { FocusableRef , FocusableRefValue , HelpTextProps , PressEvent , SpectrumLabelableProps } from '@react-types/shared' ;
56
+ import { FocusableRef , FocusableRefValue , HelpTextProps , PressEvent , RefObject , SpectrumLabelableProps } from '@react-types/shared' ;
57
57
import { FormContext , useFormProps } from './Form' ;
58
58
import { forwardRefType } from './types' ;
59
59
import { HeaderContext , HeadingContext , Text , TextContext } from './Content' ;
@@ -278,21 +278,6 @@ export const Picker = /*#__PURE__*/ (forwardRef as forwardRefType)(function Pick
278
278
menuOffset = 8 ;
279
279
}
280
280
281
- // For mouse interactions, pickers open on press start. When the popover underlay appears
282
- // it covers the trigger button, causing onPressEnd to fire immediately and no press scaling
283
- // to occur. We override this by listening for pointerup on the document ourselves.
284
- let [ isPressed , setPressed ] = useState ( false ) ;
285
- let { addGlobalListener} = useGlobalListeners ( ) ;
286
- let onPressStart = ( e : PressEvent ) => {
287
- if ( e . pointerType !== 'mouse' ) {
288
- return ;
289
- }
290
- setPressed ( true ) ;
291
- addGlobalListener ( document , 'pointerup' , ( ) => {
292
- setPressed ( false ) ;
293
- } , { once : true , capture : true } ) ;
294
- } ;
295
-
296
281
return (
297
282
< AriaSelect
298
283
{ ...pickerProps }
@@ -317,66 +302,14 @@ export const Picker = /*#__PURE__*/ (forwardRef as forwardRefType)(function Pick
317
302
contextualHelp = { props . contextualHelp } >
318
303
{ label }
319
304
</ FieldLabel >
320
- < PressResponder onPressStart = { onPressStart } isPressed = { isPressed } >
321
- < Button
322
- ref = { domRef }
323
- style = { renderProps => pressScale ( domRef ) ( renderProps ) }
324
- // Prevent press scale from sticking while Picker is open.
325
- // @ts -ignore
326
- isPressed = { false }
327
- className = { renderProps => inputButton ( {
328
- ...renderProps ,
329
- size : size ,
330
- isOpen,
331
- isQuiet
332
- } ) } >
333
- { ( renderProps ) => (
334
- < >
335
- < SelectValue className = { valueStyles ( { isQuiet} ) + ' ' + raw ( '&> * {display: none;}' ) } >
336
- { ( { defaultChildren} ) => {
337
- return (
338
- < Provider
339
- values = { [
340
- [ IconContext , {
341
- slots : {
342
- icon : {
343
- render : centerBaseline ( { slot : 'icon' , styles : iconCenterWrapper } ) ,
344
- styles : icon
345
- }
346
- }
347
- } ] ,
348
- [ TextContext , {
349
- slots : {
350
- description : { } ,
351
- label : { styles : style ( {
352
- display : 'block' ,
353
- flexGrow : 1 ,
354
- truncate : true
355
- } ) }
356
- }
357
- } ] ,
358
- [ InsideSelectValueContext , true ]
359
- ] } >
360
- { defaultChildren }
361
- </ Provider >
362
- ) ;
363
- } }
364
- </ SelectValue >
365
- { isInvalid && (
366
- < FieldErrorIcon isDisabled = { isDisabled } />
367
- ) }
368
- < ChevronIcon
369
- size = { size }
370
- className = { iconStyles } />
371
- { isFocusVisible && isQuiet && < span className = { quietFocusLine } /> }
372
- { isInvalid && ! isDisabled && ! isQuiet &&
373
- // @ts -ignore known limitation detecting functions from the theme
374
- < div className = { invalidBorder ( { ...renderProps , size} ) } />
375
- }
376
- </ >
377
- ) }
378
- </ Button >
379
- </ PressResponder >
305
+ < PickerButton
306
+ isOpen = { isOpen }
307
+ isQuiet = { isQuiet }
308
+ isFocusVisible = { isFocusVisible }
309
+ size = { size }
310
+ isInvalid = { isInvalid }
311
+ isDisabled = { isDisabled }
312
+ buttonRef = { domRef } />
380
313
< HelpText
381
314
size = { size }
382
315
isDisabled = { isDisabled }
@@ -437,6 +370,100 @@ export const Picker = /*#__PURE__*/ (forwardRef as forwardRefType)(function Pick
437
370
) ;
438
371
} ) ;
439
372
373
+ interface PickerButtonInnerProps extends PickerStyleProps , Omit < AriaSelectRenderProps , 'isRequired' | 'isFocused' > {
374
+ buttonRef : RefObject < HTMLButtonElement | null >
375
+ }
376
+
377
+ function PickerButton ( props : PickerButtonInnerProps ) {
378
+ let {
379
+ isOpen,
380
+ isQuiet,
381
+ isFocusVisible,
382
+ size,
383
+ isInvalid,
384
+ isDisabled,
385
+ buttonRef
386
+ } = props ;
387
+
388
+ // For mouse interactions, pickers open on press start. When the popover underlay appears
389
+ // it covers the trigger button, causing onPressEnd to fire immediately and no press scaling
390
+ // to occur. We override this by listening for pointerup on the document ourselves.
391
+ let [ isPressed , setPressed ] = useState ( false ) ;
392
+ let { addGlobalListener} = useGlobalListeners ( ) ;
393
+ let onPressStart = ( e : PressEvent ) => {
394
+ if ( e . pointerType !== 'mouse' ) {
395
+ return ;
396
+ }
397
+ setPressed ( true ) ;
398
+ addGlobalListener ( document , 'pointerup' , ( ) => {
399
+ setPressed ( false ) ;
400
+ } , { once : true , capture : true } ) ;
401
+ } ;
402
+
403
+ return (
404
+ < PressResponder onPressStart = { onPressStart } isPressed = { isPressed } >
405
+ < Button
406
+ ref = { buttonRef }
407
+ style = { renderProps => pressScale ( buttonRef ) ( renderProps ) }
408
+ // Prevent press scale from sticking while Picker is open.
409
+ // @ts -ignore
410
+ isPressed = { false }
411
+ className = { renderProps => inputButton ( {
412
+ ...renderProps ,
413
+ size : size ,
414
+ isOpen,
415
+ isQuiet
416
+ } ) } >
417
+ { ( renderProps ) => (
418
+ < >
419
+ < SelectValue className = { valueStyles ( { isQuiet} ) + ' ' + raw ( '&> * {display: none;}' ) } >
420
+ { ( { defaultChildren} ) => {
421
+ return (
422
+ < Provider
423
+ values = { [
424
+ [ IconContext , {
425
+ slots : {
426
+ icon : {
427
+ render : centerBaseline ( { slot : 'icon' , styles : iconCenterWrapper } ) ,
428
+ styles : icon
429
+ }
430
+ }
431
+ } ] ,
432
+ [ TextContext , {
433
+ slots : {
434
+ description : { } ,
435
+ label : { styles : style ( {
436
+ display : 'block' ,
437
+ flexGrow : 1 ,
438
+ truncate : true
439
+ } ) }
440
+ }
441
+ } ] ,
442
+ [ InsideSelectValueContext , true ]
443
+ ] } >
444
+ { defaultChildren }
445
+ </ Provider >
446
+ ) ;
447
+ } }
448
+ </ SelectValue >
449
+ { isInvalid && (
450
+ < FieldErrorIcon isDisabled = { isDisabled } />
451
+ ) }
452
+ < ChevronIcon
453
+ size = { size }
454
+ className = { iconStyles } />
455
+ { isFocusVisible && isQuiet && < span className = { quietFocusLine } /> }
456
+ { isInvalid && ! isDisabled && ! isQuiet &&
457
+ // @ts -ignore known limitation detecting functions from the theme
458
+ < div className = { invalidBorder ( { ...renderProps , size} ) } />
459
+ }
460
+ </ >
461
+ ) }
462
+ </ Button >
463
+ </ PressResponder >
464
+ ) ;
465
+ }
466
+
440
467
export interface PickerItemProps extends Omit < ListBoxItemProps , 'children' | 'style' | 'className' > , StyleProps {
441
468
children : ReactNode
442
469
}
0 commit comments