@scania/tegel
Version:
Tegel Design System
191 lines (186 loc) • 11.7 kB
JavaScript
import { p as proxyCustomElement, H, d as createEvent, h, c as Host } from './p-28ef5186.js';
const sideMenuCss = ":host{--tds-scrollbar-width-standard:thin;--tds-scrollbar-width:10px;--tds-scrollbar-height:10px;--tds-scrollbar-thumb-border-width:3px;--tds-scrollbar-thumb-border-hover-width:2px}body{scrollbar-width:thin}:host{pointer-events:none;display:block;position:fixed;top:0;width:100%;height:100%;z-index:500}:host .wrapper{height:inherit;}:host .wrapper slot:not([name])::slotted(*){border-bottom:1px solid var(--tds-sidebar-side-menu-bottom-menu-border-top)}:host .wrapper ::slotted([slot=end]){border-top:1px solid var(--tds-sidebar-side-menu-bottom-menu-border-top)}:host .wrapper .tds-side-menu-list-end{margin-top:68px}:host .state-closed{display:none}:host .state-open slot[name=overlay]::slotted(tds-side-menu-overlay){opacity:0.4}:host .state-open slot[name=close-button]::slotted(tds-side-menu-close-button){opacity:1}:host .state-upper-slot-empty .tds-side-menu-list-upper{display:none}:host .state-upper-slot-empty .tds-side-menu-list-end{margin-top:0}:host .state-upper-slot-empty ::slotted([slot=end]){border-top:none;border-bottom:1px solid var(--tds-sidebar-side-menu-bottom-menu-border-top)}@media (max-width: 992px){:host(.menu-opened){pointer-events:auto;z-index:500}}@media (min-width: 992px){:host(.menu-persistent){pointer-events:auto;position:static;width:272px;height:auto;border-right:1px solid var(--tds-sidebar-side-menu-bottom-menu-border-top)}:host(.menu-persistent) .wrapper slot[name=overlay]::slotted(tds-side-menu-overlay){display:none}:host(.menu-persistent) .wrapper slot[name=close-button]::slotted(tds-side-menu-close-button){display:none}:host(.menu-persistent) .menu{width:272px}:host(.menu-persistent) .state-closed{display:block}:host(.menu-persistent):host(.menu-collapsed){width:69px;box-sizing:border-box}:host(.menu-persistent):host(.menu-collapsed) .menu{width:68px}:host(.menu-persistent) slot[name=end]::slotted(*){display:none}}.menu{width:80%;height:inherit;position:relative;left:0;display:flex;flex-direction:column;justify-content:space-between}.menu *{padding:0;margin:0;box-sizing:border-box}@media (max-width: 384px){.menu{width:100%}}aside .tds-side-menu-wrapper{display:flex;justify-content:space-between;flex-direction:column;flex-grow:1;background-color:var(--tds-sidebar-side-menu-background-cover);overflow-y:auto}aside .tds-side-menu-wrapper:hover::-webkit-scrollbar-thumb{border:var(--tds-scrollbar-thumb-border-hover-width) solid transparent;background:var(--tds-scrollbar-hover-thumb-color);background-clip:padding-box}aside .tds-side-menu-wrapper::-webkit-scrollbar{width:var(--tds-scrollbar-width)}aside .tds-side-menu-wrapper::-webkit-scrollbar-track{background:var(--tds-scrollbar-track-color)}aside .tds-side-menu-wrapper::-webkit-scrollbar-thumb{border-radius:40px;background:var(--tds-scrollbar-thumb-color);border:var(--tds-scrollbar-thumb-border-width) solid transparent;background-clip:padding-box}aside .tds-side-menu-wrapper::-webkit-scrollbar-button{height:0;width:0}@supports not selector(::-webkit-scrollbar){aside .tds-side-menu-wrapper{scrollbar-color:var(--tds-scrollbar-thumb-color) var(--tds-scrollbar-track-color);scrollbar-width:var(--tds-scrollbar-width-standard)}}aside [role=navigation]{height:100%;display:flex;flex-direction:column}aside li{list-style:none;padding:0;margin:0}";
const TdsSideMenuStyle0 = sideMenuCss;
const GRID_LG_BREAKPOINT = 992;
const TdsSideMenu$1 = /*@__PURE__*/ proxyCustomElement(class TdsSideMenu extends H {
constructor() {
super();
this.__registerHost();
this.__attachShadow();
this.tdsCollapse = createEvent(this, "tdsCollapse", 7);
this.internalTdsCollapse = createEvent(this, "internalTdsCollapse", 6);
this.internalTdsSideMenuPropChange = createEvent(this, "internalTdsSideMenuPropChange", 6);
this.handleMatchesLgBreakpointChange = (e) => {
const isBelowLg = !e.matches;
if (isBelowLg) {
this.collapsed = false;
}
else {
this.collapsed = this.initialCollapsedState;
this.open = false;
}
};
this.open = false;
this.persistent = false;
this.collapsed = false;
this.isUpperSlotEmpty = false;
this.isCollapsed = false;
this.initialCollapsedState = false;
this.activeElementIndex = 0;
}
handleKeyDown(event) {
if (event.key === 'Escape' && this.open) {
this.open = false;
}
}
connectedCallback() {
this.matchesLgBreakpointMq = window.matchMedia(`(min-width: ${GRID_LG_BREAKPOINT}px)`);
this.matchesLgBreakpointMq.addEventListener('change', this.handleMatchesLgBreakpointChange);
this.isCollapsed = this.collapsed;
this.initialCollapsedState = this.collapsed;
}
componentDidLoad() {
const upperSlot = this.host.shadowRoot.querySelector('slot:not([name])');
const upperSlotElements = upperSlot.assignedElements();
const hasUpperSlotElements = (upperSlotElements === null || upperSlotElements === void 0 ? void 0 : upperSlotElements.length) > 0;
if (!hasUpperSlotElements) {
this.isUpperSlotEmpty = true;
}
if (window.innerWidth < GRID_LG_BREAKPOINT) {
this.collapsed = false;
}
}
disconnectedCallback() {
this.matchesLgBreakpointMq.removeEventListener('change', this.handleMatchesLgBreakpointChange);
}
onCollapsedChange(newVal) {
/** Emits the internal collapse event when the prop has changed. */
this.internalTdsSideMenuPropChange.emit({
changed: ['collapsed'],
collapsed: newVal,
});
this.isCollapsed = newVal;
}
onOpenChange(newVal) {
if (newVal) {
// When menu opens, focus the first interactive element
setTimeout(() => {
const focusableElements = this.getFocusableElements();
if (focusableElements.length > 0) {
this.activeElementIndex = 0;
focusableElements[0].focus();
}
}, 100);
}
else {
// When menu closes, focus the hamburger button
const hamburgerComponent = document.querySelector('tds-header-hamburger');
if (hamburgerComponent && hamburgerComponent.shadowRoot) {
const hamburgerButton = hamburgerComponent.shadowRoot.querySelector('button');
if (hamburgerButton) {
hamburgerButton.focus();
}
}
}
}
getFocusableElements() {
var _a;
const focusableSelectors = [
'a[href]',
'button:not([disabled])',
'textarea:not([disabled])',
'input:not([disabled])',
'select:not([disabled])',
'[tabindex]:not([tabindex="-1"])',
].join(',');
const focusableInShadowRoot = Array.from(this.host.shadowRoot.querySelectorAll(focusableSelectors));
const focusableInSlots = Array.from(this.host.querySelectorAll(focusableSelectors));
const closeBtn = (_a = this.host
.querySelector('[slot="close-button"]')) === null || _a === void 0 ? void 0 : _a.shadowRoot.querySelector('button');
let focusableElements = [...focusableInShadowRoot, ...focusableInSlots];
if (closeBtn)
focusableElements.push(closeBtn);
/** Focusable elements */
return focusableElements;
}
handleFocusTrap(event) {
// Only trap focus if the menu is open
if (!this.open)
return;
// We care only about the Tab key
if (event.key !== 'Tab')
return;
const focusableElements = this.getFocusableElements();
// If there are no focusable elements
if (focusableElements.length === 0)
return;
// Prevent default tab behavior
event.preventDefault();
// Going backwards (Shift + Tab) on the first element => move to last
if (event.shiftKey) {
this.activeElementIndex -= 1;
if (this.activeElementIndex < 0) {
this.activeElementIndex = focusableElements.length - 1;
}
}
// Going forwards (Tab) on the last element => move to first
else {
this.activeElementIndex += 1;
if (this.activeElementIndex >= focusableElements.length) {
this.activeElementIndex = 0;
}
}
// Focus the next element
const nextElement = focusableElements[this.activeElementIndex];
nextElement.focus();
}
collapsedSideMenuEventHandler(event) {
this.collapsed = event.detail.collapsed;
}
render() {
return (h(Host, { key: '62d159fdff0e4dd3d2a93e0c5542b8e672e3f287', class: {
'menu-opened': this.open,
'menu-persistent': this.persistent,
'menu-collapsed': this.collapsed,
}, "aria-expanded": !this.collapsed ? 'true' : 'false' }, h("div", { key: '17134ffc1c3ca6658f4ff87c203ca3b6ba991b83', class: {
'wrapper': true,
'state-upper-slot-empty': this.isUpperSlotEmpty,
'state-open': this.open,
'state-closed': !this.open,
} }, h("slot", { key: '8ed1f309c2188e6de12b874198c36a4698d7a69f', name: "overlay" }), h("aside", { key: '45702b7ff79693b31565550fc1985bfd64e45f92', class: `menu` }, h("div", { key: 'e799983a07a07ad0f4cac8e962e1748d08107b6b', role: "navigation" }, h("slot", { key: '4550b56dae039b94005dd58c8c5cb9818c3ab48a', name: "close-button" }), h("div", { key: 'ad2457482eb6dc9b08428f36078d53143f7b5168', class: "tds-side-menu-wrapper" }, h("ul", { key: '541323ca57ed67565c848a984bd3ac210ce6f135', class: `tds-side-menu-list tds-side-menu-list-upper` }, h("li", { key: '6248720390640a1166e1158caa0f50164fe1dfad' }, h("slot", { key: 'b3d24d582d4781fef041a2c099681fd538d01910' }))), h("ul", { key: '0a5f76474b4b3851d790ab8f698dbea9fd0fda05', class: `tds-side-menu-list tds-side-menu-list-end` }, h("li", { key: '576cf3e91cac7c1a21e6b35105475f1f443c2f45' }, h("slot", { key: '71f9c2d1c061401ef26daf68c7801b5665a25d03', name: "end" })))), h("slot", { key: '41805c2bb7c66f74f47edd2393a9a3452132c769', name: "sticky-end" }))))));
}
get host() { return this; }
static get watchers() { return {
"collapsed": ["onCollapsedChange"],
"open": ["onOpenChange"]
}; }
static get style() { return TdsSideMenuStyle0; }
}, [1, "tds-side-menu", {
"open": [1028],
"persistent": [4],
"collapsed": [1028],
"isUpperSlotEmpty": [32],
"isCollapsed": [32],
"initialCollapsedState": [32],
"activeElementIndex": [32]
}, [[8, "keydown", "handleKeyDown"], [10, "keydown", "handleFocusTrap"], [16, "internalTdsCollapse", "collapsedSideMenuEventHandler"]], {
"collapsed": ["onCollapsedChange"],
"open": ["onOpenChange"]
}]);
function defineCustomElement$1() {
if (typeof customElements === "undefined") {
return;
}
const components = ["tds-side-menu"];
components.forEach(tagName => { switch (tagName) {
case "tds-side-menu":
if (!customElements.get(tagName)) {
customElements.define(tagName, TdsSideMenu$1);
}
break;
} });
}
defineCustomElement$1();
const TdsSideMenu = TdsSideMenu$1;
const defineCustomElement = defineCustomElement$1;
export { TdsSideMenu, defineCustomElement };