@dsb.dk/designsystem
Version:
Development environment for creating components to the DSB Designsystem.
152 lines (123 loc) • 4.97 kB
JavaScript
import { h, T } from '../lit-element-a21c046d.js';
import { r as randomId } from '../id-839a82d1.js';
import { f as flip } from '../flip-60377d92.js';
var css_248z = ":host{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}aside{-webkit-transition:var(--flyout-transition);transition:var(--flyout-transition);position:fixed;left:0;top:0;width:100vw;min-height:50vh;z-index:13;background-color:var(--color-red);color:var(--color-white);-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}aside,aside[hidden]{display:-webkit-box;display:-ms-flexbox;display:flex}aside[hidden]{-webkit-transform:translateY(-100%);transform:translateY(-100%)}aside[hidden]+.backdrop{opacity:0}.backdrop{-webkit-transition:opacity .6s var(--ease-in-out-quint);transition:opacity .6s var(--ease-in-out-quint);position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.6);z-index:-1;pointer-events:none}.close-button{--icon-size:var(--units-2);position:absolute;right:0;top:0;padding:var(--icon-size)}";
const FLYOUT_WAS_TOGGLED = 'flyout-toggled';
const FLYOUT_DOM_TREE_CHANGED = 'flyout-changed';
class Flyout extends h {
static get styles() {
return [css_248z];
}
static get properties() {
return {
isOpen: { state: true },
id: { state: true },
};
}
constructor() {
super();
this.isOpen = false;
this.id = randomId();
this.activeElementBeforeOpening = null;
this.observer = null;
this.contentSize = null;
}
connectedCallback() {
super.connectedCallback();
// TODO: can't find element directly? why?
setTimeout(() => {
this.content = this.renderRoot.querySelector('aside');
this.initMutationObserver();
this.contentSize = flip.getState(this.content);
window.addEventListener('resize', this.animateSize.bind(this));
}, 10);
window.addEventListener('keydown', this.closeOnEsc.bind(this));
window.addEventListener('click', this.closeOnBodyClick.bind(this));
}
disconnectedCallback() {
super.disconnectedCallback();
window.removeEventListener('keydown', this.closeOnEsc.bind(this));
window.removeEventListener('resize', this.animateSize.bind(this));
window.removeEventListener('click', this.closeOnBodyClick.bind(this));
this.observer && this.observer.disconnect();
}
closeOnEsc(event) {
if (!this.isOpen) return;
if (event.key === 'Escape') this.toggle(false);
}
closeOnBodyClick(event) {
if (!this.isOpen) return;
if (event.clientY > this.content.getBoundingClientRect().height) {
this.toggle(false);
}
}
toggle(shouldOpen) {
this.isOpen = shouldOpen !== undefined ? shouldOpen : !this.isOpen;
if (this.isOpen && document.activeElement) {
this.activeElementBeforeOpening = document.activeElement;
}
if (!this.isOpen && this.activeElementBeforeOpening) {
this.activeElementBeforeOpening.focus();
}
this.fireCustomEvent();
}
animateSize() {
flip.expand(this.contentSize);
this.contentSize = flip.getState(this.content);
}
initMutationObserver() {
const config = { attributes: true, childList: true, subtree: true };
const callback = (mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
this.fireCustomEvent();
this.animateSize();
}
}
};
this.observer = new MutationObserver(callback);
this.observer.observe(this, config);
}
fireCustomEvent() {
this.dispatchEvent(
new CustomEvent(FLYOUT_WAS_TOGGLED, {
bubbles: true,
detail: {
message: `<dsb-flyout> with id ${this.id} was toggled`,
isOpen: this.isOpen,
contentSize: this.content.getBoundingClientRect(),
},
})
);
}
render() {
return T`
<slot
name="openButton"
=${() => this.toggle()}
aria-expanded=${this.isOpen}
aria-controls=${this.id}
></slot>
<aside
class="content ${this.isOpen ? 'is-open' : ''}"
.hidden=${!this.isOpen}
aria-hidden=${!this.isOpen}
id=${this.id}
role="dialog"
>
<div class="close-button">
<dsb-icon-button
icon="cross"
=${() => this.toggle(false)}
aria-expanded=${this.isOpen}
aria-controls=${this.id}
></dsb-icon-button>
</div>
<slot></slot>
</aside>
<div class="backdrop"></div>
`;
}
}
customElements.define('dsb-flyout', Flyout);
export { FLYOUT_DOM_TREE_CHANGED, FLYOUT_WAS_TOGGLED, Flyout };