Archived
Template
1
Fork 0
This repository has been archived on 2024-09-04. You can view files and clone it, but cannot push or open issues or pull requests.
Contour/public/@shoelace-style/shoelace/cdn/chunks/chunk.7VJ6N7Y5.js
2024-01-30 10:59:28 -05:00

367 lines
11 KiB
JavaScript

import {
dropdown_styles_default
} from "./chunk.DY6ZNNWZ.js";
import {
getTabbableBoundary
} from "./chunk.LXDTFLWU.js";
import {
SlPopup
} from "./chunk.SJLA5ROP.js";
import {
getAnimation,
setDefaultAnimation
} from "./chunk.RCZVQXWP.js";
import {
waitForEvent
} from "./chunk.B4BZKR24.js";
import {
animateTo,
stopAnimations
} from "./chunk.S7GYYU7Z.js";
import {
LocalizeController
} from "./chunk.NH3SRVOC.js";
import {
e
} from "./chunk.UZVKBFXH.js";
import {
watch
} from "./chunk.FA5RT4K4.js";
import {
ShoelaceElement,
e as e2,
n
} from "./chunk.SEXBCYCU.js";
import {
x
} from "./chunk.CXZZ2LVK.js";
import {
__decorateClass
} from "./chunk.KIILAQWQ.js";
// src/components/dropdown/dropdown.component.ts
var SlDropdown = class extends ShoelaceElement {
constructor() {
super(...arguments);
this.localize = new LocalizeController(this);
this.open = false;
this.placement = "bottom-start";
this.disabled = false;
this.stayOpenOnSelect = false;
this.distance = 0;
this.skidding = 0;
this.hoist = false;
this.handleKeyDown = (event) => {
if (this.open && event.key === "Escape") {
event.stopPropagation();
this.hide();
this.focusOnTrigger();
}
};
this.handleDocumentKeyDown = (event) => {
var _a;
if (event.key === "Escape" && this.open && !this.closeWatcher) {
event.stopPropagation();
this.focusOnTrigger();
this.hide();
return;
}
if (event.key === "Tab") {
if (this.open && ((_a = document.activeElement) == null ? void 0 : _a.tagName.toLowerCase()) === "sl-menu-item") {
event.preventDefault();
this.hide();
this.focusOnTrigger();
return;
}
setTimeout(() => {
var _a2, _b, _c;
const activeElement = ((_a2 = this.containingElement) == null ? void 0 : _a2.getRootNode()) instanceof ShadowRoot ? (_c = (_b = document.activeElement) == null ? void 0 : _b.shadowRoot) == null ? void 0 : _c.activeElement : document.activeElement;
if (!this.containingElement || (activeElement == null ? void 0 : activeElement.closest(this.containingElement.tagName.toLowerCase())) !== this.containingElement) {
this.hide();
}
});
}
};
this.handleDocumentMouseDown = (event) => {
const path = event.composedPath();
if (this.containingElement && !path.includes(this.containingElement)) {
this.hide();
}
};
this.handlePanelSelect = (event) => {
const target = event.target;
if (!this.stayOpenOnSelect && target.tagName.toLowerCase() === "sl-menu") {
this.hide();
this.focusOnTrigger();
}
};
}
connectedCallback() {
super.connectedCallback();
if (!this.containingElement) {
this.containingElement = this;
}
}
firstUpdated() {
this.panel.hidden = !this.open;
if (this.open) {
this.addOpenListeners();
this.popup.active = true;
}
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeOpenListeners();
this.hide();
}
focusOnTrigger() {
const trigger = this.trigger.assignedElements({ flatten: true })[0];
if (typeof (trigger == null ? void 0 : trigger.focus) === "function") {
trigger.focus();
}
}
getMenu() {
return this.panel.assignedElements({ flatten: true }).find((el) => el.tagName.toLowerCase() === "sl-menu");
}
handleTriggerClick() {
if (this.open) {
this.hide();
} else {
this.show();
this.focusOnTrigger();
}
}
async handleTriggerKeyDown(event) {
if ([" ", "Enter"].includes(event.key)) {
event.preventDefault();
this.handleTriggerClick();
return;
}
const menu = this.getMenu();
if (menu) {
const menuItems = menu.getAllItems();
const firstMenuItem = menuItems[0];
const lastMenuItem = menuItems[menuItems.length - 1];
if (["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
event.preventDefault();
if (!this.open) {
this.show();
await this.updateComplete;
}
if (menuItems.length > 0) {
this.updateComplete.then(() => {
if (event.key === "ArrowDown" || event.key === "Home") {
menu.setCurrentItem(firstMenuItem);
firstMenuItem.focus();
}
if (event.key === "ArrowUp" || event.key === "End") {
menu.setCurrentItem(lastMenuItem);
lastMenuItem.focus();
}
});
}
}
}
}
handleTriggerKeyUp(event) {
if (event.key === " ") {
event.preventDefault();
}
}
handleTriggerSlotChange() {
this.updateAccessibleTrigger();
}
//
// Slotted triggers can be arbitrary content, but we need to link them to the dropdown panel with `aria-haspopup` and
// `aria-expanded`. These must be applied to the "accessible trigger" (the tabbable portion of the trigger element
// that gets slotted in) so screen readers will understand them. The accessible trigger could be the slotted element,
// a child of the slotted element, or an element in the slotted element's shadow root.
//
// For example, the accessible trigger of an <sl-button> is a <button> located inside its shadow root.
//
// To determine this, we assume the first tabbable element in the trigger slot is the "accessible trigger."
//
updateAccessibleTrigger() {
const assignedElements = this.trigger.assignedElements({ flatten: true });
const accessibleTrigger = assignedElements.find((el) => getTabbableBoundary(el).start);
let target;
if (accessibleTrigger) {
switch (accessibleTrigger.tagName.toLowerCase()) {
case "sl-button":
case "sl-icon-button":
target = accessibleTrigger.button;
break;
default:
target = accessibleTrigger;
}
target.setAttribute("aria-haspopup", "true");
target.setAttribute("aria-expanded", this.open ? "true" : "false");
}
}
/** Shows the dropdown panel. */
async show() {
if (this.open) {
return void 0;
}
this.open = true;
return waitForEvent(this, "sl-after-show");
}
/** Hides the dropdown panel */
async hide() {
if (!this.open) {
return void 0;
}
this.open = false;
return waitForEvent(this, "sl-after-hide");
}
/**
* Instructs the dropdown menu to reposition. Useful when the position or size of the trigger changes when the menu
* is activated.
*/
reposition() {
this.popup.reposition();
}
addOpenListeners() {
var _a;
this.panel.addEventListener("sl-select", this.handlePanelSelect);
if ("CloseWatcher" in window) {
(_a = this.closeWatcher) == null ? void 0 : _a.destroy();
this.closeWatcher = new CloseWatcher();
this.closeWatcher.onclose = () => {
this.hide();
this.focusOnTrigger();
};
} else {
this.panel.addEventListener("keydown", this.handleKeyDown);
}
document.addEventListener("keydown", this.handleDocumentKeyDown);
document.addEventListener("mousedown", this.handleDocumentMouseDown);
}
removeOpenListeners() {
var _a;
if (this.panel) {
this.panel.removeEventListener("sl-select", this.handlePanelSelect);
this.panel.removeEventListener("keydown", this.handleKeyDown);
}
document.removeEventListener("keydown", this.handleDocumentKeyDown);
document.removeEventListener("mousedown", this.handleDocumentMouseDown);
(_a = this.closeWatcher) == null ? void 0 : _a.destroy();
}
async handleOpenChange() {
if (this.disabled) {
this.open = false;
return;
}
this.updateAccessibleTrigger();
if (this.open) {
this.emit("sl-show");
this.addOpenListeners();
await stopAnimations(this);
this.panel.hidden = false;
this.popup.active = true;
const { keyframes, options } = getAnimation(this, "dropdown.show", { dir: this.localize.dir() });
await animateTo(this.popup.popup, keyframes, options);
this.emit("sl-after-show");
} else {
this.emit("sl-hide");
this.removeOpenListeners();
await stopAnimations(this);
const { keyframes, options } = getAnimation(this, "dropdown.hide", { dir: this.localize.dir() });
await animateTo(this.popup.popup, keyframes, options);
this.panel.hidden = true;
this.popup.active = false;
this.emit("sl-after-hide");
}
}
render() {
return x`
<sl-popup
part="base"
id="dropdown"
placement=${this.placement}
distance=${this.distance}
skidding=${this.skidding}
strategy=${this.hoist ? "fixed" : "absolute"}
flip
shift
auto-size="vertical"
auto-size-padding="10"
class=${e({
dropdown: true,
"dropdown--open": this.open
})}
>
<slot
name="trigger"
slot="anchor"
part="trigger"
class="dropdown__trigger"
@click=${this.handleTriggerClick}
@keydown=${this.handleTriggerKeyDown}
@keyup=${this.handleTriggerKeyUp}
@slotchange=${this.handleTriggerSlotChange}
></slot>
<div aria-hidden=${this.open ? "false" : "true"} aria-labelledby="dropdown">
<slot part="panel" class="dropdown__panel"></slot>
</div>
</sl-popup>
`;
}
};
SlDropdown.styles = dropdown_styles_default;
SlDropdown.dependencies = { "sl-popup": SlPopup };
__decorateClass([
e2(".dropdown")
], SlDropdown.prototype, "popup", 2);
__decorateClass([
e2(".dropdown__trigger")
], SlDropdown.prototype, "trigger", 2);
__decorateClass([
e2(".dropdown__panel")
], SlDropdown.prototype, "panel", 2);
__decorateClass([
n({ type: Boolean, reflect: true })
], SlDropdown.prototype, "open", 2);
__decorateClass([
n({ reflect: true })
], SlDropdown.prototype, "placement", 2);
__decorateClass([
n({ type: Boolean, reflect: true })
], SlDropdown.prototype, "disabled", 2);
__decorateClass([
n({ attribute: "stay-open-on-select", type: Boolean, reflect: true })
], SlDropdown.prototype, "stayOpenOnSelect", 2);
__decorateClass([
n({ attribute: false })
], SlDropdown.prototype, "containingElement", 2);
__decorateClass([
n({ type: Number })
], SlDropdown.prototype, "distance", 2);
__decorateClass([
n({ type: Number })
], SlDropdown.prototype, "skidding", 2);
__decorateClass([
n({ type: Boolean })
], SlDropdown.prototype, "hoist", 2);
__decorateClass([
watch("open", { waitUntilFirstUpdate: true })
], SlDropdown.prototype, "handleOpenChange", 1);
setDefaultAnimation("dropdown.show", {
keyframes: [
{ opacity: 0, scale: 0.9 },
{ opacity: 1, scale: 1 }
],
options: { duration: 100, easing: "ease" }
});
setDefaultAnimation("dropdown.hide", {
keyframes: [
{ opacity: 1, scale: 1 },
{ opacity: 0, scale: 0.9 }
],
options: { duration: 100, easing: "ease" }
});
export {
SlDropdown
};