UNPKG

4.78 kBJavaScriptView Raw
1import WUPBaseElement from "./baseElement";
2import WUPPopupElement from "./popup/popupElement";
3import { WUPcssButton, WUPcssMenu } from "./styles";
4const tagName = "wup-dropdown";
5/** Dropdown element
6 * @example
7 * ```html
8 <wup-dropdown class="custom">
9 <button type="button">Click Me</button>
10 <wup-popup placement="bottom-middle" animation="stack">
11 <ul>
12 <li><button type="button">A</button></li>
13 <li><button type="button">B</button></li>
14 <li><button type="button">C</button></li>
15 </ul>
16 </wup-popup>
17 </wup-dropdown>
18 * ```
19 * @tutorial Troubleshooting
20 * * in comparison with Combobox Dropdown doesn't contain input but can contain in popup any items (like nav-menu etc.) */
21export default class WUPDropdownElement extends WUPBaseElement {
22 #ctr = this.constructor;
23 static get $style() {
24 return `${super.$style}
25 :host {
26 contain: style;
27 display: inline-block;
28 }${WUPcssButton(":host button")}
29 :host button {
30 min-width: initial;
31 margin: 0;
32 padding: 0.7em;
33 }${WUPcssMenu(":host>[menu]")}`;
34 }
35 /** Default options applied to every element. Change it to configure default behavior
36 * * @tutorial Troubleshooting
37 * * Popup-related options are not observed so to change it use `WUPDropdownElement.$defaults` or `element.$refPopup.$options` direclty */
38 static $defaults = {
39 ...WUPPopupElement.$defaults,
40 animation: 1 /* Animations.drawer */,
41 showCase: 4 /* ShowCases.onClick */ | 2 /* ShowCases.onFocus */,
42 hideOnPopupClick: true,
43 minHeightByTarget: true,
44 minWidthByTarget: true,
45 placement: [
46 WUPPopupElement.$placements.$bottom.$start,
47 WUPPopupElement.$placements.$bottom.$end,
48 WUPPopupElement.$placements.$top.$start,
49 WUPPopupElement.$placements.$top.$end,
50 WUPPopupElement.$placements.$bottom.$start.$resizeHeight,
51 WUPPopupElement.$placements.$bottom.$end.$resizeHeight,
52 WUPPopupElement.$placements.$top.$start.$resizeHeight,
53 WUPPopupElement.$placements.$top.$end.$resizeHeight,
54 ],
55 };
56 /** Reference to nested HTMLElement tied with $options.label */
57 $refTitle = this.firstElementChild;
58 /** Reference to popupMenu */
59 $refPopup = this.lastElementChild;
60 /** Reference to list */
61 $refMenu = this.lastElementChild;
62 gotReady() {
63 this.$refTitle = this.firstElementChild;
64 this.$refPopup = this.lastElementChild;
65 if (this.$refTitle === this.$refPopup || !this.$refPopup.$show) {
66 this.throwError("Invalid structure. Expected 1st element: <any/>, last element: <wup-popup/>");
67 }
68 else {
69 this.$refPopup.setAttribute("menu", "");
70 this.$refPopup.goShow = this.goShowPopup.bind(this);
71 this.$refPopup.goHide = this.goHidePopup.bind(this);
72 Object.assign(this.$refPopup.$options, this.$options);
73 // WA
74 const menu = this.$refPopup.querySelector("ul,ol,[items]") || this.$refPopup;
75 menu.id = menu.id || this.#ctr.$uniqueId;
76 this.$refMenu = menu;
77 const lbl = this.$refTitle;
78 lbl.setAttribute("aria-owns", menu.id);
79 lbl.setAttribute("aria-controls", menu.id);
80 lbl.setAttribute("aria-haspopup", "listbox");
81 lbl.setAttribute("aria-expanded", false);
82 // !menu.hasAttribute("role") && menu.setAttribute("role", "listbox");
83 // li.setAttribute("role", "option");
84 !menu.hasAttribute("tabindex") && menu.setAttribute("tabindex", -1); // otherwise Firefox move focus into it by keydown 'Tab'
85 // lbl.id = lbl.id || this.#ctr.$uniqueId;
86 // menu.setAttribute("aria-labelledby", lbl.id);
87 }
88 super.gotReady();
89 }
90 /** Custom function to override default `WUPPopupElement.prototype.goHide` */
91 goShowPopup(showCase, ev) {
92 const p = WUPPopupElement.prototype.goShow.call(this.$refPopup, showCase, ev);
93 this.$refPopup.$options.target.setAttribute("aria-expanded", true);
94 return p;
95 }
96 /** Custom function to override default `WUPPopupElement.prototype.goHide` */
97 goHidePopup(hideCase, ev) {
98 if (hideCase === 4 /* HideCases.onPopupClick */ && !this._opts.hideOnPopupClick) {
99 return false;
100 }
101 const p = WUPPopupElement.prototype.goHide.call(this.$refPopup, hideCase, ev);
102 this.$refPopup.$options.target.setAttribute("aria-expanded", false);
103 return p;
104 }
105}
106customElements.define(tagName, WUPDropdownElement);