@@ -207,15 +207,19 @@ export class PickerBase extends SizedMixin(Focusable) {
207
207
if ( menuChangeEvent ) {
208
208
menuChangeEvent . preventDefault ( ) ;
209
209
}
210
+ this . selectedItem . selected = false ;
211
+ if ( oldSelectedItem ) {
212
+ oldSelectedItem . selected = true ;
213
+ }
210
214
this . selectedItem = oldSelectedItem ;
211
215
this . value = oldValue ;
212
216
this . open = true ;
213
217
return ;
214
218
}
215
219
if ( oldSelectedItem ) {
216
- oldSelectedItem . selected = ! ! this . selects ? false : false ;
220
+ oldSelectedItem . selected = false ;
217
221
}
218
- item . selected = ! ! this . selects ? true : false ;
222
+ item . selected = ! ! this . selects ;
219
223
}
220
224
221
225
public toggle ( target ?: boolean ) : void {
@@ -276,11 +280,13 @@ export class PickerBase extends SizedMixin(Focusable) {
276
280
const { popover } = this ;
277
281
this . addEventListener (
278
282
'sp-opened' ,
279
- ( ) => {
280
- this . manageSelection ( ) ;
281
- this . optionsMenu . updateComplete . then ( ( ) => {
282
- this . menuStateResolver ( ) ;
283
- } ) ;
283
+ async ( ) => {
284
+ this . updateMenuItems ( ) ;
285
+ await Promise . all ( [
286
+ this . itemsUpdated ,
287
+ this . optionsMenu . updateComplete ,
288
+ ] ) ;
289
+ this . menuStateResolver ( ) ;
284
290
} ,
285
291
{ once : true }
286
292
) ;
@@ -411,10 +417,37 @@ export class PickerBase extends SizedMixin(Focusable) {
411
417
` ;
412
418
}
413
419
420
+ private _willUpdateItems = false ;
421
+ protected itemsUpdated : Promise < void > = Promise . resolve ( ) ;
422
+
423
+ /**
424
+ * Acquire the available MenuItems in the Picker by
425
+ * direct element query or by assuming the list managed
426
+ * by the Menu within the open options overlay.
427
+ */
414
428
protected updateMenuItems ( ) : void {
415
- this . menuItems = [
416
- ...this . querySelectorAll ( 'sp-menu-item' ) ,
417
- ] as MenuItem [ ] ;
429
+ if ( this . _willUpdateItems ) return ;
430
+ this . _willUpdateItems = true ;
431
+
432
+ let resolve = ( ) : void => {
433
+ return ;
434
+ } ;
435
+ this . itemsUpdated = new Promise ( ( res ) => ( resolve = res ) ) ;
436
+ // Debounce the update so we only update once
437
+ // if multiple items have changed
438
+ window . requestAnimationFrame ( async ( ) => {
439
+ if ( this . open ) {
440
+ await this . optionsMenu . updateComplete ;
441
+ this . menuItems = this . optionsMenu . childItems ;
442
+ } else {
443
+ this . menuItems = [
444
+ ...this . querySelectorAll ( 'sp-menu-item' ) ,
445
+ ] as MenuItem [ ] ;
446
+ }
447
+ this . manageSelection ( ) ;
448
+ resolve ( ) ;
449
+ this . _willUpdateItems = false ;
450
+ } ) ;
418
451
}
419
452
420
453
protected firstUpdated ( changedProperties : PropertyValues ) : void {
@@ -423,8 +456,6 @@ export class PickerBase extends SizedMixin(Focusable) {
423
456
// Since the sp-menu gets reparented by the popover, initialize it here
424
457
this . optionsMenu = this . shadowRoot . querySelector ( 'sp-menu' ) as Menu ;
425
458
426
- this . updateMenuItems ( ) ;
427
-
428
459
const deprecatedMenu = this . querySelector ( 'sp-menu' ) ;
429
460
if ( deprecatedMenu ) {
430
461
console . warn (
@@ -439,7 +470,7 @@ export class PickerBase extends SizedMixin(Focusable) {
439
470
changedProperties . has ( 'value' ) &&
440
471
! changedProperties . has ( 'selectedItem' )
441
472
) {
442
- this . manageSelection ( ) ;
473
+ this . updateMenuItems ( ) ;
443
474
}
444
475
if ( changedProperties . has ( 'disabled' ) && this . disabled ) {
445
476
this . open = false ;
@@ -460,32 +491,25 @@ export class PickerBase extends SizedMixin(Focusable) {
460
491
}
461
492
462
493
protected manageSelection ( ) : void {
463
- if ( ! this . open ) {
464
- this . updateMenuItems ( ) ;
465
- }
466
- /* c8 ignore next 3 */
467
- if ( this . menuItems . length > 0 ) {
468
- let selectedItem : MenuItem | undefined ;
469
- this . menuItems . forEach ( ( item ) => {
470
- if ( this . value === item . value && ! item . disabled ) {
471
- selectedItem = item ;
472
- } else {
473
- item . selected = ! ! this . selects ? false : false ;
474
- }
475
- } ) ;
476
- if ( selectedItem ) {
477
- selectedItem . selected = ! ! this . selects ? true : false ;
478
- this . selectedItem = selectedItem ;
494
+ let selectedItem : MenuItem | undefined ;
495
+ this . menuItems . forEach ( ( item ) => {
496
+ if ( this . value === item . value && ! item . disabled ) {
497
+ selectedItem = item ;
479
498
} else {
480
- this . value = '' ;
481
- this . selectedItem = undefined ;
482
- }
483
- if ( this . open ) {
484
- this . optionsMenu . updateComplete . then ( ( ) => {
485
- this . optionsMenu . updateSelectedItemIndex ( ) ;
486
- } ) ;
499
+ item . selected = false ;
487
500
}
488
- return ;
501
+ } ) ;
502
+ if ( selectedItem ) {
503
+ selectedItem . selected = ! ! this . selects ;
504
+ this . selectedItem = selectedItem ;
505
+ } else {
506
+ this . value = '' ;
507
+ this . selectedItem = undefined ;
508
+ }
509
+ if ( this . open ) {
510
+ this . optionsMenu . updateComplete . then ( ( ) => {
511
+ this . optionsMenu . updateSelectedItemIndex ( ) ;
512
+ } ) ;
489
513
}
490
514
}
491
515
@@ -495,13 +519,16 @@ export class PickerBase extends SizedMixin(Focusable) {
495
519
protected async _getUpdateComplete ( ) : Promise < boolean > {
496
520
const complete = ( await super . _getUpdateComplete ( ) ) as boolean ;
497
521
await this . menuStatePromise ;
522
+ await this . itemsUpdated ;
498
523
return complete ;
499
524
}
500
525
501
526
public connectedCallback ( ) : void {
502
- if ( ! this . open ) {
503
- this . updateMenuItems ( ) ;
504
- }
527
+ this . updateMenuItems ( ) ;
528
+ this . addEventListener (
529
+ 'sp-menu-item-added-or-updated' ,
530
+ this . updateMenuItems
531
+ ) ;
505
532
super . connectedCallback ( ) ;
506
533
}
507
534
0 commit comments