wj-elements
Version:
WebJET Elements is a modern set of user interface tools harnessing the power of web components designed to simplify web application development.
281 lines (280 loc) • 9.9 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import WJElement from "./wje-element.js";
const styles = "/*\n[ WJ Breadcrumbs ]\n*/\n\n:host {\n --wje-breadcrumbs-breakpoint-sm: 576px;\n --wje-breadcrumbs-breakpoint-md: 768px;\n --wje-breadcrumbs-breakpoint-lg: 992px;\n --wje-breadcrumbs-breakpoint-xl: 1200px;\n --wje-breadcrumbs-breakpoint-2xl: 1450px;\n --wje-breadcrumbs-breakpoint-xxl: 1450px;\n\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n min-width: 0;\n overflow: hidden;\n}\n";
const _Breadcrumbs = class _Breadcrumbs extends WJElement {
/**
* Breadcrumbs constructor method.
* @class
*/
constructor() {
super();
/**
* Class name for the Breadcrumbs element.
* @type {string}
*/
__publicField(this, "className", "Breadcrumbs");
this.last = false;
this._isCollapsedByBreakpoint = null;
}
/**
* Set variant attribute for the Breadcrumbs element.
* @param value
*/
set variant(value) {
this.setAttribute("variant", value);
}
/**
* Get variant attribute for the Breadcrumbs element.
* @returns {string}
*/
get variant() {
return this.getAttribute("variant") || "button";
}
/**
* Get the collapsed indicator variant.
* @returns {string}
*/
get collapsedVariant() {
return this.getAttribute("collapsed-variant") || this.variant;
}
/**
* Sets the collapse breakpoint token or value.
* @param {string} value Breakpoint token or CSS size.
*/
set breakpoint(value) {
if (value) this.setAttribute("breakpoint", value);
else this.removeAttribute("breakpoint");
}
/**
* Gets the collapse breakpoint token or value.
* @returns {string}
*/
get breakpoint() {
return this.getAttribute("breakpoint") || "";
}
/**
* Get items before collapse attribute.
* @param {string} value
*/
set maxItems(value) {
this.setAttribute("max-items", value || 0);
}
/**
* Get items before collapse attribute.
* @returns {number}
*/
get maxItems() {
return +this.getAttribute("max-items");
}
/**
* Get items before collapse attribute.
* @param value
*/
set itemsBeforeCollapse(value) {
this.setAttribute("items-before-collapse", value || 1);
}
/**
* Get items before collapse attribute.
* @returns {number}
*/
get itemsBeforeCollapse() {
return +this.getAttribute("items-before-collapse") || 1;
}
/**
* Get items after collapse attribute.
* @param value
*/
set itemsAfterCollapse(value) {
this.setAttribute("items-after-collapse", value || 1);
}
/**
* Get items after collapse attribute.
* @returns {number}
*/
get itemsAfterCollapse() {
if (this.hasAttribute("items-after-collapse")) {
return +this.getAttribute("items-after-collapse") || 1;
}
const derivedItemsAfterCollapse = this.maxItems - this.itemsBeforeCollapse - 1;
return derivedItemsAfterCollapse > 0 ? derivedItemsAfterCollapse : 1;
}
/**
* Get CSS stylesheet for the Breadcrumbs element.
* @static
* @returns {object} styles - The CSS styles
*/
static get cssStyleSheet() {
return styles;
}
/**
* Get observed attributes for the Breadcrumb element.
* @static
* @returns {Array<string>} - The observed attributes array for the Breadcrumb element.
*/
static get observedAttributes() {
return ["breakpoint", "max-items", "items-before-collapse", "items-after-collapse", "collapsed-variant", "variant"];
}
/**
* Setup attributes for the Breadcrumbs element.
*/
setupAttributes() {
this.isShadowRoot = "open";
this.setAriaState({ role: "navigation" });
}
/**
* Draw method for the Breadcrumbs element.
* @returns {object} fragment - The document fragment
*/
draw() {
let fragment = document.createDocumentFragment();
let element = document.createElement("slot");
fragment.appendChild(element);
this.defaultSlot = element;
return fragment;
}
/**
* Updates the breadcrumb elements after they are drawn on the page.
* It manages attributes on breadcrumb items and handles the logic for collapsing breadcrumbs
* if the total exceeds the specified maximum items.
* @returns {void} This method does not return a value.
*/
afterDraw() {
var _a;
this.onSlotChange = () => this.updateCollapse();
(_a = this.defaultSlot) == null ? void 0 : _a.addEventListener("slotchange", this.onSlotChange);
this.handleResize = () => this.handleBreakpointResize();
if (this.getBreakpointWidth()) {
window.addEventListener("resize", this.handleResize);
}
this.updateCollapse();
}
/**
* Removes listeners after disconnect.
*/
afterDisconnect() {
var _a;
(_a = this.defaultSlot) == null ? void 0 : _a.removeEventListener("slotchange", this.onSlotChange);
window.removeEventListener("resize", this.handleResize);
this._isCollapsedByBreakpoint = null;
}
/**
* Reacts to viewport resize only when the breakpoint mode actually changes.
* @returns {void}
*/
handleBreakpointResize() {
if (!this.getBreakpointWidth()) return;
const nextState = this.shouldApplyBreakpointCollapse();
if (this._isCollapsedByBreakpoint === nextState) return;
this.updateCollapse();
}
/**
* Recalculates breadcrumb collapse state.
* @returns {void}
*/
updateCollapse() {
let breadcrumbs = this.getBreadcrumbs();
if (breadcrumbs.length === 0) return;
this._isCollapsedByBreakpoint = this.shouldApplyBreakpointCollapse();
const effectiveItemsAfterCollapse = this.itemsAfterCollapse;
const shouldCollapse = this._isCollapsedByBreakpoint && this.maxItems > 0 && breadcrumbs.length > this.maxItems && this.itemsBeforeCollapse + effectiveItemsAfterCollapse + 1 <= this.maxItems;
const lastIndex = breadcrumbs.length - 1;
const indicatorIndex = shouldCollapse ? this.itemsBeforeCollapse : -1;
const collapseStart = this.itemsBeforeCollapse;
const collapseEnd = breadcrumbs.length - effectiveItemsAfterCollapse;
breadcrumbs.forEach((breadcrumb, index) => {
this.syncManagedAttribute(breadcrumb, "last", index === lastIndex);
this.syncManagedAttribute(breadcrumb, "show-collapsed-indicator", index === indicatorIndex);
const isCollapsed = shouldCollapse && index >= collapseStart && index < collapseEnd;
this.syncManagedAttribute(breadcrumb, "collapsed", isCollapsed);
if (!isCollapsed && breadcrumb.classList.contains("collapsed")) {
breadcrumb.classList.remove("collapsed");
}
});
}
/**
* Clears attributes/classes managed by the collapse algorithm.
* @param {Array<Element>} breadcrumbs Breadcrumb items.
*/
resetCollapseState(breadcrumbs = this.getBreadcrumbs()) {
breadcrumbs.forEach((breadcrumb) => {
breadcrumb.removeAttribute("collapsed");
breadcrumb.removeAttribute("show-collapsed-indicator");
breadcrumb.removeAttribute("last");
breadcrumb.classList.remove("collapsed");
});
}
/**
* Applies a managed boolean attribute only when its value truly changes.
* @param {Element} element Breadcrumb item whose responsive state is being synchronized.
* @param {string} name Managed state flag that should be synchronized on the breadcrumb item.
* @param {boolean} isEnabled Whether the attribute should be present.
*/
syncManagedAttribute(element, name, isEnabled) {
if (!element) return;
const hasAttribute = element.hasAttribute(name);
if (isEnabled && !hasAttribute) {
element.setAttribute(name, true);
}
if (!isEnabled && hasAttribute) {
element.removeAttribute(name);
}
}
/**
* Returns whether collapse rules should currently be applied.
* @returns {boolean}
*/
shouldApplyBreakpointCollapse() {
const breakpointWidth = this.getBreakpointWidth();
if (!breakpointWidth) return true;
return window.innerWidth < breakpointWidth;
}
/**
* Resolves the configured breakpoint to a pixel width.
* @returns {number|null}
*/
getBreakpointWidth() {
if (!this.breakpoint) return null;
const token = this.breakpoint.trim().toLowerCase();
const cssValue = getComputedStyle(this).getPropertyValue(`--wje-breadcrumbs-breakpoint-${token}`).trim();
const namedBreakpoint = _Breadcrumbs.BREAKPOINTS[token];
if (cssValue) {
const cssNumber = parseFloat(cssValue);
if (Number.isFinite(cssNumber)) return cssNumber;
}
if (Number.isFinite(namedBreakpoint)) {
return namedBreakpoint;
}
const directNumber = parseFloat(token);
return Number.isFinite(directNumber) ? directNumber : null;
}
/**
* Retrieves all breadcrumb elements within the current instance.
* @returns {Array<Element>} An array of breadcrumb elements (`wje-breadcrumb`) found within the instance. Returns an empty array if no breadcrumbs are found.
*/
getBreadcrumbs() {
return Array.from(this.querySelectorAll("wje-breadcrumb")) || [];
}
/**
* Retrieves all breadcrumb elements that have the 'collapsed' attribute.
* @returns {Array<Element>} An array of DOM elements representing breadcrumbs with the 'collapsed' attribute.
*/
getBreadcrumbsCollapsed() {
return Array.from(this.querySelectorAll("wje-breadcrumb[collapsed]")) || [];
}
};
__publicField(_Breadcrumbs, "BREAKPOINTS", {
sm: 576,
md: 768,
lg: 992,
xl: 1200,
"2xl": 1450,
xxl: 1450
});
let Breadcrumbs = _Breadcrumbs;
Breadcrumbs.define("wje-breadcrumbs", Breadcrumbs);
export {
Breadcrumbs as default
};
//# sourceMappingURL=wje-breadcrumbs.js.map