@paperbits/common
Version:
Paperbits common components.
76 lines (61 loc) • 2.84 kB
text/typescript
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { Keys, MouseButtons } from "@paperbits/common";
import { Events } from "@paperbits/common/events";
import { BehaviorHandle } from "./behavior";
export class CollapseBehavior {
public static attach(triggerElement: HTMLElement, targetSelector: string, expanded: boolean = true): BehaviorHandle {
const targetElement = document.querySelector(targetSelector);
if (!targetElement) {
console.warn(`No element found for selector ${targetSelector}.`);
return { detach: () => {} };
}
let isExpanded = expanded;
if (!triggerElement.hasAttribute("aria-label")) {
triggerElement.setAttribute("aria-label", "Toggle section");
}
triggerElement.setAttribute("role", "button");
triggerElement.setAttribute("aria-expanded", isExpanded.toString());
targetElement.setAttribute("role", "region");
targetElement.setAttribute("aria-hidden", (!isExpanded).toString());
if (!isExpanded) {
targetElement.classList.add("collapsed");
}
else {
targetElement.classList.remove("collapsed");
}
triggerElement.classList.toggle("collapsed", !isExpanded);
const toggle = (): void => {
isExpanded = !isExpanded;
triggerElement.setAttribute("aria-expanded", isExpanded.toString());
targetElement.setAttribute("aria-hidden", (!isExpanded).toString());
targetElement.classList.toggle("collapsed", !isExpanded);
triggerElement.classList.toggle("collapsed", !isExpanded);
};
const onPointerDown = (event: MouseEvent): void => {
if (event.button !== MouseButtons.Main) {
return;
}
toggle();
};
const onClick = (event: MouseEvent): void => {
event.preventDefault();
event.stopImmediatePropagation();
};
const onKeyDown = (event: KeyboardEvent): void => {
if (event.key === Keys.Enter || event.key === Keys.Space) {
toggle();
}
};
triggerElement.addEventListener(Events.Click, onClick);
triggerElement.addEventListener(Events.KeyDown, onKeyDown);
triggerElement.addEventListener(Events.MouseDown, onPointerDown);
return {
detach: () => {
triggerElement.removeEventListener(Events.Click, onClick);
triggerElement.removeEventListener(Events.KeyDown, onKeyDown);
triggerElement.removeEventListener(Events.MouseDown, onPointerDown);
}
};
}
}