wj-elements 0.4.4 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/wje-breadcrumbs/breadcrumbs.element.d.ts +59 -0
- package/dist/packages/wje-tab-group/tab-group.element.d.ts +14 -0
- package/dist/packages/wje-toolbar/toolbar.element.d.ts +96 -0
- package/dist/packages/wje-toolbar-action/toolbar-action.element.d.ts +143 -0
- package/dist/wje-breadcrumb.js +2 -2
- package/dist/wje-breadcrumb.js.map +1 -1
- package/dist/wje-breadcrumbs.js +146 -17
- package/dist/wje-breadcrumbs.js.map +1 -1
- package/dist/wje-menu-item.js +3 -1
- package/dist/wje-menu-item.js.map +1 -1
- package/dist/wje-tab-group.js +46 -8
- package/dist/wje-tab-group.js.map +1 -1
- package/dist/wje-toolbar-action.js +367 -11
- package/dist/wje-toolbar-action.js.map +1 -1
- package/dist/wje-toolbar.js +259 -1
- package/dist/wje-toolbar.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wje-tab-group.js","sources":["../packages/wje-tab-group/tab-group.element.js","../packages/wje-tab-group/tab-group.js"],"sourcesContent":["import { default as WJElement } from '../wje-element/element.js';\nimport styles from './styles/styles.css?inline';\n\n/**\n * `TabGroup` is a custom web component that represents a group of tabs.\n * @summary This element represents a group of tabs.\n * @documentation https://elements.webjet.sk/components/tab-group\n * @status stable\n * @augments WJElement\n * @param {string} type The type of the tab group. Can be either 'panel' or 'route'.\n * @slot - The default slot for the tab group.\n * @slot nav - Slot for the navigation of the tab group.\n * @cssproperty [--wje-tab-group-padding=1rem] - Specifies the padding inside the tab group. This property defines the space between the content of the tab group and its outer boundary. Accepts any valid CSS length unit (e.g., `px`, `rem`, `em`, `%`).\n * @tag wje-tab-group\n */\n\nexport default class TabGroup extends WJElement {\n static _instanceId = 0;\n\n /**\n * Creates an instance of TabGroup.\n * @class\n */\n constructor() {\n super();\n\n this._instanceId = ++TabGroup._instanceId;\n this._lastNavWidth = null;\n this._initialized = false;\n }\n\n /**\n * Sets the value for the 'variant' attribute of the element.\n * @param {string} value The value to set for the 'variant' attribute.\n */\n set variant(value) {\n this.setAttribute('variant', value);\n this.setAriaState({\n orientation: (value === 'start' || value === 'end') ? 'vertical' : 'horizontal',\n });\n }\n\n /**\n * Gets the value of the 'variant' attribute.\n * If the attribute is not set, it defaults to 'top'.\n * @returns {string} The value of the 'variant' attribute or the default value 'top' if not set.\n */\n get variant() {\n return this.getAttribute('variant') || 'top';\n }\n\n /**\n * Sets the 'type' attribute of the element to the specified value.\n * @param {string} value The value to set for the 'type' attribute.\n */\n set type(value) {\n this.setAttribute('type', value);\n }\n\n /**\n * Retrieves the `type` attribute of the element.\n * If the `type` attribute is not set, it defaults to `'panel'`.\n * @returns {string} The value of the `type` attribute or the default value `'panel'`.\n */\n get type() {\n return this.getAttribute('type') || 'panel';\n }\n\n className = 'TabGroup';\n\n /**\n * Returns the CSS styles for the component.\n * @static\n * @returns {CSSStyleSheet}\n */\n static get cssStyleSheet() {\n return styles;\n }\n\n /**\n * Sets up the attributes for the component.\n */\n setupAttributes() {\n this.isShadowRoot = 'open';\n\n this.setAriaState({\n role: 'tablist',\n orientation: (this.variant === 'start' || this.variant === 'end') ? 'vertical' : 'horizontal',\n });\n }\n\n /**\n * Sets up the event listeners before the component is drawn.\n * This method is called before the component is drawn.\n * It is used to set up event listeners.\n */\n beforeDraw() {\n let activeTabName = location.hash.replace('#', '');\n\n // skontrolujeme ci sa nachadza v paneloch\n if (this.getPanelAllName().includes(activeTabName)) {\n window.addEventListener('load', (e) => {\n this.setActiveTab(activeTabName);\n });\n }\n }\n\n /**\n * Creates and returns a document fragment containing a structured layout for a tab group.\n * The tab group layout includes a `header` section with navigational elements,\n * a `section` element for tab panels, and slots for customization such as additional navigation items,\n * dropdowns, and more.\n * The structure comprises:\n * - A `div` container with relevant styling and part attributes.\n * - A `header` for tabs, including a slot for navigation (`nav`) and additional tabs in a dropdown (`moreDropdown`).\n * - A `section` for tab panels with a customizable `slot`.\n * This function also initializes the `nav` and `moreDropdown` properties for external use.\n * @returns {DocumentFragment} The completed document fragment containing the tab group layout.\n */\n draw() {\n let fragment = document.createDocumentFragment();\n\n let native = document.createElement('div');\n native.setAttribute('part', 'native');\n native.classList.add('native-tab-group');\n\n let header = document.createElement('header');\n header.setAttribute('part', 'tabs');\n header.classList.add('scroll-snap-x');\n\n let nav = document.createElement('nav');\n nav.setAttribute('part', 'nav');\n\n let section = document.createElement('section');\n section.setAttribute('part', 'panels');\n\n let slot = document.createElement('slot');\n\n let slotNav = document.createElement('slot');\n slotNav.setAttribute('name', 'nav');\n\n // More dropdown\n let icon = document.createElement('wje-icon');\n icon.setAttribute('name', 'dots');\n\n let button = document.createElement('wje-button');\n button.setAttribute('slot', 'trigger');\n button.setAttribute('fill', 'link');\n\n let menu = document.createElement('wje-menu');\n menu.setAttribute('variant', 'context');\n\n let slotMore = document.createElement('slot');\n slotMore.setAttribute('name', 'more');\n\n let moreDropdown = document.createElement('wje-dropdown');\n moreDropdown.setAttribute('placement', 'bottom-end');\n moreDropdown.setAttribute('collapsible', '');\n moreDropdown.classList.add('more-tabs');\n\n // APPEND\n button.append(icon);\n\n menu.append(slotMore);\n\n moreDropdown.append(button);\n moreDropdown.append(menu);\n\n header.append(nav);\n\n nav.append(slotNav);\n\n if(this.variant === 'top' || this.variant === 'bottom') {\n nav.append(moreDropdown);\n }\n\n section.append(slot);\n\n native.append(header);\n native.append(section);\n\n fragment.append(native);\n\n this.nav = nav;\n this.moreDropdown = moreDropdown;\n\n return fragment;\n }\n\n /**\n * Executes necessary initializations and attaches event listeners after a drawing operation.\n * Handles active tab selection, 'wje-tab:change' event binding, and window resize event for overflow checking.\n * @returns {void} Does not return a value.\n */\n afterDraw() {\n let activeTab = this.getActiveTab();\n let activeTabName = activeTab ? activeTab[0][this.type] : this.getTabAll()[0][this.type];\n\n this.setActiveTab(activeTabName);\n\n this.addEventListener('wje-tab:change', (e) => {\n if (e.detail.context.hasAttribute('disabled')) return;\n this.setActiveTab(e.detail.context.panel);\n });\n\n if (this.variant === 'top' || this.variant === 'bottom') {\n this.initTabMetrics();\n\n this._resizeObserver = new ResizeObserver(entries => {\n const width = entries[0].contentRect.width;\n\n if (width !== this._lastNavWidth) {\n this._lastNavWidth = width;\n this.checkOverflow();\n }\n });\n\n this._resizeObserver.observe(this);\n }\n }\n\n /**\n * Removes the 'active' class from all panel and tab elements.\n * @returns {void} This method does not return a value.\n */\n removeActiveTab() {\n this.getPanelAll().forEach((el) => {\n el.classList.remove('active');\n });\n\n this.getTabAll().forEach((el) => {\n el.classList.remove('active');\n });\n }\n\n /**\n * Sets the active tab and panel.\n * @param {string} tab The name of the tab to set as active.\n */\n setActiveTab(tab) {\n this.removeActiveTab();\n\n const el = this.querySelector(`[${this.type}=\"${tab}\"]`)\n el?.classList.add('active');\n\n if(this.type === 'panel')\n this.querySelector(`[name=\"${tab}\"]`)?.classList.add('active');\n\n if(el)\n this.dropdownActive(el);\n\n this.syncAria();\n }\n\n /**\n * Returns the currently active tab.\n * @returns {Element|null} The active tab, or null if no tab is active.\n */\n getActiveTab() {\n let activeTabs = Array.from(this.querySelectorAll('wje-tab.active'));\n return activeTabs.length > 0 ? activeTabs : null;\n }\n\n /**\n * Returns all tabs.\n * @returns {Array<Element>} An array of all tabs.\n */\n getTabAll() {\n return this.context.querySelector('[name=\"nav\"]').assignedElements();\n }\n\n /**\n * Returns all tabs, including those moved to \"more\".\n * @returns {Array<Element>} An array of all tabs.\n */\n getAllTabs() {\n return Array.from(this.querySelectorAll('wje-tab'));\n }\n\n /**\n * Returns all panels.\n * @returns {Array<Element>} An array of all panels.\n */\n getPanelAll() {\n return Array.from(this.querySelectorAll('wje-tab-panel'));\n }\n\n /**\n * Returns the names of all tabs.\n * @returns {Array<string>} An array of all tab names.\n */\n getPanelAllName() {\n return this.getPanelAll().map((el) => el.getAttribute('name'));\n }\n\n /**\n * Toggles the visibility of the \"more\" dropdown based on the presence of tabs in the \"more\" slot.\n * @returns {void} Does not return a value.\n */\n toggleMoreVisibility() {\n const hasTabsInMore = !!this.querySelector('wje-tab[slot=\"more\"]');\n const nextHidden = !hasTabsInMore;\n\n if (this.moreDropdown.hidden !== nextHidden) {\n this.moreDropdown.hidden = nextHidden;\n }\n }\n\n /**\n * Initializes metrics for tabs within the component. Assigns each tab to the navigation slot\n * and calculates their dimensions for further operations.\n * @returns {void} Does not return any value.\n */\n initTabMetrics() {\n const tabs = Array.from(this.querySelectorAll('wje-tab'));\n\n // všetko do nav – LEN RAZ\n tabs.forEach(tab => tab.setAttribute('slot', 'nav'));\n\n requestAnimationFrame(() => {\n this._tabMetrics = tabs.map(tab => ({\n el: tab,\n width: tab.getBoundingClientRect().width\n }));\n\n this._initialized = true;\n this.checkOverflow(); // prvý výpočet\n this._lastNavWidth = this.nav.getBoundingClientRect().width;\n });\n }\n\n /**\n * Checks if the tabs within a navigation bar overflow the available space.\n * Moves overflowing tabs into a dropdown menu and updates their state accordingly.\n * @returns {void} This method does not return a value.\n */\n checkOverflow() {\n if (!this._initialized) return;\n\n const navWidth = this.nav.getBoundingClientRect().width;\n const moreWidth = this.moreDropdown.offsetWidth || 48;\n const totalWidth = this._tabMetrics.reduce((sum, { width }) => sum + width, 0);\n\n if (totalWidth <= navWidth) {\n this._tabMetrics.forEach(({ el }) => el.setAttribute('slot', 'nav'));\n this.toggleMoreVisibility();\n return;\n }\n\n let used = 0;\n let overflowStarted = false;\n const availableWidth = Math.max(navWidth - moreWidth, 0);\n\n for (const { el, width } of this._tabMetrics) {\n used += width;\n\n const shouldOverflow = used > availableWidth;\n\n el.setAttribute('slot', shouldOverflow || overflowStarted ? 'more' : 'nav');\n overflowStarted ||= shouldOverflow;\n }\n\n this.toggleMoreVisibility();\n }\n\n /**\n * Toggles the \"dropdown-active\" class on the element based on its \"active\" status\n * and the value of its \"slot\" attribute.\n * @param {HTMLElement} el The HTML element to evaluate and apply the toggle logic.\n * @returns {void} This method does not return any value.\n */\n dropdownActive(el) {\n if(el.classList.contains('active')) {\n if(el.getAttribute('slot') === 'more')\n this.moreDropdown.classList.add('dropdown-active');\n else\n this.moreDropdown.classList.remove('dropdown-active');\n }\n }\n\n /**\n * Syncs ARIA attributes on tabs and panels.\n */\n syncAria() {\n const tabs = this.getAllTabs();\n const panels = this.getPanelAll();\n const panelByName = new Map(panels.map((p) => [p.getAttribute('name'), p]));\n const groupId = this.id || `wje-tab-group-${this._instanceId}`;\n\n this.setAriaState({\n orientation: (this.variant === 'start' || this.variant === 'end') ? 'vertical' : 'horizontal',\n });\n\n tabs.forEach((tab, index) => {\n const tabName = tab.getAttribute(this.type) || tab.panel || tab.route || String(index);\n const isActive = tab.classList.contains('active');\n const isDisabled = tab.hasAttribute('disabled');\n\n if (!tab.id) tab.id = `wje-tab-${tabName}`;\n\n let controlsId = '';\n if (this.type === 'panel') {\n const panel = panelByName.get(tabName);\n if (panel) {\n if (!panel.id) panel.id = `wje-tab-panel-${tabName}`;\n controlsId = panel.id;\n panel.setAriaState({\n role: 'tabpanel',\n labelledBy: tab.id,\n });\n }\n }\n\n tab.setAriaState({\n role: 'tab',\n selected: isActive,\n disabled: isDisabled,\n controls: controlsId || '',\n });\n\n if (typeof tab.setRovingTabIndex === 'function') {\n tab.setRovingTabIndex(isActive ? 0 : -1);\n }\n });\n }\n\n disconnectedCallback() {\n super.disconnectedCallback?.();\n this._resizeObserver?.disconnect();\n }\n}\n","import TabGroup from './tab-group.element.js';\n\nexport default TabGroup;\n\nTabGroup.define('wje-tab-group', TabGroup);\n"],"names":[],"mappings":";;;;;AAgBe,MAAM,YAAN,MAAM,kBAAiB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5C,cAAc;AACV,UAAK;AA4CT,qCAAY;AA1CR,SAAK,cAAc,EAAE,UAAS;AAC9B,SAAK,gBAAgB;AACrB,SAAK,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,QAAQ,OAAO;AACf,SAAK,aAAa,WAAW,KAAK;AAClC,SAAK,aAAa;AAAA,MACd,aAAc,UAAU,WAAW,UAAU,QAAS,aAAa;AAAA,IAC/E,CAAS;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,UAAU;AACV,WAAO,KAAK,aAAa,SAAS,KAAK;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,KAAK,OAAO;AACZ,SAAK,aAAa,QAAQ,KAAK;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,OAAO;AACP,WAAO,KAAK,aAAa,MAAM,KAAK;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,gBAAgB;AACvB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB;AACd,SAAK,eAAe;AAEpB,SAAK,aAAa;AAAA,MACd,MAAM;AAAA,MACN,aAAc,KAAK,YAAY,WAAW,KAAK,YAAY,QAAS,aAAa;AAAA,IAC7F,CAAS;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa;AACT,QAAI,gBAAgB,SAAS,KAAK,QAAQ,KAAK,EAAE;AAGjD,QAAI,KAAK,gBAAe,EAAG,SAAS,aAAa,GAAG;AAChD,aAAO,iBAAiB,QAAQ,CAAC,MAAM;AACnC,aAAK,aAAa,aAAa;AAAA,MACnC,CAAC;AAAA,IACL;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,OAAO;AACH,QAAI,WAAW,SAAS,uBAAsB;AAE9C,QAAI,SAAS,SAAS,cAAc,KAAK;AACzC,WAAO,aAAa,QAAQ,QAAQ;AACpC,WAAO,UAAU,IAAI,kBAAkB;AAEvC,QAAI,SAAS,SAAS,cAAc,QAAQ;AAC5C,WAAO,aAAa,QAAQ,MAAM;AAClC,WAAO,UAAU,IAAI,eAAe;AAEpC,QAAI,MAAM,SAAS,cAAc,KAAK;AACtC,QAAI,aAAa,QAAQ,KAAK;AAE9B,QAAI,UAAU,SAAS,cAAc,SAAS;AAC9C,YAAQ,aAAa,QAAQ,QAAQ;AAErC,QAAI,OAAO,SAAS,cAAc,MAAM;AAExC,QAAI,UAAU,SAAS,cAAc,MAAM;AAC3C,YAAQ,aAAa,QAAQ,KAAK;AAGlC,QAAI,OAAO,SAAS,cAAc,UAAU;AAC5C,SAAK,aAAa,QAAQ,MAAM;AAEhC,QAAI,SAAS,SAAS,cAAc,YAAY;AAChD,WAAO,aAAa,QAAQ,SAAS;AACrC,WAAO,aAAa,QAAQ,MAAM;AAElC,QAAI,OAAO,SAAS,cAAc,UAAU;AAC5C,SAAK,aAAa,WAAW,SAAS;AAEtC,QAAI,WAAW,SAAS,cAAc,MAAM;AAC5C,aAAS,aAAa,QAAQ,MAAM;AAEpC,QAAI,eAAe,SAAS,cAAc,cAAc;AACxD,iBAAa,aAAa,aAAa,YAAY;AACnD,iBAAa,aAAa,eAAe,EAAE;AAC3C,iBAAa,UAAU,IAAI,WAAW;AAGtC,WAAO,OAAO,IAAI;AAElB,SAAK,OAAO,QAAQ;AAEpB,iBAAa,OAAO,MAAM;AAC1B,iBAAa,OAAO,IAAI;AAExB,WAAO,OAAO,GAAG;AAEjB,QAAI,OAAO,OAAO;AAElB,QAAG,KAAK,YAAY,SAAS,KAAK,YAAY,UAAU;AACpD,UAAI,OAAO,YAAY;AAAA,IAC3B;AAEA,YAAQ,OAAO,IAAI;AAEnB,WAAO,OAAO,MAAM;AACpB,WAAO,OAAO,OAAO;AAErB,aAAS,OAAO,MAAM;AAEtB,SAAK,MAAM;AACX,SAAK,eAAe;AAEpB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY;AACR,QAAI,YAAY,KAAK,aAAY;AACjC,QAAI,gBAAgB,YAAY,UAAU,CAAC,EAAE,KAAK,IAAI,IAAI,KAAK,UAAS,EAAG,CAAC,EAAE,KAAK,IAAI;AAEvF,SAAK,aAAa,aAAa;AAE/B,SAAK,iBAAiB,kBAAkB,CAAC,MAAM;AAC3C,UAAI,EAAE,OAAO,QAAQ,aAAa,UAAU,EAAG;AAC/C,WAAK,aAAa,EAAE,OAAO,QAAQ,KAAK;AAAA,IAC5C,CAAC;AAED,QAAI,KAAK,YAAY,SAAS,KAAK,YAAY,UAAU;AACrD,WAAK,eAAc;AAEnB,WAAK,kBAAkB,IAAI,eAAe,aAAW;AACjD,cAAM,QAAQ,QAAQ,CAAC,EAAE,YAAY;AAErC,YAAI,UAAU,KAAK,eAAe;AAC9B,eAAK,gBAAgB;AACrB,eAAK,cAAa;AAAA,QACtB;AAAA,MACJ,CAAC;AAED,WAAK,gBAAgB,QAAQ,IAAI;AAAA,IACrC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB;AACd,SAAK,YAAW,EAAG,QAAQ,CAAC,OAAO;AAC/B,SAAG,UAAU,OAAO,QAAQ;AAAA,IAChC,CAAC;AAED,SAAK,UAAS,EAAG,QAAQ,CAAC,OAAO;AAC7B,SAAG,UAAU,OAAO,QAAQ;AAAA,IAChC,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,KAAK;;AACd,SAAK,gBAAe;AAEpB,UAAM,KAAK,KAAK,cAAc,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI;AACvD,6BAAI,UAAU,IAAI;AAElB,QAAG,KAAK,SAAS;AACb,iBAAK,cAAc,UAAU,GAAG,IAAI,MAApC,mBAAuC,UAAU,IAAI;AAEzD,QAAG;AACC,WAAK,eAAe,EAAE;AAE1B,SAAK,SAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe;AACX,QAAI,aAAa,MAAM,KAAK,KAAK,iBAAiB,gBAAgB,CAAC;AACnE,WAAO,WAAW,SAAS,IAAI,aAAa;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY;AACR,WAAO,KAAK,QAAQ,cAAc,cAAc,EAAE,iBAAgB;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa;AACT,WAAO,MAAM,KAAK,KAAK,iBAAiB,SAAS,CAAC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc;AACV,WAAO,MAAM,KAAK,KAAK,iBAAiB,eAAe,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB;AACd,WAAO,KAAK,YAAW,EAAG,IAAI,CAAC,OAAO,GAAG,aAAa,MAAM,CAAC;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAuB;AACnB,UAAM,gBAAgB,CAAC,CAAC,KAAK,cAAc,sBAAsB;AACjE,UAAM,aAAa,CAAC;AAEpB,QAAI,KAAK,aAAa,WAAW,YAAY;AACzC,WAAK,aAAa,SAAS;AAAA,IAC/B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB;AACb,UAAM,OAAO,MAAM,KAAK,KAAK,iBAAiB,SAAS,CAAC;AAGxD,SAAK,QAAQ,SAAO,IAAI,aAAa,QAAQ,KAAK,CAAC;AAEnD,0BAAsB,MAAM;AACxB,WAAK,cAAc,KAAK,IAAI,UAAQ;AAAA,QAChC,IAAI;AAAA,QACJ,OAAO,IAAI,wBAAwB;AAAA,MACnD,EAAc;AAEF,WAAK,eAAe;AACpB,WAAK,cAAa;AAClB,WAAK,gBAAgB,KAAK,IAAI,sBAAqB,EAAG;AAAA,IAC1D,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB;AACZ,QAAI,CAAC,KAAK,aAAc;AAExB,UAAM,WAAW,KAAK,IAAI,sBAAqB,EAAG;AAClD,UAAM,YAAY,KAAK,aAAa,eAAe;AACnD,UAAM,aAAa,KAAK,YAAY,OAAO,CAAC,KAAK,EAAE,MAAK,MAAO,MAAM,OAAO,CAAC;AAE7E,QAAI,cAAc,UAAU;AACxB,WAAK,YAAY,QAAQ,CAAC,EAAE,SAAS,GAAG,aAAa,QAAQ,KAAK,CAAC;AACnE,WAAK,qBAAoB;AACzB;AAAA,IACJ;AAEA,QAAI,OAAO;AACX,QAAI,kBAAkB;AACtB,UAAM,iBAAiB,KAAK,IAAI,WAAW,WAAW,CAAC;AAEvD,eAAW,EAAE,IAAI,MAAK,KAAM,KAAK,aAAa;AAC1C,cAAQ;AAER,YAAM,iBAAiB,OAAO;AAE9B,SAAG,aAAa,QAAQ,kBAAkB,kBAAkB,SAAS,KAAK;AAC1E,4CAAoB;AAAA,IACxB;AAEA,SAAK,qBAAoB;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAe,IAAI;AACf,QAAG,GAAG,UAAU,SAAS,QAAQ,GAAG;AAChC,UAAG,GAAG,aAAa,MAAM,MAAM;AAC3B,aAAK,aAAa,UAAU,IAAI,iBAAiB;AAAA;AAEjD,aAAK,aAAa,UAAU,OAAO,iBAAiB;AAAA,IAC5D;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW;AACP,UAAM,OAAO,KAAK,WAAU;AAC5B,UAAM,SAAS,KAAK,YAAW;AAC/B,UAAM,cAAc,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,aAAa,MAAM,GAAG,CAAC,CAAC,CAAC;AAC1D,SAAK,MAAM,iBAAiB,KAAK,WAAW;AAE5D,SAAK,aAAa;AAAA,MACd,aAAc,KAAK,YAAY,WAAW,KAAK,YAAY,QAAS,aAAa;AAAA,IAC7F,CAAS;AAED,SAAK,QAAQ,CAAC,KAAK,UAAU;AACzB,YAAM,UAAU,IAAI,aAAa,KAAK,IAAI,KAAK,IAAI,SAAS,IAAI,SAAS,OAAO,KAAK;AACrF,YAAM,WAAW,IAAI,UAAU,SAAS,QAAQ;AAChD,YAAM,aAAa,IAAI,aAAa,UAAU;AAE9C,UAAI,CAAC,IAAI,GAAI,KAAI,KAAK,WAAW,OAAO;AAExC,UAAI,aAAa;AACjB,UAAI,KAAK,SAAS,SAAS;AACvB,cAAM,QAAQ,YAAY,IAAI,OAAO;AACrC,YAAI,OAAO;AACP,cAAI,CAAC,MAAM,GAAI,OAAM,KAAK,iBAAiB,OAAO;AAClD,uBAAa,MAAM;AACnB,gBAAM,aAAa;AAAA,YACf,MAAM;AAAA,YACN,YAAY,IAAI;AAAA,UACxC,CAAqB;AAAA,QACL;AAAA,MACJ;AAEA,UAAI,aAAa;AAAA,QACb,MAAM;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,cAAc;AAAA,MACxC,CAAa;AAED,UAAI,OAAO,IAAI,sBAAsB,YAAY;AAC7C,YAAI,kBAAkB,WAAW,IAAI,EAAE;AAAA,MAC3C;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EAEA,uBAAuB;;AACnB,gBAAM,yBAAN;AACA,eAAK,oBAAL,mBAAsB;AAAA,EAC1B;AACJ;AA7ZI,cADiB,WACV,eAAc;AADV,IAAM,WAAN;ACZf,SAAS,OAAO,iBAAiB,QAAQ;"}
|
|
1
|
+
{"version":3,"file":"wje-tab-group.js","sources":["../packages/wje-tab-group/tab-group.element.js","../packages/wje-tab-group/tab-group.js"],"sourcesContent":["import { default as WJElement } from '../wje-element/element.js';\nimport styles from './styles/styles.css?inline';\n\n/**\n * `TabGroup` is a custom web component that represents a group of tabs.\n * @summary This element represents a group of tabs.\n * @documentation https://elements.webjet.sk/components/tab-group\n * @status stable\n * @augments WJElement\n * @param {string} type The type of the tab group. Can be either 'panel' or 'route'.\n * @slot - The default slot for the tab group.\n * @slot nav - Slot for the navigation of the tab group.\n * @cssproperty [--wje-tab-group-padding=1rem] - Specifies the padding inside the tab group. This property defines the space between the content of the tab group and its outer boundary. Accepts any valid CSS length unit (e.g., `px`, `rem`, `em`, `%`).\n * @tag wje-tab-group\n */\n\nexport default class TabGroup extends WJElement {\n static _instanceId = 0;\n\n /**\n * Creates an instance of TabGroup.\n * @class\n */\n constructor() {\n super();\n\n this._instanceId = ++TabGroup._instanceId;\n this._lastNavWidth = null;\n this._initialized = false;\n this._moreWidth = 0;\n }\n\n /**\n * Sets the value for the 'variant' attribute of the element.\n * @param {string} value The value to set for the 'variant' attribute.\n */\n set variant(value) {\n this.setAttribute('variant', value);\n this.setAriaState({\n orientation: (value === 'start' || value === 'end') ? 'vertical' : 'horizontal',\n });\n }\n\n /**\n * Gets the value of the 'variant' attribute.\n * If the attribute is not set, it defaults to 'top'.\n * @returns {string} The value of the 'variant' attribute or the default value 'top' if not set.\n */\n get variant() {\n return this.getAttribute('variant') || 'top';\n }\n\n /**\n * Sets the 'type' attribute of the element to the specified value.\n * @param {string} value The value to set for the 'type' attribute.\n */\n set type(value) {\n this.setAttribute('type', value);\n }\n\n /**\n * Retrieves the `type` attribute of the element.\n * If the `type` attribute is not set, it defaults to `'panel'`.\n * @returns {string} The value of the `type` attribute or the default value `'panel'`.\n */\n get type() {\n return this.getAttribute('type') || 'panel';\n }\n\n className = 'TabGroup';\n\n /**\n * Returns the CSS styles for the component.\n * @static\n * @returns {CSSStyleSheet}\n */\n static get cssStyleSheet() {\n return styles;\n }\n\n /**\n * Sets up the attributes for the component.\n */\n setupAttributes() {\n this.isShadowRoot = 'open';\n\n this.setAriaState({\n role: 'tablist',\n orientation: (this.variant === 'start' || this.variant === 'end') ? 'vertical' : 'horizontal',\n });\n }\n\n /**\n * Sets up the event listeners before the component is drawn.\n * This method is called before the component is drawn.\n * It is used to set up event listeners.\n */\n beforeDraw() {\n let activeTabName = location.hash.replace('#', '');\n\n // skontrolujeme ci sa nachadza v paneloch\n if (this.getPanelAllName().includes(activeTabName)) {\n window.addEventListener('load', (e) => {\n this.setActiveTab(activeTabName);\n });\n }\n }\n\n /**\n * Creates and returns a document fragment containing a structured layout for a tab group.\n * The tab group layout includes a `header` section with navigational elements,\n * a `section` element for tab panels, and slots for customization such as additional navigation items,\n * dropdowns, and more.\n * The structure comprises:\n * - A `div` container with relevant styling and part attributes.\n * - A `header` for tabs, including a slot for navigation (`nav`) and additional tabs in a dropdown (`moreDropdown`).\n * - A `section` for tab panels with a customizable `slot`.\n * This function also initializes the `nav` and `moreDropdown` properties for external use.\n * @returns {DocumentFragment} The completed document fragment containing the tab group layout.\n */\n draw() {\n let fragment = document.createDocumentFragment();\n\n let native = document.createElement('div');\n native.setAttribute('part', 'native');\n native.classList.add('native-tab-group');\n\n let header = document.createElement('header');\n header.setAttribute('part', 'tabs');\n header.classList.add('scroll-snap-x');\n\n let nav = document.createElement('nav');\n nav.setAttribute('part', 'nav');\n\n let section = document.createElement('section');\n section.setAttribute('part', 'panels');\n\n let slot = document.createElement('slot');\n\n let slotNav = document.createElement('slot');\n slotNav.setAttribute('name', 'nav');\n\n // More dropdown\n let icon = document.createElement('wje-icon');\n icon.setAttribute('name', 'dots');\n\n let button = document.createElement('wje-button');\n button.setAttribute('slot', 'trigger');\n button.setAttribute('fill', 'link');\n\n let menu = document.createElement('wje-menu');\n menu.setAttribute('variant', 'context');\n\n let slotMore = document.createElement('slot');\n slotMore.setAttribute('name', 'more');\n\n let moreDropdown = document.createElement('wje-dropdown');\n moreDropdown.setAttribute('placement', 'bottom-end');\n moreDropdown.setAttribute('collapsible', '');\n moreDropdown.classList.add('more-tabs');\n\n // APPEND\n button.append(icon);\n\n menu.append(slotMore);\n\n moreDropdown.append(button);\n moreDropdown.append(menu);\n\n header.append(nav);\n\n nav.append(slotNav);\n\n if(this.variant === 'top' || this.variant === 'bottom') {\n nav.append(moreDropdown);\n }\n\n section.append(slot);\n\n native.append(header);\n native.append(section);\n\n fragment.append(native);\n\n this.nav = nav;\n this.moreDropdown = moreDropdown;\n\n return fragment;\n }\n\n /**\n * Executes necessary initializations and attaches event listeners after a drawing operation.\n * Handles active tab selection, 'wje-tab:change' event binding, and window resize event for overflow checking.\n * @returns {void} Does not return a value.\n */\n afterDraw() {\n let activeTab = this.getActiveTab();\n let activeTabName = activeTab ? activeTab[0][this.type] : this.getTabAll()[0][this.type];\n\n this.setActiveTab(activeTabName);\n\n this.addEventListener('wje-tab:change', (e) => {\n if (e.detail.context.hasAttribute('disabled')) return;\n this.setActiveTab(e.detail.context.panel);\n });\n\n if (this.variant === 'top' || this.variant === 'bottom') {\n this.initTabMetrics();\n\n this._resizeObserver = new ResizeObserver(entries => {\n const width = entries[0].contentRect.width;\n\n if (width !== this._lastNavWidth) {\n this._lastNavWidth = width;\n this.checkOverflow();\n }\n });\n\n this._resizeObserver.observe(this);\n }\n }\n\n /**\n * Removes the 'active' class from all panel and tab elements.\n * @returns {void} This method does not return a value.\n */\n removeActiveTab() {\n this.getPanelAll().forEach((el) => {\n el.classList.remove('active');\n });\n\n this.getTabAll().forEach((el) => {\n el.classList.remove('active');\n });\n }\n\n /**\n * Sets the active tab and panel.\n * @param {string} tab The name of the tab to set as active.\n */\n setActiveTab(tab) {\n this.removeActiveTab();\n\n const el = this.querySelector(`[${this.type}=\"${tab}\"]`)\n el?.classList.add('active');\n\n if(this.type === 'panel')\n this.querySelector(`[name=\"${tab}\"]`)?.classList.add('active');\n\n if(el)\n this.dropdownActive(el);\n\n this.syncAria();\n }\n\n /**\n * Returns the currently active tab.\n * @returns {Element|null} The active tab, or null if no tab is active.\n */\n getActiveTab() {\n let activeTabs = Array.from(this.querySelectorAll('wje-tab.active'));\n return activeTabs.length > 0 ? activeTabs : null;\n }\n\n /**\n * Returns all tabs.\n * @returns {Array<Element>} An array of all tabs.\n */\n getTabAll() {\n return this.context.querySelector('[name=\"nav\"]').assignedElements();\n }\n\n /**\n * Returns all tabs, including those moved to \"more\".\n * @returns {Array<Element>} An array of all tabs.\n */\n getAllTabs() {\n return Array.from(this.querySelectorAll('wje-tab'));\n }\n\n /**\n * Returns all panels.\n * @returns {Array<Element>} An array of all panels.\n */\n getPanelAll() {\n return Array.from(this.querySelectorAll('wje-tab-panel'));\n }\n\n /**\n * Returns the names of all tabs.\n * @returns {Array<string>} An array of all tab names.\n */\n getPanelAllName() {\n return this.getPanelAll().map((el) => el.getAttribute('name'));\n }\n\n /**\n * Toggles the visibility of the \"more\" dropdown based on the presence of tabs in the \"more\" slot.\n * @returns {void} Does not return a value.\n */\n toggleMoreVisibility() {\n const hasTabsInMore = !!this.querySelector('wje-tab[slot=\"more\"]');\n const nextHidden = !hasTabsInMore;\n\n if (this.moreDropdown.hidden !== nextHidden) {\n this.moreDropdown.hidden = nextHidden;\n }\n }\n\n /**\n * Initializes metrics for tabs within the component. Assigns each tab to the navigation slot\n * and calculates their dimensions for further operations.\n * @returns {void} Does not return any value.\n */\n initTabMetrics() {\n requestAnimationFrame(() => {\n this._tabMetrics = this.measureTabMetrics();\n this.measureMoreWidth();\n this._initialized = true;\n this.checkOverflow(); // prvý výpočet\n this._lastNavWidth = this.nav.getBoundingClientRect().width;\n });\n }\n\n /**\n * Measures current tab widths while all tabs are temporarily placed into the main nav slot.\n * @returns {Array<{el: Element, width: number}>}\n */\n measureTabMetrics() {\n const tabs = Array.from(this.querySelectorAll('wje-tab'));\n\n tabs.forEach(tab => tab.setAttribute('slot', 'nav'));\n\n return tabs.map(tab => ({\n el: tab,\n width: tab.getBoundingClientRect().width\n }));\n }\n\n /**\n * Stores the measured width of the more dropdown trigger when available.\n * @returns {void}\n */\n measureMoreWidth() {\n const wasHidden = this.moreDropdown.hidden;\n const previousVisibility = this.moreDropdown.style.visibility;\n\n if (wasHidden) {\n this.moreDropdown.hidden = false;\n this.moreDropdown.style.visibility = 'hidden';\n }\n\n const width = this.moreDropdown.getBoundingClientRect().width || 0;\n\n if (wasHidden) {\n this.moreDropdown.hidden = true;\n this.moreDropdown.style.visibility = previousVisibility;\n }\n\n if (width > 0) {\n this._moreWidth = width;\n }\n }\n\n /**\n * Checks if the tabs within a navigation bar overflow the available space.\n * Moves overflowing tabs into a dropdown menu and updates their state accordingly.\n * @returns {void} This method does not return a value.\n */\n checkOverflow() {\n if (!this._initialized) return;\n\n this._tabMetrics = this.measureTabMetrics();\n this.measureMoreWidth();\n\n const navWidth = this.nav.getBoundingClientRect().width;\n const moreWidth = this._moreWidth || 48;\n const totalWidth = this._tabMetrics.reduce((sum, { width }) => sum + width, 0);\n\n if (totalWidth <= navWidth) {\n this._tabMetrics.forEach(({ el }) => el.setAttribute('slot', 'nav'));\n this.toggleMoreVisibility();\n this.dropdownActive(this.getActiveTab()?.[0]);\n return;\n }\n\n let used = 0;\n let overflowStarted = false;\n const availableWidth = Math.max(navWidth - moreWidth, 0);\n\n for (const { el, width } of this._tabMetrics) {\n used += width;\n\n const shouldOverflow = used > availableWidth;\n\n el.setAttribute('slot', shouldOverflow || overflowStarted ? 'more' : 'nav');\n overflowStarted ||= shouldOverflow;\n }\n\n this.toggleMoreVisibility();\n this.dropdownActive(this.getActiveTab()?.[0]);\n }\n\n /**\n * Toggles the \"dropdown-active\" class on the element based on its \"active\" status\n * and the value of its \"slot\" attribute.\n * @param {HTMLElement} el The HTML element to evaluate and apply the toggle logic.\n * @returns {void} This method does not return any value.\n */\n dropdownActive(el) {\n if (!el) {\n this.moreDropdown.classList.remove('dropdown-active');\n return;\n }\n\n if(el.classList.contains('active')) {\n if(el.getAttribute('slot') === 'more')\n this.moreDropdown.classList.add('dropdown-active');\n else\n this.moreDropdown.classList.remove('dropdown-active');\n }\n }\n\n /**\n * Syncs ARIA attributes on tabs and panels.\n */\n syncAria() {\n const tabs = this.getAllTabs();\n const panels = this.getPanelAll();\n const panelByName = new Map(panels.map((p) => [p.getAttribute('name'), p]));\n const groupId = this.id || `wje-tab-group-${this._instanceId}`;\n\n this.setAriaState({\n orientation: (this.variant === 'start' || this.variant === 'end') ? 'vertical' : 'horizontal',\n });\n\n tabs.forEach((tab, index) => {\n const tabName = tab.getAttribute(this.type) || tab.panel || tab.route || String(index);\n const isActive = tab.classList.contains('active');\n const isDisabled = tab.hasAttribute('disabled');\n\n if (!tab.id) tab.id = `wje-tab-${tabName}`;\n\n let controlsId = '';\n if (this.type === 'panel') {\n const panel = panelByName.get(tabName);\n if (panel) {\n if (!panel.id) panel.id = `wje-tab-panel-${tabName}`;\n controlsId = panel.id;\n panel.setAriaState({\n role: 'tabpanel',\n labelledBy: tab.id,\n });\n }\n }\n\n tab.setAriaState({\n role: 'tab',\n selected: isActive,\n disabled: isDisabled,\n controls: controlsId || '',\n });\n\n if (typeof tab.setRovingTabIndex === 'function') {\n tab.setRovingTabIndex(isActive ? 0 : -1);\n }\n });\n }\n\n disconnectedCallback() {\n super.disconnectedCallback?.();\n this._resizeObserver?.disconnect();\n }\n}\n","import TabGroup from './tab-group.element.js';\n\nexport default TabGroup;\n\nTabGroup.define('wje-tab-group', TabGroup);\n"],"names":[],"mappings":"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"}
|
|
@@ -2,8 +2,8 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import WJElement from "./wje-element.js";
|
|
5
|
-
const styles = "/*\n[ WJ Toolbar Action ]\n*/\n\n:host {\n .native-toolbar-action {\n display: flex;\n gap: var(--wje-toolbar-action-gap);\n }\n}\n";
|
|
6
|
-
class
|
|
5
|
+
const styles = "/*\n[ WJ Toolbar Action ]\n*/\n\n:host {\n --wje-toolbar-action-breakpoint-sm: 576px;\n --wje-toolbar-action-breakpoint-md: 768px;\n --wje-toolbar-action-breakpoint-lg: 992px;\n --wje-toolbar-action-breakpoint-xl: 1200px;\n --wje-toolbar-action-breakpoint-2xl: 1450px;\n --wje-toolbar-action-breakpoint-xxl: 1450px;\n\n .native-toolbar-action {\n display: flex;\n align-items: center;\n gap: var(--wje-toolbar-action-gap);\n }\n\n .toolbar-action-more {\n flex: 0 0 auto;\n }\n}\n";
|
|
6
|
+
const _ToolbarAction = class _ToolbarAction extends WJElement {
|
|
7
7
|
/**
|
|
8
8
|
* Creates an instance of ToolbarAction.
|
|
9
9
|
*/
|
|
@@ -14,6 +14,9 @@ class ToolbarAction extends WJElement {
|
|
|
14
14
|
* @type {string}
|
|
15
15
|
*/
|
|
16
16
|
__publicField(this, "className", "ToolbarAction");
|
|
17
|
+
this._managedHiddenActions = /* @__PURE__ */ new WeakSet();
|
|
18
|
+
this._isCollapsedByBreakpoint = null;
|
|
19
|
+
this._managedOverflowNodes = /* @__PURE__ */ new WeakSet();
|
|
17
20
|
}
|
|
18
21
|
/**
|
|
19
22
|
* Returns the CSS stylesheet for the component.
|
|
@@ -29,7 +32,56 @@ class ToolbarAction extends WJElement {
|
|
|
29
32
|
* @returns {Array} An empty array
|
|
30
33
|
*/
|
|
31
34
|
static get observedAttributes() {
|
|
32
|
-
return [];
|
|
35
|
+
return ["breakpoint", "max-items", "visible-items"];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Sets the collapse breakpoint token or value.
|
|
39
|
+
* @param {string} value Breakpoint token or CSS size.
|
|
40
|
+
*/
|
|
41
|
+
set breakpoint(value) {
|
|
42
|
+
if (value) this.setAttribute("breakpoint", value);
|
|
43
|
+
else this.removeAttribute("breakpoint");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Gets the collapse breakpoint token or value.
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
get breakpoint() {
|
|
50
|
+
return this.getAttribute("breakpoint") || "";
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Sets the maximum number of visible actions.
|
|
54
|
+
* @param {number|string} value The maximum number of visible actions.
|
|
55
|
+
*/
|
|
56
|
+
set maxItems(value) {
|
|
57
|
+
this.setAttribute("max-items", value || 0);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Gets the maximum number of visible actions.
|
|
61
|
+
* @returns {number}
|
|
62
|
+
*/
|
|
63
|
+
get maxItems() {
|
|
64
|
+
return +this.getAttribute("max-items") || 0;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Sets the responsive visible action count.
|
|
68
|
+
* @param {number|string} value The visible action count.
|
|
69
|
+
*/
|
|
70
|
+
set visibleItems(value) {
|
|
71
|
+
if (value === null || value === void 0 || value === "") {
|
|
72
|
+
this.removeAttribute("visible-items");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
this.setAttribute("visible-items", value);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Gets the responsive visible action count.
|
|
79
|
+
* @returns {number|null}
|
|
80
|
+
*/
|
|
81
|
+
get visibleItems() {
|
|
82
|
+
if (!this.hasAttribute("visible-items")) return null;
|
|
83
|
+
const value = +this.getAttribute("visible-items");
|
|
84
|
+
return Number.isFinite(value) ? value : null;
|
|
33
85
|
}
|
|
34
86
|
/**
|
|
35
87
|
* Sets up the attributes for the component.
|
|
@@ -43,28 +95,332 @@ class ToolbarAction extends WJElement {
|
|
|
43
95
|
*/
|
|
44
96
|
draw() {
|
|
45
97
|
let fragment = document.createDocumentFragment();
|
|
46
|
-
let maxItems = +this.maxItems || 0;
|
|
47
|
-
let actions = this.getActions();
|
|
48
98
|
let slot = document.createElement("slot");
|
|
49
99
|
let element = document.createElement("div");
|
|
50
100
|
element.setAttribute("part", "native");
|
|
51
101
|
element.classList.add("native-toolbar-action");
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
102
|
+
let dropdown = document.createElement("wje-dropdown");
|
|
103
|
+
dropdown.setAttribute("placement", "bottom-end");
|
|
104
|
+
dropdown.setAttribute("collapsible", "");
|
|
105
|
+
dropdown.classList.add("toolbar-action-more");
|
|
106
|
+
dropdown.hidden = true;
|
|
107
|
+
let trigger = document.createElement("wje-button");
|
|
108
|
+
trigger.setAttribute("slot", "trigger");
|
|
109
|
+
trigger.setAttribute("fill", "link");
|
|
110
|
+
trigger.setAttribute("aria-label", "Show more actions");
|
|
111
|
+
trigger.innerHTML = '<wje-icon name="dots"></wje-icon>';
|
|
112
|
+
let menu = document.createElement("wje-menu");
|
|
113
|
+
menu.setAttribute("variant", "context");
|
|
114
|
+
dropdown.append(trigger, menu);
|
|
56
115
|
element.appendChild(slot);
|
|
116
|
+
element.appendChild(dropdown);
|
|
57
117
|
fragment.appendChild(element);
|
|
118
|
+
this.defaultSlot = slot;
|
|
119
|
+
this.native = element;
|
|
120
|
+
this.moreDropdown = dropdown;
|
|
121
|
+
this.moreMenu = menu;
|
|
58
122
|
return fragment;
|
|
59
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Applies the current visible action limit after the component is drawn.
|
|
126
|
+
*/
|
|
127
|
+
afterDraw() {
|
|
128
|
+
var _a;
|
|
129
|
+
this.onSlotChange = () => this.applyOverflow();
|
|
130
|
+
(_a = this.defaultSlot) == null ? void 0 : _a.addEventListener("slotchange", this.onSlotChange);
|
|
131
|
+
this.handleResize = () => this.handleBreakpointResize();
|
|
132
|
+
if (this.getBreakpointWidth()) {
|
|
133
|
+
window.addEventListener("resize", this.handleResize);
|
|
134
|
+
}
|
|
135
|
+
this.applyOverflow();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Removes listeners after disconnect.
|
|
139
|
+
*/
|
|
140
|
+
afterDisconnect() {
|
|
141
|
+
var _a;
|
|
142
|
+
(_a = this.defaultSlot) == null ? void 0 : _a.removeEventListener("slotchange", this.onSlotChange);
|
|
143
|
+
window.removeEventListener("resize", this.handleResize);
|
|
144
|
+
this._isCollapsedByBreakpoint = null;
|
|
145
|
+
}
|
|
60
146
|
/**
|
|
61
147
|
* Returns the actions for the toolbar action.
|
|
62
148
|
* @returns {Array} An array of wje-button elements
|
|
63
149
|
*/
|
|
64
150
|
getActions() {
|
|
65
|
-
return
|
|
151
|
+
return this.getAssignedElements().filter(
|
|
152
|
+
(element) => {
|
|
153
|
+
var _a;
|
|
154
|
+
return ((_a = element.tagName) == null ? void 0 : _a.toLowerCase()) === "wje-button" && element.getAttribute("slot") !== "trigger";
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Returns direct children assigned to the default slot.
|
|
160
|
+
* @returns {Array<HTMLElement>}
|
|
161
|
+
*/
|
|
162
|
+
getAssignedElements() {
|
|
163
|
+
var _a, _b;
|
|
164
|
+
return ((_b = (_a = this.defaultSlot) == null ? void 0 : _a.assignedElements) == null ? void 0 : _b.call(_a)) || Array.from(this.children);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Returns an existing top-level dropdown if present.
|
|
168
|
+
* @returns {HTMLElement|null}
|
|
169
|
+
*/
|
|
170
|
+
getExistingDropdown() {
|
|
171
|
+
return this.getAssignedElements().find((element) => {
|
|
172
|
+
var _a;
|
|
173
|
+
return ((_a = element.tagName) == null ? void 0 : _a.toLowerCase()) === "wje-dropdown";
|
|
174
|
+
}) || null;
|
|
66
175
|
}
|
|
67
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Returns the dropdown that should receive overflow items.
|
|
178
|
+
* @returns {HTMLElement}
|
|
179
|
+
*/
|
|
180
|
+
getOverflowDropdown() {
|
|
181
|
+
return this.getExistingDropdown() || this.moreDropdown;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Returns the menu used for overflow items.
|
|
185
|
+
* @returns {HTMLElement|null}
|
|
186
|
+
*/
|
|
187
|
+
getOverflowMenu() {
|
|
188
|
+
const existingDropdown = this.getExistingDropdown();
|
|
189
|
+
if (existingDropdown) {
|
|
190
|
+
return Array.from(existingDropdown.children).find((element) => {
|
|
191
|
+
var _a;
|
|
192
|
+
return ((_a = element.tagName) == null ? void 0 : _a.toLowerCase()) === "wje-menu";
|
|
193
|
+
}) || null;
|
|
194
|
+
}
|
|
195
|
+
return this.moreMenu;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Gets the number of actions that should stay visible.
|
|
199
|
+
* @returns {number}
|
|
200
|
+
*/
|
|
201
|
+
getVisibleLimit() {
|
|
202
|
+
const actions = this.getActions();
|
|
203
|
+
if (this.isCollapsedByBreakpoint()) {
|
|
204
|
+
return 0;
|
|
205
|
+
}
|
|
206
|
+
const maxItems = this.maxItems > 0 ? this.maxItems : actions.length;
|
|
207
|
+
const visibleItems = this.visibleItems;
|
|
208
|
+
const limit = visibleItems === null ? maxItems : Math.min(visibleItems, maxItems);
|
|
209
|
+
return Math.max(0, Math.min(limit, actions.length));
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Returns whether the toolbar action should collapse based on the configured breakpoint.
|
|
213
|
+
* @returns {boolean}
|
|
214
|
+
*/
|
|
215
|
+
shouldCollapseByBreakpoint() {
|
|
216
|
+
const breakpointWidth = this.getBreakpointWidth();
|
|
217
|
+
if (!breakpointWidth) return false;
|
|
218
|
+
return window.innerWidth < breakpointWidth;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Returns the cached breakpoint collapse state.
|
|
222
|
+
* @returns {boolean}
|
|
223
|
+
*/
|
|
224
|
+
isCollapsedByBreakpoint() {
|
|
225
|
+
if (!this.getBreakpointWidth()) {
|
|
226
|
+
this._isCollapsedByBreakpoint = false;
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
const nextState = this.shouldCollapseByBreakpoint();
|
|
230
|
+
this._isCollapsedByBreakpoint = nextState;
|
|
231
|
+
return nextState;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Reacts to viewport resize only when the breakpoint mode actually changes.
|
|
235
|
+
* @returns {void}
|
|
236
|
+
*/
|
|
237
|
+
handleBreakpointResize() {
|
|
238
|
+
if (!this.getBreakpointWidth()) return;
|
|
239
|
+
const nextState = this.shouldCollapseByBreakpoint();
|
|
240
|
+
if (this._isCollapsedByBreakpoint === nextState) return;
|
|
241
|
+
this._isCollapsedByBreakpoint = nextState;
|
|
242
|
+
this.applyOverflow();
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Resolves the configured breakpoint to a pixel width.
|
|
246
|
+
* @returns {number|null}
|
|
247
|
+
*/
|
|
248
|
+
getBreakpointWidth() {
|
|
249
|
+
if (!this.breakpoint) return null;
|
|
250
|
+
const token = this.breakpoint.trim().toLowerCase();
|
|
251
|
+
const cssValue = getComputedStyle(this).getPropertyValue(`--wje-toolbar-action-breakpoint-${token}`).trim();
|
|
252
|
+
const namedBreakpoint = _ToolbarAction.BREAKPOINTS[token];
|
|
253
|
+
if (cssValue) {
|
|
254
|
+
const cssNumber = parseFloat(cssValue);
|
|
255
|
+
if (Number.isFinite(cssNumber)) return cssNumber;
|
|
256
|
+
}
|
|
257
|
+
if (Number.isFinite(namedBreakpoint)) {
|
|
258
|
+
return namedBreakpoint;
|
|
259
|
+
}
|
|
260
|
+
const directNumber = parseFloat(token);
|
|
261
|
+
return Number.isFinite(directNumber) ? directNumber : null;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Updates visible actions and the overflow dropdown.
|
|
265
|
+
* @returns {void}
|
|
266
|
+
*/
|
|
267
|
+
applyOverflow() {
|
|
268
|
+
var _a;
|
|
269
|
+
const actions = this.getActions();
|
|
270
|
+
const visibleLimit = this.getVisibleLimit();
|
|
271
|
+
const overflowActions = actions.slice(visibleLimit);
|
|
272
|
+
const existingDropdown = this.getExistingDropdown();
|
|
273
|
+
const overflowMenu = this.getOverflowMenu();
|
|
274
|
+
this.restoreManagedActions(actions);
|
|
275
|
+
this.restoreManagedOverflowContent();
|
|
276
|
+
if (!existingDropdown) {
|
|
277
|
+
(_a = this.moreMenu) == null ? void 0 : _a.replaceChildren();
|
|
278
|
+
}
|
|
279
|
+
overflowActions.forEach((action) => {
|
|
280
|
+
action.hidden = true;
|
|
281
|
+
action.style.display = "none";
|
|
282
|
+
this._managedHiddenActions.add(action);
|
|
283
|
+
});
|
|
284
|
+
if (overflowMenu && existingDropdown && overflowActions.length > 0 && overflowMenu.children.length > 0) {
|
|
285
|
+
overflowMenu.append(this.createOverflowDivider());
|
|
286
|
+
}
|
|
287
|
+
overflowActions.forEach((action) => {
|
|
288
|
+
overflowMenu == null ? void 0 : overflowMenu.append(this.createMenuItem(action));
|
|
289
|
+
});
|
|
290
|
+
if (!existingDropdown && this.moreDropdown) {
|
|
291
|
+
this.moreDropdown.hidden = overflowActions.length === 0;
|
|
292
|
+
} else if (existingDropdown && this.moreDropdown) {
|
|
293
|
+
this.moreDropdown.hidden = true;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Restores buttons hidden by this component.
|
|
298
|
+
* @param {Array<HTMLElement>} actions Toolbar buttons.
|
|
299
|
+
*/
|
|
300
|
+
restoreManagedActions(actions = this.getActions()) {
|
|
301
|
+
actions.forEach((action) => {
|
|
302
|
+
if (this._managedHiddenActions.has(action)) {
|
|
303
|
+
action.hidden = false;
|
|
304
|
+
action.style.removeProperty("display");
|
|
305
|
+
this._managedHiddenActions.delete(action);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Removes overflow menu nodes that were previously injected by this component.
|
|
311
|
+
*/
|
|
312
|
+
restoreManagedOverflowContent() {
|
|
313
|
+
const dropdown = this.getExistingDropdown();
|
|
314
|
+
if (!dropdown) return;
|
|
315
|
+
const menu = this.getOverflowMenu();
|
|
316
|
+
if (!menu) return;
|
|
317
|
+
Array.from(menu.children).forEach((child) => {
|
|
318
|
+
if (this._managedOverflowNodes.has(child)) {
|
|
319
|
+
child.remove();
|
|
320
|
+
this._managedOverflowNodes.delete(child);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Creates a dropdown menu proxy for an overflowed button.
|
|
326
|
+
* @param {HTMLElement} action The original action button.
|
|
327
|
+
* @returns {HTMLElement}
|
|
328
|
+
*/
|
|
329
|
+
createMenuItem(action) {
|
|
330
|
+
let menuItem = document.createElement("wje-menu-item");
|
|
331
|
+
menuItem.innerHTML = action.innerHTML;
|
|
332
|
+
if (action.hasAttribute("disabled") || action.getAttribute("aria-disabled") === "true") {
|
|
333
|
+
menuItem.setAttribute("disabled", "");
|
|
334
|
+
}
|
|
335
|
+
menuItem.addEventListener("wje-menu-item:click", (e) => this.handleMenuItemClick(e, action));
|
|
336
|
+
menuItem.addEventListener("click", (e) => this.handleMenuItemClick(e, action));
|
|
337
|
+
this._managedOverflowNodes.add(menuItem);
|
|
338
|
+
return menuItem;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Creates a divider separating existing dropdown actions from responsive overflow actions.
|
|
342
|
+
* @returns {HTMLElement}
|
|
343
|
+
*/
|
|
344
|
+
createOverflowDivider() {
|
|
345
|
+
const divider = document.createElement("wje-divider");
|
|
346
|
+
this._managedOverflowNodes.add(divider);
|
|
347
|
+
return divider;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Forwards menu item activation to the original button.
|
|
351
|
+
* @param {Event} e The menu event.
|
|
352
|
+
* @param {HTMLElement} action The original action button.
|
|
353
|
+
*/
|
|
354
|
+
handleMenuItemClick(e, action) {
|
|
355
|
+
var _a;
|
|
356
|
+
(_a = e.preventDefault) == null ? void 0 : _a.call(e);
|
|
357
|
+
e.stopPropagation();
|
|
358
|
+
if (!action || action.hasAttribute("disabled") || action.getAttribute("aria-disabled") === "true") return;
|
|
359
|
+
action.click();
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Measures action widths while preserving current overflow state.
|
|
363
|
+
* @returns {{count: number, widths: number[], gap: number, moreWidth: number, getWidthForCount: Function}}
|
|
364
|
+
*/
|
|
365
|
+
measureActionMetrics() {
|
|
366
|
+
const actions = this.getActions();
|
|
367
|
+
const hasExistingDropdown = !!this.getExistingDropdown();
|
|
368
|
+
this.restoreManagedActions(actions);
|
|
369
|
+
const widths = actions.map((action) => action.getBoundingClientRect().width);
|
|
370
|
+
const style = this.native ? getComputedStyle(this.native) : null;
|
|
371
|
+
const gap = style ? parseFloat(style.columnGap || style.gap || "0") || 0 : 0;
|
|
372
|
+
const moreWidth = this.measureMoreWidth();
|
|
373
|
+
this.applyOverflow();
|
|
374
|
+
return {
|
|
375
|
+
count: actions.length,
|
|
376
|
+
widths,
|
|
377
|
+
gap,
|
|
378
|
+
moreWidth,
|
|
379
|
+
getWidthForCount: (visibleCount) => {
|
|
380
|
+
const count = Math.max(0, Math.min(visibleCount, actions.length));
|
|
381
|
+
const overflowCount = actions.length - count;
|
|
382
|
+
const visibleWidth = widths.slice(0, count).reduce((sum, width) => sum + width, 0);
|
|
383
|
+
const visibleGaps = Math.max(count - 1, 0) * gap;
|
|
384
|
+
const usesDropdown = hasExistingDropdown || overflowCount > 0;
|
|
385
|
+
const moreGap = count > 0 && usesDropdown ? gap : 0;
|
|
386
|
+
return visibleWidth + visibleGaps + (usesDropdown ? moreWidth + moreGap : 0);
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Measures the overflow dropdown trigger.
|
|
392
|
+
* @returns {number}
|
|
393
|
+
*/
|
|
394
|
+
measureMoreWidth() {
|
|
395
|
+
const dropdown = this.getOverflowDropdown();
|
|
396
|
+
if (!dropdown) return 48;
|
|
397
|
+
const isInternalDropdown = dropdown === this.moreDropdown;
|
|
398
|
+
const wasHidden = dropdown.hidden;
|
|
399
|
+
const previousVisibility = dropdown.style.visibility;
|
|
400
|
+
if (isInternalDropdown && wasHidden) {
|
|
401
|
+
dropdown.hidden = false;
|
|
402
|
+
dropdown.style.visibility = "hidden";
|
|
403
|
+
}
|
|
404
|
+
const width = dropdown.getBoundingClientRect().width || 48;
|
|
405
|
+
if (isInternalDropdown && wasHidden) {
|
|
406
|
+
dropdown.hidden = true;
|
|
407
|
+
dropdown.style.visibility = previousVisibility;
|
|
408
|
+
}
|
|
409
|
+
if (dropdown === this.moreDropdown && this.getExistingDropdown()) {
|
|
410
|
+
this.moreDropdown.hidden = true;
|
|
411
|
+
}
|
|
412
|
+
return width;
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
__publicField(_ToolbarAction, "BREAKPOINTS", {
|
|
416
|
+
sm: 576,
|
|
417
|
+
md: 768,
|
|
418
|
+
lg: 992,
|
|
419
|
+
xl: 1200,
|
|
420
|
+
"2xl": 1450,
|
|
421
|
+
xxl: 1450
|
|
422
|
+
});
|
|
423
|
+
let ToolbarAction = _ToolbarAction;
|
|
68
424
|
ToolbarAction.define("wje-toolbar-action", ToolbarAction);
|
|
69
425
|
export {
|
|
70
426
|
ToolbarAction as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wje-toolbar-action.js","sources":["../packages/wje-toolbar-action/toolbar-action.element.js","../packages/wje-toolbar-action/toolbar-action.js"],"sourcesContent":["import { default as WJElement } from '../wje-element/element.js';\nimport styles from './styles/styles.css?inline';\n\n/**\n * `ToolbarAction` is a custom web component that represents a toolbar action.\n * @summary This element represents a toolbar action.\n * @documentation https://elements.webjet.sk/components/toolbar-action\n * @status stable\n * @augments {WJElement}\n * @csspart native - The native toolbar action wrapper.\n * @slot - The default slot for the toolbar action.\n * @tag wje-toolbar-action\n */\nexport default class ToolbarAction extends WJElement {\n /**\n * Creates an instance of ToolbarAction.\n */\n constructor() {\n super();\n }\n\n /**\n * The class name for the component.\n * @type {string}\n */\n className = 'ToolbarAction';\n\n /**\n * Returns the CSS stylesheet for the component.\n * @static\n * @returns {CSSStyleSheet} The CSS stylesheet\n */\n static get cssStyleSheet() {\n return styles;\n }\n\n /**\n * Returns the list of observed attributes.\n * @static\n * @returns {Array} An empty array\n */\n static get observedAttributes() {\n return [];\n }\n\n /**\n * Sets up the attributes for the component.\n */\n setupAttributes() {\n this.isShadowRoot = 'open';\n }\n\n /**\n * Draws the component for the toolbar action.\n * @returns {object} Document fragment\n */\n draw() {\n let fragment = document.createDocumentFragment();\n\n let maxItems = +this.maxItems || 0;\n let actions = this.getActions();\n\n let slot = document.createElement('slot');\n\n let element = document.createElement('div');\n element.setAttribute('part', 'native');\n element.classList.add('native-toolbar-action');\n\n const shouldCollapse = maxItems !== 0 && actions.length > maxItems;\n if (shouldCollapse) {\n element = document.createElement('wje-dropdown');\n }\n\n element.appendChild(slot);\n\n fragment.appendChild(element);\n\n return fragment;\n }\n\n /**\n * Returns the actions for the toolbar action.\n * @returns {Array} An array of wje-button elements\n */\n getActions() {\n return Array.from(this.querySelectorAll('wje-button'));\n }\n}\n","import ToolbarAction from './toolbar-action.element.js';\n\nexport default ToolbarAction;\n\nToolbarAction.define('wje-toolbar-action', ToolbarAction);\n"],"names":[],"mappings":";;;;;AAae,MAAM,sBAAsB,UAAU;AAAA;AAAA;AAAA;AAAA,EAIjD,cAAc;AACV,UAAK;AAOT;AAAA;AAAA;AAAA;AAAA,qCAAY;AAAA,EANZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,WAAW,gBAAgB;AACvB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,qBAAqB;AAC5B,WAAO,CAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB;AACd,SAAK,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO;AACH,QAAI,WAAW,SAAS,uBAAsB;AAE9C,QAAI,WAAW,CAAC,KAAK,YAAY;AACjC,QAAI,UAAU,KAAK,WAAU;AAE7B,QAAI,OAAO,SAAS,cAAc,MAAM;AAExC,QAAI,UAAU,SAAS,cAAc,KAAK;AAC1C,YAAQ,aAAa,QAAQ,QAAQ;AACrC,YAAQ,UAAU,IAAI,uBAAuB;AAE7C,UAAM,iBAAiB,aAAa,KAAK,QAAQ,SAAS;AAC1D,QAAI,gBAAgB;AAChB,gBAAU,SAAS,cAAc,cAAc;AAAA,IACnD;AAEA,YAAQ,YAAY,IAAI;AAExB,aAAS,YAAY,OAAO;AAE5B,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa;AACT,WAAO,MAAM,KAAK,KAAK,iBAAiB,YAAY,CAAC;AAAA,EACzD;AACJ;ACnFA,cAAc,OAAO,sBAAsB,aAAa;"}
|
|
1
|
+
{"version":3,"file":"wje-toolbar-action.js","sources":["../packages/wje-toolbar-action/toolbar-action.element.js","../packages/wje-toolbar-action/toolbar-action.js"],"sourcesContent":["import { default as WJElement } from '../wje-element/element.js';\nimport styles from './styles/styles.css?inline';\n\n/**\n * `ToolbarAction` is a custom web component that represents a toolbar action.\n * @summary This element represents a toolbar action.\n * @documentation https://elements.webjet.sk/components/toolbar-action\n * @status stable\n * @augments {WJElement}\n * @csspart native - The native toolbar action wrapper.\n * @slot - The default slot for the toolbar action.\n * @tag wje-toolbar-action\n */\nexport default class ToolbarAction extends WJElement {\n static BREAKPOINTS = {\n sm: 576,\n md: 768,\n lg: 992,\n xl: 1200,\n '2xl': 1450,\n xxl: 1450,\n };\n\n /**\n * Creates an instance of ToolbarAction.\n */\n constructor() {\n super();\n this._managedHiddenActions = new WeakSet();\n this._isCollapsedByBreakpoint = null;\n this._managedOverflowNodes = new WeakSet();\n }\n\n /**\n * The class name for the component.\n * @type {string}\n */\n className = 'ToolbarAction';\n\n /**\n * Returns the CSS stylesheet for the component.\n * @static\n * @returns {CSSStyleSheet} The CSS stylesheet\n */\n static get cssStyleSheet() {\n return styles;\n }\n\n /**\n * Returns the list of observed attributes.\n * @static\n * @returns {Array} An empty array\n */\n static get observedAttributes() {\n return ['breakpoint', 'max-items', 'visible-items'];\n }\n\n /**\n * Sets the collapse breakpoint token or value.\n * @param {string} value Breakpoint token or CSS size.\n */\n set breakpoint(value) {\n if (value) this.setAttribute('breakpoint', value);\n else this.removeAttribute('breakpoint');\n }\n\n /**\n * Gets the collapse breakpoint token or value.\n * @returns {string}\n */\n get breakpoint() {\n return this.getAttribute('breakpoint') || '';\n }\n\n /**\n * Sets the maximum number of visible actions.\n * @param {number|string} value The maximum number of visible actions.\n */\n set maxItems(value) {\n this.setAttribute('max-items', value || 0);\n }\n\n /**\n * Gets the maximum number of visible actions.\n * @returns {number}\n */\n get maxItems() {\n return +this.getAttribute('max-items') || 0;\n }\n\n /**\n * Sets the responsive visible action count.\n * @param {number|string} value The visible action count.\n */\n set visibleItems(value) {\n if (value === null || value === undefined || value === '') {\n this.removeAttribute('visible-items');\n return;\n }\n\n this.setAttribute('visible-items', value);\n }\n\n /**\n * Gets the responsive visible action count.\n * @returns {number|null}\n */\n get visibleItems() {\n if (!this.hasAttribute('visible-items')) return null;\n const value = +this.getAttribute('visible-items');\n return Number.isFinite(value) ? value : null;\n }\n\n /**\n * Sets up the attributes for the component.\n */\n setupAttributes() {\n this.isShadowRoot = 'open';\n }\n\n /**\n * Draws the component for the toolbar action.\n * @returns {object} Document fragment\n */\n draw() {\n let fragment = document.createDocumentFragment();\n\n let slot = document.createElement('slot');\n\n let element = document.createElement('div');\n element.setAttribute('part', 'native');\n element.classList.add('native-toolbar-action');\n\n let dropdown = document.createElement('wje-dropdown');\n dropdown.setAttribute('placement', 'bottom-end');\n dropdown.setAttribute('collapsible', '');\n dropdown.classList.add('toolbar-action-more');\n dropdown.hidden = true;\n\n let trigger = document.createElement('wje-button');\n trigger.setAttribute('slot', 'trigger');\n trigger.setAttribute('fill', 'link');\n trigger.setAttribute('aria-label', 'Show more actions');\n trigger.innerHTML = '<wje-icon name=\"dots\"></wje-icon>';\n\n let menu = document.createElement('wje-menu');\n menu.setAttribute('variant', 'context');\n\n dropdown.append(trigger, menu);\n\n element.appendChild(slot);\n element.appendChild(dropdown);\n\n fragment.appendChild(element);\n\n this.defaultSlot = slot;\n this.native = element;\n this.moreDropdown = dropdown;\n this.moreMenu = menu;\n\n return fragment;\n }\n\n /**\n * Applies the current visible action limit after the component is drawn.\n */\n afterDraw() {\n this.onSlotChange = () => this.applyOverflow();\n this.defaultSlot?.addEventListener('slotchange', this.onSlotChange);\n this.handleResize = () => this.handleBreakpointResize();\n\n if (this.getBreakpointWidth()) {\n window.addEventListener('resize', this.handleResize);\n }\n\n this.applyOverflow();\n }\n\n /**\n * Removes listeners after disconnect.\n */\n afterDisconnect() {\n this.defaultSlot?.removeEventListener('slotchange', this.onSlotChange);\n window.removeEventListener('resize', this.handleResize);\n this._isCollapsedByBreakpoint = null;\n }\n\n /**\n * Returns the actions for the toolbar action.\n * @returns {Array} An array of wje-button elements\n */\n getActions() {\n return this.getAssignedElements().filter(\n (element) => element.tagName?.toLowerCase() === 'wje-button' && element.getAttribute('slot') !== 'trigger'\n );\n }\n\n /**\n * Returns direct children assigned to the default slot.\n * @returns {Array<HTMLElement>}\n */\n getAssignedElements() {\n return this.defaultSlot?.assignedElements?.() || Array.from(this.children);\n }\n\n /**\n * Returns an existing top-level dropdown if present.\n * @returns {HTMLElement|null}\n */\n getExistingDropdown() {\n return this.getAssignedElements().find((element) => element.tagName?.toLowerCase() === 'wje-dropdown') || null;\n }\n\n /**\n * Returns the dropdown that should receive overflow items.\n * @returns {HTMLElement}\n */\n getOverflowDropdown() {\n return this.getExistingDropdown() || this.moreDropdown;\n }\n\n /**\n * Returns the menu used for overflow items.\n * @returns {HTMLElement|null}\n */\n getOverflowMenu() {\n const existingDropdown = this.getExistingDropdown();\n\n if (existingDropdown) {\n return (\n Array.from(existingDropdown.children).find((element) => element.tagName?.toLowerCase() === 'wje-menu') ||\n null\n );\n }\n\n return this.moreMenu;\n }\n\n /**\n * Gets the number of actions that should stay visible.\n * @returns {number}\n */\n getVisibleLimit() {\n const actions = this.getActions();\n\n if (this.isCollapsedByBreakpoint()) {\n return 0;\n }\n\n const maxItems = this.maxItems > 0 ? this.maxItems : actions.length;\n const visibleItems = this.visibleItems;\n const limit = visibleItems === null ? maxItems : Math.min(visibleItems, maxItems);\n\n return Math.max(0, Math.min(limit, actions.length));\n }\n\n /**\n * Returns whether the toolbar action should collapse based on the configured breakpoint.\n * @returns {boolean}\n */\n shouldCollapseByBreakpoint() {\n const breakpointWidth = this.getBreakpointWidth();\n\n if (!breakpointWidth) return false;\n\n return window.innerWidth < breakpointWidth;\n }\n\n /**\n * Returns the cached breakpoint collapse state.\n * @returns {boolean}\n */\n isCollapsedByBreakpoint() {\n if (!this.getBreakpointWidth()) {\n this._isCollapsedByBreakpoint = false;\n return false;\n }\n\n const nextState = this.shouldCollapseByBreakpoint();\n this._isCollapsedByBreakpoint = nextState;\n\n return nextState;\n }\n\n /**\n * Reacts to viewport resize only when the breakpoint mode actually changes.\n * @returns {void}\n */\n handleBreakpointResize() {\n if (!this.getBreakpointWidth()) return;\n\n const nextState = this.shouldCollapseByBreakpoint();\n\n if (this._isCollapsedByBreakpoint === nextState) return;\n\n this._isCollapsedByBreakpoint = nextState;\n this.applyOverflow();\n }\n\n /**\n * Resolves the configured breakpoint to a pixel width.\n * @returns {number|null}\n */\n getBreakpointWidth() {\n if (!this.breakpoint) return null;\n\n const token = this.breakpoint.trim().toLowerCase();\n const cssValue = getComputedStyle(this).getPropertyValue(`--wje-toolbar-action-breakpoint-${token}`).trim();\n const namedBreakpoint = ToolbarAction.BREAKPOINTS[token];\n\n if (cssValue) {\n const cssNumber = parseFloat(cssValue);\n if (Number.isFinite(cssNumber)) return cssNumber;\n }\n\n if (Number.isFinite(namedBreakpoint)) {\n return namedBreakpoint;\n }\n\n const directNumber = parseFloat(token);\n return Number.isFinite(directNumber) ? directNumber : null;\n }\n\n /**\n * Updates visible actions and the overflow dropdown.\n * @returns {void}\n */\n applyOverflow() {\n const actions = this.getActions();\n const visibleLimit = this.getVisibleLimit();\n const overflowActions = actions.slice(visibleLimit);\n const existingDropdown = this.getExistingDropdown();\n const overflowMenu = this.getOverflowMenu();\n\n this.restoreManagedActions(actions);\n this.restoreManagedOverflowContent();\n\n if (!existingDropdown) {\n this.moreMenu?.replaceChildren();\n }\n\n overflowActions.forEach((action) => {\n action.hidden = true;\n action.style.display = 'none';\n this._managedHiddenActions.add(action);\n });\n\n if (overflowMenu && existingDropdown && overflowActions.length > 0 && overflowMenu.children.length > 0) {\n overflowMenu.append(this.createOverflowDivider());\n }\n\n overflowActions.forEach((action) => {\n overflowMenu?.append(this.createMenuItem(action));\n });\n\n if (!existingDropdown && this.moreDropdown) {\n this.moreDropdown.hidden = overflowActions.length === 0;\n } else if (existingDropdown && this.moreDropdown) {\n this.moreDropdown.hidden = true;\n }\n }\n\n /**\n * Restores buttons hidden by this component.\n * @param {Array<HTMLElement>} actions Toolbar buttons.\n */\n restoreManagedActions(actions = this.getActions()) {\n actions.forEach((action) => {\n if (this._managedHiddenActions.has(action)) {\n action.hidden = false;\n action.style.removeProperty('display');\n this._managedHiddenActions.delete(action);\n }\n });\n }\n\n /**\n * Removes overflow menu nodes that were previously injected by this component.\n */\n restoreManagedOverflowContent() {\n const dropdown = this.getExistingDropdown();\n\n if (!dropdown) return;\n\n const menu = this.getOverflowMenu();\n if (!menu) return;\n\n Array.from(menu.children).forEach((child) => {\n if (this._managedOverflowNodes.has(child)) {\n child.remove();\n this._managedOverflowNodes.delete(child);\n }\n });\n }\n\n /**\n * Creates a dropdown menu proxy for an overflowed button.\n * @param {HTMLElement} action The original action button.\n * @returns {HTMLElement}\n */\n createMenuItem(action) {\n let menuItem = document.createElement('wje-menu-item');\n menuItem.innerHTML = action.innerHTML;\n\n if (action.hasAttribute('disabled') || action.getAttribute('aria-disabled') === 'true') {\n menuItem.setAttribute('disabled', '');\n }\n\n menuItem.addEventListener('wje-menu-item:click', (e) => this.handleMenuItemClick(e, action));\n menuItem.addEventListener('click', (e) => this.handleMenuItemClick(e, action));\n this._managedOverflowNodes.add(menuItem);\n\n return menuItem;\n }\n\n /**\n * Creates a divider separating existing dropdown actions from responsive overflow actions.\n * @returns {HTMLElement}\n */\n createOverflowDivider() {\n const divider = document.createElement('wje-divider');\n this._managedOverflowNodes.add(divider);\n return divider;\n }\n\n /**\n * Forwards menu item activation to the original button.\n * @param {Event} e The menu event.\n * @param {HTMLElement} action The original action button.\n */\n handleMenuItemClick(e, action) {\n e.preventDefault?.();\n e.stopPropagation();\n\n if (!action || action.hasAttribute('disabled') || action.getAttribute('aria-disabled') === 'true') return;\n\n action.click();\n }\n\n /**\n * Measures action widths while preserving current overflow state.\n * @returns {{count: number, widths: number[], gap: number, moreWidth: number, getWidthForCount: Function}}\n */\n measureActionMetrics() {\n const actions = this.getActions();\n const hasExistingDropdown = !!this.getExistingDropdown();\n\n this.restoreManagedActions(actions);\n\n const widths = actions.map((action) => action.getBoundingClientRect().width);\n const style = this.native ? getComputedStyle(this.native) : null;\n const gap = style ? parseFloat(style.columnGap || style.gap || '0') || 0 : 0;\n const moreWidth = this.measureMoreWidth();\n\n this.applyOverflow();\n\n return {\n count: actions.length,\n widths,\n gap,\n moreWidth,\n getWidthForCount: (visibleCount) => {\n const count = Math.max(0, Math.min(visibleCount, actions.length));\n const overflowCount = actions.length - count;\n const visibleWidth = widths.slice(0, count).reduce((sum, width) => sum + width, 0);\n const visibleGaps = Math.max(count - 1, 0) * gap;\n const usesDropdown = hasExistingDropdown || overflowCount > 0;\n const moreGap = count > 0 && usesDropdown ? gap : 0;\n\n return visibleWidth + visibleGaps + (usesDropdown ? moreWidth + moreGap : 0);\n },\n };\n }\n\n /**\n * Measures the overflow dropdown trigger.\n * @returns {number}\n */\n measureMoreWidth() {\n const dropdown = this.getOverflowDropdown();\n if (!dropdown) return 48;\n\n const isInternalDropdown = dropdown === this.moreDropdown;\n const wasHidden = dropdown.hidden;\n const previousVisibility = dropdown.style.visibility;\n\n if (isInternalDropdown && wasHidden) {\n dropdown.hidden = false;\n dropdown.style.visibility = 'hidden';\n }\n\n const width = dropdown.getBoundingClientRect().width || 48;\n\n if (isInternalDropdown && wasHidden) {\n dropdown.hidden = true;\n dropdown.style.visibility = previousVisibility;\n }\n\n if (dropdown === this.moreDropdown && this.getExistingDropdown()) {\n this.moreDropdown.hidden = true;\n }\n\n return width;\n }\n}\n","import ToolbarAction from './toolbar-action.element.js';\n\nexport default ToolbarAction;\n\nToolbarAction.define('wje-toolbar-action', ToolbarAction);\n"],"names":[],"mappings":";;;;;AAae,MAAM,iBAAN,MAAM,uBAAsB,UAAU;AAAA;AAAA;AAAA;AAAA,EAajD,cAAc;AACV,UAAK;AAUT;AAAA;AAAA;AAAA;AAAA,qCAAY;AATR,SAAK,wBAAwB,oBAAI,QAAO;AACxC,SAAK,2BAA2B;AAChC,SAAK,wBAAwB,oBAAI,QAAO;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,WAAW,gBAAgB;AACvB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,qBAAqB;AAC5B,WAAO,CAAC,cAAc,aAAa,eAAe;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,WAAW,OAAO;AAClB,QAAI,MAAO,MAAK,aAAa,cAAc,KAAK;AAAA,QAC3C,MAAK,gBAAgB,YAAY;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,aAAa;AACb,WAAO,KAAK,aAAa,YAAY,KAAK;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,SAAS,OAAO;AAChB,SAAK,aAAa,aAAa,SAAS,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,WAAW;AACX,WAAO,CAAC,KAAK,aAAa,WAAW,KAAK;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,aAAa,OAAO;AACpB,QAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,IAAI;AACvD,WAAK,gBAAgB,eAAe;AACpC;AAAA,IACJ;AAEA,SAAK,aAAa,iBAAiB,KAAK;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,eAAe;AACf,QAAI,CAAC,KAAK,aAAa,eAAe,EAAG,QAAO;AAChD,UAAM,QAAQ,CAAC,KAAK,aAAa,eAAe;AAChD,WAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB;AACd,SAAK,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO;AACH,QAAI,WAAW,SAAS,uBAAsB;AAE9C,QAAI,OAAO,SAAS,cAAc,MAAM;AAExC,QAAI,UAAU,SAAS,cAAc,KAAK;AAC1C,YAAQ,aAAa,QAAQ,QAAQ;AACrC,YAAQ,UAAU,IAAI,uBAAuB;AAE7C,QAAI,WAAW,SAAS,cAAc,cAAc;AACpD,aAAS,aAAa,aAAa,YAAY;AAC/C,aAAS,aAAa,eAAe,EAAE;AACvC,aAAS,UAAU,IAAI,qBAAqB;AAC5C,aAAS,SAAS;AAElB,QAAI,UAAU,SAAS,cAAc,YAAY;AACjD,YAAQ,aAAa,QAAQ,SAAS;AACtC,YAAQ,aAAa,QAAQ,MAAM;AACnC,YAAQ,aAAa,cAAc,mBAAmB;AACtD,YAAQ,YAAY;AAEpB,QAAI,OAAO,SAAS,cAAc,UAAU;AAC5C,SAAK,aAAa,WAAW,SAAS;AAEtC,aAAS,OAAO,SAAS,IAAI;AAE7B,YAAQ,YAAY,IAAI;AACxB,YAAQ,YAAY,QAAQ;AAE5B,aAAS,YAAY,OAAO;AAE5B,SAAK,cAAc;AACnB,SAAK,SAAS;AACd,SAAK,eAAe;AACpB,SAAK,WAAW;AAEhB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY;;AACR,SAAK,eAAe,MAAM,KAAK,cAAa;AAC5C,eAAK,gBAAL,mBAAkB,iBAAiB,cAAc,KAAK;AACtD,SAAK,eAAe,MAAM,KAAK,uBAAsB;AAErD,QAAI,KAAK,sBAAsB;AAC3B,aAAO,iBAAiB,UAAU,KAAK,YAAY;AAAA,IACvD;AAEA,SAAK,cAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB;;AACd,eAAK,gBAAL,mBAAkB,oBAAoB,cAAc,KAAK;AACzD,WAAO,oBAAoB,UAAU,KAAK,YAAY;AACtD,SAAK,2BAA2B;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa;AACT,WAAO,KAAK,oBAAmB,EAAG;AAAA,MAC9B,CAAC,YAAO;;AAAK,8BAAQ,YAAR,mBAAiB,mBAAkB,gBAAgB,QAAQ,aAAa,MAAM,MAAM;AAAA;AAAA,IAC7G;AAAA,EACI;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB;;AAClB,aAAO,gBAAK,gBAAL,mBAAkB,qBAAlB,gCAA0C,MAAM,KAAK,KAAK,QAAQ;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB;AAClB,WAAO,KAAK,sBAAsB,KAAK,CAAC;;AAAY,4BAAQ,YAAR,mBAAiB,mBAAkB;AAAA,KAAc,KAAK;AAAA,EAC9G;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB;AAClB,WAAO,KAAK,yBAAyB,KAAK;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB;AACd,UAAM,mBAAmB,KAAK,oBAAmB;AAEjD,QAAI,kBAAkB;AAClB,aACI,MAAM,KAAK,iBAAiB,QAAQ,EAAE,KAAK,CAAC,YAAO;;AAAK,8BAAQ,YAAR,mBAAiB,mBAAkB;AAAA,OAAU,KACrG;AAAA,IAER;AAEA,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB;AACd,UAAM,UAAU,KAAK,WAAU;AAE/B,QAAI,KAAK,2BAA2B;AAChC,aAAO;AAAA,IACX;AAEA,UAAM,WAAW,KAAK,WAAW,IAAI,KAAK,WAAW,QAAQ;AAC7D,UAAM,eAAe,KAAK;AAC1B,UAAM,QAAQ,iBAAiB,OAAO,WAAW,KAAK,IAAI,cAAc,QAAQ;AAEhF,WAAO,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,QAAQ,MAAM,CAAC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,6BAA6B;AACzB,UAAM,kBAAkB,KAAK,mBAAkB;AAE/C,QAAI,CAAC,gBAAiB,QAAO;AAE7B,WAAO,OAAO,aAAa;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,0BAA0B;AACtB,QAAI,CAAC,KAAK,sBAAsB;AAC5B,WAAK,2BAA2B;AAChC,aAAO;AAAA,IACX;AAEA,UAAM,YAAY,KAAK,2BAA0B;AACjD,SAAK,2BAA2B;AAEhC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBAAyB;AACrB,QAAI,CAAC,KAAK,qBAAsB;AAEhC,UAAM,YAAY,KAAK,2BAA0B;AAEjD,QAAI,KAAK,6BAA6B,UAAW;AAEjD,SAAK,2BAA2B;AAChC,SAAK,cAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqB;AACjB,QAAI,CAAC,KAAK,WAAY,QAAO;AAE7B,UAAM,QAAQ,KAAK,WAAW,KAAI,EAAG,YAAW;AAChD,UAAM,WAAW,iBAAiB,IAAI,EAAE,iBAAiB,mCAAmC,KAAK,EAAE,EAAE,KAAI;AACzG,UAAM,kBAAkB,eAAc,YAAY,KAAK;AAEvD,QAAI,UAAU;AACV,YAAM,YAAY,WAAW,QAAQ;AACrC,UAAI,OAAO,SAAS,SAAS,EAAG,QAAO;AAAA,IAC3C;AAEA,QAAI,OAAO,SAAS,eAAe,GAAG;AAClC,aAAO;AAAA,IACX;AAEA,UAAM,eAAe,WAAW,KAAK;AACrC,WAAO,OAAO,SAAS,YAAY,IAAI,eAAe;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB;;AACZ,UAAM,UAAU,KAAK,WAAU;AAC/B,UAAM,eAAe,KAAK,gBAAe;AACzC,UAAM,kBAAkB,QAAQ,MAAM,YAAY;AAClD,UAAM,mBAAmB,KAAK,oBAAmB;AACjD,UAAM,eAAe,KAAK,gBAAe;AAEzC,SAAK,sBAAsB,OAAO;AAClC,SAAK,8BAA6B;AAElC,QAAI,CAAC,kBAAkB;AACnB,iBAAK,aAAL,mBAAe;AAAA,IACnB;AAEA,oBAAgB,QAAQ,CAAC,WAAW;AAChC,aAAO,SAAS;AAChB,aAAO,MAAM,UAAU;AACvB,WAAK,sBAAsB,IAAI,MAAM;AAAA,IACzC,CAAC;AAED,QAAI,gBAAgB,oBAAoB,gBAAgB,SAAS,KAAK,aAAa,SAAS,SAAS,GAAG;AACpG,mBAAa,OAAO,KAAK,uBAAuB;AAAA,IACpD;AAEA,oBAAgB,QAAQ,CAAC,WAAW;AAChC,mDAAc,OAAO,KAAK,eAAe,MAAM;AAAA,IACnD,CAAC;AAED,QAAI,CAAC,oBAAoB,KAAK,cAAc;AACxC,WAAK,aAAa,SAAS,gBAAgB,WAAW;AAAA,IAC1D,WAAW,oBAAoB,KAAK,cAAc;AAC9C,WAAK,aAAa,SAAS;AAAA,IAC/B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB,UAAU,KAAK,cAAc;AAC/C,YAAQ,QAAQ,CAAC,WAAW;AACxB,UAAI,KAAK,sBAAsB,IAAI,MAAM,GAAG;AACxC,eAAO,SAAS;AAChB,eAAO,MAAM,eAAe,SAAS;AACrC,aAAK,sBAAsB,OAAO,MAAM;AAAA,MAC5C;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA,gCAAgC;AAC5B,UAAM,WAAW,KAAK,oBAAmB;AAEzC,QAAI,CAAC,SAAU;AAEf,UAAM,OAAO,KAAK,gBAAe;AACjC,QAAI,CAAC,KAAM;AAEX,UAAM,KAAK,KAAK,QAAQ,EAAE,QAAQ,CAAC,UAAU;AACzC,UAAI,KAAK,sBAAsB,IAAI,KAAK,GAAG;AACvC,cAAM,OAAM;AACZ,aAAK,sBAAsB,OAAO,KAAK;AAAA,MAC3C;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAe,QAAQ;AACnB,QAAI,WAAW,SAAS,cAAc,eAAe;AACrD,aAAS,YAAY,OAAO;AAE5B,QAAI,OAAO,aAAa,UAAU,KAAK,OAAO,aAAa,eAAe,MAAM,QAAQ;AACpF,eAAS,aAAa,YAAY,EAAE;AAAA,IACxC;AAEA,aAAS,iBAAiB,uBAAuB,CAAC,MAAM,KAAK,oBAAoB,GAAG,MAAM,CAAC;AAC3F,aAAS,iBAAiB,SAAS,CAAC,MAAM,KAAK,oBAAoB,GAAG,MAAM,CAAC;AAC7E,SAAK,sBAAsB,IAAI,QAAQ;AAEvC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAAwB;AACpB,UAAM,UAAU,SAAS,cAAc,aAAa;AACpD,SAAK,sBAAsB,IAAI,OAAO;AACtC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAoB,GAAG,QAAQ;;AAC3B,YAAE,mBAAF;AACA,MAAE,gBAAe;AAEjB,QAAI,CAAC,UAAU,OAAO,aAAa,UAAU,KAAK,OAAO,aAAa,eAAe,MAAM,OAAQ;AAEnG,WAAO,MAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAuB;AACnB,UAAM,UAAU,KAAK,WAAU;AAC/B,UAAM,sBAAsB,CAAC,CAAC,KAAK,oBAAmB;AAEtD,SAAK,sBAAsB,OAAO;AAElC,UAAM,SAAS,QAAQ,IAAI,CAAC,WAAW,OAAO,sBAAqB,EAAG,KAAK;AAC3E,UAAM,QAAQ,KAAK,SAAS,iBAAiB,KAAK,MAAM,IAAI;AAC5D,UAAM,MAAM,QAAQ,WAAW,MAAM,aAAa,MAAM,OAAO,GAAG,KAAK,IAAI;AAC3E,UAAM,YAAY,KAAK,iBAAgB;AAEvC,SAAK,cAAa;AAElB,WAAO;AAAA,MACH,OAAO,QAAQ;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAkB,CAAC,iBAAiB;AAChC,cAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,cAAc,QAAQ,MAAM,CAAC;AAChE,cAAM,gBAAgB,QAAQ,SAAS;AACvC,cAAM,eAAe,OAAO,MAAM,GAAG,KAAK,EAAE,OAAO,CAAC,KAAK,UAAU,MAAM,OAAO,CAAC;AACjF,cAAM,cAAc,KAAK,IAAI,QAAQ,GAAG,CAAC,IAAI;AAC7C,cAAM,eAAe,uBAAuB,gBAAgB;AAC5D,cAAM,UAAU,QAAQ,KAAK,eAAe,MAAM;AAElD,eAAO,eAAe,eAAe,eAAe,YAAY,UAAU;AAAA,MAC9E;AAAA,IACZ;AAAA,EACI;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB;AACf,UAAM,WAAW,KAAK,oBAAmB;AACzC,QAAI,CAAC,SAAU,QAAO;AAEtB,UAAM,qBAAqB,aAAa,KAAK;AAC7C,UAAM,YAAY,SAAS;AAC3B,UAAM,qBAAqB,SAAS,MAAM;AAE1C,QAAI,sBAAsB,WAAW;AACjC,eAAS,SAAS;AAClB,eAAS,MAAM,aAAa;AAAA,IAChC;AAEA,UAAM,QAAQ,SAAS,sBAAqB,EAAG,SAAS;AAExD,QAAI,sBAAsB,WAAW;AACjC,eAAS,SAAS;AAClB,eAAS,MAAM,aAAa;AAAA,IAChC;AAEA,QAAI,aAAa,KAAK,gBAAgB,KAAK,oBAAmB,GAAI;AAC9D,WAAK,aAAa,SAAS;AAAA,IAC/B;AAEA,WAAO;AAAA,EACX;AACJ;AA1eI,cADiB,gBACV,eAAc;AAAA,EACjB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,KAAK;AACb;AARe,IAAM,gBAAN;ACTf,cAAc,OAAO,sBAAsB,aAAa;"}
|