@@ -27,7 +27,7 @@ import pickerStyles from './picker.css.js';
2727import chevronStyles from '@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js' ;
2828
2929import { Focusable } from '@spectrum-web-components/shared/src/focusable.js' ;
30- import reparentChildren from '@spectrum-web-components/shared/src/reparent-children.js' ;
30+ import { reparentChildren } from '@spectrum-web-components/shared/src/reparent-children.js' ;
3131import '@spectrum-web-components/icon/sp-icon.js' ;
3232import { Chevron100Icon } from '@spectrum-web-components/icons-ui' ;
3333import '@spectrum-web-components/icons-workflow/icons/sp-icon-alert.js' ;
@@ -39,6 +39,7 @@ import {
3939 MenuQueryRoleEventDetail ,
4040} from '@spectrum-web-components/menu' ;
4141import '@spectrum-web-components/popover/sp-popover.js' ;
42+ import { Popover } from '@spectrum-web-components/popover/src/popover.js' ;
4243import {
4344 Placement ,
4445 openOverlay ,
@@ -95,9 +96,10 @@ export class PickerBase extends SizedMixin(Focusable) {
9596 @property ( { type : Boolean , reflect : true } )
9697 public open = false ;
9798
98- private reparentableChildren ?: Element [ ] ;
99+ public menuItems : MenuItem [ ] = [ ] ;
99100 private restoreChildren ?: Function ;
100- public optionsMenu ?: Menu ;
101+
102+ public optionsMenu ! : Menu ;
101103
102104 /**
103105 * @type {"auto" | "auto-start" | "auto-end" | "top" | "bottom" | "right" | "left" | "top-start" | "top-end" | "bottom-start" | "bottom-end" | "right-start" | "right-end" | "left-start" | "left-end" | "none" }
@@ -119,7 +121,7 @@ export class PickerBase extends SizedMixin(Focusable) {
119121 private closeOverlay ?: ( ) => void ;
120122
121123 @query ( 'sp-popover' )
122- private popover ?: HTMLElement ;
124+ private popover ! : Popover ;
123125
124126 protected listRole = 'listbox' ;
125127 protected itemRole = 'option' ;
@@ -145,7 +147,7 @@ export class PickerBase extends SizedMixin(Focusable) {
145147 }
146148
147149 public get focusElement ( ) : HTMLElement {
148- if ( this . open && this . optionsMenu ) {
150+ if ( this . open ) {
149151 return this . optionsMenu ;
150152 }
151153 return this . button ;
@@ -193,10 +195,6 @@ export class PickerBase extends SizedMixin(Focusable) {
193195 return ;
194196 }
195197 event . preventDefault ( ) ;
196- /* c8 ignore next 3 */
197- if ( ! this . optionsMenu ) {
198- return ;
199- }
200198 this . open = true ;
201199 } ;
202200
@@ -249,18 +247,26 @@ export class PickerBase extends SizedMixin(Focusable) {
249247
250248 private async openMenu ( ) : Promise < void > {
251249 /* c8 ignore next 9 */
252- if (
253- ! this . popover ||
254- ! this . optionsMenu ||
255- ! this . reparentableChildren ||
256- this . reparentableChildren . length === 0
257- ) {
250+ let reparentableChildren : Element [ ] = [ ] ;
251+
252+ const deprecatedMenu = this . querySelector ( 'sp-menu' ) ;
253+ if ( deprecatedMenu ) {
254+ reparentableChildren = Array . from ( deprecatedMenu . children ) ;
255+ } else {
256+ reparentableChildren = Array . from ( this . children ) . filter (
257+ ( element ) => {
258+ return ! element . hasAttribute ( 'slot' ) ;
259+ }
260+ ) ;
261+ }
262+
263+ if ( reparentableChildren . length === 0 ) {
258264 this . menuStateResolver ( ) ;
259265 return ;
260266 }
261267
262268 this . restoreChildren = reparentChildren (
263- this . reparentableChildren ,
269+ reparentableChildren ,
264270 this . optionsMenu
265271 ) ;
266272
@@ -339,21 +345,27 @@ export class PickerBase extends SizedMixin(Focusable) {
339345
340346 protected render ( ) : TemplateResult {
341347 return html `
342- ${ this . renderButton }
348+ ${ this . renderButton } ${ this . renderPopover }
349+ ` ;
350+ }
351+
352+ protected get renderPopover ( ) : TemplateResult {
353+ return html `
343354 < sp-popover
344355 open
345356 id ="popover "
346357 @click =${ this . onClick }
347358 @sp-overlay-closed =${ this . onOverlayClosed }
348359 >
349- < sp-menu id ="menu " role ="listbox "> </ sp-menu >
360+ < sp-menu id ="menu " role ="${ this . listRole } "> </ sp-menu >
350361 </ sp-popover >
351362 ` ;
352363 }
353364
354365 protected firstUpdated ( changedProperties : PropertyValues ) : void {
355366 super . firstUpdated ( changedProperties ) ;
356367
368+ // Since the sp-menu gets reparented by the popover, initialize it here
357369 this . optionsMenu = this . shadowRoot . querySelector ( 'sp-menu' ) as Menu ;
358370
359371 const deprecatedMenu = this . querySelector ( 'sp-menu' ) ;
@@ -362,14 +374,14 @@ export class PickerBase extends SizedMixin(Focusable) {
362374 `Deprecation Notice: You no longer need to provide an sp-menu child to ${ this . tagName . toLowerCase ( ) } . Any styling or attributes on the sp-menu will be ignored.`
363375 ) ;
364376 }
365- this . reparentableChildren = Array . from (
366- ( deprecatedMenu || this ) . children
367- ) ;
377+ this . menuItems = [
378+ ... this . querySelectorAll ( `sp-menu-item` ) ,
379+ ] as MenuItem [ ] ;
368380 }
369381
370382 protected updated ( changedProperties : PropertyValues ) : void {
371383 super . updated ( changedProperties ) ;
372- if ( changedProperties . has ( 'value' ) && this . reparentableChildren ) {
384+ if ( changedProperties . has ( 'value' ) ) {
373385 this . manageSelection ( ) ;
374386 }
375387 if ( changedProperties . has ( 'disabled' ) && this . disabled ) {
@@ -390,20 +402,15 @@ export class PickerBase extends SizedMixin(Focusable) {
390402 }
391403 }
392404
393- private async manageSelection ( ) : Promise < void > {
405+ protected async manageSelection ( ) : Promise < void > {
394406 /* c8 ignore next 3 */
395- if ( ! this . reparentableChildren ) {
396- return ;
397- }
398- if ( this . reparentableChildren . length ) {
407+ if ( this . menuItems . length > 0 ) {
399408 let selectedItem : MenuItem | undefined ;
400- this . reparentableChildren . map ( ( item ) => {
401- if ( item instanceof MenuItem ) {
402- if ( this . value === item . value && ! item . disabled ) {
403- selectedItem = item ;
404- } else {
405- item . selected = false ;
406- }
409+ this . menuItems . forEach ( ( item ) => {
410+ if ( this . value === item . value && ! item . disabled ) {
411+ selectedItem = item ;
412+ } else {
413+ item . selected = false ;
407414 }
408415 } ) ;
409416 if ( selectedItem ) {
@@ -413,12 +420,12 @@ export class PickerBase extends SizedMixin(Focusable) {
413420 this . value = '' ;
414421 this . selectedItemText = '' ;
415422 }
416- if ( this . open && this . optionsMenu ) {
423+ if ( this . open ) {
417424 this . optionsMenu . updateSelectedItemIndex ( ) ;
418425 }
419426 return ;
420427 }
421- if ( this . open && this . optionsMenu ) {
428+ if ( this . open ) {
422429 await this . optionsMenu . updateComplete ;
423430 if ( this . optionsMenu . menuItems . length ) {
424431 this . manageSelection ( ) ;
0 commit comments