@spectrum-web-components/picker 0.40.3 → 0.40.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/custom-elements.json +84 -4
- package/package.json +15 -15
- package/src/Picker.d.ts +4 -2
- package/src/Picker.dev.js +47 -15
- package/src/Picker.dev.js.map +2 -2
- package/src/Picker.js +17 -16
- package/src/Picker.js.map +2 -2
- package/test/index.js +126 -21
- package/test/index.js.map +2 -2
package/src/Picker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var m=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var
|
|
1
|
+
"use strict";var m=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var i=(d,a,e,t)=>{for(var s=t>1?void 0:t?f(a,e):a,o=d.length-1,l;o>=0;o--)(l=d[o])&&(s=(t?l(a,e,s):l(s))||s);return t&&s&&m(a,e,s),s};import{html as n,nothing as b,SizedMixin as v}from"@spectrum-web-components/base";import{classMap as y,ifDefined as c,styleMap as u}from"@spectrum-web-components/base/src/directives.js";import{property as r,query as p,state as h}from"@spectrum-web-components/base/src/decorators.js";import g from"./picker.css.js";import w from"@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js";import{Focusable as I}from"@spectrum-web-components/shared/src/focusable.js";import"@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js";import"@spectrum-web-components/icons-workflow/icons/sp-icon-alert.js";import"@spectrum-web-components/menu/sp-menu.js";import{IS_MOBILE as M,MatchMediaController as S}from"@spectrum-web-components/reactive-controllers/src/MatchMedia.js";const $={s:"spectrum-UIIcon-ChevronDown75",m:"spectrum-UIIcon-ChevronDown100",l:"spectrum-UIIcon-ChevronDown200",xl:"spectrum-UIIcon-ChevronDown300"};export const DESCRIPTION_ID="option-picker";export class PickerBase extends v(I,{noDefaultSize:!0}){constructor(){super(...arguments);this.isMobile=new S(this,M);this.deprecatedMenu=null;this.disabled=!1;this.focused=!1;this.invalid=!1;this.open=!1;this.readonly=!1;this.selects="single";this.placement="bottom-start";this.quiet=!1;this.value="";this.listRole="listbox";this.itemRole="option";this.preventNextToggle="no";this.pointerdownState=!1;this.handleKeydown=e=>{this.focused=!0,!(e.code!=="ArrowDown"&&e.code!=="ArrowUp")&&(e.stopPropagation(),e.preventDefault(),this.toggle(!0))};this.applyFocusElementLabel=e=>{this.appliedLabel=e};this.dependenciesLoaded=!1;this.dependenciesToLoad={};this.hasRenderedOverlay=!1;this.willManageSelection=!1;this.selectionPromise=Promise.resolve();this.recentlyConnected=!1;this.enterKeydownOn=null;this.handleEnterKeydown=e=>{if(e.code==="Enter"){if(this.enterKeydownOn){e.preventDefault();return}this.enterKeydownOn=e.target,this.addEventListener("keyup",async t=>{t.code==="Enter"&&(this.enterKeydownOn=null)},{once:!0})}}}get menuItems(){return this.optionsMenu.childItems}get selectedItem(){return this._selectedItem}set selectedItem(e){if(this.selectedItemContent=e?e.itemChildren:void 0,e===this.selectedItem)return;const t=this.selectedItem;this._selectedItem=e,this.requestUpdate("selectedItem",t)}get focusElement(){return this.open?this.optionsMenu:this.button}forceFocusVisible(){this.focused=!0}click(){this.disabled||this.toggle()}handleButtonBlur(){this.focused=!1}handleButtonPointerdown(e){if(e.button!==0)return;this.pointerdownState=this.open,this.preventNextToggle="maybe";const t=()=>{document.removeEventListener("pointerup",t),document.removeEventListener("pointercancel",t),requestAnimationFrame(()=>{this.preventNextToggle="no"})};document.addEventListener("pointerup",t),document.addEventListener("pointercancel",t),this.handleActivate()}handleButtonFocus(e){this.preventNextToggle==="maybe"&&e.relatedTarget===this.optionsMenu&&(this.preventNextToggle="yes")}handleActivate(e){this.enterKeydownOn&&this.enterKeydownOn!==this.button||this.preventNextToggle!=="yes"&&((e==null?void 0:e.type)==="click"&&this.open!==this.pointerdownState||this.toggle())}focus(e){super.focus(e),!this.disabled&&this.focusElement&&(this.focused=this.hasVisibleFocusInTree())}handleHelperFocus(){this.focused=!0,this.button.focus()}handleChange(e){const t=e.target,[s]=t.selectedItems;e.stopPropagation(),e.cancelable?this.setValueFromItem(s,e):this.open=!1}async setValueFromItem(e,t){this.open=!1;const s=this.selectedItem,o=this.value;if(this.selectedItem=e,this.value=e.value,await this.updateComplete,!this.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0,composed:!0}))&&this.selects){t&&t.preventDefault(),this.setMenuItemSelected(this.selectedItem,!1),s&&this.setMenuItemSelected(s,!0),this.selectedItem=s,this.value=o,this.open=!0;return}else if(!this.selects){this.selectedItem=s,this.value=o;return}s&&this.setMenuItemSelected(s,!1),this.setMenuItemSelected(e,!!this.selects)}setMenuItemSelected(e,t){this.selects!=null&&(e.selected=t)}toggle(e){this.readonly||(this.open=typeof e!="undefined"?e:!this.open)}close(){this.readonly||(this.open=!1)}get containerStyles(){return this.isMobile.matches?{"--swc-menu-width":"100%"}:{}}get selectedItemContent(){return this._selectedItemContent||{icon:[],content:[]}}set selectedItemContent(e){if(e===this.selectedItemContent)return;const t=this.selectedItemContent;this._selectedItemContent=e,this.requestUpdate("selectedItemContent",t)}handleTooltipSlotchange(e){this.tooltipEl=e.target.assignedElements()[0]}renderLabelContent(e){return this.value&&this.selectedItem?e:n`
|
|
2
2
|
<slot name="label" id="label">
|
|
3
3
|
<span
|
|
4
4
|
aria-hidden=${c(this.appliedLabel?void 0:"true")}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
${this.label}
|
|
7
7
|
</span>
|
|
8
8
|
</slot>
|
|
9
|
-
`}get buttonContent(){const e={"visually-hidden":this.icons==="only"&&!!this.value,placeholder:!this.value,label:!0},t=this.appliedLabel||this.label;return[
|
|
9
|
+
`}get buttonContent(){const e={"visually-hidden":this.icons==="only"&&!!this.value,placeholder:!this.value,label:!0},t=this.appliedLabel||this.label;return[n`
|
|
10
10
|
<span id="icon" ?hidden=${this.icons==="none"}>
|
|
11
11
|
${this.selectedItemContent.icon}
|
|
12
12
|
</span>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
>
|
|
17
17
|
${this.renderLabelContent(this.selectedItemContent.content)}
|
|
18
18
|
</span>
|
|
19
|
-
${this.value&&this.selectedItem?
|
|
19
|
+
${this.value&&this.selectedItem?n`
|
|
20
20
|
<span
|
|
21
21
|
aria-hidden="true"
|
|
22
22
|
class="visually-hidden"
|
|
@@ -25,14 +25,14 @@
|
|
|
25
25
|
${t}
|
|
26
26
|
<slot name="label"></slot>
|
|
27
27
|
</span>
|
|
28
|
-
`:
|
|
28
|
+
`:n`
|
|
29
29
|
<span hidden id="applied-label">${t}</span>
|
|
30
30
|
`}
|
|
31
|
-
${this.invalid?
|
|
31
|
+
${this.invalid?n`
|
|
32
32
|
<sp-icon-alert
|
|
33
33
|
class="validation-icon"
|
|
34
34
|
></sp-icon-alert>
|
|
35
|
-
`:
|
|
35
|
+
`:b}
|
|
36
36
|
<sp-icon-chevron100
|
|
37
37
|
class="picker ${$[this.size]}"
|
|
38
38
|
></sp-icon-chevron100>
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
id="tooltip"
|
|
43
43
|
@slotchange=${this.handleTooltipSlotchange}
|
|
44
44
|
></slot>
|
|
45
|
-
`]}renderOverlay(e){const t=this.renderContainer(e);return this.trackDependency("sp-overlay"),import("@spectrum-web-components/overlay/sp-overlay.js"),
|
|
45
|
+
`]}renderOverlay(e){const t=this.renderContainer(e);return this.trackDependency("sp-overlay"),import("@spectrum-web-components/overlay/sp-overlay.js"),n`
|
|
46
46
|
<sp-overlay
|
|
47
47
|
.triggerElement=${this}
|
|
48
48
|
.offset=${0}
|
|
@@ -50,15 +50,16 @@
|
|
|
50
50
|
.placement=${this.isMobile.matches?void 0:this.placement}
|
|
51
51
|
.type=${this.isMobile.matches?"modal":"auto"}
|
|
52
52
|
.receivesFocus=${"true"}
|
|
53
|
+
.willPreventClose=${this.preventNextToggle!=="no"&&this.open&&this.dependenciesLoaded}
|
|
53
54
|
@beforetoggle=${s=>{s.composedPath()[0]===s.target&&(s.newState==="closed"&&(this.open=!1),this.open||(this.optionsMenu.updateSelectedItemIndex(),this.optionsMenu.closeDescendentOverlays()))}}
|
|
54
55
|
>
|
|
55
56
|
${t}
|
|
56
57
|
</sp-overlay>
|
|
57
|
-
`}get renderDescriptionSlot(){return
|
|
58
|
+
`}get renderDescriptionSlot(){return n`
|
|
58
59
|
<div id=${DESCRIPTION_ID}>
|
|
59
60
|
<slot name="description"></slot>
|
|
60
61
|
</div>
|
|
61
|
-
`}render(){return this.tooltipEl&&(this.tooltipEl.disabled=this.open),
|
|
62
|
+
`}render(){return this.tooltipEl&&(this.tooltipEl.disabled=this.open),n`
|
|
62
63
|
<span
|
|
63
64
|
id="focus-helper"
|
|
64
65
|
tabindex="${this.focused||this.open?"-1":"0"}"
|
|
@@ -74,9 +75,9 @@
|
|
|
74
75
|
id="button"
|
|
75
76
|
class="button"
|
|
76
77
|
@blur=${this.handleButtonBlur}
|
|
78
|
+
@click=${this.handleActivate}
|
|
77
79
|
@pointerdown=${this.handleButtonPointerdown}
|
|
78
80
|
@focus=${this.handleButtonFocus}
|
|
79
|
-
@click=${this.handleButtonClick}
|
|
80
81
|
@keydown=${{handleEvent:this.handleEnterKeydown,capture:!0}}
|
|
81
82
|
?disabled=${this.disabled}
|
|
82
83
|
tabindex="-1"
|
|
@@ -84,7 +85,7 @@
|
|
|
84
85
|
${this.buttonContent}
|
|
85
86
|
</button>
|
|
86
87
|
${this.renderMenu} ${this.renderDescriptionSlot}
|
|
87
|
-
`}update(e){var t,s;this.selects&&(this.selects="single"),e.has("disabled")&&this.disabled&&(this.open=!1),e.has("value")&&this.shouldScheduleManageSelection(),this.hasUpdated||(this.deprecatedMenu=this.querySelector(":scope > sp-menu"),(t=this.deprecatedMenu)==null||t.toggleAttribute("ignore",!0),(s=this.deprecatedMenu)==null||s.setAttribute("selects","inherit")),super.update(e)}bindButtonKeydownListener(){this.button.addEventListener("keydown",this.handleKeydown)}firstUpdated(e){super.firstUpdated(e),this.bindButtonKeydownListener()}get dismissHelper(){return
|
|
88
|
+
`}update(e){var t,s;this.selects&&(this.selects="single"),e.has("disabled")&&this.disabled&&(this.open=!1),e.has("value")&&this.shouldScheduleManageSelection(),this.hasUpdated||(this.deprecatedMenu=this.querySelector(":scope > sp-menu"),(t=this.deprecatedMenu)==null||t.toggleAttribute("ignore",!0),(s=this.deprecatedMenu)==null||s.setAttribute("selects","inherit")),super.update(e)}bindButtonKeydownListener(){this.button.addEventListener("keydown",this.handleKeydown)}firstUpdated(e){super.firstUpdated(e),this.bindButtonKeydownListener()}get dismissHelper(){return n`
|
|
88
89
|
<div class="visually-hidden">
|
|
89
90
|
<button
|
|
90
91
|
tabindex="-1"
|
|
@@ -92,9 +93,9 @@
|
|
|
92
93
|
@click=${this.close}
|
|
93
94
|
></button>
|
|
94
95
|
</div>
|
|
95
|
-
`}trackDependency(e,t){const s=!!customElements.get(e)||this.dependenciesToLoad[e]||!!t;s||customElements.whenDefined(e).then(()=>{this.trackDependency(e,!0)}),this.dependenciesToLoad={...this.dependenciesToLoad,[e]:s},this.dependenciesLoaded=Object.values(this.dependenciesToLoad).every(o=>o)}renderContainer(e){const t=
|
|
96
|
+
`}trackDependency(e,t){const s=!!customElements.get(e)||this.dependenciesToLoad[e]||!!t;s||customElements.whenDefined(e).then(()=>{this.trackDependency(e,!0)}),this.dependenciesToLoad={...this.dependenciesToLoad,[e]:s},this.dependenciesLoaded=Object.values(this.dependenciesToLoad).every(o=>o)}renderContainer(e){const t=n`
|
|
96
97
|
${this.dismissHelper} ${e} ${this.dismissHelper}
|
|
97
|
-
`;return this.isMobile.matches?(this.trackDependency("sp-tray"),import("@spectrum-web-components/tray/sp-tray.js"),
|
|
98
|
+
`;return this.isMobile.matches?(this.trackDependency("sp-tray"),import("@spectrum-web-components/tray/sp-tray.js"),n`
|
|
98
99
|
<sp-tray
|
|
99
100
|
id="popover"
|
|
100
101
|
role="presentation"
|
|
@@ -102,7 +103,7 @@
|
|
|
102
103
|
>
|
|
103
104
|
${t}
|
|
104
105
|
</sp-tray>
|
|
105
|
-
`):(this.trackDependency("sp-popover"),import("@spectrum-web-components/popover/sp-popover.js"),
|
|
106
|
+
`):(this.trackDependency("sp-popover"),import("@spectrum-web-components/popover/sp-popover.js"),n`
|
|
106
107
|
<sp-popover
|
|
107
108
|
id="popover"
|
|
108
109
|
role="presentation"
|
|
@@ -111,7 +112,7 @@
|
|
|
111
112
|
>
|
|
112
113
|
${t}
|
|
113
114
|
</sp-popover>
|
|
114
|
-
`)}get renderMenu(){const e=
|
|
115
|
+
`)}get renderMenu(){const e=n`
|
|
115
116
|
<sp-menu
|
|
116
117
|
aria-labelledby="applied-label"
|
|
117
118
|
@change=${this.handleChange}
|
|
@@ -125,5 +126,5 @@
|
|
|
125
126
|
>
|
|
126
127
|
<slot @slotchange=${this.shouldScheduleManageSelection}></slot>
|
|
127
128
|
</sp-menu>
|
|
128
|
-
`;return this.hasRenderedOverlay=this.hasRenderedOverlay||this.focused||this.open||!!this.deprecatedMenu,this.hasRenderedOverlay?this.renderOverlay(e):e}shouldScheduleManageSelection(e){!this.willManageSelection&&(!e||e.target.getRootNode().host===this)&&(this.willManageSelection=!0,requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.manageSelection()})}))}shouldManageSelection(){this.willManageSelection||(this.willManageSelection=!0,this.manageSelection())}async manageSelection(){if(this.selects==null)return;this.selectionPromise=new Promise(t=>this.selectionResolver=t);let e;await this.optionsMenu.updateComplete,this.recentlyConnected&&(await new Promise(t=>requestAnimationFrame(()=>t(!0))),this.recentlyConnected=!1),this.menuItems.forEach(t=>{this.value===t.value&&!t.disabled?e=t:t.selected=!1}),e?(e.selected=!!this.selects,this.selectedItem=e):(this.value="",this.selectedItem=void 0),this.open&&(await this.optionsMenu.updateComplete,this.optionsMenu.updateSelectedItemIndex()),this.selectionResolver(),this.willManageSelection=!1}async getUpdateComplete(){const e=await super.getUpdateComplete();return await this.selectionPromise,this.overlayElement&&await this.overlayElement.updateComplete,e}connectedCallback(){super.connectedCallback(),this.recentlyConnected=this.hasUpdated}disconnectedCallback(){this.close(),super.disconnectedCallback()}}
|
|
129
|
+
`;return this.hasRenderedOverlay=this.hasRenderedOverlay||this.focused||this.open||!!this.deprecatedMenu,this.hasRenderedOverlay?this.renderOverlay(e):e}shouldScheduleManageSelection(e){!this.willManageSelection&&(!e||e.target.getRootNode().host===this)&&(this.willManageSelection=!0,requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.manageSelection()})}))}shouldManageSelection(){this.willManageSelection||(this.willManageSelection=!0,this.manageSelection())}async manageSelection(){if(this.selects==null)return;this.selectionPromise=new Promise(t=>this.selectionResolver=t);let e;await this.optionsMenu.updateComplete,this.recentlyConnected&&(await new Promise(t=>requestAnimationFrame(()=>t(!0))),this.recentlyConnected=!1),this.menuItems.forEach(t=>{this.value===t.value&&!t.disabled?e=t:t.selected=!1}),e?(e.selected=!!this.selects,this.selectedItem=e):(this.value="",this.selectedItem=void 0),this.open&&(await this.optionsMenu.updateComplete,this.optionsMenu.updateSelectedItemIndex()),this.selectionResolver(),this.willManageSelection=!1}async getUpdateComplete(){const e=await super.getUpdateComplete();return await this.selectionPromise,this.overlayElement&&await this.overlayElement.updateComplete,e}connectedCallback(){super.connectedCallback(),this.recentlyConnected=this.hasUpdated}disconnectedCallback(){this.close(),super.disconnectedCallback()}}i([h()],PickerBase.prototype,"appliedLabel",2),i([p("#button")],PickerBase.prototype,"button",2),i([r({type:Boolean,reflect:!0})],PickerBase.prototype,"disabled",2),i([r({type:Boolean,reflect:!0})],PickerBase.prototype,"focused",2),i([r({type:String,reflect:!0})],PickerBase.prototype,"icons",2),i([r({type:Boolean,reflect:!0})],PickerBase.prototype,"invalid",2),i([r()],PickerBase.prototype,"label",2),i([r({type:Boolean,reflect:!0})],PickerBase.prototype,"open",2),i([r({type:Boolean,reflect:!0})],PickerBase.prototype,"readonly",2),i([p("sp-menu")],PickerBase.prototype,"optionsMenu",2),i([p("sp-overlay")],PickerBase.prototype,"overlayElement",2),i([r()],PickerBase.prototype,"placement",2),i([r({type:Boolean,reflect:!0})],PickerBase.prototype,"quiet",2),i([r({type:String})],PickerBase.prototype,"value",2),i([r({attribute:!1})],PickerBase.prototype,"selectedItem",1),i([r({attribute:!1})],PickerBase.prototype,"selectedItemContent",1),i([h()],PickerBase.prototype,"dependenciesLoaded",2);export class Picker extends PickerBase{constructor(){super(...arguments);this.handleKeydown=e=>{const{code:t}=e;if(this.focused=!0,!t.startsWith("Arrow")||this.readonly)return;if(t==="ArrowUp"||t==="ArrowDown"){this.toggle(!0),e.preventDefault();return}e.preventDefault();const s=this.selectedItem?this.menuItems.indexOf(this.selectedItem):-1,o=s<0||t==="ArrowRight"?1:-1;let l=s+o;for(;this.menuItems[l]&&this.menuItems[l].disabled;)l+=o;!this.menuItems[l]||this.menuItems[l].disabled||(!this.value||l!==s)&&this.setValueFromItem(this.menuItems[l])}}static get styles(){return[g,w]}get containerStyles(){const e=super.containerStyles;return this.quiet||(e["min-width"]=`${this.offsetWidth}px`),e}}
|
|
129
130
|
//# sourceMappingURL=Picker.js.map
|
package/src/Picker.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Picker.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2020 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport {\n CSSResultArray,\n DefaultElementSize,\n html,\n nothing,\n PropertyValues,\n SizedMixin,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n classMap,\n ifDefined,\n StyleInfo,\n styleMap,\n} from '@spectrum-web-components/base/src/directives.js';\nimport {\n property,\n query,\n state,\n} from '@spectrum-web-components/base/src/decorators.js';\n\nimport pickerStyles from './picker.css.js';\nimport chevronStyles from '@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js';\n\nimport { Focusable } from '@spectrum-web-components/shared/src/focusable.js';\nimport type { Tooltip } from '@spectrum-web-components/tooltip';\nimport '@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js';\nimport '@spectrum-web-components/icons-workflow/icons/sp-icon-alert.js';\nimport '@spectrum-web-components/menu/sp-menu.js';\nimport type {\n Menu,\n MenuItem,\n MenuItemChildren,\n} from '@spectrum-web-components/menu';\nimport { Placement } from '@spectrum-web-components/overlay';\nimport {\n IS_MOBILE,\n MatchMediaController,\n} from '@spectrum-web-components/reactive-controllers/src/MatchMedia.js';\nimport type { Overlay } from '@spectrum-web-components/overlay/src/Overlay.js';\n\nconst chevronClass = {\n s: 'spectrum-UIIcon-ChevronDown75',\n m: 'spectrum-UIIcon-ChevronDown100',\n l: 'spectrum-UIIcon-ChevronDown200',\n xl: 'spectrum-UIIcon-ChevronDown300',\n};\n\nexport const DESCRIPTION_ID = 'option-picker';\nexport class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {\n protected isMobile = new MatchMediaController(this, IS_MOBILE);\n\n @state()\n appliedLabel?: string;\n\n @query('#button')\n public button!: HTMLButtonElement;\n\n private deprecatedMenu: Menu | null = null;\n\n @property({ type: Boolean, reflect: true })\n public override disabled = false;\n\n @property({ type: Boolean, reflect: true })\n public focused = false;\n\n @property({ type: String, reflect: true })\n public icons?: 'only' | 'none';\n\n @property({ type: Boolean, reflect: true })\n public invalid = false;\n\n @property()\n public label?: string;\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n @property({ type: Boolean, reflect: true })\n public readonly = false;\n\n public selects: undefined | 'single' = 'single';\n\n protected get menuItems(): MenuItem[] {\n return this.optionsMenu.childItems;\n }\n\n @query('sp-menu')\n protected optionsMenu!: Menu;\n\n @query('sp-overlay')\n protected overlayElement!: Overlay;\n\n protected tooltipEl?: Tooltip;\n\n /**\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n * @attr\n */\n\n @property()\n public placement: Placement = 'bottom-start';\n\n @property({ type: Boolean, reflect: true })\n public quiet = false;\n\n @property({ type: String })\n public value = '';\n\n @property({ attribute: false })\n public get selectedItem(): MenuItem | undefined {\n return this._selectedItem;\n }\n\n public set selectedItem(selectedItem: MenuItem | undefined) {\n this.selectedItemContent = selectedItem\n ? selectedItem.itemChildren\n : undefined;\n\n if (selectedItem === this.selectedItem) return;\n const oldSelectedItem = this.selectedItem;\n this._selectedItem = selectedItem;\n this.requestUpdate('selectedItem', oldSelectedItem);\n }\n\n _selectedItem?: MenuItem;\n\n protected listRole: 'listbox' | 'menu' = 'listbox';\n protected itemRole = 'option';\n\n public override get focusElement(): HTMLElement {\n if (this.open) {\n return this.optionsMenu;\n }\n return this.button;\n }\n\n public forceFocusVisible(): void {\n this.focused = true;\n }\n\n public handleButtonBlur(): void {\n this.focused = false;\n }\n\n protected preventNextToggle: 'no' | 'maybe' | 'yes' = 'no';\n\n protected handleButtonPointerdown(): void {\n this.preventNextToggle = 'maybe';\n const cleanup = (): void => {\n document.removeEventListener('pointerup', cleanup);\n document.removeEventListener('pointercancel', cleanup);\n requestAnimationFrame(() => {\n // Complete cleanup on the animation frame so that `click` can go first.\n this.preventNextToggle = 'no';\n });\n };\n // Ensure that however the pointer goes up we do `cleanup()`.\n document.addEventListener('pointerup', cleanup);\n document.addEventListener('pointercancel', cleanup);\n }\n\n protected handleButtonFocus(event: FocusEvent): void {\n // When focus comes from a pointer event, and the related target is the Menu,\n // we don't want to reopen the Menu.\n if (\n this.preventNextToggle === 'maybe' &&\n event.relatedTarget === this.optionsMenu\n ) {\n this.preventNextToggle = 'yes';\n }\n }\n\n protected handleButtonClick(): void {\n if (this.enterKeydownOn && this.enterKeydownOn !== this.button) {\n return;\n }\n if (this.preventNextToggle === 'yes') {\n return;\n }\n this.toggle();\n }\n\n public override focus(options?: FocusOptions): void {\n super.focus(options);\n\n if (!this.disabled && this.focusElement) {\n this.focused = this.hasVisibleFocusInTree();\n }\n }\n\n public handleHelperFocus(): void {\n // set focused to true here instead of handleButtonFocus so clicks don't flash a focus outline\n this.focused = true;\n this.button.focus();\n }\n\n public handleChange(event: Event): void {\n const target = event.target as Menu;\n const [selected] = target.selectedItems;\n event.stopPropagation();\n if (event.cancelable) {\n this.setValueFromItem(selected, event);\n } else {\n // Non-cancelable \"change\" events announce a selection with no value\n // change that should close the Picker element.\n this.open = false;\n }\n }\n\n protected handleKeydown = (event: KeyboardEvent): void => {\n this.focused = true;\n if (event.code !== 'ArrowDown' && event.code !== 'ArrowUp') {\n return;\n }\n event.preventDefault();\n this.toggle(true);\n };\n\n protected async setValueFromItem(\n item: MenuItem,\n menuChangeEvent?: Event\n ): Promise<void> {\n // should always close when \"setting\" a value.\n this.open = false;\n const oldSelectedItem = this.selectedItem;\n const oldValue = this.value;\n\n // Set a value.\n this.selectedItem = item;\n this.value = item.value;\n await this.updateComplete;\n const applyDefault = this.dispatchEvent(\n new Event('change', {\n bubbles: true,\n // Allow it to be prevented.\n cancelable: true,\n composed: true,\n })\n );\n if (!applyDefault && this.selects) {\n if (menuChangeEvent) {\n menuChangeEvent.preventDefault();\n }\n this.setMenuItemSelected(this.selectedItem as MenuItem, false);\n if (oldSelectedItem) {\n this.setMenuItemSelected(oldSelectedItem, true);\n }\n this.selectedItem = oldSelectedItem;\n this.value = oldValue;\n this.open = true;\n return;\n } else if (!this.selects) {\n // Unset the value if not carrying a selection\n this.selectedItem = oldSelectedItem;\n this.value = oldValue;\n return;\n }\n if (oldSelectedItem) {\n this.setMenuItemSelected(oldSelectedItem, false);\n }\n this.setMenuItemSelected(item, !!this.selects);\n }\n\n protected setMenuItemSelected(item: MenuItem, value: boolean): void {\n // matches null | undefined\n if (this.selects == null) return;\n item.selected = value;\n }\n\n public toggle(target?: boolean): void {\n if (this.readonly) {\n return;\n }\n this.open = typeof target !== 'undefined' ? target : !this.open;\n }\n\n public close(): void {\n if (this.readonly) {\n return;\n }\n this.open = false;\n }\n\n protected get containerStyles(): StyleInfo {\n // @todo: test in mobile\n /* c8 ignore next 5 */\n if (this.isMobile.matches) {\n return {\n '--swc-menu-width': '100%',\n };\n }\n return {};\n }\n\n @property({ attribute: false })\n protected get selectedItemContent(): MenuItemChildren {\n return this._selectedItemContent || { icon: [], content: [] };\n }\n\n protected set selectedItemContent(\n selectedItemContent: MenuItemChildren | undefined\n ) {\n if (selectedItemContent === this.selectedItemContent) return;\n\n const oldContent = this.selectedItemContent;\n this._selectedItemContent = selectedItemContent;\n this.requestUpdate('selectedItemContent', oldContent);\n }\n\n _selectedItemContent?: MenuItemChildren;\n\n protected handleTooltipSlotchange(\n event: Event & { target: HTMLSlotElement }\n ): void {\n this.tooltipEl = event.target.assignedElements()[0] as\n | Tooltip\n | undefined;\n }\n\n protected renderLabelContent(content: Node[]): TemplateResult | Node[] {\n if (this.value && this.selectedItem) {\n return content;\n }\n return html`\n <slot name=\"label\" id=\"label\">\n <span\n aria-hidden=${ifDefined(\n this.appliedLabel ? undefined : 'true'\n )}\n >\n ${this.label}\n </span>\n </slot>\n `;\n }\n\n protected get buttonContent(): TemplateResult[] {\n const labelClasses = {\n 'visually-hidden': this.icons === 'only' && !!this.value,\n placeholder: !this.value,\n label: true,\n };\n const appliedLabel = this.appliedLabel || this.label;\n return [\n html`\n <span id=\"icon\" ?hidden=${this.icons === 'none'}>\n ${this.selectedItemContent.icon}\n </span>\n <span\n id=${ifDefined(\n this.value && this.selectedItem ? 'label' : undefined\n )}\n class=${classMap(labelClasses)}\n >\n ${this.renderLabelContent(this.selectedItemContent.content)}\n </span>\n ${this.value && this.selectedItem\n ? html`\n <span\n aria-hidden=\"true\"\n class=\"visually-hidden\"\n id=\"applied-label\"\n >\n ${appliedLabel}\n <slot name=\"label\"></slot>\n </span>\n `\n : html`\n <span hidden id=\"applied-label\">${appliedLabel}</span>\n `}\n ${this.invalid\n ? html`\n <sp-icon-alert\n class=\"validation-icon\"\n ></sp-icon-alert>\n `\n : nothing}\n <sp-icon-chevron100\n class=\"picker ${chevronClass[\n this.size as DefaultElementSize\n ]}\"\n ></sp-icon-chevron100>\n <slot\n aria-hidden=\"true\"\n name=\"tooltip\"\n id=\"tooltip\"\n @slotchange=${this.handleTooltipSlotchange}\n ></slot>\n `,\n ];\n }\n\n applyFocusElementLabel = (value?: string): void => {\n this.appliedLabel = value;\n };\n\n protected renderOverlay(menu: TemplateResult): TemplateResult {\n const container = this.renderContainer(menu);\n this.trackDependency('sp-overlay');\n import('@spectrum-web-components/overlay/sp-overlay.js');\n return html`\n <sp-overlay\n .triggerElement=${this as HTMLElement}\n .offset=${0}\n ?open=${this.open && this.dependenciesLoaded}\n .placement=${this.isMobile.matches ? undefined : this.placement}\n .type=${this.isMobile.matches ? 'modal' : 'auto'}\n .receivesFocus=${'true'}\n @beforetoggle=${(\n event: Event & {\n target: Overlay;\n newState: 'open' | 'closed';\n }\n ) => {\n if (event.composedPath()[0] !== event.target) {\n return;\n }\n if (event.newState === 'closed') {\n this.open = false;\n }\n if (!this.open) {\n this.optionsMenu.updateSelectedItemIndex();\n this.optionsMenu.closeDescendentOverlays();\n }\n }}\n >\n ${container}\n </sp-overlay>\n `;\n }\n\n protected get renderDescriptionSlot(): TemplateResult {\n return html`\n <div id=${DESCRIPTION_ID}>\n <slot name=\"description\"></slot>\n </div>\n `;\n }\n // a helper to throw focus to the button is needed because Safari\n // won't include buttons in the tab order even with tabindex=\"0\"\n protected override render(): TemplateResult {\n if (this.tooltipEl) {\n this.tooltipEl.disabled = this.open;\n }\n return html`\n <span\n id=\"focus-helper\"\n tabindex=\"${this.focused || this.open ? '-1' : '0'}\"\n @focus=${this.handleHelperFocus}\n aria-describedby=${DESCRIPTION_ID}\n ></span>\n <button\n aria-controls=${ifDefined(this.open ? 'menu' : undefined)}\n aria-describedby=\"tooltip\"\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-haspopup=\"true\"\n aria-labelledby=\"icon label applied-label\"\n id=\"button\"\n class=\"button\"\n @blur=${this.handleButtonBlur}\n @pointerdown=${this.handleButtonPointerdown}\n @focus=${this.handleButtonFocus}\n @click=${this.handleButtonClick}\n @keydown=${{\n handleEvent: this.handleEnterKeydown,\n capture: true,\n }}\n ?disabled=${this.disabled}\n tabindex=\"-1\"\n >\n ${this.buttonContent}\n </button>\n ${this.renderMenu} ${this.renderDescriptionSlot}\n `;\n }\n\n protected override update(changes: PropertyValues<this>): void {\n if (this.selects) {\n // Always force `selects` to \"single\" when set.\n // TODO: Add support functionally and visually for \"multiple\"\n this.selects = 'single';\n }\n if (changes.has('disabled') && this.disabled) {\n this.open = false;\n }\n if (changes.has('value')) {\n // MenuItems update a frame late for <slot> management,\n // await the same here.\n this.shouldScheduleManageSelection();\n }\n // Maybe it's finally time to remove this support?\n if (!this.hasUpdated) {\n this.deprecatedMenu = this.querySelector(':scope > sp-menu');\n this.deprecatedMenu?.toggleAttribute('ignore', true);\n this.deprecatedMenu?.setAttribute('selects', 'inherit');\n }\n if (window.__swc.DEBUG) {\n if (!this.hasUpdated && this.querySelector(':scope > sp-menu')) {\n const { localName } = this;\n window.__swc.warn(\n this,\n `You no longer need to provide an <sp-menu> child to ${localName}. Any styling or attributes on the <sp-menu> will be ignored.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/picker/#sizes',\n { level: 'deprecation' }\n );\n }\n }\n super.update(changes);\n }\n\n protected bindButtonKeydownListener(): void {\n this.button.addEventListener('keydown', this.handleKeydown);\n }\n\n protected override firstUpdated(changes: PropertyValues<this>): void {\n super.firstUpdated(changes);\n this.bindButtonKeydownListener();\n }\n\n protected get dismissHelper(): TemplateResult {\n return html`\n <div class=\"visually-hidden\">\n <button\n tabindex=\"-1\"\n aria-label=\"Dismiss\"\n @click=${this.close}\n ></button>\n </div>\n `;\n }\n\n @state()\n private dependenciesLoaded = false;\n private dependenciesToLoad: Record<string, boolean> = {};\n\n private trackDependency(dependency: string, flag?: boolean): void {\n const loaded =\n !!customElements.get(dependency) ||\n this.dependenciesToLoad[dependency] ||\n !!flag;\n if (!loaded) {\n customElements.whenDefined(dependency).then(() => {\n this.trackDependency(dependency, true);\n });\n }\n this.dependenciesToLoad = {\n ...this.dependenciesToLoad,\n [dependency]: loaded,\n };\n this.dependenciesLoaded = Object.values(this.dependenciesToLoad).every(\n (loaded) => loaded\n );\n }\n\n protected renderContainer(menu: TemplateResult): TemplateResult {\n const accessibleMenu = html`\n ${this.dismissHelper} ${menu} ${this.dismissHelper}\n `;\n // @todo: test in mobile\n /* c8 ignore next 11 */\n if (this.isMobile.matches) {\n this.trackDependency('sp-tray');\n import('@spectrum-web-components/tray/sp-tray.js');\n return html`\n <sp-tray\n id=\"popover\"\n role=\"presentation\"\n style=${styleMap(this.containerStyles)}\n >\n ${accessibleMenu}\n </sp-tray>\n `;\n }\n this.trackDependency('sp-popover');\n import('@spectrum-web-components/popover/sp-popover.js');\n return html`\n <sp-popover\n id=\"popover\"\n role=\"presentation\"\n style=${styleMap(this.containerStyles)}\n placement=${this.placement}\n >\n ${accessibleMenu}\n </sp-popover>\n `;\n }\n\n protected hasRenderedOverlay = false;\n\n protected get renderMenu(): TemplateResult {\n const menu = html`\n <sp-menu\n aria-labelledby=\"applied-label\"\n @change=${this.handleChange}\n id=\"menu\"\n @keydown=${{\n handleEvent: this.handleEnterKeydown,\n capture: true,\n }}\n role=${this.listRole}\n .selects=${this.selects}\n .selected=${this.value ? [this.value] : []}\n size=${this.size}\n @sp-menu-item-added-or-updated=${this.shouldManageSelection}\n >\n <slot @slotchange=${this.shouldScheduleManageSelection}></slot>\n </sp-menu>\n `;\n this.hasRenderedOverlay =\n this.hasRenderedOverlay ||\n this.focused ||\n this.open ||\n !!this.deprecatedMenu;\n if (this.hasRenderedOverlay) {\n return this.renderOverlay(menu);\n }\n return menu;\n }\n\n private willManageSelection = false;\n\n protected shouldScheduleManageSelection(event?: Event): void {\n if (\n !this.willManageSelection &&\n (!event ||\n ((event.target as HTMLElement).getRootNode() as ShadowRoot)\n .host === this)\n ) {\n this.willManageSelection = true;\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.manageSelection();\n });\n });\n }\n }\n\n protected shouldManageSelection(): void {\n if (this.willManageSelection) {\n return;\n }\n this.willManageSelection = true;\n this.manageSelection();\n }\n\n protected async manageSelection(): Promise<void> {\n if (this.selects == null) return;\n\n this.selectionPromise = new Promise(\n (res) => (this.selectionResolver = res)\n );\n let selectedItem: MenuItem | undefined;\n await this.optionsMenu.updateComplete;\n if (this.recentlyConnected) {\n // Work around for attach timing differences in Safari and Firefox.\n // Remove when refactoring to Menu passthrough wrapper.\n await new Promise((res) => requestAnimationFrame(() => res(true)));\n this.recentlyConnected = false;\n }\n this.menuItems.forEach((item) => {\n if (this.value === item.value && !item.disabled) {\n selectedItem = item;\n } else {\n item.selected = false;\n }\n });\n if (selectedItem) {\n selectedItem.selected = !!this.selects;\n this.selectedItem = selectedItem;\n } else {\n this.value = '';\n this.selectedItem = undefined;\n }\n if (this.open) {\n await this.optionsMenu.updateComplete;\n this.optionsMenu.updateSelectedItemIndex();\n }\n this.selectionResolver();\n this.willManageSelection = false;\n }\n\n private selectionPromise = Promise.resolve();\n private selectionResolver!: () => void;\n\n protected override async getUpdateComplete(): Promise<boolean> {\n const complete = (await super.getUpdateComplete()) as boolean;\n await this.selectionPromise;\n if (this.overlayElement) {\n await this.overlayElement.updateComplete;\n }\n return complete;\n }\n\n private recentlyConnected = false;\n\n private enterKeydownOn: EventTarget | null = null;\n\n protected handleEnterKeydown = (event: KeyboardEvent): void => {\n if (event.code !== 'Enter') {\n return;\n }\n\n if (this.enterKeydownOn) {\n event.preventDefault();\n return;\n } else {\n this.addEventListener(\n 'keyup',\n (keyupEvent: KeyboardEvent) => {\n if (keyupEvent.code !== 'Enter') {\n return;\n }\n this.enterKeydownOn = null;\n },\n { once: true }\n );\n }\n this.enterKeydownOn = this.enterKeydownOn || event.target;\n };\n\n public override connectedCallback(): void {\n super.connectedCallback();\n this.recentlyConnected = this.hasUpdated;\n }\n\n public override disconnectedCallback(): void {\n this.close();\n\n super.disconnectedCallback();\n }\n}\n\n/**\n * @element sp-picker\n *\n * @slot label - The placeholder content for the Picker\n * @slot description - The description content for the Picker\n * @slot tooltip - Tooltip to to be applied to the the Picker Button\n * @slot - menu items to be listed in the Picker\n * @fires change - Announces that the `value` of the element has changed\n * @fires sp-opened - Announces that the overlay has been opened\n * @fires sp-closed - Announces that the overlay has been closed\n */\nexport class Picker extends PickerBase {\n public static override get styles(): CSSResultArray {\n return [pickerStyles, chevronStyles];\n }\n\n protected override get containerStyles(): StyleInfo {\n const styles = super.containerStyles;\n if (!this.quiet) {\n styles['min-width'] = `${this.offsetWidth}px`;\n }\n return styles;\n }\n\n protected override handleKeydown = (event: KeyboardEvent): void => {\n const { code } = event;\n this.focused = true;\n if (!code.startsWith('Arrow') || this.readonly) {\n return;\n }\n if (code === 'ArrowUp' || code === 'ArrowDown') {\n this.toggle(true);\n return;\n }\n event.preventDefault();\n const selectedIndex = this.selectedItem\n ? this.menuItems.indexOf(this.selectedItem)\n : -1;\n // use a positive offset to find the first non-disabled item when no selection is available.\n const nextOffset = selectedIndex < 0 || code === 'ArrowRight' ? 1 : -1;\n let nextIndex = selectedIndex + nextOffset;\n while (\n this.menuItems[nextIndex] &&\n this.menuItems[nextIndex].disabled\n ) {\n nextIndex += nextOffset;\n }\n if (!this.menuItems[nextIndex] || this.menuItems[nextIndex].disabled) {\n return;\n }\n if (!this.value || nextIndex !== selectedIndex) {\n this.setValueFromItem(this.menuItems[nextIndex]);\n }\n };\n}\n"],
|
|
5
|
-
"mappings": "qNAYA,OAGI,QAAAA,EACA,WAAAC,EAEA,cAAAC,MAEG,gCACP,OACI,YAAAC,EACA,aAAAC,EAEA,YAAAC,MACG,kDACP,OACI,YAAAC,EACA,SAAAC,EACA,SAAAC,MACG,kDAEP,OAAOC,MAAkB,kBACzB,OAAOC,MAAmB,iEAE1B,OAAS,aAAAC,MAAiB,mDAE1B,MAAO,gEACP,MAAO,iEACP,MAAO,2CAOP,OACI,aAAAC,EACA,wBAAAC,MACG,kEAGP,MAAMC,EAAe,CACjB,EAAG,gCACH,EAAG,iCACH,EAAG,iCACH,GAAI,gCACR,EAEO,aAAM,eAAiB,gBACvB,aAAM,mBAAmBZ,EAAWS,EAAW,CAAE,cAAe,EAAK,CAAC,CAAE,CAAxE,kCACH,KAAU,SAAW,IAAIE,EAAqB,KAAMD,CAAS,EAQ7D,KAAQ,eAA8B,KAGtC,KAAgB,SAAW,GAG3B,KAAO,QAAU,GAMjB,KAAO,QAAU,GAMjB,KAAO,KAAO,GAGd,KAAO,SAAW,GAElB,KAAO,QAAgC,SAoBvC,KAAO,UAAuB,eAG9B,KAAO,MAAQ,GAGf,KAAO,MAAQ,GAoBf,KAAU,SAA+B,UACzC,KAAU,SAAW,
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2020 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport {\n CSSResultArray,\n DefaultElementSize,\n html,\n nothing,\n PropertyValues,\n SizedMixin,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n classMap,\n ifDefined,\n StyleInfo,\n styleMap,\n} from '@spectrum-web-components/base/src/directives.js';\nimport {\n property,\n query,\n state,\n} from '@spectrum-web-components/base/src/decorators.js';\n\nimport pickerStyles from './picker.css.js';\nimport chevronStyles from '@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js';\n\nimport { Focusable } from '@spectrum-web-components/shared/src/focusable.js';\nimport type { Tooltip } from '@spectrum-web-components/tooltip';\nimport '@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js';\nimport '@spectrum-web-components/icons-workflow/icons/sp-icon-alert.js';\nimport '@spectrum-web-components/menu/sp-menu.js';\nimport type {\n Menu,\n MenuItem,\n MenuItemChildren,\n} from '@spectrum-web-components/menu';\nimport { Placement } from '@spectrum-web-components/overlay';\nimport {\n IS_MOBILE,\n MatchMediaController,\n} from '@spectrum-web-components/reactive-controllers/src/MatchMedia.js';\nimport type { Overlay } from '@spectrum-web-components/overlay/src/Overlay.js';\n\nconst chevronClass = {\n s: 'spectrum-UIIcon-ChevronDown75',\n m: 'spectrum-UIIcon-ChevronDown100',\n l: 'spectrum-UIIcon-ChevronDown200',\n xl: 'spectrum-UIIcon-ChevronDown300',\n};\n\nexport const DESCRIPTION_ID = 'option-picker';\nexport class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {\n protected isMobile = new MatchMediaController(this, IS_MOBILE);\n\n @state()\n appliedLabel?: string;\n\n @query('#button')\n public button!: HTMLButtonElement;\n\n private deprecatedMenu: Menu | null = null;\n\n @property({ type: Boolean, reflect: true })\n public override disabled = false;\n\n @property({ type: Boolean, reflect: true })\n public focused = false;\n\n @property({ type: String, reflect: true })\n public icons?: 'only' | 'none';\n\n @property({ type: Boolean, reflect: true })\n public invalid = false;\n\n @property()\n public label?: string;\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n @property({ type: Boolean, reflect: true })\n public readonly = false;\n\n public selects: undefined | 'single' = 'single';\n\n protected get menuItems(): MenuItem[] {\n return this.optionsMenu.childItems;\n }\n\n @query('sp-menu')\n protected optionsMenu!: Menu;\n\n @query('sp-overlay')\n protected overlayElement!: Overlay;\n\n protected tooltipEl?: Tooltip;\n\n /**\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n * @attr\n */\n\n @property()\n public placement: Placement = 'bottom-start';\n\n @property({ type: Boolean, reflect: true })\n public quiet = false;\n\n @property({ type: String })\n public value = '';\n\n @property({ attribute: false })\n public get selectedItem(): MenuItem | undefined {\n return this._selectedItem;\n }\n\n public set selectedItem(selectedItem: MenuItem | undefined) {\n this.selectedItemContent = selectedItem\n ? selectedItem.itemChildren\n : undefined;\n\n if (selectedItem === this.selectedItem) return;\n const oldSelectedItem = this.selectedItem;\n this._selectedItem = selectedItem;\n this.requestUpdate('selectedItem', oldSelectedItem);\n }\n\n _selectedItem?: MenuItem;\n\n protected listRole: 'listbox' | 'menu' = 'listbox';\n protected itemRole = 'option';\n\n public override get focusElement(): HTMLElement {\n if (this.open) {\n return this.optionsMenu;\n }\n return this.button;\n }\n\n public forceFocusVisible(): void {\n this.focused = true;\n }\n\n public override click(): void {\n if (this.disabled) {\n return;\n }\n\n this.toggle();\n }\n\n public handleButtonBlur(): void {\n this.focused = false;\n }\n\n protected preventNextToggle: 'no' | 'maybe' | 'yes' = 'no';\n private pointerdownState = false;\n\n protected handleButtonPointerdown(event: PointerEvent): void {\n if (event.button !== 0) {\n return;\n }\n this.pointerdownState = this.open;\n this.preventNextToggle = 'maybe';\n const cleanup = (): void => {\n document.removeEventListener('pointerup', cleanup);\n document.removeEventListener('pointercancel', cleanup);\n requestAnimationFrame(() => {\n // Complete cleanup on the animation frame so that `click` can go first.\n this.preventNextToggle = 'no';\n });\n };\n // Ensure that however the pointer goes up we do `cleanup()`.\n document.addEventListener('pointerup', cleanup);\n document.addEventListener('pointercancel', cleanup);\n this.handleActivate();\n }\n\n protected handleButtonFocus(event: FocusEvent): void {\n // When focus comes from a pointer event, and the related target is the Menu,\n // we don't want to reopen the Menu.\n if (\n this.preventNextToggle === 'maybe' &&\n event.relatedTarget === this.optionsMenu\n ) {\n this.preventNextToggle = 'yes';\n }\n }\n\n protected handleActivate(event?: Event): void {\n if (this.enterKeydownOn && this.enterKeydownOn !== this.button) {\n return;\n }\n if (this.preventNextToggle === 'yes') {\n return;\n }\n if (event?.type === 'click' && this.open !== this.pointerdownState) {\n // When activation comes from a `click` event ensure that the `pointerup`\n // event didn't already toggle the Picker state before doing so.\n return;\n }\n this.toggle();\n }\n\n public override focus(options?: FocusOptions): void {\n super.focus(options);\n\n if (!this.disabled && this.focusElement) {\n this.focused = this.hasVisibleFocusInTree();\n }\n }\n\n public handleHelperFocus(): void {\n // set focused to true here instead of handleButtonFocus so clicks don't flash a focus outline\n this.focused = true;\n this.button.focus();\n }\n\n public handleChange(event: Event): void {\n const target = event.target as Menu;\n const [selected] = target.selectedItems;\n event.stopPropagation();\n if (event.cancelable) {\n this.setValueFromItem(selected, event);\n } else {\n // Non-cancelable \"change\" events announce a selection with no value\n // change that should close the Picker element.\n this.open = false;\n }\n }\n\n protected handleKeydown = (event: KeyboardEvent): void => {\n this.focused = true;\n if (event.code !== 'ArrowDown' && event.code !== 'ArrowUp') {\n return;\n }\n event.stopPropagation();\n event.preventDefault();\n this.toggle(true);\n };\n\n protected async setValueFromItem(\n item: MenuItem,\n menuChangeEvent?: Event\n ): Promise<void> {\n // should always close when \"setting\" a value.\n this.open = false;\n const oldSelectedItem = this.selectedItem;\n const oldValue = this.value;\n\n // Set a value.\n this.selectedItem = item;\n this.value = item.value;\n await this.updateComplete;\n const applyDefault = this.dispatchEvent(\n new Event('change', {\n bubbles: true,\n // Allow it to be prevented.\n cancelable: true,\n composed: true,\n })\n );\n if (!applyDefault && this.selects) {\n if (menuChangeEvent) {\n menuChangeEvent.preventDefault();\n }\n this.setMenuItemSelected(this.selectedItem as MenuItem, false);\n if (oldSelectedItem) {\n this.setMenuItemSelected(oldSelectedItem, true);\n }\n this.selectedItem = oldSelectedItem;\n this.value = oldValue;\n this.open = true;\n return;\n } else if (!this.selects) {\n // Unset the value if not carrying a selection\n this.selectedItem = oldSelectedItem;\n this.value = oldValue;\n return;\n }\n if (oldSelectedItem) {\n this.setMenuItemSelected(oldSelectedItem, false);\n }\n this.setMenuItemSelected(item, !!this.selects);\n }\n\n protected setMenuItemSelected(item: MenuItem, value: boolean): void {\n // matches null | undefined\n if (this.selects == null) return;\n item.selected = value;\n }\n\n public toggle(target?: boolean): void {\n if (this.readonly) {\n return;\n }\n this.open = typeof target !== 'undefined' ? target : !this.open;\n }\n\n public close(): void {\n if (this.readonly) {\n return;\n }\n this.open = false;\n }\n\n protected get containerStyles(): StyleInfo {\n // @todo: test in mobile\n /* c8 ignore next 5 */\n if (this.isMobile.matches) {\n return {\n '--swc-menu-width': '100%',\n };\n }\n return {};\n }\n\n @property({ attribute: false })\n protected get selectedItemContent(): MenuItemChildren {\n return this._selectedItemContent || { icon: [], content: [] };\n }\n\n protected set selectedItemContent(\n selectedItemContent: MenuItemChildren | undefined\n ) {\n if (selectedItemContent === this.selectedItemContent) return;\n\n const oldContent = this.selectedItemContent;\n this._selectedItemContent = selectedItemContent;\n this.requestUpdate('selectedItemContent', oldContent);\n }\n\n _selectedItemContent?: MenuItemChildren;\n\n protected handleTooltipSlotchange(\n event: Event & { target: HTMLSlotElement }\n ): void {\n this.tooltipEl = event.target.assignedElements()[0] as\n | Tooltip\n | undefined;\n }\n\n protected renderLabelContent(content: Node[]): TemplateResult | Node[] {\n if (this.value && this.selectedItem) {\n return content;\n }\n return html`\n <slot name=\"label\" id=\"label\">\n <span\n aria-hidden=${ifDefined(\n this.appliedLabel ? undefined : 'true'\n )}\n >\n ${this.label}\n </span>\n </slot>\n `;\n }\n\n protected get buttonContent(): TemplateResult[] {\n const labelClasses = {\n 'visually-hidden': this.icons === 'only' && !!this.value,\n placeholder: !this.value,\n label: true,\n };\n const appliedLabel = this.appliedLabel || this.label;\n return [\n html`\n <span id=\"icon\" ?hidden=${this.icons === 'none'}>\n ${this.selectedItemContent.icon}\n </span>\n <span\n id=${ifDefined(\n this.value && this.selectedItem ? 'label' : undefined\n )}\n class=${classMap(labelClasses)}\n >\n ${this.renderLabelContent(this.selectedItemContent.content)}\n </span>\n ${this.value && this.selectedItem\n ? html`\n <span\n aria-hidden=\"true\"\n class=\"visually-hidden\"\n id=\"applied-label\"\n >\n ${appliedLabel}\n <slot name=\"label\"></slot>\n </span>\n `\n : html`\n <span hidden id=\"applied-label\">${appliedLabel}</span>\n `}\n ${this.invalid\n ? html`\n <sp-icon-alert\n class=\"validation-icon\"\n ></sp-icon-alert>\n `\n : nothing}\n <sp-icon-chevron100\n class=\"picker ${chevronClass[\n this.size as DefaultElementSize\n ]}\"\n ></sp-icon-chevron100>\n <slot\n aria-hidden=\"true\"\n name=\"tooltip\"\n id=\"tooltip\"\n @slotchange=${this.handleTooltipSlotchange}\n ></slot>\n `,\n ];\n }\n\n applyFocusElementLabel = (value?: string): void => {\n this.appliedLabel = value;\n };\n\n protected renderOverlay(menu: TemplateResult): TemplateResult {\n const container = this.renderContainer(menu);\n this.trackDependency('sp-overlay');\n import('@spectrum-web-components/overlay/sp-overlay.js');\n return html`\n <sp-overlay\n .triggerElement=${this as HTMLElement}\n .offset=${0}\n ?open=${this.open && this.dependenciesLoaded}\n .placement=${this.isMobile.matches ? undefined : this.placement}\n .type=${this.isMobile.matches ? 'modal' : 'auto'}\n .receivesFocus=${'true'}\n .willPreventClose=${this.preventNextToggle !== 'no' &&\n this.open &&\n this.dependenciesLoaded}\n @beforetoggle=${(\n event: Event & {\n target: Overlay;\n newState: 'open' | 'closed';\n }\n ) => {\n if (event.composedPath()[0] !== event.target) {\n return;\n }\n if (event.newState === 'closed') {\n this.open = false;\n }\n if (!this.open) {\n this.optionsMenu.updateSelectedItemIndex();\n this.optionsMenu.closeDescendentOverlays();\n }\n }}\n >\n ${container}\n </sp-overlay>\n `;\n }\n\n protected get renderDescriptionSlot(): TemplateResult {\n return html`\n <div id=${DESCRIPTION_ID}>\n <slot name=\"description\"></slot>\n </div>\n `;\n }\n // a helper to throw focus to the button is needed because Safari\n // won't include buttons in the tab order even with tabindex=\"0\"\n protected override render(): TemplateResult {\n if (this.tooltipEl) {\n this.tooltipEl.disabled = this.open;\n }\n return html`\n <span\n id=\"focus-helper\"\n tabindex=\"${this.focused || this.open ? '-1' : '0'}\"\n @focus=${this.handleHelperFocus}\n aria-describedby=${DESCRIPTION_ID}\n ></span>\n <button\n aria-controls=${ifDefined(this.open ? 'menu' : undefined)}\n aria-describedby=\"tooltip\"\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-haspopup=\"true\"\n aria-labelledby=\"icon label applied-label\"\n id=\"button\"\n class=\"button\"\n @blur=${this.handleButtonBlur}\n @click=${this.handleActivate}\n @pointerdown=${this.handleButtonPointerdown}\n @focus=${this.handleButtonFocus}\n @keydown=${{\n handleEvent: this.handleEnterKeydown,\n capture: true,\n }}\n ?disabled=${this.disabled}\n tabindex=\"-1\"\n >\n ${this.buttonContent}\n </button>\n ${this.renderMenu} ${this.renderDescriptionSlot}\n `;\n }\n\n protected override update(changes: PropertyValues<this>): void {\n if (this.selects) {\n // Always force `selects` to \"single\" when set.\n // TODO: Add support functionally and visually for \"multiple\"\n this.selects = 'single';\n }\n if (changes.has('disabled') && this.disabled) {\n this.open = false;\n }\n if (changes.has('value')) {\n // MenuItems update a frame late for <slot> management,\n // await the same here.\n this.shouldScheduleManageSelection();\n }\n // Maybe it's finally time to remove this support?\n if (!this.hasUpdated) {\n this.deprecatedMenu = this.querySelector(':scope > sp-menu');\n this.deprecatedMenu?.toggleAttribute('ignore', true);\n this.deprecatedMenu?.setAttribute('selects', 'inherit');\n }\n if (window.__swc.DEBUG) {\n if (\n !this.label &&\n !this.getAttribute('aria-label') &&\n !this.getAttribute('aria-labelledby') &&\n !this.appliedLabel\n ) {\n window.__swc.warn(\n this,\n '<sp-picker> needs one of the following to be accessible:',\n 'https://opensource.adobe.com/spectrum-web-components/components/picker/#accessibility',\n {\n type: 'accessibility',\n issues: [\n 'an <sp-field-label> element with a `for` attribute referencing the `id` of the `<sp-picker>`, or',\n 'value supplied to the \"label\" attribute, which will be displayed visually as placeholder text, or',\n 'text content supplied in a <span> with slot=\"label\", which will also be displayed visually as placeholder text.',\n ],\n }\n );\n }\n if (!this.hasUpdated && this.querySelector(':scope > sp-menu')) {\n const { localName } = this;\n window.__swc.warn(\n this,\n `You no longer need to provide an <sp-menu> child to ${localName}. Any styling or attributes on the <sp-menu> will be ignored.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/picker/#sizes',\n { level: 'deprecation' }\n );\n }\n }\n super.update(changes);\n }\n\n protected bindButtonKeydownListener(): void {\n this.button.addEventListener('keydown', this.handleKeydown);\n }\n\n protected override firstUpdated(changes: PropertyValues<this>): void {\n super.firstUpdated(changes);\n this.bindButtonKeydownListener();\n }\n\n protected get dismissHelper(): TemplateResult {\n return html`\n <div class=\"visually-hidden\">\n <button\n tabindex=\"-1\"\n aria-label=\"Dismiss\"\n @click=${this.close}\n ></button>\n </div>\n `;\n }\n\n @state()\n private dependenciesLoaded = false;\n private dependenciesToLoad: Record<string, boolean> = {};\n\n private trackDependency(dependency: string, flag?: boolean): void {\n const loaded =\n !!customElements.get(dependency) ||\n this.dependenciesToLoad[dependency] ||\n !!flag;\n if (!loaded) {\n customElements.whenDefined(dependency).then(() => {\n this.trackDependency(dependency, true);\n });\n }\n this.dependenciesToLoad = {\n ...this.dependenciesToLoad,\n [dependency]: loaded,\n };\n this.dependenciesLoaded = Object.values(this.dependenciesToLoad).every(\n (loaded) => loaded\n );\n }\n\n protected renderContainer(menu: TemplateResult): TemplateResult {\n const accessibleMenu = html`\n ${this.dismissHelper} ${menu} ${this.dismissHelper}\n `;\n // @todo: test in mobile\n /* c8 ignore next 11 */\n if (this.isMobile.matches) {\n this.trackDependency('sp-tray');\n import('@spectrum-web-components/tray/sp-tray.js');\n return html`\n <sp-tray\n id=\"popover\"\n role=\"presentation\"\n style=${styleMap(this.containerStyles)}\n >\n ${accessibleMenu}\n </sp-tray>\n `;\n }\n this.trackDependency('sp-popover');\n import('@spectrum-web-components/popover/sp-popover.js');\n return html`\n <sp-popover\n id=\"popover\"\n role=\"presentation\"\n style=${styleMap(this.containerStyles)}\n placement=${this.placement}\n >\n ${accessibleMenu}\n </sp-popover>\n `;\n }\n\n protected hasRenderedOverlay = false;\n\n protected get renderMenu(): TemplateResult {\n const menu = html`\n <sp-menu\n aria-labelledby=\"applied-label\"\n @change=${this.handleChange}\n id=\"menu\"\n @keydown=${{\n handleEvent: this.handleEnterKeydown,\n capture: true,\n }}\n role=${this.listRole}\n .selects=${this.selects}\n .selected=${this.value ? [this.value] : []}\n size=${this.size}\n @sp-menu-item-added-or-updated=${this.shouldManageSelection}\n >\n <slot @slotchange=${this.shouldScheduleManageSelection}></slot>\n </sp-menu>\n `;\n this.hasRenderedOverlay =\n this.hasRenderedOverlay ||\n this.focused ||\n this.open ||\n !!this.deprecatedMenu;\n if (this.hasRenderedOverlay) {\n return this.renderOverlay(menu);\n }\n return menu;\n }\n\n private willManageSelection = false;\n\n protected shouldScheduleManageSelection(event?: Event): void {\n if (\n !this.willManageSelection &&\n (!event ||\n ((event.target as HTMLElement).getRootNode() as ShadowRoot)\n .host === this)\n ) {\n this.willManageSelection = true;\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.manageSelection();\n });\n });\n }\n }\n\n protected shouldManageSelection(): void {\n if (this.willManageSelection) {\n return;\n }\n this.willManageSelection = true;\n this.manageSelection();\n }\n\n protected async manageSelection(): Promise<void> {\n if (this.selects == null) return;\n\n this.selectionPromise = new Promise(\n (res) => (this.selectionResolver = res)\n );\n let selectedItem: MenuItem | undefined;\n await this.optionsMenu.updateComplete;\n if (this.recentlyConnected) {\n // Work around for attach timing differences in Safari and Firefox.\n // Remove when refactoring to Menu passthrough wrapper.\n await new Promise((res) => requestAnimationFrame(() => res(true)));\n this.recentlyConnected = false;\n }\n this.menuItems.forEach((item) => {\n if (this.value === item.value && !item.disabled) {\n selectedItem = item;\n } else {\n item.selected = false;\n }\n });\n if (selectedItem) {\n selectedItem.selected = !!this.selects;\n this.selectedItem = selectedItem;\n } else {\n this.value = '';\n this.selectedItem = undefined;\n }\n if (this.open) {\n await this.optionsMenu.updateComplete;\n this.optionsMenu.updateSelectedItemIndex();\n }\n this.selectionResolver();\n this.willManageSelection = false;\n }\n\n private selectionPromise = Promise.resolve();\n private selectionResolver!: () => void;\n\n protected override async getUpdateComplete(): Promise<boolean> {\n const complete = (await super.getUpdateComplete()) as boolean;\n await this.selectionPromise;\n if (this.overlayElement) {\n await this.overlayElement.updateComplete;\n }\n return complete;\n }\n\n private recentlyConnected = false;\n\n private enterKeydownOn: EventTarget | null = null;\n\n protected handleEnterKeydown = (event: KeyboardEvent): void => {\n if (event.code !== 'Enter') {\n return;\n }\n\n if (this.enterKeydownOn) {\n event.preventDefault();\n return;\n }\n this.enterKeydownOn = event.target;\n this.addEventListener(\n 'keyup',\n async (keyupEvent: KeyboardEvent) => {\n if (keyupEvent.code !== 'Enter') {\n return;\n }\n this.enterKeydownOn = null;\n },\n { once: true }\n );\n };\n\n public override connectedCallback(): void {\n super.connectedCallback();\n this.recentlyConnected = this.hasUpdated;\n }\n\n public override disconnectedCallback(): void {\n this.close();\n\n super.disconnectedCallback();\n }\n}\n\n/**\n * @element sp-picker\n *\n * @slot label - The placeholder content for the Picker\n * @slot description - The description content for the Picker\n * @slot tooltip - Tooltip to to be applied to the the Picker Button\n * @slot - menu items to be listed in the Picker\n * @fires change - Announces that the `value` of the element has changed\n * @fires sp-opened - Announces that the overlay has been opened\n * @fires sp-closed - Announces that the overlay has been closed\n */\nexport class Picker extends PickerBase {\n public static override get styles(): CSSResultArray {\n return [pickerStyles, chevronStyles];\n }\n\n protected override get containerStyles(): StyleInfo {\n const styles = super.containerStyles;\n if (!this.quiet) {\n styles['min-width'] = `${this.offsetWidth}px`;\n }\n return styles;\n }\n\n protected override handleKeydown = (event: KeyboardEvent): void => {\n const { code } = event;\n this.focused = true;\n if (!code.startsWith('Arrow') || this.readonly) {\n return;\n }\n if (code === 'ArrowUp' || code === 'ArrowDown') {\n this.toggle(true);\n event.preventDefault();\n return;\n }\n event.preventDefault();\n const selectedIndex = this.selectedItem\n ? this.menuItems.indexOf(this.selectedItem)\n : -1;\n // use a positive offset to find the first non-disabled item when no selection is available.\n const nextOffset = selectedIndex < 0 || code === 'ArrowRight' ? 1 : -1;\n let nextIndex = selectedIndex + nextOffset;\n while (\n this.menuItems[nextIndex] &&\n this.menuItems[nextIndex].disabled\n ) {\n nextIndex += nextOffset;\n }\n if (!this.menuItems[nextIndex] || this.menuItems[nextIndex].disabled) {\n return;\n }\n if (!this.value || nextIndex !== selectedIndex) {\n this.setValueFromItem(this.menuItems[nextIndex]);\n }\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["html", "nothing", "SizedMixin", "classMap", "ifDefined", "styleMap", "property", "query", "state", "pickerStyles", "chevronStyles", "Focusable", "IS_MOBILE", "MatchMediaController", "chevronClass", "event", "value", "keyupEvent", "selectedItem", "oldSelectedItem", "cleanup", "options", "target", "selected", "item", "menuChangeEvent", "oldValue", "selectedItemContent", "oldContent", "content", "labelClasses", "appliedLabel", "menu", "container", "changes", "_a", "_b", "dependency", "flag", "loaded", "accessibleMenu", "res", "complete", "__decorateClass", "code", "selectedIndex", "nextOffset", "nextIndex", "styles"]
|
|
7
7
|
}
|
package/test/index.js
CHANGED
|
@@ -407,6 +407,39 @@ export function runPickerTests() {
|
|
|
407
407
|
"finally, not visually focused"
|
|
408
408
|
);
|
|
409
409
|
});
|
|
410
|
+
it("opens with visible focus on a menu item on `Space`", async function() {
|
|
411
|
+
var _a, _b;
|
|
412
|
+
const firstItem = el.querySelector("sp-menu-item");
|
|
413
|
+
await elementUpdated(el);
|
|
414
|
+
expect(firstItem.focused, "should not visually focused").to.be.false;
|
|
415
|
+
el.focus();
|
|
416
|
+
await elementUpdated(el);
|
|
417
|
+
const opened = oneEvent(el, "sp-opened");
|
|
418
|
+
await sendKeys({ press: "ArrowRight" });
|
|
419
|
+
await sendKeys({ press: "ArrowLeft" });
|
|
420
|
+
await sendKeys({ press: "Space" });
|
|
421
|
+
await opened;
|
|
422
|
+
expect(el.open).to.be.true;
|
|
423
|
+
expect(firstItem.focused, "should be visually focused").to.be.true;
|
|
424
|
+
const closed = oneEvent(el, "sp-closed");
|
|
425
|
+
await sendKeys({
|
|
426
|
+
press: "Escape"
|
|
427
|
+
});
|
|
428
|
+
await closed;
|
|
429
|
+
expect(el.open).to.be.false;
|
|
430
|
+
expect(
|
|
431
|
+
document.activeElement === el,
|
|
432
|
+
`focused ${(_a = document.activeElement) == null ? void 0 : _a.localName} instead of back on Picker`
|
|
433
|
+
).to.be.true;
|
|
434
|
+
expect(
|
|
435
|
+
el.shadowRoot.activeElement === el.button,
|
|
436
|
+
`focused ${(_b = el.shadowRoot.activeElement) == null ? void 0 : _b.localName} instead of back on button`
|
|
437
|
+
).to.be.true;
|
|
438
|
+
await waitUntil(
|
|
439
|
+
() => !firstItem.focused,
|
|
440
|
+
"finally, not visually focused"
|
|
441
|
+
);
|
|
442
|
+
});
|
|
410
443
|
it("opens, on click, without visible focus on a menu item", async () => {
|
|
411
444
|
await nextFrame();
|
|
412
445
|
await nextFrame();
|
|
@@ -429,6 +462,50 @@ export function runPickerTests() {
|
|
|
429
462
|
expect(el.open).to.be.true;
|
|
430
463
|
expect(firstItem.focused, "still not visually focused").to.be.false;
|
|
431
464
|
});
|
|
465
|
+
it("opens and selects in a single pointer button interaction", async () => {
|
|
466
|
+
await nextFrame();
|
|
467
|
+
await nextFrame();
|
|
468
|
+
const thirdItem = el.querySelector(
|
|
469
|
+
"sp-menu-item:nth-of-type(3)"
|
|
470
|
+
);
|
|
471
|
+
const boundingRect = el.button.getBoundingClientRect();
|
|
472
|
+
expect(el.value).to.not.equal(thirdItem.value);
|
|
473
|
+
const opened = oneEvent(el, "sp-opened");
|
|
474
|
+
await sendMouse({
|
|
475
|
+
steps: [
|
|
476
|
+
{
|
|
477
|
+
type: "move",
|
|
478
|
+
position: [
|
|
479
|
+
boundingRect.x + boundingRect.width / 2,
|
|
480
|
+
boundingRect.y + boundingRect.height / 2
|
|
481
|
+
]
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
type: "down"
|
|
485
|
+
}
|
|
486
|
+
]
|
|
487
|
+
});
|
|
488
|
+
await opened;
|
|
489
|
+
const thirdItemRect = thirdItem.getBoundingClientRect();
|
|
490
|
+
const closed = oneEvent(el, "sp-closed");
|
|
491
|
+
await sendMouse({
|
|
492
|
+
steps: [
|
|
493
|
+
{
|
|
494
|
+
type: "move",
|
|
495
|
+
position: [
|
|
496
|
+
thirdItemRect.x + thirdItemRect.width / 2,
|
|
497
|
+
thirdItemRect.y + thirdItemRect.height / 2
|
|
498
|
+
]
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
type: "up"
|
|
502
|
+
}
|
|
503
|
+
]
|
|
504
|
+
});
|
|
505
|
+
await closed;
|
|
506
|
+
expect(el.open).to.be.false;
|
|
507
|
+
expect(el.value).to.equal(thirdItem.value);
|
|
508
|
+
});
|
|
432
509
|
it("opens/closes multiple times", async () => {
|
|
433
510
|
expect(el.open).to.be.false;
|
|
434
511
|
const boundingRect = el.button.getBoundingClientRect();
|
|
@@ -520,9 +597,8 @@ export function runPickerTests() {
|
|
|
520
597
|
const secondItem = el.querySelector(
|
|
521
598
|
"sp-menu-item:nth-of-type(2)"
|
|
522
599
|
);
|
|
523
|
-
const button = el.button;
|
|
524
600
|
const opened = oneEvent(el, "sp-opened");
|
|
525
|
-
|
|
601
|
+
el.click();
|
|
526
602
|
await opened;
|
|
527
603
|
expect(el.open).to.be.true;
|
|
528
604
|
expect((_a = el.selectedItem) == null ? void 0 : _a.itemText).to.be.undefined;
|
|
@@ -542,9 +618,8 @@ export function runPickerTests() {
|
|
|
542
618
|
const secondItem = el.querySelector(
|
|
543
619
|
"sp-menu-item:nth-of-type(2)"
|
|
544
620
|
);
|
|
545
|
-
const button = el.button;
|
|
546
621
|
let opened = oneEvent(el, "sp-opened");
|
|
547
|
-
|
|
622
|
+
el.click();
|
|
548
623
|
await opened;
|
|
549
624
|
expect(el.open).to.be.true;
|
|
550
625
|
expect((_a = el.selectedItem) == null ? void 0 : _a.itemText).to.be.undefined;
|
|
@@ -556,7 +631,7 @@ export function runPickerTests() {
|
|
|
556
631
|
expect((_b = el.selectedItem) == null ? void 0 : _b.itemText).to.equal("Select Inverse");
|
|
557
632
|
expect(el.value).to.equal("option-2");
|
|
558
633
|
opened = oneEvent(el, "sp-opened");
|
|
559
|
-
|
|
634
|
+
el.click();
|
|
560
635
|
await opened;
|
|
561
636
|
expect(el.open).to.be.true;
|
|
562
637
|
expect((_c = el.selectedItem) == null ? void 0 : _c.itemText).to.equal("Select Inverse");
|
|
@@ -592,9 +667,8 @@ export function runPickerTests() {
|
|
|
592
667
|
const secondItem = el.querySelector(
|
|
593
668
|
"sp-menu-item:nth-of-type(2)"
|
|
594
669
|
);
|
|
595
|
-
const button = el.button;
|
|
596
670
|
const opened = oneEvent(el, "sp-opened");
|
|
597
|
-
|
|
671
|
+
el.click();
|
|
598
672
|
await opened;
|
|
599
673
|
expect(el.open).to.be.true;
|
|
600
674
|
expect((_a = el.selectedItem) == null ? void 0 : _a.itemText).to.be.undefined;
|
|
@@ -619,9 +693,8 @@ export function runPickerTests() {
|
|
|
619
693
|
const secondItem = el.querySelector(
|
|
620
694
|
"sp-menu-item:nth-of-type(2)"
|
|
621
695
|
);
|
|
622
|
-
const button = el.button;
|
|
623
696
|
const opened = oneEvent(el, "sp-opened");
|
|
624
|
-
|
|
697
|
+
el.click();
|
|
625
698
|
await opened;
|
|
626
699
|
await elementUpdated(el);
|
|
627
700
|
expect(el.open).to.be.true;
|
|
@@ -940,8 +1013,7 @@ export function runPickerTests() {
|
|
|
940
1013
|
it("does not open when [readonly]", async () => {
|
|
941
1014
|
el.readonly = true;
|
|
942
1015
|
await elementUpdated(el);
|
|
943
|
-
|
|
944
|
-
button.click();
|
|
1016
|
+
el.click();
|
|
945
1017
|
await elementUpdated(el);
|
|
946
1018
|
expect(el.open).to.be.false;
|
|
947
1019
|
});
|
|
@@ -1065,7 +1137,24 @@ export function runPickerTests() {
|
|
|
1065
1137
|
await expect(el).to.be.accessible();
|
|
1066
1138
|
});
|
|
1067
1139
|
});
|
|
1068
|
-
describe("
|
|
1140
|
+
describe("Dev mode", () => {
|
|
1141
|
+
let consoleWarnStub;
|
|
1142
|
+
before(() => {
|
|
1143
|
+
window.__swc.verbose = true;
|
|
1144
|
+
consoleWarnStub = stub(console, "warn");
|
|
1145
|
+
});
|
|
1146
|
+
afterEach(() => {
|
|
1147
|
+
consoleWarnStub.resetHistory();
|
|
1148
|
+
});
|
|
1149
|
+
after(async () => {
|
|
1150
|
+
window.__swc.verbose = false;
|
|
1151
|
+
consoleWarnStub.restore();
|
|
1152
|
+
if (el.open) {
|
|
1153
|
+
const closed = oneEvent(el, "sp-closed");
|
|
1154
|
+
el.open = false;
|
|
1155
|
+
await closed;
|
|
1156
|
+
}
|
|
1157
|
+
});
|
|
1069
1158
|
const pickerFixture2 = async () => {
|
|
1070
1159
|
const test = await fixture(
|
|
1071
1160
|
html`
|
|
@@ -1095,9 +1184,31 @@ export function runPickerTests() {
|
|
|
1095
1184
|
);
|
|
1096
1185
|
return test.querySelector("sp-picker");
|
|
1097
1186
|
};
|
|
1098
|
-
|
|
1187
|
+
it("warns in Dev Mode when accessible attributes are not leveraged", async () => {
|
|
1188
|
+
el = await fixture(html`
|
|
1189
|
+
<sp-picker>
|
|
1190
|
+
<sp-menu-item>Feather...</sp-menu-item>
|
|
1191
|
+
<sp-menu-item>Select and Mask...</sp-menu-item>
|
|
1192
|
+
<sp-menu-item>Save Selection</sp-menu-item>
|
|
1193
|
+
</sp-picker>
|
|
1194
|
+
`);
|
|
1195
|
+
await elementUpdated(el);
|
|
1196
|
+
expect(consoleWarnStub.called).to.be.true;
|
|
1197
|
+
const spyCall = consoleWarnStub.getCall(0);
|
|
1198
|
+
expect(
|
|
1199
|
+
spyCall.args.at(0).includes("accessible"),
|
|
1200
|
+
"confirm accessibility-centric message"
|
|
1201
|
+
).to.be.true;
|
|
1202
|
+
expect(spyCall.args.at(-1), "confirm `data` shape").to.deep.equal({
|
|
1203
|
+
data: {
|
|
1204
|
+
localName: "sp-picker",
|
|
1205
|
+
type: "accessibility",
|
|
1206
|
+
level: "default"
|
|
1207
|
+
}
|
|
1208
|
+
});
|
|
1209
|
+
});
|
|
1210
|
+
describe("deprecated", () => {
|
|
1099
1211
|
it("warns in Dev Mode of deprecated `<sp-menu>` usage", async () => {
|
|
1100
|
-
const consoleWarnStub = stub(console, "warn");
|
|
1101
1212
|
el = await pickerFixture2();
|
|
1102
1213
|
await elementUpdated(el);
|
|
1103
1214
|
expect(consoleWarnStub.called).to.be.true;
|
|
@@ -1116,12 +1227,6 @@ export function runPickerTests() {
|
|
|
1116
1227
|
level: "deprecation"
|
|
1117
1228
|
}
|
|
1118
1229
|
});
|
|
1119
|
-
consoleWarnStub.restore();
|
|
1120
|
-
if (el.open) {
|
|
1121
|
-
const closed = oneEvent(el, "sp-closed");
|
|
1122
|
-
el.open = false;
|
|
1123
|
-
await closed;
|
|
1124
|
-
}
|
|
1125
1230
|
});
|
|
1126
1231
|
});
|
|
1127
1232
|
describe("Dev mode ignored", () => {
|
|
@@ -1152,7 +1257,7 @@ export function runPickerTests() {
|
|
|
1152
1257
|
"sp-menu-item:nth-of-type(2)"
|
|
1153
1258
|
);
|
|
1154
1259
|
const opened = oneEvent(el, "sp-opened");
|
|
1155
|
-
el.
|
|
1260
|
+
el.click();
|
|
1156
1261
|
await opened;
|
|
1157
1262
|
expect(el.open).to.be.true;
|
|
1158
1263
|
expect((_a = el.selectedItem) == null ? void 0 : _a.itemText).to.be.undefined;
|