From ae6666e3bd1e30f42c314213fd67f257c1990995 Mon Sep 17 00:00:00 2001 From: Andrey Lechev Date: Sun, 7 Jun 2026 01:59:28 +0200 Subject: [PATCH 1/7] Add component to handle context menus --- .../le-context-menu/le-context-menu.css | 64 +++ .../le-context-menu/le-context-menu.spec.tsx | 330 +++++++++++++ .../le-context-menu/le-context-menu.tsx | 448 ++++++++++++++++++ .../src/components/le-context-menu/readme.md | 146 ++++++ .../le-navigation/le-navigation.css | 19 +- .../le-navigation/le-navigation.tsx | 32 +- 6 files changed, 1037 insertions(+), 2 deletions(-) create mode 100644 packages/core/src/components/le-context-menu/le-context-menu.css create mode 100644 packages/core/src/components/le-context-menu/le-context-menu.spec.tsx create mode 100644 packages/core/src/components/le-context-menu/le-context-menu.tsx create mode 100644 packages/core/src/components/le-context-menu/readme.md diff --git a/packages/core/src/components/le-context-menu/le-context-menu.css b/packages/core/src/components/le-context-menu/le-context-menu.css new file mode 100644 index 0000000..4189282 --- /dev/null +++ b/packages/core/src/components/le-context-menu/le-context-menu.css @@ -0,0 +1,64 @@ +:host { + display: contents; +} + +.context-menu-trigger-zone { + display: contents; +} + +.le-context-menu-backdrop { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.45); + backdrop-filter: blur(5px); + -webkit-backdrop-filter: blur(5px); + z-index: 9990; + opacity: 0; + pointer-events: none; + transition: opacity 0.22s cubic-bezier(0.16, 1, 0.3, 1); +} + +:host([open]) .le-context-menu-backdrop { + opacity: 1; + pointer-events: auto; +} + +:host([has-backdrop]) ::slotted(.le-context-menu-active-item) { + position: relative !important; + z-index: 9995 !important; + box-shadow: var(--le-shadow-lg, 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.15)); + transition: transform 0.22s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.22s cubic-bezier(0.16, 1, 0.3, 1); +} + +:host([open][has-backdrop]) ::slotted(.le-context-menu-active-item) { + transform: scale(1.02); +} + +le-popover { + position: fixed !important; + pointer-events: none; + z-index: 9999 !important; +} + +le-popover::part(content) { + pointer-events: auto; + padding: var(--le-spacing-1, 4px); +} + +le-popover::part(trigger) { + width: 100%; + height: 100%; + opacity: 0; + pointer-events: none; +} + +le-navigation { + --le-nav-padding: 0; + --le-nav-item-padding-x: var(--le-spacing-2, 8px); + --le-nav-item-indent: var(--le-spacing-3, 12px); + --le-items-gap: 0; + --le-font-size: var(--le-font-size-sm, 0.875rem); +} diff --git a/packages/core/src/components/le-context-menu/le-context-menu.spec.tsx b/packages/core/src/components/le-context-menu/le-context-menu.spec.tsx new file mode 100644 index 0000000..9a1eef2 --- /dev/null +++ b/packages/core/src/components/le-context-menu/le-context-menu.spec.tsx @@ -0,0 +1,330 @@ +import { beforeAll, describe, expect, it } from '@jest/globals'; +import { newSpecPage } from '@stencil/core/testing'; +import { mockMutationObserver } from '../../utils/test-helpers'; +import { LeContextMenu } from './le-context-menu'; +import { LePopover } from '../le-popover/le-popover'; +import { LeNavigation } from '../le-navigation/le-navigation'; + +beforeAll(() => { + mockMutationObserver(); +}); + +describe('le-context-menu', () => { + it('renders default host structure and properties', async () => { + const page = await newSpecPage({ + components: [LeContextMenu, LePopover, LeNavigation], + html: ` + +
Right click me
+
+ `, + }); + + const host = page.root as any; + expect(host).not.toBeNull(); + expect(host.backdrop).toBe(false); + expect(host.pageScrollBehavior).toBe('fixed-menu'); + expect(host.position).toBe('mouse'); + expect(host.align).toBe('start'); + + const triggerZone = host.shadowRoot?.querySelector('.context-menu-trigger-zone'); + expect(triggerZone).not.toBeNull(); + }); + + it('toggles open state and sets coordinates on right click', async () => { + const page = await newSpecPage({ + components: [LeContextMenu, LePopover, LeNavigation], + html: ` + +
Right click me
+
+ `, + }); + + const host = page.root as any; + const triggerZone = host.shadowRoot?.querySelector('.context-menu-trigger-zone') as HTMLElement; + + expect(host.open).toBe(false); + + // Dispatch contextmenu event + const contextMenuEvent = new MouseEvent('contextmenu', { + bubbles: true, + cancelable: true, + clientX: 100, + clientY: 200, + }); + triggerZone.dispatchEvent(contextMenuEvent); + await page.waitForChanges(); + + expect(host.open).toBe(true); + const popover = host.shadowRoot?.querySelector('le-popover') as HTMLElement; + expect(popover.style.left).toBe('100px'); + expect(popover.style.top).toBe('200px'); + }); + + it('renders backdrop when backdrop prop is set and elevates trigger item', async () => { + const page = await newSpecPage({ + components: [LeContextMenu, LePopover, LeNavigation], + html: ` + +
Right click me
+
+ `, + }); + + const host = page.root as any; + expect(host.backdrop).toBe(true); + expect(host.hasAttribute('has-backdrop')).toBe(true); + + const triggerEl = host.querySelector('.trigger') as HTMLElement; + const triggerZone = host.shadowRoot?.querySelector('.context-menu-trigger-zone') as HTMLElement; + + const component = page.rootInstance as any; + component.activeTriggerEl = triggerEl; + + // Open the menu by clicking the trigger + const contextMenuEvent = new MouseEvent('contextmenu', { + bubbles: true, + cancelable: true, + clientX: 100, + clientY: 200, + }); + triggerZone.dispatchEvent(contextMenuEvent); + await page.waitForChanges(); + + expect(host.open).toBe(true); + + // Verify backdrop element is rendered in shadow DOM + const backdrop = host.shadowRoot?.querySelector('.le-context-menu-backdrop') as HTMLElement; + expect(backdrop).not.toBeNull(); + + // Verify trigger item has the active-item class added to it + expect(triggerEl.classList.contains('le-context-menu-active-item')).toBe(true); + + // Click backdrop to close + backdrop.click(); + await page.waitForChanges(); + + expect(host.open).toBe(false); + }); + + it('does not add class when backdrop prop is false', async () => { + const page = await newSpecPage({ + components: [LeContextMenu, LePopover, LeNavigation], + html: ` + +
Right click me
+
+ `, + }); + + const host = page.root as any; + const triggerEl = host.querySelector('.trigger') as HTMLElement; + const triggerZone = host.shadowRoot?.querySelector('.context-menu-trigger-zone') as HTMLElement; + + const component = page.rootInstance as any; + component.activeTriggerEl = triggerEl; + + const contextMenuEvent = new MouseEvent('contextmenu', { + bubbles: true, + cancelable: true, + clientX: 100, + clientY: 200, + }); + triggerZone.dispatchEvent(contextMenuEvent); + await page.waitForChanges(); + + expect(host.open).toBe(true); + // Since backdrop is false, we should verify the active item class is NOT added, + // and the host does not have has-backdrop attribute. + expect(triggerEl.classList.contains('le-context-menu-active-item')).toBe(false); + expect(host.hasAttribute('has-backdrop')).toBe(false); + }); + + it('closes menu on scroll when pageScrollBehavior is menu-close', async () => { + const page = await newSpecPage({ + components: [LeContextMenu, LePopover, LeNavigation], + html: ` + +
Right click me
+
+ `, + }); + + const host = page.root as any; + const triggerEl = host.querySelector('.trigger') as HTMLElement; + const triggerZone = host.shadowRoot?.querySelector('.context-menu-trigger-zone') as HTMLElement; + + const component = page.rootInstance as any; + component.activeTriggerEl = triggerEl; + + // Open menu + const contextMenuEvent = new MouseEvent('contextmenu', { + bubbles: true, + cancelable: true, + clientX: 100, + clientY: 200, + }); + triggerZone.dispatchEvent(contextMenuEvent); + await page.waitForChanges(); + expect(host.open).toBe(true); + + // Manually trigger popover open callback to set up scroll listener in JSDOM + component.handlePopoverOpen(); + await page.waitForChanges(); + + // Simulate page scroll + const scrollEvent = new Event('scroll', { bubbles: true }); + window.dispatchEvent(scrollEvent); + await page.waitForChanges(); + + expect(host.open).toBe(false); + }); + + it('updates coordinates on scroll when pageScrollBehavior is fixed-menu', async () => { + const page = await newSpecPage({ + components: [LeContextMenu, LePopover, LeNavigation], + html: ` + +
Right click me
+
+ `, + }); + + const host = page.root as any; + const triggerEl = host.querySelector('.trigger') as HTMLElement; + const triggerZone = host.shadowRoot?.querySelector('.context-menu-trigger-zone') as HTMLElement; + + // Mock initial client rects + triggerEl.getBoundingClientRect = () => ({ + top: 100, + left: 100, + width: 100, + height: 50, + bottom: 150, + right: 200, + x: 100, + y: 100, + toJSON: () => {} + } as DOMRect); + + const component = page.rootInstance as any; + component.activeTriggerEl = triggerEl; + + // Open menu + const contextMenuEvent = new MouseEvent('contextmenu', { + bubbles: true, + cancelable: true, + clientX: 150, + clientY: 250, + }); + triggerZone.dispatchEvent(contextMenuEvent); + await page.waitForChanges(); + expect(host.open).toBe(true); + + // Manually trigger popover open callback to set up scroll listener in JSDOM + component.handlePopoverOpen(); + await page.waitForChanges(); + + // Now mock triggerEl moving due to scroll: moves up by 50px (top becomes 50) + triggerEl.getBoundingClientRect = () => ({ + top: 50, + left: 100, + width: 100, + height: 50, + bottom: 100, + right: 200, + x: 100, + y: 50, + toJSON: () => {} + } as DOMRect); + + // Simulate page scroll + const scrollEvent = new Event('scroll', { bubbles: true }); + window.dispatchEvent(scrollEvent); + await page.waitForChanges(); + + // Delta dy = 50 - 100 = -50px. + // New coords-y should be clientY (250) + dy (-50) = 200px. + const popover = host.shadowRoot?.querySelector('le-popover') as HTMLElement; + expect(popover.style.top).toBe('200px'); + expect(popover.style.left).toBe('150px'); + }); + + it('updates coordinates on scroll for touch trigger', async () => { + const page = await newSpecPage({ + components: [LeContextMenu, LePopover, LeNavigation], + html: ` + +
Long press me
+
+ `, + }); + + const host = page.root as any; + const triggerEl = host.querySelector('.trigger') as HTMLElement; + const triggerZone = host.shadowRoot?.querySelector('.context-menu-trigger-zone') as HTMLElement; + + // Mock initial client rects + triggerEl.getBoundingClientRect = () => ({ + top: 100, + left: 100, + width: 100, + height: 50, + bottom: 150, + right: 200, + x: 100, + y: 100, + toJSON: () => {} + } as DOMRect); + + triggerZone.getBoundingClientRect = () => ({ + top: 100, + left: 100, + width: 100, + height: 50, + bottom: 150, + right: 200, + x: 100, + y: 100, + toJSON: () => {} + } as DOMRect); + + const component = page.rootInstance as any; + component.activeTriggerEl = triggerEl; + + // Open menu using touch/show + await component.show(); + await page.waitForChanges(); + expect(host.open).toBe(true); + + // Manually trigger popover open callback to set up scroll listener in JSDOM + component.handlePopoverOpen(); + await page.waitForChanges(); + + // Now mock triggerEl moving due to scroll: moves up by 50px (top becomes 50) + triggerEl.getBoundingClientRect = () => ({ + top: 50, + left: 100, + width: 100, + height: 50, + bottom: 100, + right: 200, + x: 100, + y: 50, + toJSON: () => {} + } as DOMRect); + + // Simulate page scroll + const scrollEvent = new Event('scroll', { bubbles: true }); + window.dispatchEvent(scrollEvent); + await page.waitForChanges(); + + // In touch mode, coordinates should exactly match the moving element box! + const popover = host.shadowRoot?.querySelector('le-popover') as HTMLElement; + expect(popover.style.top).toBe('50px'); + expect(popover.style.left).toBe('100px'); + expect(popover.style.width).toBe('100px'); + expect(popover.style.height).toBe('50px'); + }); +}); diff --git a/packages/core/src/components/le-context-menu/le-context-menu.tsx b/packages/core/src/components/le-context-menu/le-context-menu.tsx new file mode 100644 index 0000000..c2f7329 --- /dev/null +++ b/packages/core/src/components/le-context-menu/le-context-menu.tsx @@ -0,0 +1,448 @@ +import { + Component, + Prop, + State, + Event, + EventEmitter, + Element, + Method, + Watch, + h, + Host, +} from '@stencil/core'; +import type { LeOption } from '../../types/options'; +import { parseOptionInput } from '../../utils/utils'; +import type { LeNavigationItemSelectDetail } from '../le-navigation/le-navigation'; + +export interface LeContextMenuSelectDetail { + id: string; + item: LeOption; + originalEvent: MouseEvent | KeyboardEvent; +} + +/** + * Context menu component that displays a vertical navigation menu + * when the user right-clicks or long-presses on its children. + * + * @slot - Trigger content + */ +@Component({ + tag: 'le-context-menu', + styleUrl: 'le-context-menu.css', + shadow: true, +}) +export class LeContextMenu { + @Element() el!: HTMLElement; + + private popoverEl?: HTMLLePopoverElement; + private navigationEl?: HTMLLeNavigationElement; + private containerEl?: HTMLElement; + private activeTriggerEl?: HTMLElement; + + private touchTimeout?: any; + private startX = 0; + private startY = 0; + private isLongPressActive = false; + private readonly LONG_PRESS_DURATION = 500; // ms + private readonly MOVE_THRESHOLD = 10; // px + + private initialTriggerRect?: DOMRect; + private initialCoords = { x: 0, y: 0 }; + private isMenuOpen = false; + + /** + * Whether the context menu is open. + */ + @Prop({ mutable: true, reflect: true }) open: boolean = false; + + /** + * Disables right-click and touch interactions. + */ + @Prop() disabled: boolean = false; + + /** + * List of menu items represented as options. + */ + @Prop() items: LeOption[] | string = []; + + /** + * Whether to show a backdrop behind the menu, lifting the active item. + */ + @Prop() backdrop: boolean = false; + + /** + * Behavior of the menu on page scroll: + * - 'blocked': blocks page scroll + * - 'menu-close': closes the menu automatically on scroll + * - 'fixed-menu': menu scrolls with the page (default) + */ + @Prop() pageScrollBehavior: 'blocked' | 'menu-close' | 'fixed-menu' = 'fixed-menu'; + + /** + * Position of the menu relative to the trigger. + * If 'mouse', positions next to mouse/touch coords. + */ + @Prop() position: 'top' | 'bottom' | 'left' | 'right' | 'mouse' = 'mouse'; + + /** + * Alignment of the menu relative to the trigger. + */ + @Prop() align: 'start' | 'center' | 'end' = 'start'; + + @State() private coords = { x: 0, y: 0 }; + @State() private lastTriggerType: 'mouse' | 'touch' = 'mouse'; + + /** + * Emitted when a menu item is selected. + */ + @Event({ cancelable: true }) + leContextMenuSelect!: EventEmitter; + + /** + * Emitted when the context menu is closed. + */ + @Event() leContextMenuClose!: EventEmitter; + + @Watch('open') + handleOpenChange(nextOpen: boolean) { + if (nextOpen) { + const triggerEl = this.activeTriggerEl || this.containerEl; + if (triggerEl) { + this.initialTriggerRect = triggerEl.getBoundingClientRect(); + } + this.initialCoords = { ...this.coords }; + + if (this.backdrop && this.activeTriggerEl) { + this.activeTriggerEl.classList.add('le-context-menu-active-item'); + } + } else { + this.initialTriggerRect = undefined; + const el = this.activeTriggerEl; + if (el) { + if (this.backdrop) { + // Remove class after transition completes + setTimeout(() => { + el.classList.remove('le-context-menu-active-item'); + }, 250); + } + this.activeTriggerEl = undefined; + } + } + } + + componentDidUpdate() { + if (this.isMenuOpen) { + void this.popoverEl?.updatePosition(); + } + } + + disconnectedCallback() { + this.removeScrollListener(); + } + + @Method() + async show(x?: number, y?: number) { + if (this.disabled) return; + if (x !== undefined && y !== undefined) { + this.coords = { x, y }; + this.lastTriggerType = 'mouse'; + } else { + if (this.containerEl) { + const rect = this.containerEl.getBoundingClientRect(); + this.coords = { + x: rect.left + rect.width / 2, + y: rect.top + rect.height / 2, + }; + } + this.lastTriggerType = 'touch'; + } + this.open = true; + + requestAnimationFrame(() => { + void this.popoverEl?.updatePosition(); + void this.navigationEl?.focusActiveItem(); + }); + } + + @Method() + async hide() { + this.open = false; + } + + @Method() + async toggle(x?: number, y?: number) { + if (this.open) { + await this.hide(); + } else { + await this.show(x, y); + } + } + + private parseItems(input: LeOption[] | string): LeOption[] { + return parseOptionInput(input, 'le-context-menu', 'items'); + } + + private handlePopoverOpen = () => { + if (this.isMenuOpen) return; + this.isMenuOpen = true; + + if (this.pageScrollBehavior === 'blocked') { + document.body.style.overflow = 'hidden'; + } + + this.addScrollListener(); + + requestAnimationFrame(() => { + void this.navigationEl?.focusActiveItem(); + }); + }; + + private handlePopoverClose = () => { + if (!this.isMenuOpen) return; + this.isMenuOpen = false; + this.open = false; + + if (this.pageScrollBehavior === 'blocked') { + document.body.style.overflow = ''; + } + + this.removeScrollListener(); + + this.leContextMenuClose.emit(); + }; + + private handleScroll = () => { + if (!this.isMenuOpen) return; + + if (this.pageScrollBehavior === 'menu-close') { + void this.hide(); + } else if (this.pageScrollBehavior === 'fixed-menu') { + this.updateCoordsOnScroll(); + } + }; + + private updateCoordsOnScroll() { + if (!this.isMenuOpen) return; + + const triggerEl = this.activeTriggerEl || this.containerEl; + const isTouch = this.lastTriggerType === 'touch'; + const useElementBox = this.position !== 'mouse' || isTouch; + + let x = this.coords.x; + let y = this.coords.y; + let width = 0; + let height = 0; + + if (useElementBox && triggerEl && this.initialTriggerRect) { + const currentRect = triggerEl.getBoundingClientRect(); + x = currentRect.left; + y = currentRect.top; + width = currentRect.width; + height = currentRect.height; + } else if (this.initialTriggerRect && triggerEl) { + const currentRect = triggerEl.getBoundingClientRect(); + const dx = currentRect.left - this.initialTriggerRect.left; + const dy = currentRect.top - this.initialTriggerRect.top; + x = this.initialCoords.x + dx; + y = this.initialCoords.y + dy; + } + + // Direct DOM manipulation to avoid Stencil render cycle on scroll and ensure synchronous layout updates + if (this.popoverEl) { + this.popoverEl.style.left = `${x}px`; + this.popoverEl.style.top = `${y}px`; + this.popoverEl.style.width = `${width}px`; + this.popoverEl.style.height = `${height}px`; + } + + void this.popoverEl?.updatePosition(); + } + + private addScrollListener() { + window.addEventListener('scroll', this.handleScroll, true); + } + + private removeScrollListener() { + window.removeEventListener('scroll', this.handleScroll, true); + } + + private triggerMenu(x: number, y: number, event: MouseEvent | TouchEvent) { + let target = event.target as HTMLElement; + while (target && target.parentElement !== this.el && target !== this.el) { + target = target.parentElement as HTMLElement; + } + + if (target && target !== this.el) { + this.activeTriggerEl = target; + } + + this.lastTriggerType = event.type.startsWith('touch') ? 'touch' : 'mouse'; + this.coords = { x, y }; + this.open = true; + + requestAnimationFrame(() => { + void this.popoverEl?.updatePosition(); + void this.navigationEl?.focusActiveItem(); + }); + } + + private handleTouchStart = (e: TouchEvent) => { + if (this.disabled) return; + const touch = e.touches[0]; + this.startX = touch.clientX; + this.startY = touch.clientY; + this.isLongPressActive = false; + + this.clearTouchTimeout(); + + this.touchTimeout = setTimeout(() => { + this.isLongPressActive = true; + this.triggerMenu(touch.clientX, touch.clientY, e); + }, this.LONG_PRESS_DURATION); + }; + + private handleTouchMove = (e: TouchEvent) => { + if (!this.touchTimeout) return; + const touch = e.touches[0]; + const dx = touch.clientX - this.startX; + const dy = touch.clientY - this.startY; + + if (Math.hypot(dx, dy) > this.MOVE_THRESHOLD) { + this.clearTouchTimeout(); + } + }; + + private handleTouchEnd = (e: TouchEvent) => { + this.clearTouchTimeout(); + if (this.isLongPressActive) { + e.preventDefault(); + setTimeout(() => { + this.isLongPressActive = false; + }, 100); + } + }; + + private clearTouchTimeout() { + if (this.touchTimeout) { + clearTimeout(this.touchTimeout); + this.touchTimeout = undefined; + } + } + + private handleContextMenu = (e: MouseEvent) => { + if (this.disabled) return; + e.preventDefault(); + + if (this.isLongPressActive) { + return; + } + + this.triggerMenu(e.clientX, e.clientY, e); + }; + + private handleNavigationSelect = (event: CustomEvent) => { + const { item, id, originalEvent } = event.detail; + + originalEvent.stopPropagation(); + + if (item.disabled) return; + + if (!item.href && !item.action && (item.children?.length || 0) > 0) { + return; + } + + const emitted = this.leContextMenuSelect.emit({ + id: item.id || id, + item, + originalEvent, + }); + + if (!emitted.defaultPrevented) { + this.open = false; + } + }; + + render() { + const parsedItems = this.parseItems(this.items); + + const triggerEl = this.activeTriggerEl || this.containerEl; + const isTouch = this.lastTriggerType === 'touch'; + const useElementBox = this.position !== 'mouse' || isTouch; + + let x = this.coords.x; + let y = this.coords.y; + let width = 0; + let height = 0; + + if (useElementBox && triggerEl && this.initialTriggerRect) { + const currentRect = triggerEl.getBoundingClientRect(); + x = currentRect.left; + y = currentRect.top; + width = currentRect.width; + height = currentRect.height; + } else if (this.initialTriggerRect && triggerEl) { + const currentRect = triggerEl.getBoundingClientRect(); + const dx = currentRect.left - this.initialTriggerRect.left; + const dy = currentRect.top - this.initialTriggerRect.top; + x = this.initialCoords.x + dx; + y = this.initialCoords.y + dy; + } + + const popoverPosition = this.position === 'mouse' ? (isTouch ? 'bottom' : 'auto') : this.position; + const popoverAlign = this.position === 'mouse' ? (isTouch ? 'center' : 'start') : this.align; + + return ( + +
(this.containerEl = el)} + class="context-menu-trigger-zone" + onContextMenu={this.handleContextMenu} + onTouchStart={this.handleTouchStart} + onTouchMove={this.handleTouchMove} + onTouchEnd={this.handleTouchEnd} + > + +
+ + {this.backdrop && ( +
this.hide()} + /> + )} + + (this.popoverEl = el)} + style={{ + left: `${x}px`, + top: `${y}px`, + width: `${width}px`, + height: `${height}px`, + }} + open={this.open} + position={popoverPosition} + align={popoverAlign} + showClose={false} + closeOnClickOutside={true} + closeOnEscape={true} + minWidth="160px" + onLePopoverOpen={this.handlePopoverOpen} + onLePopoverClose={this.handlePopoverClose} + > +
+ {parsedItems.length > 0 && ( + (this.navigationEl = el)} + orientation="vertical" + toggle-position="end" + items={parsedItems} + onLeNavItemSelect={this.handleNavigationSelect} + /> + )} + + + ); + } +} diff --git a/packages/core/src/components/le-context-menu/readme.md b/packages/core/src/components/le-context-menu/readme.md new file mode 100644 index 0000000..c8159b7 --- /dev/null +++ b/packages/core/src/components/le-context-menu/readme.md @@ -0,0 +1,146 @@ +# le-context-menu + + + + + + +## Overview + +Context menu component that displays a vertical navigation menu +when the user right-clicks or long-presses on its children. + +## Properties + +| Property | Attribute | Description | Type | Default | +| -------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | -------------- | +| `align` | `align` | Alignment of the menu relative to the trigger. | `"center" \| "end" \| "start"` | `'start'` | +| `backdrop` | `backdrop` | Whether to show a backdrop behind the menu, lifting the active item. | `boolean` | `false` | +| `disabled` | `disabled` | Disables right-click and touch interactions. | `boolean` | `false` | +| `items` | `items` | List of menu items represented as options. | `LeOption[] \| string` | `[]` | +| `open` | `open` | Whether the context menu is open. | `boolean` | `false` | +| `pageScrollBehavior` | `page-scroll-behavior` | Behavior of the menu on page scroll: - 'blocked': blocks page scroll - 'menu-close': closes the menu automatically on scroll - 'fixed-menu': menu scrolls with the page (default) | `"blocked" \| "fixed-menu" \| "menu-close"` | `'fixed-menu'` | +| `position` | `position` | Position of the menu relative to the trigger. If 'mouse', positions next to mouse/touch coords. | `"bottom" \| "left" \| "mouse" \| "right" \| "top"` | `'mouse'` | + + +## Events + +| Event | Description | Type | +| --------------------- | ---------------------------------------- | ---------------------------------------- | +| `leContextMenuClose` | Emitted when the context menu is closed. | `CustomEvent` | +| `leContextMenuSelect` | Emitted when a menu item is selected. | `CustomEvent` | + + +## Methods + +### `hide() => Promise` + + + +#### Returns + +Type: `Promise` + + + +### `show(x?: number, y?: number) => Promise` + + + +#### Parameters + +| Name | Type | Description | +| ---- | --------------------- | ----------- | +| `x` | `number \| undefined` | | +| `y` | `number \| undefined` | | + +#### Returns + +Type: `Promise` + + + +### `toggle(x?: number, y?: number) => Promise` + + + +#### Parameters + +| Name | Type | Description | +| ---- | --------------------- | ----------- | +| `x` | `number \| undefined` | | +| `y` | `number \| undefined` | | + +#### Returns + +Type: `Promise` + + + + +## Slots + +| Slot | Description | +| ---- | --------------- | +| | Trigger content | + + +## Dependencies + +### Depends on + +- [le-popover](../le-popover) +- [le-navigation](../le-navigation) + +### Graph +```mermaid +graph TD; + le-context-menu --> le-popover + le-context-menu --> le-navigation + le-navigation --> le-icon + le-navigation --> le-string-input + le-navigation --> le-collapse + le-navigation --> le-popover + le-navigation --> le-bar + le-navigation --> le-component + le-string-input --> le-component + le-string-input --> le-button + le-string-input --> le-icon + le-string-input --> le-slot + le-component --> le-button + le-component --> le-select + le-component --> le-checkbox + le-component --> le-string-input + le-component --> le-popover + le-component --> le-popup + le-button --> le-icon + le-button --> le-visibility + le-button --> le-slot + le-button --> le-component + le-button --> le-tooltip + le-slot --> le-popover + le-slot --> le-button + le-slot --> le-string-input + le-tooltip --> le-component + le-select --> le-component + le-select --> le-dropdown-base + le-select --> le-button + le-dropdown-base --> le-popover + le-checkbox --> le-component + le-checkbox --> le-slot + le-popup --> le-slot + le-popup --> le-button + le-popup --> le-component + le-collapse --> le-component + le-bar --> le-icon + le-bar --> le-overflow-menu + le-overflow-menu --> le-navigation + le-overflow-menu --> le-popover + le-overflow-menu --> le-button + le-overflow-menu --> le-icon + style le-context-menu fill:#f9f,stroke:#333,stroke-width:4px +``` + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/packages/core/src/components/le-navigation/le-navigation.css b/packages/core/src/components/le-navigation/le-navigation.css index 9ee768a..dd9cd02 100644 --- a/packages/core/src/components/le-navigation/le-navigation.css +++ b/packages/core/src/components/le-navigation/le-navigation.css @@ -84,7 +84,7 @@ padding: 0; display: flex; flex-direction: column; - gap: var(--le-spacing-1); + gap: var(--le-items-gap, var(--le-spacing-1)); } .nav-row { @@ -469,3 +469,20 @@ le-popover::part(content) { padding: var(--le-spacing-1); } + +.nav-check-icon { + flex-shrink: 0; + width: 16px; + height: 16px; + display: inline-flex; + align-items: center; + justify-content: center; + color: currentColor; +} + +.nav-check-spacer { + flex-shrink: 0; + width: 16px; + height: 16px; + display: inline-block; +} diff --git a/packages/core/src/components/le-navigation/le-navigation.tsx b/packages/core/src/components/le-navigation/le-navigation.tsx index ee4cb00..aab9241 100644 --- a/packages/core/src/components/le-navigation/le-navigation.tsx +++ b/packages/core/src/components/le-navigation/le-navigation.tsx @@ -209,7 +209,7 @@ export class LeNavigation { private pendingInitialScrollFrame?: number; private renderLabel(label: string | HTMLCollection) { - if (label instanceof HTMLCollection) { + if (typeof HTMLCollection !== 'undefined' && label instanceof HTMLCollection) { const div = document.createElement('div'); Array.from(label).forEach(n => div.appendChild(n.cloneNode(true))); label = div.innerHTML; @@ -221,9 +221,13 @@ export class LeNavigation { } private renderIcon(icon: string) { + console.log('Rendering icon:', icon); if (icon.includes('<')) { return ; } + if (icon.length > 3) { + return ; + } return icon; } @@ -1150,6 +1154,7 @@ export class LeNavigation { const filtered = query ? this.filterTree(items, query, pathPrefix, openFromSearch) : items; const ancestorLeadingSlots = leadingToggleAncestors ?? 0; const levelHasChildren = filtered.some(item => this.getChildItems(item).length > 0); + const hasCheckableItems = filtered.some(item => item.checked !== undefined); const topLevelEndToggles = depth === 0 && this.togglePosition === 'end'; const useLeadingToggleSlot = !topLevelEndToggles && levelHasChildren; const firstEnabledId = filtered.find(item => !item.disabled) @@ -1275,6 +1280,12 @@ export class LeNavigation { {useLeadingToggleSlot && !hasChildren && (
+
+

Context Menu Component

+

Right-click on desktop or long-press on mobile to show context menus. Supports checkmarks and backdrop elevation.

+
+
+ + +
+ Right-Click / Long-Press Here +
+
+
+ +
+ + +
+ Right-Click / Long-Press (Backdrop) +
+
+
+
+
+

Tooltip Component

Hover on desktop or long-press on touch devices. Uses top-layer popover behavior with viewport-aware positioning.

From 703314006a654d96a525a3dbf382574d871667ab Mon Sep 17 00:00:00 2001 From: Andrey Lechev Date: Sun, 7 Jun 2026 14:22:01 +0200 Subject: [PATCH 3/7] Fixes for the PR #2 --- packages/core/src/assets/custom-elements.json | 5518 ++++++++--------- packages/core/src/components.d.ts | 8 +- .../le-context-menu/le-context-menu.css | 3 - .../le-context-menu/le-context-menu.tsx | 15 +- .../le-navigation/le-navigation.tsx | 1 - packages/core/src/themes/index.css | 7 + packages/core/src/utils/constants.ts | 13 + 7 files changed, 2790 insertions(+), 2775 deletions(-) create mode 100644 packages/core/src/utils/constants.ts diff --git a/packages/core/src/assets/custom-elements.json b/packages/core/src/assets/custom-elements.json index 19ebe7e..dc877ed 100644 --- a/packages/core/src/assets/custom-elements.json +++ b/packages/core/src/assets/custom-elements.json @@ -1840,32 +1840,12 @@ }, { "kind": "javascript-module", - "path": "src/components/le-button-group/le-button-group.tsx", + "path": "src/components/le-breadcrumbs/le-breadcrumbs.tsx", "declarations": [ { "kind": "class", - "description": "Groups multiple `le-button` elements and optionally collapses low-priority actions\ninto an overflow \"more\" menu.", - "name": "LeButtonGroup", - "cssParts": [ - { - "description": "The grouped buttons frame", - "name": "group" - }, - { - "description": "The overflow trigger button", - "name": "more-button" - } - ], - "slots": [ - { - "description": "Group button elements (`le-button` children)", - "name": "" - }, - { - "description": "Custom icon/content for the overflow trigger button", - "name": "more" - } - ], + "description": "", + "name": "LeBreadcrumbs", "members": [ { "kind": "field", @@ -1876,111 +1856,112 @@ }, { "kind": "field", - "name": "label", + "name": "items", "type": { - "text": "string | undefined" + "text": "LeOption[] | string" }, - "description": "Optional label used when the whole group is represented as a parent item\ninside another component's overflow menu." + "default": "[]", + "description": "Breadcrumb items (supports JSON string)." }, { "kind": "field", - "name": "collapse", + "name": "label", "type": { - "text": "boolean | number | string | undefined" + "text": "string" }, - "description": "Collapse mode.\n\n- `true`: show only the top-priority button\n- positive number: show top N buttons\n- `0`: show only the more button\n- negative number: hide abs(N) lowest-priority buttons\n\nNon-integers are rounded with `Math.round`." + "default": "'Breadcrumbs'", + "description": "Accessible label for the breadcrumbs navigation." }, { "kind": "field", - "name": "overflowIcons", + "name": "separatorIcon", "type": { - "text": "boolean" + "text": "string" }, - "default": "false", - "description": "When true, icons from collapsed buttons are shown in the overflow navigation list." + "default": "'chevron-right'", + "description": "Separator icon name (used if no separator slot is provided)." }, { "kind": "field", - "name": "disabled", + "name": "overflowMode", "type": { - "text": "boolean" + "text": "'collapse' | 'wrap' | 'scroll'" }, - "default": "false", - "description": "Disabled attribute, when the button group is disabled,\nall buttons inside will be disabled and the overflow menu will not be accessible." + "default": "'collapse'", + "description": "Overflow behavior: collapse (default), wrap, or scroll." }, { "kind": "field", - "name": "visibility", + "name": "minVisibleItems", "type": { - "text": "'visible' | 'collapsing' | 'collapsed' | 'expanding'" + "text": "number" }, - "default": "'visible'", - "description": "Visibility state used by responsive containers such as le-toolbar." + "default": "2", + "description": "Minimum visible items before collapsing." }, { "kind": "field", - "name": "overflowItems", + "name": "hiddenIndices", "type": { - "text": "LeOption[]" + "text": "number[]" }, "privacy": "private", "default": "[]" }, { "kind": "field", - "name": "hasOverflow", + "name": "separatorTemplate", "type": { - "text": "boolean" + "text": "string" }, "privacy": "private", - "default": "false" + "default": "''" }, { "kind": "field", - "name": "buttonSlots", + "name": "declarativeItems", "type": { - "text": "string[]" + "text": "LeOption[]" }, "privacy": "private", "default": "[]" }, { "kind": "field", - "name": "mutationObserver", + "name": "isDeclarativeMode", "type": { - "text": "MutationObserver | undefined" + "text": "boolean" }, - "privacy": "private" + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "instanceId", + "name": "listEl", "type": { - "text": "string" + "text": "HTMLElement | undefined" }, "privacy": "private" }, { "kind": "field", - "name": "syncingLayout", + "name": "resizeObserver", "type": { - "text": "boolean" + "text": "ResizeObserver | undefined" }, - "privacy": "private", - "default": "false" + "privacy": "private" }, { "kind": "field", - "name": "pendingSync", + "name": "instanceId", "type": { - "text": "boolean" + "text": "string" }, - "privacy": "private", - "default": "false" + "privacy": "private" }, { "kind": "field", - "name": "hasAuthorCollapse", + "name": "recomputeQueued", "type": { "text": "boolean" }, @@ -1989,262 +1970,143 @@ }, { "kind": "field", - "name": "buttonMap", + "name": "mutationObserver", "type": { - "text": "Map" + "text": "MutationObserver | undefined" }, - "privacy": "private", - "default": "new Map()" - }, - { - "kind": "method", - "name": "handleCollapseChange" - }, - { - "kind": "method", - "name": "handleOverflowIconsChange" + "privacy": "private" }, { "kind": "method", - "name": "handleDisabledChange", + "name": "handleGeneralSlotChange", "parameters": [ { - "name": "newValue", + "name": "ev", "type": { - "text": "boolean" + "text": "Event" } } ] }, { "kind": "method", - "name": "getItemsMeta", - "return": { - "type": { - "text": "Promise" - } - } - }, - { - "kind": "method", - "name": "getToolbarOverflowGroupOption", - "return": { - "type": { - "text": "Promise" - } - } + "name": "buildDeclarativeItems", + "privacy": "private" }, { "kind": "method", - "name": "whenLayoutSettled", - "return": { - "type": { - "text": "Promise" - } - } + "name": "handleInputsChange" }, { "kind": "method", - "name": "getToolbarOverflowItems", - "return": { - "type": { - "text": "Promise" - } - } + "name": "setupResizeObserver", + "privacy": "private" }, { - "kind": "method", - "name": "getCollapseMeta", - "return": { - "type": { - "text": "Promise" - } + "kind": "field", + "name": "parsedItems", + "type": { + "text": "LeOption[]" }, - "description": "Returns collapse meta for toolbar integration." - }, - { - "kind": "method", - "name": "getButtonChildren", "privacy": "private", - "return": { - "type": { - "text": "HTMLElement[]" - } - } + "readonly": true }, { "kind": "method", - "name": "syncButtonSlots", + "name": "getItemId", "privacy": "private", "return": { "type": { - "text": "string[]" + "text": "string" } }, "parameters": [ { - "name": "buttons", + "name": "item", "type": { - "text": "HTMLElement[]" + "text": "LeOption" + } + }, + { + "name": "index", + "type": { + "text": "number" } } ] }, + { + "kind": "field", + "name": "handleSeparatorSlotChange", + "privacy": "private" + }, { "kind": "method", - "name": "getVisibilityState", + "name": "scheduleOverflowRecompute", + "privacy": "private" + }, + { + "kind": "method", + "name": "nextFrame", "privacy": "private", "return": { "type": { - "text": "'visible' | 'collapsed'" + "text": "Promise" } - }, + } + }, + { + "kind": "method", + "name": "recomputeOverflow", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleItemClick", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleKeyDown", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderSeparator", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderItem", + "privacy": "private", "parameters": [ { - "name": "value", + "name": "item", "type": { - "text": "string | null" + "text": "LeOption" + } + }, + { + "name": "index", + "type": { + "text": "number" } } ] }, { "kind": "method", - "name": "setDisabledState", + "name": "renderMore", "privacy": "private", "parameters": [ { - "name": "disabled", + "name": "hiddenItems", "type": { - "text": "boolean" + "text": "LeOption[]" } } ] }, - { - "kind": "method", - "name": "getGroupLabel", - "privacy": "private", - "return": { - "type": { - "text": "string" - } - } - }, - { - "kind": "method", - "name": "isFullyCollapsed", - "privacy": "private", - "return": { - "type": { - "text": "boolean" - } - } - }, - { - "kind": "method", - "name": "getToolbarVisibleCountsSync", - "privacy": "private", - "return": { - "type": { - "text": "number[]" - } - } - }, - { - "kind": "method", - "name": "getButtonId", - "privacy": "private", - "return": { - "type": { - "text": "string" - } - }, - "parameters": [ - { - "name": "button", - "type": { - "text": "HTMLElement" - } - }, - { - "name": "index", - "type": { - "text": "number" - } - } - ] - }, - { - "kind": "method", - "name": "getButtonPriority", - "privacy": "private", - "return": { - "type": { - "text": "number" - } - }, - "parameters": [ - { - "name": "button", - "type": { - "text": "HTMLElement" - } - }, - { - "name": "index", - "type": { - "text": "number" - } - } - ] - }, - { - "kind": "method", - "name": "parseCollapseValue", - "privacy": "private", - "return": { - "type": { - "text": "{ active: boolean; visibleCount: number }" - } - }, - "parameters": [ - { - "name": "totalButtons", - "type": { - "text": "number" - } - } - ] - }, - { - "kind": "method", - "name": "buildOverflowOption", - "privacy": "private", - "return": { - "type": { - "text": "Promise" - } - }, - "parameters": [ - { - "name": "item", - "type": { - "text": "RankedButton" - } - } - ] - }, - { - "kind": "method", - "name": "syncLayout", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleOverflowSelect", - "privacy": "private" - }, { "kind": "method", "name": "render" @@ -2252,56 +2114,59 @@ ], "attributes": [ { - "name": "label", - "fieldName": "label", - "description": "Optional label used when the whole group is represented as a parent item\ninside another component's overflow menu.", + "name": "items", + "fieldName": "items", + "default": "[]", + "description": "Breadcrumb items (supports JSON string).", "type": { - "text": "string" + "text": "LeOption[] | string" } }, { - "name": "collapse", - "fieldName": "collapse", - "description": "Collapse mode.\n\n- `true`: show only the top-priority button\n- positive number: show top N buttons\n- `0`: show only the more button\n- negative number: hide abs(N) lowest-priority buttons\n\nNon-integers are rounded with `Math.round`.", + "name": "label", + "fieldName": "label", + "default": "'Breadcrumbs'", + "description": "Accessible label for the breadcrumbs navigation.", "type": { - "text": "boolean | number | string" + "text": "string" } }, { - "name": "overflow-icons", - "fieldName": "overflowIcons", - "default": "false", - "description": "When true, icons from collapsed buttons are shown in the overflow navigation list.", + "name": "separator-icon", + "fieldName": "separatorIcon", + "default": "'chevron-right'", + "description": "Separator icon name (used if no separator slot is provided).", "type": { - "text": "boolean" + "text": "string" } }, { - "name": "disabled", - "fieldName": "disabled", - "default": "false", - "description": "Disabled attribute, when the button group is disabled,\nall buttons inside will be disabled and the overflow menu will not be accessible.", + "name": "overflow-mode", + "fieldName": "overflowMode", + "default": "'collapse'", + "description": "Overflow behavior: collapse (default), wrap, or scroll.", "type": { - "text": "boolean" + "text": "'collapse' | 'wrap' | 'scroll'" } }, { - "name": "visibility", - "fieldName": "visibility", - "default": "'visible'", - "description": "Visibility state used by responsive containers such as le-toolbar.", + "name": "min-visible-items", + "fieldName": "minVisibleItems", + "default": "2", + "description": "Minimum visible items before collapsing.", "type": { - "text": "'visible' | 'collapsing' | 'collapsed' | 'expanding'" + "text": "number" } } ], - "tagName": "le-button-group", + "tagName": "le-breadcrumbs", "events": [ { - "name": "leOverflowSelect", + "name": "leBreadcrumbSelect", "type": { - "text": "EventEmitter<{ id: string }>" - } + "text": "EventEmitter" + }, + "description": "Emitted when a breadcrumb item is selected." } ], "customElement": true @@ -2310,18 +2175,18 @@ "exports": [ { "kind": "js", - "name": "LeButtonGroup", + "name": "LeBreadcrumbs", "declaration": { - "name": "LeButtonGroup", - "module": "src/components/le-button-group/le-button-group.tsx" + "name": "LeBreadcrumbs", + "module": "src/components/le-breadcrumbs/le-breadcrumbs.tsx" } }, { "kind": "custom-element-definition", - "name": "le-button-group", + "name": "le-breadcrumbs", "declaration": { - "name": "LeButtonGroup", - "module": "src/components/le-button-group/le-button-group.tsx" + "name": "LeBreadcrumbs", + "module": "src/components/le-breadcrumbs/le-breadcrumbs.tsx" } } ] @@ -2461,38 +2326,30 @@ }, { "kind": "javascript-module", - "path": "src/components/le-checkbox/le-checkbox.tsx", + "path": "src/components/le-button-group/le-button-group.tsx", "declarations": [ { "kind": "class", - "description": "A checkbox component with support for labels, descriptions, and external IDs.", - "name": "LeCheckbox", - "cssProperties": [ - { - "description": "Size of the checkbox input", - "name": "--le-checkbox-size" - }, - { - "description": "Color of the checkbox when checked", - "name": "--le-checkbox-color" - }, + "description": "Groups multiple `le-button` elements and optionally collapses low-priority actions\ninto an overflow \"more\" menu.", + "name": "LeButtonGroup", + "cssParts": [ { - "description": "Color of the label text", - "name": "--le-checkbox-label-color" + "description": "The grouped buttons frame", + "name": "group" }, { - "description": "Color of the description text", - "name": "--le-checkbox-desc-color" + "description": "The overflow trigger button", + "name": "more-button" } ], "slots": [ { - "description": "The label text for the checkbox", + "description": "Group button elements (`le-button` children)", "name": "" }, { - "description": "Additional description text displayed below the label", - "name": "description" + "description": "Custom icon/content for the overflow trigger button", + "name": "more" } ], "members": [ @@ -2505,241 +2362,111 @@ }, { "kind": "field", - "name": "id", + "name": "label", "type": { - "text": "string" + "text": "string | undefined" }, - "default": "`le-checkbox-${Math.random().toString(36).substring(2, 9)}`", - "description": "The ID of the checkbox input. This is used for linking the label to the input for accessibility.\nIn case there is no ID provided, a random one will be generated internally." + "description": "Optional label used when the whole group is represented as a parent item\ninside another component's overflow menu." }, { "kind": "field", - "name": "checked", + "name": "collapse", "type": { - "text": "boolean" + "text": "boolean | number | string | undefined" }, - "default": "false", - "description": "Whether the checkbox is checked" + "description": "Collapse mode.\n\n- `true`: show only the top-priority button\n- positive number: show top N buttons\n- `0`: show only the more button\n- negative number: hide abs(N) lowest-priority buttons\n\nNon-integers are rounded with `Math.round`." }, { "kind": "field", - "name": "disabled", + "name": "overflowIcons", "type": { "text": "boolean" }, "default": "false", - "description": "Whether the checkbox is disabled" + "description": "When true, icons from collapsed buttons are shown in the overflow navigation list." }, { "kind": "field", - "name": "name", + "name": "disabled", "type": { - "text": "string | undefined" + "text": "boolean" }, - "description": "The name of the checkbox input" + "default": "false", + "description": "Disabled attribute, when the button group is disabled,\nall buttons inside will be disabled and the overflow menu will not be accessible." }, { "kind": "field", - "name": "value", + "name": "visibility", "type": { - "text": "string | undefined" + "text": "'visible' | 'collapsing' | 'collapsed' | 'expanding'" }, - "description": "The value of the checkbox input" + "default": "'visible'", + "description": "Visibility state used by responsive containers such as le-toolbar." }, { "kind": "field", - "name": "externalId", + "name": "overflowItems", "type": { - "text": "string | undefined" + "text": "LeOption[]" }, - "description": "External ID for linking with external systems (e.g. database ID, PDF form field ID)" + "privacy": "private", + "default": "[]" }, { "kind": "field", - "name": "handleChange", - "privacy": "private" - }, - { - "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "id", - "fieldName": "id", - "default": "`le-checkbox-${Math.random().toString(36).substring(2, 9)}`", - "description": "The ID of the checkbox input. This is used for linking the label to the input for accessibility.\nIn case there is no ID provided, a random one will be generated internally.", - "type": { - "text": "string" - } - }, - { - "name": "checked", - "fieldName": "checked", - "default": "false", - "description": "Whether the checkbox is checked", - "type": { - "text": "boolean" - } - }, - { - "name": "disabled", - "fieldName": "disabled", - "default": "false", - "description": "Whether the checkbox is disabled", + "name": "hasOverflow", "type": { "text": "boolean" - } - }, - { - "name": "name", - "fieldName": "name", - "description": "The name of the checkbox input", - "type": { - "text": "string" - } - }, - { - "name": "value", - "fieldName": "value", - "description": "The value of the checkbox input", - "type": { - "text": "string" - } - }, - { - "name": "external-id", - "fieldName": "externalId", - "description": "External ID for linking with external systems (e.g. database ID, PDF form field ID)", - "type": { - "text": "string" - } - } - ], - "tagName": "le-checkbox", - "events": [ - { - "name": "change", - "type": { - "text": "EventEmitter<{\n checked: boolean;\n value?: string;\n name?: string;\n externalId?: string;\n }>" }, - "description": "Emitted when the checked state changes" - } - ], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeCheckbox", - "declaration": { - "name": "LeCheckbox", - "module": "src/components/le-checkbox/le-checkbox.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-checkbox", - "declaration": { - "name": "LeCheckbox", - "module": "src/components/le-checkbox/le-checkbox.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-breadcrumbs/le-breadcrumbs.tsx", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "LeBreadcrumbs", - "members": [ - { - "kind": "field", - "name": "el", - "type": { - "text": "HTMLElement" - } + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "items", + "name": "buttonSlots", "type": { - "text": "LeOption[] | string" + "text": "string[]" }, - "default": "[]", - "description": "Breadcrumb items (supports JSON string)." + "privacy": "private", + "default": "[]" }, { "kind": "field", - "name": "label", + "name": "mutationObserver", "type": { - "text": "string" + "text": "MutationObserver | undefined" }, - "default": "'Breadcrumbs'", - "description": "Accessible label for the breadcrumbs navigation." + "privacy": "private" }, { "kind": "field", - "name": "separatorIcon", + "name": "instanceId", "type": { "text": "string" }, - "default": "'chevron-right'", - "description": "Separator icon name (used if no separator slot is provided)." - }, - { - "kind": "field", - "name": "overflowMode", - "type": { - "text": "'collapse' | 'wrap' | 'scroll'" - }, - "default": "'collapse'", - "description": "Overflow behavior: collapse (default), wrap, or scroll." - }, - { - "kind": "field", - "name": "minVisibleItems", - "type": { - "text": "number" - }, - "default": "2", - "description": "Minimum visible items before collapsing." - }, - { - "kind": "field", - "name": "hiddenIndices", - "type": { - "text": "number[]" - }, - "privacy": "private", - "default": "[]" + "privacy": "private" }, { "kind": "field", - "name": "separatorTemplate", + "name": "syncingLayout", "type": { - "text": "string" + "text": "boolean" }, "privacy": "private", - "default": "''" + "default": "false" }, { "kind": "field", - "name": "declarativeItems", + "name": "pendingSync", "type": { - "text": "LeOption[]" + "text": "boolean" }, "privacy": "private", - "default": "[]" + "default": "false" }, { "kind": "field", - "name": "isDeclarativeMode", + "name": "hasAuthorCollapse", "type": { "text": "boolean" }, @@ -2748,153 +2475,206 @@ }, { "kind": "field", - "name": "listEl", - "type": { - "text": "HTMLElement | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "resizeObserver", - "type": { - "text": "ResizeObserver | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "instanceId", + "name": "buttonMap", "type": { - "text": "string" + "text": "Map" }, - "privacy": "private" + "privacy": "private", + "default": "new Map()" }, { - "kind": "field", - "name": "recomputeQueued", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" + "kind": "method", + "name": "handleCollapseChange" }, { - "kind": "field", - "name": "mutationObserver", - "type": { - "text": "MutationObserver | undefined" - }, - "privacy": "private" + "kind": "method", + "name": "handleOverflowIconsChange" }, { "kind": "method", - "name": "handleGeneralSlotChange", + "name": "handleDisabledChange", "parameters": [ { - "name": "ev", + "name": "newValue", "type": { - "text": "Event" + "text": "boolean" } } ] }, { "kind": "method", - "name": "buildDeclarativeItems", - "privacy": "private" + "name": "getItemsMeta", + "return": { + "type": { + "text": "Promise" + } + } }, { "kind": "method", - "name": "handleInputsChange" + "name": "getToolbarOverflowGroupOption", + "return": { + "type": { + "text": "Promise" + } + } }, { "kind": "method", - "name": "setupResizeObserver", - "privacy": "private" + "name": "whenLayoutSettled", + "return": { + "type": { + "text": "Promise" + } + } }, { - "kind": "field", - "name": "parsedItems", - "type": { - "text": "LeOption[]" - }, - "privacy": "private", - "readonly": true + "kind": "method", + "name": "getToolbarOverflowItems", + "return": { + "type": { + "text": "Promise" + } + } }, { "kind": "method", - "name": "getItemId", - "privacy": "private", + "name": "getCollapseMeta", "return": { "type": { - "text": "string" + "text": "Promise" + } + }, + "description": "Returns collapse meta for toolbar integration." + }, + { + "kind": "method", + "name": "getButtonChildren", + "privacy": "private", + "return": { + "type": { + "text": "HTMLElement[]" + } + } + }, + { + "kind": "method", + "name": "syncButtonSlots", + "privacy": "private", + "return": { + "type": { + "text": "string[]" } }, "parameters": [ { - "name": "item", + "name": "buttons", "type": { - "text": "LeOption" + "text": "HTMLElement[]" } - }, + } + ] + }, + { + "kind": "method", + "name": "getVisibilityState", + "privacy": "private", + "return": { + "type": { + "text": "'visible' | 'collapsed'" + } + }, + "parameters": [ { - "name": "index", + "name": "value", "type": { - "text": "number" + "text": "string | null" } } ] }, - { - "kind": "field", - "name": "handleSeparatorSlotChange", - "privacy": "private" - }, { "kind": "method", - "name": "scheduleOverflowRecompute", - "privacy": "private" + "name": "setDisabledState", + "privacy": "private", + "parameters": [ + { + "name": "disabled", + "type": { + "text": "boolean" + } + } + ] }, { "kind": "method", - "name": "nextFrame", + "name": "getGroupLabel", "privacy": "private", "return": { "type": { - "text": "Promise" + "text": "string" } } }, { "kind": "method", - "name": "recomputeOverflow", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleItemClick", - "privacy": "private" + "name": "isFullyCollapsed", + "privacy": "private", + "return": { + "type": { + "text": "boolean" + } + } }, { - "kind": "field", - "name": "handleKeyDown", - "privacy": "private" + "kind": "method", + "name": "getToolbarVisibleCountsSync", + "privacy": "private", + "return": { + "type": { + "text": "number[]" + } + } }, { "kind": "method", - "name": "renderSeparator", - "privacy": "private" + "name": "getButtonId", + "privacy": "private", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "button", + "type": { + "text": "HTMLElement" + } + }, + { + "name": "index", + "type": { + "text": "number" + } + } + ] }, { "kind": "method", - "name": "renderItem", + "name": "getButtonPriority", "privacy": "private", + "return": { + "type": { + "text": "number" + } + }, "parameters": [ { - "name": "item", + "name": "button", "type": { - "text": "LeOption" + "text": "HTMLElement" } }, { @@ -2907,17 +2687,50 @@ }, { "kind": "method", - "name": "renderMore", + "name": "parseCollapseValue", "privacy": "private", + "return": { + "type": { + "text": "{ active: boolean; visibleCount: number }" + } + }, "parameters": [ { - "name": "hiddenItems", + "name": "totalButtons", "type": { - "text": "LeOption[]" + "text": "number" } } ] }, + { + "kind": "method", + "name": "buildOverflowOption", + "privacy": "private", + "return": { + "type": { + "text": "Promise" + } + }, + "parameters": [ + { + "name": "item", + "type": { + "text": "RankedButton" + } + } + ] + }, + { + "kind": "method", + "name": "syncLayout", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleOverflowSelect", + "privacy": "private" + }, { "kind": "method", "name": "render" @@ -2925,59 +2738,246 @@ ], "attributes": [ { - "name": "items", - "fieldName": "items", - "default": "[]", - "description": "Breadcrumb items (supports JSON string).", + "name": "label", + "fieldName": "label", + "description": "Optional label used when the whole group is represented as a parent item\ninside another component's overflow menu.", "type": { - "text": "LeOption[] | string" + "text": "string" } }, { - "name": "label", - "fieldName": "label", - "default": "'Breadcrumbs'", - "description": "Accessible label for the breadcrumbs navigation.", + "name": "collapse", + "fieldName": "collapse", + "description": "Collapse mode.\n\n- `true`: show only the top-priority button\n- positive number: show top N buttons\n- `0`: show only the more button\n- negative number: hide abs(N) lowest-priority buttons\n\nNon-integers are rounded with `Math.round`.", + "type": { + "text": "boolean | number | string" + } + }, + { + "name": "overflow-icons", + "fieldName": "overflowIcons", + "default": "false", + "description": "When true, icons from collapsed buttons are shown in the overflow navigation list.", + "type": { + "text": "boolean" + } + }, + { + "name": "disabled", + "fieldName": "disabled", + "default": "false", + "description": "Disabled attribute, when the button group is disabled,\nall buttons inside will be disabled and the overflow menu will not be accessible.", + "type": { + "text": "boolean" + } + }, + { + "name": "visibility", + "fieldName": "visibility", + "default": "'visible'", + "description": "Visibility state used by responsive containers such as le-toolbar.", + "type": { + "text": "'visible' | 'collapsing' | 'collapsed' | 'expanding'" + } + } + ], + "tagName": "le-button-group", + "events": [ + { + "name": "leOverflowSelect", + "type": { + "text": "EventEmitter<{ id: string }>" + } + } + ], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeButtonGroup", + "declaration": { + "name": "LeButtonGroup", + "module": "src/components/le-button-group/le-button-group.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-button-group", + "declaration": { + "name": "LeButtonGroup", + "module": "src/components/le-button-group/le-button-group.tsx" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/components/le-checkbox/le-checkbox.tsx", + "declarations": [ + { + "kind": "class", + "description": "A checkbox component with support for labels, descriptions, and external IDs.", + "name": "LeCheckbox", + "cssProperties": [ + { + "description": "Size of the checkbox input", + "name": "--le-checkbox-size" + }, + { + "description": "Color of the checkbox when checked", + "name": "--le-checkbox-color" + }, + { + "description": "Color of the label text", + "name": "--le-checkbox-label-color" + }, + { + "description": "Color of the description text", + "name": "--le-checkbox-desc-color" + } + ], + "slots": [ + { + "description": "The label text for the checkbox", + "name": "" + }, + { + "description": "Additional description text displayed below the label", + "name": "description" + } + ], + "members": [ + { + "kind": "field", + "name": "el", + "type": { + "text": "HTMLElement" + } + }, + { + "kind": "field", + "name": "id", + "type": { + "text": "string" + }, + "default": "`le-checkbox-${Math.random().toString(36).substring(2, 9)}`", + "description": "The ID of the checkbox input. This is used for linking the label to the input for accessibility.\nIn case there is no ID provided, a random one will be generated internally." + }, + { + "kind": "field", + "name": "checked", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether the checkbox is checked" + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether the checkbox is disabled" + }, + { + "kind": "field", + "name": "name", + "type": { + "text": "string | undefined" + }, + "description": "The name of the checkbox input" + }, + { + "kind": "field", + "name": "value", + "type": { + "text": "string | undefined" + }, + "description": "The value of the checkbox input" + }, + { + "kind": "field", + "name": "externalId", + "type": { + "text": "string | undefined" + }, + "description": "External ID for linking with external systems (e.g. database ID, PDF form field ID)" + }, + { + "kind": "field", + "name": "handleChange", + "privacy": "private" + }, + { + "kind": "method", + "name": "render" + } + ], + "attributes": [ + { + "name": "id", + "fieldName": "id", + "default": "`le-checkbox-${Math.random().toString(36).substring(2, 9)}`", + "description": "The ID of the checkbox input. This is used for linking the label to the input for accessibility.\nIn case there is no ID provided, a random one will be generated internally.", "type": { "text": "string" } }, { - "name": "separator-icon", - "fieldName": "separatorIcon", - "default": "'chevron-right'", - "description": "Separator icon name (used if no separator slot is provided).", + "name": "checked", + "fieldName": "checked", + "default": "false", + "description": "Whether the checkbox is checked", + "type": { + "text": "boolean" + } + }, + { + "name": "disabled", + "fieldName": "disabled", + "default": "false", + "description": "Whether the checkbox is disabled", + "type": { + "text": "boolean" + } + }, + { + "name": "name", + "fieldName": "name", + "description": "The name of the checkbox input", "type": { "text": "string" } }, { - "name": "overflow-mode", - "fieldName": "overflowMode", - "default": "'collapse'", - "description": "Overflow behavior: collapse (default), wrap, or scroll.", + "name": "value", + "fieldName": "value", + "description": "The value of the checkbox input", "type": { - "text": "'collapse' | 'wrap' | 'scroll'" + "text": "string" } }, { - "name": "min-visible-items", - "fieldName": "minVisibleItems", - "default": "2", - "description": "Minimum visible items before collapsing.", + "name": "external-id", + "fieldName": "externalId", + "description": "External ID for linking with external systems (e.g. database ID, PDF form field ID)", "type": { - "text": "number" + "text": "string" } } ], - "tagName": "le-breadcrumbs", + "tagName": "le-checkbox", "events": [ { - "name": "leBreadcrumbSelect", + "name": "change", "type": { - "text": "EventEmitter" + "text": "EventEmitter<{\n checked: boolean;\n value?: string;\n name?: string;\n externalId?: string;\n }>" }, - "description": "Emitted when a breadcrumb item is selected." + "description": "Emitted when the checked state changes" } ], "customElement": true @@ -2986,18 +2986,18 @@ "exports": [ { "kind": "js", - "name": "LeBreadcrumbs", + "name": "LeCheckbox", "declaration": { - "name": "LeBreadcrumbs", - "module": "src/components/le-breadcrumbs/le-breadcrumbs.tsx" + "name": "LeCheckbox", + "module": "src/components/le-checkbox/le-checkbox.tsx" } }, { "kind": "custom-element-definition", - "name": "le-breadcrumbs", + "name": "le-checkbox", "declaration": { - "name": "LeBreadcrumbs", - "module": "src/components/le-breadcrumbs/le-breadcrumbs.tsx" + "name": "LeCheckbox", + "module": "src/components/le-checkbox/le-checkbox.tsx" } } ] @@ -4007,6 +4007,112 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/components/le-current-heading/le-current-heading.tsx", + "declarations": [ + { + "kind": "class", + "description": "Shows a \"smart\" header title based on what has scrolled out of view.\n\nWhen `selector` matches multiple elements, the title becomes the last element\n(top-to-bottom) that has fully scrolled out above the viewport.", + "name": "LeCurrentHeading", + "cssParts": [ + { + "description": "The rendered title", + "name": "title" + } + ], + "slots": [ + { + "description": "Optional fallback content if no watched title is active", + "name": "" + } + ], + "members": [ + { + "kind": "field", + "name": "el", + "type": { + "text": "HTMLElement" + } + }, + { + "kind": "field", + "name": "selector", + "type": { + "text": "string" + }, + "default": "''", + "description": "CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`)." + }, + { + "kind": "field", + "name": "activeText", + "type": { + "text": "string | null" + }, + "privacy": "private", + "default": "null" + }, + { + "kind": "method", + "name": "onSelectorChange", + "privacy": "protected" + }, + { + "kind": "method", + "name": "onScroll", + "privacy": "protected" + }, + { + "kind": "method", + "name": "onResize", + "privacy": "protected" + }, + { + "kind": "method", + "name": "updateActiveTitle", + "privacy": "private" + }, + { + "kind": "method", + "name": "render" + } + ], + "attributes": [ + { + "name": "selector", + "fieldName": "selector", + "default": "''", + "description": "CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`).", + "type": { + "text": "string" + } + } + ], + "tagName": "le-current-heading", + "events": [], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeCurrentHeading", + "declaration": { + "name": "LeCurrentHeading", + "module": "src/components/le-current-heading/le-current-heading.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-current-heading", + "declaration": { + "name": "LeCurrentHeading", + "module": "src/components/le-current-heading/le-current-heading.tsx" + } + } + ] + }, { "kind": "javascript-module", "path": "src/components/le-component/le-component.tsx", @@ -4716,200 +4822,94 @@ }, { "name": "disabled", - "fieldName": "disabled", - "default": "false", - "description": "Disables right-click and touch interactions.", - "type": { - "text": "boolean" - } - }, - { - "name": "items", - "fieldName": "items", - "default": "[]", - "description": "List of menu items represented as options.", - "type": { - "text": "LeOption[] | string" - } - }, - { - "name": "backdrop", - "fieldName": "backdrop", - "default": "false", - "description": "Whether to show a backdrop behind the menu, lifting the active item.", - "type": { - "text": "boolean" - } - }, - { - "name": "page-scroll-behavior", - "fieldName": "pageScrollBehavior", - "default": "'fixed-menu'", - "description": "Behavior of the menu on page scroll:\n- 'blocked': blocks page scroll\n- 'menu-close': closes the menu automatically on scroll\n- 'fixed-menu': menu scrolls with the page (default)", - "type": { - "text": "'blocked' | 'menu-close' | 'fixed-menu'" - } - }, - { - "name": "position", - "fieldName": "position", - "default": "'mouse'", - "description": "Position of the menu relative to the trigger.\nIf 'mouse', positions next to mouse/touch coords.", - "type": { - "text": "'top' | 'bottom' | 'left' | 'right' | 'mouse'" - } - }, - { - "name": "align", - "fieldName": "align", - "default": "'start'", - "description": "Alignment of the menu relative to the trigger.", - "type": { - "text": "'start' | 'center' | 'end'" - } - } - ], - "tagName": "le-context-menu", - "events": [ - { - "name": "leContextMenuSelect", - "type": { - "text": "EventEmitter" - }, - "description": "Emitted when a menu item is selected." - }, - { - "name": "leContextMenuClose", - "type": { - "text": "EventEmitter" - }, - "description": "Emitted when the context menu is closed." - } - ], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeContextMenu", - "declaration": { - "name": "LeContextMenu", - "module": "src/components/le-context-menu/le-context-menu.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-context-menu", - "declaration": { - "name": "LeContextMenu", - "module": "src/components/le-context-menu/le-context-menu.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-current-heading/le-current-heading.tsx", - "declarations": [ - { - "kind": "class", - "description": "Shows a \"smart\" header title based on what has scrolled out of view.\n\nWhen `selector` matches multiple elements, the title becomes the last element\n(top-to-bottom) that has fully scrolled out above the viewport.", - "name": "LeCurrentHeading", - "cssParts": [ - { - "description": "The rendered title", - "name": "title" - } - ], - "slots": [ - { - "description": "Optional fallback content if no watched title is active", - "name": "" - } - ], - "members": [ - { - "kind": "field", - "name": "el", - "type": { - "text": "HTMLElement" - } - }, - { - "kind": "field", - "name": "selector", - "type": { - "text": "string" - }, - "default": "''", - "description": "CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`)." - }, - { - "kind": "field", - "name": "activeText", + "fieldName": "disabled", + "default": "false", + "description": "Disables right-click and touch interactions.", "type": { - "text": "string | null" - }, - "privacy": "private", - "default": "null" + "text": "boolean" + } }, { - "kind": "method", - "name": "onSelectorChange", - "privacy": "protected" + "name": "items", + "fieldName": "items", + "default": "[]", + "description": "List of menu items represented as options.", + "type": { + "text": "LeOption[] | string" + } }, { - "kind": "method", - "name": "onScroll", - "privacy": "protected" + "name": "backdrop", + "fieldName": "backdrop", + "default": "false", + "description": "Whether to show a backdrop behind the menu, lifting the active item.", + "type": { + "text": "boolean" + } }, { - "kind": "method", - "name": "onResize", - "privacy": "protected" + "name": "page-scroll-behavior", + "fieldName": "pageScrollBehavior", + "default": "'fixed-menu'", + "description": "Behavior of the menu on page scroll:\n- 'blocked': blocks page scroll\n- 'menu-close': closes the menu automatically on scroll\n- 'fixed-menu': menu scrolls with the page (default)", + "type": { + "text": "'blocked' | 'menu-close' | 'fixed-menu'" + } }, { - "kind": "method", - "name": "updateActiveTitle", - "privacy": "private" + "name": "position", + "fieldName": "position", + "default": "'mouse'", + "description": "Position of the menu relative to the trigger.\nIf 'mouse', positions next to mouse/touch coords.", + "type": { + "text": "'top' | 'bottom' | 'left' | 'right' | 'mouse'" + } }, { - "kind": "method", - "name": "render" + "name": "align", + "fieldName": "align", + "default": "'start'", + "description": "Alignment of the menu relative to the trigger.", + "type": { + "text": "'start' | 'center' | 'end'" + } } ], - "attributes": [ + "tagName": "le-context-menu", + "events": [ { - "name": "selector", - "fieldName": "selector", - "default": "''", - "description": "CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`).", + "name": "leContextMenuSelect", "type": { - "text": "string" - } + "text": "EventEmitter" + }, + "description": "Emitted when a menu item is selected." + }, + { + "name": "leContextMenuClose", + "type": { + "text": "EventEmitter" + }, + "description": "Emitted when the context menu is closed." } ], - "tagName": "le-current-heading", - "events": [], "customElement": true } ], "exports": [ { "kind": "js", - "name": "LeCurrentHeading", + "name": "LeContextMenu", "declaration": { - "name": "LeCurrentHeading", - "module": "src/components/le-current-heading/le-current-heading.tsx" + "name": "LeContextMenu", + "module": "src/components/le-context-menu/le-context-menu.tsx" } }, { "kind": "custom-element-definition", - "name": "le-current-heading", + "name": "le-context-menu", "declaration": { - "name": "LeCurrentHeading", - "module": "src/components/le-current-heading/le-current-heading.tsx" + "name": "LeContextMenu", + "module": "src/components/le-context-menu/le-context-menu.tsx" } } ] @@ -4996,6 +4996,50 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/components/le-header-placeholder/le-header-placeholder.tsx", + "declarations": [ + { + "kind": "class", + "description": "Placeholder for `le-header`.\n\nReserves space using the global CSS variable `--le-header-height`.\nThe header component updates that variable when it renders.", + "name": "LeHeaderPlaceholder", + "cssProperties": [ + { + "description": "Published header height (px)", + "name": "--le-header-height" + } + ], + "members": [ + { + "kind": "method", + "name": "render" + } + ], + "tagName": "le-header-placeholder", + "events": [], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeHeaderPlaceholder", + "declaration": { + "name": "LeHeaderPlaceholder", + "module": "src/components/le-header-placeholder/le-header-placeholder.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-header-placeholder", + "declaration": { + "name": "LeHeaderPlaceholder", + "module": "src/components/le-header-placeholder/le-header-placeholder.tsx" + } + } + ] + }, { "kind": "javascript-module", "path": "src/components/le-dropdown-base/le-dropdown-base.tsx", @@ -6126,50 +6170,6 @@ } ] }, - { - "kind": "javascript-module", - "path": "src/components/le-header-placeholder/le-header-placeholder.tsx", - "declarations": [ - { - "kind": "class", - "description": "Placeholder for `le-header`.\n\nReserves space using the global CSS variable `--le-header-height`.\nThe header component updates that variable when it renders.", - "name": "LeHeaderPlaceholder", - "cssProperties": [ - { - "description": "Published header height (px)", - "name": "--le-header-height" - } - ], - "members": [ - { - "kind": "method", - "name": "render" - } - ], - "tagName": "le-header-placeholder", - "events": [], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeHeaderPlaceholder", - "declaration": { - "name": "LeHeaderPlaceholder", - "module": "src/components/le-header-placeholder/le-header-placeholder.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-header-placeholder", - "declaration": { - "name": "LeHeaderPlaceholder", - "module": "src/components/le-header-placeholder/le-header-placeholder.tsx" - } - } - ] - }, { "kind": "javascript-module", "path": "src/components/le-icon/le-icon.tsx", @@ -8954,126 +8954,220 @@ }, { "kind": "javascript-module", - "path": "src/components/le-overflow-menu/le-overflow-menu.tsx", + "path": "src/components/le-popover/le-popover.tsx", "declarations": [ { "kind": "class", - "description": "", - "name": "LeOverflowMenu", + "description": "A popover component for displaying floating content.\n\nUses the native HTML Popover API for proper layering with dialogs\nand other top-layer elements. Falls back gracefully in older browsers.", + "name": "LePopover", + "cssParts": [ + { + "description": "The popover trigger element", + "name": "trigger" + }, + { + "description": "The popover content wrapper", + "name": "content" + } + ], + "slots": [ + { + "description": "Content to display inside the popover", + "name": "" + }, + { + "description": "Element that triggers the popover (optional)", + "name": "trigger" + } + ], "members": [ { "kind": "field", - "name": "popoverEl", + "name": "el", + "type": { + "text": "HTMLElement" + } + }, + { + "kind": "field", + "name": "mode", + "type": { + "text": "'default' | 'admin'" + }, + "default": "'default'", + "description": "Mode of the popover should be 'default' for internal use" + }, + { + "kind": "field", + "name": "open", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether the popover is currently open" + }, + { + "kind": "field", + "name": "position", + "type": { + "text": "'top' | 'bottom' | 'left' | 'right' | 'auto'" + }, + "default": "'bottom'", + "description": "Position of the popover relative to its trigger" + }, + { + "kind": "field", + "name": "align", + "type": { + "text": "'start' | 'center' | 'end'" + }, + "default": "'start'", + "description": "Alignment of the popover" + }, + { + "kind": "field", + "name": "popoverTitle", + "type": { + "text": "string | undefined" + }, + "description": "Optional title for the popover header" + }, + { + "kind": "field", + "name": "showClose", "type": { - "text": "HTMLLePopoverElement | undefined" + "text": "boolean" }, - "privacy": "private" + "default": "true", + "description": "Whether to show a close button in the header" }, { "kind": "field", - "name": "navigationEl", + "name": "closeOnClickOutside", "type": { - "text": "HTMLLeNavigationElement | undefined" + "text": "boolean" }, - "privacy": "private" + "default": "true", + "description": "Whether clicking outside closes the popover" }, { "kind": "field", - "name": "triggerEl", + "name": "closeOnEscape", "type": { - "text": "HTMLElement | undefined" + "text": "boolean" }, - "privacy": "private" + "default": "true", + "description": "Whether pressing Escape closes the popover" }, { "kind": "field", - "name": "open", + "name": "offset", "type": { - "text": "boolean" + "text": "number" }, - "default": "false", - "description": "Whether the menu popover is open." + "default": "8", + "description": "Offset from the trigger element (in pixels)" }, { "kind": "field", - "name": "disabled", + "name": "width", "type": { - "text": "boolean" + "text": "string | undefined" }, - "default": "false", - "description": "Disables trigger interactions." + "description": "Fixed width for the popover (e.g., '300px', '20rem')" }, { "kind": "field", - "name": "position", + "name": "minWidth", "type": { - "text": "'top' | 'right' | 'bottom' | 'left'" + "text": "string | undefined" }, - "default": "'bottom'", - "description": "Popover position." + "default": "'200px'", + "description": "Minimum width for the popover (e.g., '200px', '15rem')" }, { "kind": "field", - "name": "align", + "name": "maxWidth", "type": { - "text": "'start' | 'center' | 'end'" + "text": "string | undefined" }, - "default": "'end'", - "description": "Popover alignment relative to trigger." + "description": "Maximum width for the popover (e.g., '400px', '25rem')" }, { "kind": "field", - "name": "offset", + "name": "triggerFullWidth", "type": { - "text": "number" + "text": "boolean" }, - "default": "8", - "description": "Popover offset in px." + "default": "false", + "description": "Should the popover's trigger take full width of its container" + }, + { + "kind": "method", + "name": "updatePosition", + "description": "Method to update the popover position from a parent component" }, { "kind": "field", - "name": "minWidth", + "name": "isPositioned", "type": { - "text": "string" + "text": "boolean" }, - "default": "'160px'", - "description": "Minimum popover width." + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "icon", + "name": "triggerEl", "type": { - "text": "string" + "text": "HTMLElement | undefined" }, - "default": "'ellipsis-horizontal'", - "description": "Fallback icon name for trigger." + "privacy": "private" }, { "kind": "field", - "name": "triggerAriaLabel", + "name": "popoverEl", "type": { - "text": "string" + "text": "HTMLElement | undefined" }, - "default": "'Open menu'", - "description": "Aria label for fallback trigger button." + "privacy": "private" }, { "kind": "field", - "name": "triggerPart", + "name": "uniqueId", "type": { "text": "string" }, - "default": "'trigger-button'", - "description": "Part name for fallback trigger button." + "privacy": "private", + "default": "`le-popover-${Math.random().toString(36).substr(2, 9)}`" }, { "kind": "field", - "name": "items", + "name": "scrollParents", "type": { - "text": "LeOverflowMenuItem[] | string" + "text": "Element[]" }, - "default": "[]", - "description": "List of menu items represented as options." + "privacy": "private", + "default": "[]" + }, + { + "kind": "field", + "name": "isListeningForDismiss", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "method", + "name": "isNativePopoverOpen", + "privacy": "private", + "return": { + "type": { + "text": "boolean" + } + } }, { "kind": "method", @@ -9087,68 +9181,158 @@ } ] }, + { + "kind": "field", + "name": "supportsPopoverApi", + "type": { + "text": "boolean" + }, + "privacy": "private", + "readonly": true + }, { "kind": "method", - "name": "show" + "name": "shadowContains", + "privacy": "private", + "return": { + "type": { + "text": "boolean" + } + }, + "parameters": [ + { + "name": "container", + "type": { + "text": "HTMLElement" + } + }, + { + "name": "node", + "type": { + "text": "HTMLElement" + } + } + ] }, { "kind": "method", - "name": "hide" + "name": "addDismissListeners", + "privacy": "private" }, { "kind": "method", - "name": "toggle" + "name": "removeDismissListeners", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleDocumentPointerDown", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleDocumentKeyDown", + "privacy": "private" }, { "kind": "method", - "name": "parseItems", + "name": "getScrollParents", "privacy": "private", "return": { "type": { - "text": "LeOverflowMenuItem[]" + "text": "Element[]" } }, "parameters": [ { - "name": "input", + "name": "element", "type": { - "text": "LeOverflowMenuItem[] | string" + "text": "Element" } } - ] + ], + "description": "Find all scrollable parent elements" + }, + { + "kind": "method", + "name": "addScrollListeners", + "privacy": "private", + "description": "Add scroll listeners to all scrollable parents" + }, + { + "kind": "method", + "name": "removeScrollListeners", + "privacy": "private", + "description": "Remove scroll listeners" }, { "kind": "field", - "name": "handlePopoverOpen", + "name": "handleScroll", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleOpened", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleClosed", "privacy": "private" }, { "kind": "field", - "name": "handlePopoverClose", + "name": "handlePopoverToggle", "privacy": "private" }, { "kind": "field", - "name": "handleItemClick", + "name": "handleOtherPopoverOpen", "privacy": "private" }, + { + "kind": "method", + "name": "show", + "description": "Opens the popover" + }, + { + "kind": "method", + "name": "hide", + "description": "Closes the popover" + }, + { + "kind": "method", + "name": "toggle", + "description": "Toggles the popover" + }, { "kind": "field", - "name": "handleNavigationSelect", + "name": "handleTriggerClick", "privacy": "private" }, { "kind": "method", - "name": "renderItems", + "name": "getUnscaledPopoverSize", "privacy": "private", + "return": { + "type": { + "text": "{ width: number; height: number }" + } + }, "parameters": [ { - "name": "items", + "name": "rect", "type": { - "text": "LeOverflowMenuItem[]" + "text": "DOMRect" } } - ] + ], + "description": "During opening animation we scale the popover (e.g. 0.95 -> 1).\ngetBoundingClientRect() returns transformed dimensions, so for initial\npositioning we compensate back to the unscaled size." + }, + { + "kind": "method", + "name": "_updatePosition", + "privacy": "private" }, { "kind": "method", @@ -9157,19 +9341,19 @@ ], "attributes": [ { - "name": "open", - "fieldName": "open", - "default": "false", - "description": "Whether the menu popover is open.", + "name": "mode", + "fieldName": "mode", + "default": "'default'", + "description": "Mode of the popover should be 'default' for internal use", "type": { - "text": "boolean" + "text": "'default' | 'admin'" } }, { - "name": "disabled", - "fieldName": "disabled", + "name": "open", + "fieldName": "open", "default": "false", - "description": "Disables trigger interactions.", + "description": "Whether the popover is currently open", "type": { "text": "boolean" } @@ -9178,88 +9362,114 @@ "name": "position", "fieldName": "position", "default": "'bottom'", - "description": "Popover position.", + "description": "Position of the popover relative to its trigger", "type": { - "text": "'top' | 'right' | 'bottom' | 'left'" + "text": "'top' | 'bottom' | 'left' | 'right' | 'auto'" } }, { "name": "align", "fieldName": "align", - "default": "'end'", - "description": "Popover alignment relative to trigger.", + "default": "'start'", + "description": "Alignment of the popover", "type": { "text": "'start' | 'center' | 'end'" } }, { - "name": "offset", - "fieldName": "offset", - "default": "8", - "description": "Popover offset in px.", + "name": "popover-title", + "fieldName": "popoverTitle", + "description": "Optional title for the popover header", "type": { - "text": "number" + "text": "string" } }, { - "name": "min-width", - "fieldName": "minWidth", - "default": "'160px'", - "description": "Minimum popover width.", + "name": "show-close", + "fieldName": "showClose", + "default": "true", + "description": "Whether to show a close button in the header", "type": { - "text": "string" + "text": "boolean" } }, { - "name": "icon", - "fieldName": "icon", - "default": "'ellipsis-horizontal'", - "description": "Fallback icon name for trigger.", + "name": "close-on-click-outside", + "fieldName": "closeOnClickOutside", + "default": "true", + "description": "Whether clicking outside closes the popover", + "type": { + "text": "boolean" + } + }, + { + "name": "close-on-escape", + "fieldName": "closeOnEscape", + "default": "true", + "description": "Whether pressing Escape closes the popover", + "type": { + "text": "boolean" + } + }, + { + "name": "offset", + "fieldName": "offset", + "default": "8", + "description": "Offset from the trigger element (in pixels)", + "type": { + "text": "number" + } + }, + { + "name": "width", + "fieldName": "width", + "description": "Fixed width for the popover (e.g., '300px', '20rem')", "type": { "text": "string" } }, { - "name": "trigger-aria-label", - "fieldName": "triggerAriaLabel", - "default": "'Open menu'", - "description": "Aria label for fallback trigger button.", + "name": "min-width", + "fieldName": "minWidth", + "default": "'200px'", + "description": "Minimum width for the popover (e.g., '200px', '15rem')", "type": { "text": "string" } }, { - "name": "trigger-part", - "fieldName": "triggerPart", - "default": "'trigger-button'", - "description": "Part name for fallback trigger button.", + "name": "max-width", + "fieldName": "maxWidth", + "description": "Maximum width for the popover (e.g., '400px', '25rem')", "type": { "text": "string" } }, { - "name": "items", - "fieldName": "items", - "default": "[]", - "description": "List of menu items represented as options.", + "name": "trigger-full-width", + "fieldName": "triggerFullWidth", + "default": "false", + "description": "Should the popover's trigger take full width of its container", "type": { - "text": "LeOverflowMenuItem[] | string" + "text": "boolean" } } ], - "tagName": "le-overflow-menu", + "tagName": "le-popover", "events": [ { - "name": "leOverflowMenuItemSelect", + "name": "lePopoverOpen", "type": { - "text": "EventEmitter" - } + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the popover opens" }, { - "name": "leOverflowMenuClose", + "name": "lePopoverClose", "type": { - "text": "EventEmitter" - } + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the popover closes" } ], "customElement": true @@ -9268,128 +9478,90 @@ "exports": [ { "kind": "js", - "name": "LeOverflowMenu", + "name": "LePopover", "declaration": { - "name": "LeOverflowMenu", - "module": "src/components/le-overflow-menu/le-overflow-menu.tsx" + "name": "LePopover", + "module": "src/components/le-popover/le-popover.tsx" } }, { "kind": "custom-element-definition", - "name": "le-overflow-menu", + "name": "le-popover", "declaration": { - "name": "LeOverflowMenu", - "module": "src/components/le-overflow-menu/le-overflow-menu.tsx" + "name": "LePopover", + "module": "src/components/le-popover/le-popover.tsx" } } ] }, { "kind": "javascript-module", - "path": "src/components/le-popover/le-popover.tsx", + "path": "src/components/le-overflow-menu/le-overflow-menu.tsx", "declarations": [ { "kind": "class", - "description": "A popover component for displaying floating content.\n\nUses the native HTML Popover API for proper layering with dialogs\nand other top-layer elements. Falls back gracefully in older browsers.", - "name": "LePopover", - "cssParts": [ - { - "description": "The popover trigger element", - "name": "trigger" - }, - { - "description": "The popover content wrapper", - "name": "content" - } - ], - "slots": [ - { - "description": "Content to display inside the popover", - "name": "" - }, - { - "description": "Element that triggers the popover (optional)", - "name": "trigger" - } - ], + "description": "", + "name": "LeOverflowMenu", "members": [ { "kind": "field", - "name": "el", - "type": { - "text": "HTMLElement" - } - }, - { - "kind": "field", - "name": "mode", - "type": { - "text": "'default' | 'admin'" - }, - "default": "'default'", - "description": "Mode of the popover should be 'default' for internal use" - }, - { - "kind": "field", - "name": "open", + "name": "popoverEl", "type": { - "text": "boolean" + "text": "HTMLLePopoverElement | undefined" }, - "default": "false", - "description": "Whether the popover is currently open" + "privacy": "private" }, { "kind": "field", - "name": "position", + "name": "navigationEl", "type": { - "text": "'top' | 'bottom' | 'left' | 'right' | 'auto'" + "text": "HTMLLeNavigationElement | undefined" }, - "default": "'bottom'", - "description": "Position of the popover relative to its trigger" + "privacy": "private" }, { "kind": "field", - "name": "align", + "name": "triggerEl", "type": { - "text": "'start' | 'center' | 'end'" + "text": "HTMLElement | undefined" }, - "default": "'start'", - "description": "Alignment of the popover" + "privacy": "private" }, { "kind": "field", - "name": "popoverTitle", + "name": "open", "type": { - "text": "string | undefined" + "text": "boolean" }, - "description": "Optional title for the popover header" + "default": "false", + "description": "Whether the menu popover is open." }, { "kind": "field", - "name": "showClose", + "name": "disabled", "type": { "text": "boolean" }, - "default": "true", - "description": "Whether to show a close button in the header" + "default": "false", + "description": "Disables trigger interactions." }, { "kind": "field", - "name": "closeOnClickOutside", + "name": "position", "type": { - "text": "boolean" + "text": "'top' | 'right' | 'bottom' | 'left'" }, - "default": "true", - "description": "Whether clicking outside closes the popover" + "default": "'bottom'", + "description": "Popover position." }, { "kind": "field", - "name": "closeOnEscape", + "name": "align", "type": { - "text": "boolean" + "text": "'start' | 'center' | 'end'" }, - "default": "true", - "description": "Whether pressing Escape closes the popover" + "default": "'end'", + "description": "Popover alignment relative to trigger." }, { "kind": "field", @@ -9397,109 +9569,53 @@ "type": { "text": "number" }, - "default": "8", - "description": "Offset from the trigger element (in pixels)" - }, - { - "kind": "field", - "name": "width", - "type": { - "text": "string | undefined" - }, - "description": "Fixed width for the popover (e.g., '300px', '20rem')" - }, - { - "kind": "field", - "name": "minWidth", - "type": { - "text": "string | undefined" - }, - "default": "'200px'", - "description": "Minimum width for the popover (e.g., '200px', '15rem')" - }, - { - "kind": "field", - "name": "maxWidth", - "type": { - "text": "string | undefined" - }, - "description": "Maximum width for the popover (e.g., '400px', '25rem')" - }, - { - "kind": "field", - "name": "triggerFullWidth", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Should the popover's trigger take full width of its container" - }, - { - "kind": "method", - "name": "updatePosition", - "description": "Method to update the popover position from a parent component" - }, - { - "kind": "field", - "name": "isPositioned", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" + "default": "8", + "description": "Popover offset in px." }, { "kind": "field", - "name": "triggerEl", + "name": "minWidth", "type": { - "text": "HTMLElement | undefined" + "text": "string" }, - "privacy": "private" + "default": "'160px'", + "description": "Minimum popover width." }, { "kind": "field", - "name": "popoverEl", + "name": "icon", "type": { - "text": "HTMLElement | undefined" + "text": "string" }, - "privacy": "private" + "default": "'ellipsis-horizontal'", + "description": "Fallback icon name for trigger." }, { "kind": "field", - "name": "uniqueId", + "name": "triggerAriaLabel", "type": { "text": "string" }, - "privacy": "private", - "default": "`le-popover-${Math.random().toString(36).substr(2, 9)}`" + "default": "'Open menu'", + "description": "Aria label for fallback trigger button." }, { "kind": "field", - "name": "scrollParents", + "name": "triggerPart", "type": { - "text": "Element[]" + "text": "string" }, - "privacy": "private", - "default": "[]" + "default": "'trigger-button'", + "description": "Part name for fallback trigger button." }, { "kind": "field", - "name": "isListeningForDismiss", + "name": "items", "type": { - "text": "boolean" + "text": "LeOverflowMenuItem[] | string" }, - "privacy": "private", - "default": "false" - }, - { - "kind": "method", - "name": "isNativePopoverOpen", - "privacy": "private", - "return": { - "type": { - "text": "boolean" - } - } + "default": "[]", + "description": "List of menu items represented as options." }, { "kind": "method", @@ -9513,158 +9629,68 @@ } ] }, - { - "kind": "field", - "name": "supportsPopoverApi", - "type": { - "text": "boolean" - }, - "privacy": "private", - "readonly": true - }, { "kind": "method", - "name": "shadowContains", - "privacy": "private", - "return": { - "type": { - "text": "boolean" - } - }, - "parameters": [ - { - "name": "container", - "type": { - "text": "HTMLElement" - } - }, - { - "name": "node", - "type": { - "text": "HTMLElement" - } - } - ] + "name": "show" }, { "kind": "method", - "name": "addDismissListeners", - "privacy": "private" + "name": "hide" }, { "kind": "method", - "name": "removeDismissListeners", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleDocumentPointerDown", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleDocumentKeyDown", - "privacy": "private" + "name": "toggle" }, { "kind": "method", - "name": "getScrollParents", + "name": "parseItems", "privacy": "private", "return": { "type": { - "text": "Element[]" + "text": "LeOverflowMenuItem[]" } }, "parameters": [ { - "name": "element", + "name": "input", "type": { - "text": "Element" + "text": "LeOverflowMenuItem[] | string" } } - ], - "description": "Find all scrollable parent elements" - }, - { - "kind": "method", - "name": "addScrollListeners", - "privacy": "private", - "description": "Add scroll listeners to all scrollable parents" - }, - { - "kind": "method", - "name": "removeScrollListeners", - "privacy": "private", - "description": "Remove scroll listeners" + ] }, { "kind": "field", - "name": "handleScroll", - "privacy": "private" - }, - { - "kind": "method", - "name": "handleOpened", - "privacy": "private" - }, - { - "kind": "method", - "name": "handleClosed", + "name": "handlePopoverOpen", "privacy": "private" }, { "kind": "field", - "name": "handlePopoverToggle", + "name": "handlePopoverClose", "privacy": "private" }, { "kind": "field", - "name": "handleOtherPopoverOpen", + "name": "handleItemClick", "privacy": "private" }, - { - "kind": "method", - "name": "show", - "description": "Opens the popover" - }, - { - "kind": "method", - "name": "hide", - "description": "Closes the popover" - }, - { - "kind": "method", - "name": "toggle", - "description": "Toggles the popover" - }, { "kind": "field", - "name": "handleTriggerClick", + "name": "handleNavigationSelect", "privacy": "private" }, { "kind": "method", - "name": "getUnscaledPopoverSize", + "name": "renderItems", "privacy": "private", - "return": { - "type": { - "text": "{ width: number; height: number }" - } - }, "parameters": [ { - "name": "rect", + "name": "items", "type": { - "text": "DOMRect" + "text": "LeOverflowMenuItem[]" } } - ], - "description": "During opening animation we scale the popover (e.g. 0.95 -> 1).\ngetBoundingClientRect() returns transformed dimensions, so for initial\npositioning we compensate back to the unscaled size." - }, - { - "kind": "method", - "name": "_updatePosition", - "privacy": "private" + ] }, { "kind": "method", @@ -9673,19 +9699,19 @@ ], "attributes": [ { - "name": "mode", - "fieldName": "mode", - "default": "'default'", - "description": "Mode of the popover should be 'default' for internal use", + "name": "open", + "fieldName": "open", + "default": "false", + "description": "Whether the menu popover is open.", "type": { - "text": "'default' | 'admin'" + "text": "boolean" } }, { - "name": "open", - "fieldName": "open", + "name": "disabled", + "fieldName": "disabled", "default": "false", - "description": "Whether the popover is currently open", + "description": "Disables trigger interactions.", "type": { "text": "boolean" } @@ -9694,114 +9720,88 @@ "name": "position", "fieldName": "position", "default": "'bottom'", - "description": "Position of the popover relative to its trigger", + "description": "Popover position.", "type": { - "text": "'top' | 'bottom' | 'left' | 'right' | 'auto'" + "text": "'top' | 'right' | 'bottom' | 'left'" } }, { "name": "align", "fieldName": "align", - "default": "'start'", - "description": "Alignment of the popover", + "default": "'end'", + "description": "Popover alignment relative to trigger.", "type": { "text": "'start' | 'center' | 'end'" } }, - { - "name": "popover-title", - "fieldName": "popoverTitle", - "description": "Optional title for the popover header", - "type": { - "text": "string" - } - }, - { - "name": "show-close", - "fieldName": "showClose", - "default": "true", - "description": "Whether to show a close button in the header", - "type": { - "text": "boolean" - } - }, - { - "name": "close-on-click-outside", - "fieldName": "closeOnClickOutside", - "default": "true", - "description": "Whether clicking outside closes the popover", - "type": { - "text": "boolean" - } - }, - { - "name": "close-on-escape", - "fieldName": "closeOnEscape", - "default": "true", - "description": "Whether pressing Escape closes the popover", - "type": { - "text": "boolean" - } - }, { "name": "offset", "fieldName": "offset", "default": "8", - "description": "Offset from the trigger element (in pixels)", + "description": "Popover offset in px.", "type": { "text": "number" } }, { - "name": "width", - "fieldName": "width", - "description": "Fixed width for the popover (e.g., '300px', '20rem')", + "name": "min-width", + "fieldName": "minWidth", + "default": "'160px'", + "description": "Minimum popover width.", "type": { "text": "string" } }, { - "name": "min-width", - "fieldName": "minWidth", - "default": "'200px'", - "description": "Minimum width for the popover (e.g., '200px', '15rem')", + "name": "icon", + "fieldName": "icon", + "default": "'ellipsis-horizontal'", + "description": "Fallback icon name for trigger.", + "type": { + "text": "string" + } + }, + { + "name": "trigger-aria-label", + "fieldName": "triggerAriaLabel", + "default": "'Open menu'", + "description": "Aria label for fallback trigger button.", "type": { "text": "string" } }, { - "name": "max-width", - "fieldName": "maxWidth", - "description": "Maximum width for the popover (e.g., '400px', '25rem')", + "name": "trigger-part", + "fieldName": "triggerPart", + "default": "'trigger-button'", + "description": "Part name for fallback trigger button.", "type": { "text": "string" } }, { - "name": "trigger-full-width", - "fieldName": "triggerFullWidth", - "default": "false", - "description": "Should the popover's trigger take full width of its container", + "name": "items", + "fieldName": "items", + "default": "[]", + "description": "List of menu items represented as options.", "type": { - "text": "boolean" + "text": "LeOverflowMenuItem[] | string" } } ], - "tagName": "le-popover", + "tagName": "le-overflow-menu", "events": [ { - "name": "lePopoverOpen", + "name": "leOverflowMenuItemSelect", "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the popover opens" + "text": "EventEmitter" + } }, { - "name": "lePopoverClose", + "name": "leOverflowMenuClose", "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the popover closes" + "text": "EventEmitter" + } } ], "customElement": true @@ -9810,18 +9810,18 @@ "exports": [ { "kind": "js", - "name": "LePopover", + "name": "LeOverflowMenu", "declaration": { - "name": "LePopover", - "module": "src/components/le-popover/le-popover.tsx" + "name": "LeOverflowMenu", + "module": "src/components/le-overflow-menu/le-overflow-menu.tsx" } }, { "kind": "custom-element-definition", - "name": "le-popover", + "name": "le-overflow-menu", "declaration": { - "name": "LePopover", - "module": "src/components/le-popover/le-popover.tsx" + "name": "LeOverflowMenu", + "module": "src/components/le-overflow-menu/le-overflow-menu.tsx" } } ] @@ -10975,6 +10975,192 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/components/le-scroll-progress/le-scroll-progress.tsx", + "declarations": [ + { + "kind": "class", + "description": "Displays scroll progress as a simple bar.\n\nIf `track-scroll-progress` is present without a value, tracks the full document.\nIf it is a selector string, tracks progress within the matched element.", + "name": "LeScrollProgress", + "cssProperties": [ + { + "description": "Bar height", + "name": "--le-scroll-progress-height" + }, + { + "description": "Track background", + "name": "--le-scroll-progress-bg" + }, + { + "description": "Fill color", + "name": "--le-scroll-progress-fill" + }, + { + "description": "If sticky, stop position to parent top", + "name": "--le-scroll-progress-sticky-top" + }, + { + "description": "If fixed, distance from window top", + "name": "--le-scroll-progress-fixed-top" + }, + { + "description": "If fixed, distance from window left", + "name": "--le-scroll-progress-fixed-left" + }, + { + "description": "If fixed, distance from window right", + "name": "--le-scroll-progress-fixed-right" + }, + { + "description": "Z-index of the progress bar (1001 by default, above header)", + "name": "--le-scroll-progress-z" + } + ], + "cssParts": [ + { + "description": "Outer track", + "name": "track" + }, + { + "description": "Inner fill", + "name": "fill" + } + ], + "members": [ + { + "kind": "field", + "name": "el", + "type": { + "text": "HTMLElement" + } + }, + { + "kind": "field", + "name": "trackScrollProgress", + "type": { + "text": "string | undefined" + }, + "description": "Boolean or selector string." + }, + { + "kind": "field", + "name": "progress", + "type": { + "text": "number" + }, + "privacy": "private", + "default": "0" + }, + { + "kind": "field", + "name": "rafId", + "type": { + "text": "number | null" + }, + "privacy": "private", + "default": "null" + }, + { + "kind": "field", + "name": "targetEl", + "type": { + "text": "Element | null" + }, + "privacy": "private", + "default": "null" + }, + { + "kind": "method", + "name": "onTrackChange", + "privacy": "protected" + }, + { + "kind": "method", + "name": "onScroll", + "privacy": "protected" + }, + { + "kind": "method", + "name": "onResize", + "privacy": "protected" + }, + { + "kind": "method", + "name": "scheduleUpdate", + "privacy": "private", + "parameters": [ + { + "name": "force", + "default": "false", + "type": { + "text": "boolean" + } + } + ] + }, + { + "kind": "method", + "name": "resolveTarget", + "privacy": "private" + }, + { + "kind": "method", + "name": "clamp01", + "privacy": "private", + "parameters": [ + { + "name": "n", + "type": { + "text": "number" + } + } + ] + }, + { + "kind": "method", + "name": "updateProgress", + "privacy": "private" + }, + { + "kind": "method", + "name": "render" + } + ], + "attributes": [ + { + "name": "track-scroll-progress", + "fieldName": "trackScrollProgress", + "description": "Boolean or selector string.", + "type": { + "text": "string" + } + } + ], + "tagName": "le-scroll-progress", + "events": [], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeScrollProgress", + "declaration": { + "name": "LeScrollProgress", + "module": "src/components/le-scroll-progress/le-scroll-progress.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-scroll-progress", + "declaration": { + "name": "LeScrollProgress", + "module": "src/components/le-scroll-progress/le-scroll-progress.tsx" + } + } + ] + }, { "kind": "javascript-module", "path": "src/components/le-round-progress/le-round-progress.tsx", @@ -11143,54 +11329,42 @@ }, { "kind": "javascript-module", - "path": "src/components/le-scroll-progress/le-scroll-progress.tsx", + "path": "src/components/le-segmented-control/le-segmented-control.tsx", "declarations": [ { "kind": "class", - "description": "Displays scroll progress as a simple bar.\n\nIf `track-scroll-progress` is present without a value, tracks the full document.\nIf it is a selector string, tracks progress within the matched element.", - "name": "LeScrollProgress", + "description": "A segmented control component (iOS-style toggle buttons).\n\nPerfect for toggling between a small set of related options.", + "name": "LeSegmentedControl", "cssProperties": [ { - "description": "Bar height", - "name": "--le-scroll-progress-height" - }, - { - "description": "Track background", - "name": "--le-scroll-progress-bg" - }, - { - "description": "Fill color", - "name": "--le-scroll-progress-fill" - }, - { - "description": "If sticky, stop position to parent top", - "name": "--le-scroll-progress-sticky-top" - }, - { - "description": "If fixed, distance from window top", - "name": "--le-scroll-progress-fixed-top" + "description": "Background color of the control", + "name": "--le-segmented-bg" }, { - "description": "If fixed, distance from window left", - "name": "--le-scroll-progress-fixed-left" + "description": "Padding around segments", + "name": "--le-segmented-padding" }, { - "description": "If fixed, distance from window right", - "name": "--le-scroll-progress-fixed-right" + "description": "Gap between segments", + "name": "--le-segmented-gap" }, { - "description": "Z-index of the progress bar (1001 by default, above header)", - "name": "--le-scroll-progress-z" + "description": "Border radius of the control", + "name": "--le-segmented-radius" } ], "cssParts": [ { - "description": "Outer track", - "name": "track" + "description": "The main container", + "name": "container" }, { - "description": "Inner fill", - "name": "fill" + "description": "Individual segment buttons", + "name": "segment" + }, + { + "description": "The currently active segment", + "name": "segment-active" } ], "members": [ @@ -11203,80 +11377,230 @@ }, { "kind": "field", - "name": "trackScrollProgress", + "name": "containerRef", "type": { - "text": "string | undefined" + "text": "HTMLElement | undefined" }, - "description": "Boolean or selector string." + "privacy": "private" }, { "kind": "field", - "name": "progress", + "name": "options", + "type": { + "text": "LeOption[] | string" + }, + "default": "[]", + "description": "Array of options for the segmented control." + }, + { + "kind": "field", + "name": "value", + "type": { + "text": "LeOptionValue | undefined" + }, + "description": "The value of the currently selected option." + }, + { + "kind": "field", + "name": "size", + "type": { + "text": "'small' | 'medium' | 'large'" + }, + "default": "'medium'", + "description": "Size of the control." + }, + { + "kind": "field", + "name": "overflow", + "type": { + "text": "'auto' | 'hidden' | 'visible' | 'scroll'" + }, + "default": "'auto'", + "description": "Scroll behavior for overflowing tabs." + }, + { + "kind": "field", + "name": "fullWidth", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether the control should take full width." + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether the control is disabled." + }, + { + "kind": "field", + "name": "segmentConfigs", + "type": { + "text": "SegmentConfig[]" + }, + "privacy": "private", + "default": "[]", + "description": "Internal segment configurations built from declarative items or options prop." + }, + { + "kind": "field", + "name": "focusedIndex", "type": { "text": "number" }, "privacy": "private", - "default": "0" + "default": "0", + "description": "Internal state for focused index (keyboard navigation)" }, { "kind": "field", - "name": "rafId", + "name": "isDeclarativeMode", "type": { - "text": "number | null" + "text": "boolean" }, "privacy": "private", - "default": "null" + "default": "false", + "description": "Whether we're using declarative mode (le-item children)" }, { "kind": "field", - "name": "targetEl", + "name": "declarativeOptions", "type": { - "text": "Element | null" + "text": "LeOption[]" }, "privacy": "private", - "default": "null" + "default": "[]" + }, + { + "kind": "field", + "name": "mutationObserver", + "type": { + "text": "MutationObserver | undefined" + }, + "privacy": "private" }, { "kind": "method", - "name": "onTrackChange", - "privacy": "protected" + "name": "handleOptionsChange" }, { "kind": "method", - "name": "onScroll", - "privacy": "protected" + "name": "handleSlotChange" }, { "kind": "method", - "name": "onResize", - "privacy": "protected" + "name": "syncDeclarativeOptionsAndSegments", + "privacy": "private" }, { "kind": "method", - "name": "scheduleUpdate", + "name": "buildDeclarativeOptions", + "privacy": "private" + }, + { + "kind": "field", + "name": "parsedOptions", + "type": { + "text": "LeOption[]" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "buildSegmentsConfigs", + "privacy": "private" + }, + { + "kind": "method", + "name": "getOptionValue", "privacy": "private", + "return": { + "type": { + "text": "LeOptionValue" + } + }, "parameters": [ { - "name": "force", - "default": "false", + "name": "option", "type": { - "text": "boolean" + "text": "LeOption" } } ] }, { "kind": "method", - "name": "resolveTarget", + "name": "selectOption", + "privacy": "private", + "parameters": [ + { + "name": "option", + "type": { + "text": "LeOption" + } + } + ] + }, + { + "kind": "field", + "name": "handleClick", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleKeyDown", "privacy": "private" }, { "kind": "method", - "name": "clamp01", + "name": "findNextEnabled", "privacy": "private", + "return": { + "type": { + "text": "number" + } + }, "parameters": [ { - "name": "n", + "name": "direction", + "type": { + "text": "1 | -1" + } + } + ] + }, + { + "kind": "method", + "name": "findFirstEnabled", + "privacy": "private", + "return": { + "type": { + "text": "number" + } + } + }, + { + "kind": "method", + "name": "findLastEnabled", + "privacy": "private", + "return": { + "type": { + "text": "number" + } + } + }, + { + "kind": "method", + "name": "focusSegment", + "privacy": "private", + "parameters": [ + { + "name": "index", "type": { "text": "number" } @@ -11284,89 +11608,105 @@ ] }, { - "kind": "method", - "name": "updateProgress", - "privacy": "private" + "kind": "method", + "name": "render" + } + ], + "attributes": [ + { + "name": "options", + "fieldName": "options", + "default": "[]", + "description": "Array of options for the segmented control.", + "type": { + "text": "LeOption[] | string" + } + }, + { + "name": "value", + "fieldName": "value", + "description": "The value of the currently selected option.", + "type": { + "text": "LeOptionValue" + } + }, + { + "name": "size", + "fieldName": "size", + "default": "'medium'", + "description": "Size of the control.", + "type": { + "text": "'small' | 'medium' | 'large'" + } + }, + { + "name": "overflow", + "fieldName": "overflow", + "default": "'auto'", + "description": "Scroll behavior for overflowing tabs.", + "type": { + "text": "'auto' | 'hidden' | 'visible' | 'scroll'" + } }, { - "kind": "method", - "name": "render" + "name": "full-width", + "fieldName": "fullWidth", + "default": "false", + "description": "Whether the control should take full width.", + "type": { + "text": "boolean" + } + }, + { + "name": "disabled", + "fieldName": "disabled", + "default": "false", + "description": "Whether the control is disabled.", + "type": { + "text": "boolean" + } } ], - "attributes": [ + "tagName": "le-segmented-control", + "events": [ { - "name": "track-scroll-progress", - "fieldName": "trackScrollProgress", - "description": "Boolean or selector string.", + "name": "leChange", "type": { - "text": "string" - } + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the selection changes." } ], - "tagName": "le-scroll-progress", - "events": [], "customElement": true } ], "exports": [ { "kind": "js", - "name": "LeScrollProgress", + "name": "LeSegmentedControl", "declaration": { - "name": "LeScrollProgress", - "module": "src/components/le-scroll-progress/le-scroll-progress.tsx" + "name": "LeSegmentedControl", + "module": "src/components/le-segmented-control/le-segmented-control.tsx" } }, { "kind": "custom-element-definition", - "name": "le-scroll-progress", + "name": "le-segmented-control", "declaration": { - "name": "LeScrollProgress", - "module": "src/components/le-scroll-progress/le-scroll-progress.tsx" + "name": "LeSegmentedControl", + "module": "src/components/le-segmented-control/le-segmented-control.tsx" } } ] }, { "kind": "javascript-module", - "path": "src/components/le-segmented-control/le-segmented-control.tsx", + "path": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx", "declarations": [ { "kind": "class", - "description": "A segmented control component (iOS-style toggle buttons).\n\nPerfect for toggling between a small set of related options.", - "name": "LeSegmentedControl", - "cssProperties": [ - { - "description": "Background color of the control", - "name": "--le-segmented-bg" - }, - { - "description": "Padding around segments", - "name": "--le-segmented-padding" - }, - { - "description": "Gap between segments", - "name": "--le-segmented-gap" - }, - { - "description": "Border radius of the control", - "name": "--le-segmented-radius" - } - ], - "cssParts": [ - { - "description": "The main container", - "name": "container" - }, - { - "description": "Individual segment buttons", - "name": "segment" - }, - { - "description": "The currently active segment", - "name": "segment-active" - } - ], + "description": "", + "name": "LeSidePanelToggle", "members": [ { "kind": "field", @@ -11377,235 +11717,213 @@ }, { "kind": "field", - "name": "containerRef", + "name": "panelId", "type": { - "text": "HTMLElement | undefined" + "text": "string | undefined" }, - "privacy": "private" + "description": "Optional id used to target a specific panel." }, { "kind": "field", - "name": "options", + "name": "action", "type": { - "text": "LeOption[] | string" + "text": "LeSidePanelToggleAction" }, - "default": "[]", - "description": "Array of options for the segmented control." + "default": "'toggle'", + "description": "Action to emit. Default toggles the panel." }, { "kind": "field", - "name": "value", + "name": "shortcut", "type": { - "text": "LeOptionValue | undefined" + "text": "string | undefined" }, - "description": "The value of the currently selected option." + "description": "Optional keyboard shortcut like `Mod+B` or `Alt+N`." }, { "kind": "field", - "name": "size", + "name": "disabled", "type": { - "text": "'small' | 'medium' | 'large'" + "text": "boolean" }, - "default": "'medium'", - "description": "Size of the control." + "default": "false", + "description": "Disables the toggle." }, { "kind": "field", - "name": "overflow", + "name": "mode", "type": { - "text": "'auto' | 'hidden' | 'visible' | 'scroll'" + "text": "'default' | 'admin'" }, - "default": "'auto'", - "description": "Scroll behavior for overflowing tabs." + "default": "'default'" }, { "kind": "field", - "name": "fullWidth", + "name": "variant", "type": { - "text": "boolean" + "text": "'solid' | 'outlined' | 'clear' | 'system'" }, - "default": "false", - "description": "Whether the control should take full width." + "default": "'solid'" }, { "kind": "field", - "name": "disabled", + "name": "color", "type": { - "text": "boolean" + "text": "'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'" }, - "default": "false", - "description": "Whether the control is disabled." + "default": "'primary'" }, { "kind": "field", - "name": "segmentConfigs", + "name": "size", "type": { - "text": "SegmentConfig[]" + "text": "'small' | 'medium' | 'large'" }, - "privacy": "private", - "default": "[]", - "description": "Internal segment configurations built from declarative items or options prop." + "default": "'medium'" }, { "kind": "field", - "name": "focusedIndex", + "name": "selected", "type": { - "text": "number" + "text": "boolean" }, - "privacy": "private", - "default": "0", - "description": "Internal state for focused index (keyboard navigation)" + "default": "false" }, { "kind": "field", - "name": "isDeclarativeMode", + "name": "fullWidth", "type": { "text": "boolean" }, - "privacy": "private", - "default": "false", - "description": "Whether we're using declarative mode (le-item children)" + "default": "false" }, { "kind": "field", - "name": "declarativeOptions", + "name": "iconOnly", "type": { - "text": "LeOption[]" - }, - "privacy": "private", - "default": "[]" + "text": "string | Node | undefined" + } }, { "kind": "field", - "name": "mutationObserver", + "name": "iconStart", "type": { - "text": "MutationObserver | undefined" - }, - "privacy": "private" + "text": "string | Node | undefined" + } }, { - "kind": "method", - "name": "handleOptionsChange" + "kind": "field", + "name": "iconEnd", + "type": { + "text": "string | Node | undefined" + } }, { - "kind": "method", - "name": "handleSlotChange" + "kind": "field", + "name": "type", + "type": { + "text": "'button' | 'submit' | 'reset'" + }, + "default": "'button'" }, { - "kind": "method", - "name": "syncDeclarativeOptionsAndSegments", - "privacy": "private" + "kind": "field", + "name": "href", + "type": { + "text": "string | undefined" + } }, { - "kind": "method", - "name": "buildDeclarativeOptions", - "privacy": "private" + "kind": "field", + "name": "target", + "type": { + "text": "string | undefined" + } }, { "kind": "field", - "name": "parsedOptions", + "name": "align", "type": { - "text": "LeOption[]" + "text": "'start' | 'center' | 'space-between' | 'end'" }, - "privacy": "private", - "readonly": true - }, - { - "kind": "method", - "name": "buildSegmentsConfigs", - "privacy": "private" + "default": "'center'" }, { - "kind": "method", - "name": "getOptionValue", - "privacy": "private", - "return": { - "type": { - "text": "LeOptionValue" - } + "kind": "field", + "name": "shortcutSpec", + "type": { + "text": "ShortcutSpec | undefined" }, - "parameters": [ - { - "name": "option", - "type": { - "text": "LeOption" - } - } - ] + "privacy": "private" }, { - "kind": "method", - "name": "selectOption", - "privacy": "private", - "parameters": [ - { - "name": "option", - "type": { - "text": "LeOption" - } - } - ] + "kind": "field", + "name": "expanded", + "type": { + "text": "boolean | undefined" + }, + "privacy": "private" }, { "kind": "field", - "name": "handleClick", + "name": "buttonEl", + "type": { + "text": "HTMLElement | undefined" + }, "privacy": "private" }, { "kind": "field", - "name": "handleKeyDown", + "name": "forwardedNodes", + "type": { + "text": "ChildNode[] | undefined" + }, "privacy": "private" }, { "kind": "method", - "name": "findNextEnabled", - "privacy": "private", - "return": { - "type": { - "text": "number" - } - }, - "parameters": [ - { - "name": "direction", - "type": { - "text": "1 | -1" - } - } - ] + "name": "onShortcutChanged", + "privacy": "protected" }, { "kind": "method", - "name": "findFirstEnabled", - "privacy": "private", - "return": { - "type": { - "text": "number" - } - } + "name": "syncShortcutListener", + "privacy": "private" }, { "kind": "method", - "name": "findLastEnabled", + "name": "getResolvedPanelId", "privacy": "private", "return": { "type": { - "text": "number" + "text": "string | undefined" } } }, { "kind": "method", - "name": "focusSegment", - "privacy": "private", - "parameters": [ - { - "name": "index", - "type": { - "text": "number" - } - } - ] + "name": "emitRequest", + "privacy": "private" + }, + { + "kind": "field", + "name": "onDocumentKeyDown", + "privacy": "private" + }, + { + "kind": "field", + "name": "onPanelStateChange", + "privacy": "private" + }, + { + "kind": "method", + "name": "syncForwardedNodesIntoButton", + "privacy": "private" + }, + { + "kind": "method", + "name": "syncAriaExpanded", + "privacy": "private" }, { "kind": "method", @@ -11614,67 +11932,146 @@ ], "attributes": [ { - "name": "options", - "fieldName": "options", - "default": "[]", - "description": "Array of options for the segmented control.", + "name": "panel-id", + "fieldName": "panelId", + "description": "Optional id used to target a specific panel.", "type": { - "text": "LeOption[] | string" + "text": "string" } }, { - "name": "value", - "fieldName": "value", - "description": "The value of the currently selected option.", + "name": "action", + "fieldName": "action", + "default": "'toggle'", + "description": "Action to emit. Default toggles the panel.", "type": { - "text": "LeOptionValue" + "text": "LeSidePanelToggleAction" + } + }, + { + "name": "shortcut", + "fieldName": "shortcut", + "description": "Optional keyboard shortcut like `Mod+B` or `Alt+N`.", + "type": { + "text": "string" + } + }, + { + "name": "disabled", + "fieldName": "disabled", + "default": "false", + "description": "Disables the toggle.", + "type": { + "text": "boolean" + } + }, + { + "name": "mode", + "fieldName": "mode", + "default": "'default'", + "type": { + "text": "'default' | 'admin'" + } + }, + { + "name": "variant", + "fieldName": "variant", + "default": "'solid'", + "type": { + "text": "'solid' | 'outlined' | 'clear' | 'system'" + } + }, + { + "name": "color", + "fieldName": "color", + "default": "'primary'", + "type": { + "text": "'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'" } }, { "name": "size", "fieldName": "size", "default": "'medium'", - "description": "Size of the control.", "type": { "text": "'small' | 'medium' | 'large'" } }, { - "name": "overflow", - "fieldName": "overflow", - "default": "'auto'", - "description": "Scroll behavior for overflowing tabs.", + "name": "selected", + "fieldName": "selected", + "default": "false", "type": { - "text": "'auto' | 'hidden' | 'visible' | 'scroll'" + "text": "boolean" } }, { "name": "full-width", "fieldName": "fullWidth", "default": "false", - "description": "Whether the control should take full width.", "type": { "text": "boolean" } }, { - "name": "disabled", - "fieldName": "disabled", - "default": "false", - "description": "Whether the control is disabled.", + "name": "icon-only", + "fieldName": "iconOnly", "type": { - "text": "boolean" + "text": "string | Node" + } + }, + { + "name": "icon-start", + "fieldName": "iconStart", + "type": { + "text": "string | Node" + } + }, + { + "name": "icon-end", + "fieldName": "iconEnd", + "type": { + "text": "string | Node" + } + }, + { + "name": "type", + "fieldName": "type", + "default": "'button'", + "type": { + "text": "'button' | 'submit' | 'reset'" + } + }, + { + "name": "href", + "fieldName": "href", + "type": { + "text": "string" + } + }, + { + "name": "target", + "fieldName": "target", + "type": { + "text": "string" + } + }, + { + "name": "align", + "fieldName": "align", + "default": "'center'", + "type": { + "text": "'start' | 'center' | 'space-between' | 'end'" } } ], - "tagName": "le-segmented-control", + "tagName": "le-side-panel-toggle", "events": [ { - "name": "leChange", + "name": "leSidePanelRequestToggle", "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the selection changes." + "text": "EventEmitter" + } } ], "customElement": true @@ -11683,18 +12080,18 @@ "exports": [ { "kind": "js", - "name": "LeSegmentedControl", + "name": "LeSidePanelToggle", "declaration": { - "name": "LeSegmentedControl", - "module": "src/components/le-segmented-control/le-segmented-control.tsx" + "name": "LeSidePanelToggle", + "module": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx" } }, { "kind": "custom-element-definition", - "name": "le-segmented-control", + "name": "le-side-panel-toggle", "declaration": { - "name": "LeSegmentedControl", - "module": "src/components/le-segmented-control/le-segmented-control.tsx" + "name": "LeSidePanelToggle", + "module": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx" } } ] @@ -12843,12 +13240,18 @@ }, { "kind": "javascript-module", - "path": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx", + "path": "src/components/le-slot/le-slot.tsx", "declarations": [ { "kind": "class", - "description": "", - "name": "LeSidePanelToggle", + "description": "Slot placeholder component for admin/CMS mode.\n\nThis component renders a visual placeholder for slots when in admin mode,\nallowing CMS systems to show available drop zones for content or inline editing.\n\nIn non-admin mode, this component renders nothing and acts as a passthrough.", + "name": "LeSlot", + "slots": [ + { + "description": "Default slot for placeholder content or drop zone UI", + "name": "" + } + ], "members": [ { "kind": "field", @@ -12859,361 +13262,359 @@ }, { "kind": "field", - "name": "panelId", - "type": { - "text": "string | undefined" - }, - "description": "Optional id used to target a specific panel." - }, - { - "kind": "field", - "name": "action", - "type": { - "text": "LeSidePanelToggleAction" - }, - "default": "'toggle'", - "description": "Action to emit. Default toggles the panel." - }, - { - "kind": "field", - "name": "shortcut", - "type": { - "text": "string | undefined" - }, - "description": "Optional keyboard shortcut like `Mod+B` or `Alt+N`." - }, - { - "kind": "field", - "name": "disabled", + "name": "type", "type": { - "text": "boolean" + "text": "'slot' | 'text' | 'textarea'" }, - "default": "false", - "description": "Disables the toggle." + "default": "'slot'", + "description": "The type of slot content.\n- `slot`: Default, shows a dropzone for components (default)\n- `text`: Shows a single-line text input\n- `textarea`: Shows a multi-line text area" }, { "kind": "field", - "name": "mode", + "name": "name", "type": { - "text": "'default' | 'admin'" + "text": "string" }, - "default": "'default'" + "default": "''", + "description": "The name of the slot this placeholder represents.\nShould match the slot name in the parent component." }, { "kind": "field", - "name": "variant", + "name": "label", "type": { - "text": "'solid' | 'outlined' | 'clear' | 'system'" + "text": "string | undefined" }, - "default": "'solid'" + "description": "Label to display in admin mode.\nIf not provided, the slot name will be used." }, { "kind": "field", - "name": "color", + "name": "description", "type": { - "text": "'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'" + "text": "string | undefined" }, - "default": "'primary'" + "description": "Description of what content this slot accepts.\nShown in admin mode to guide content editors." }, { "kind": "field", - "name": "size", + "name": "allowedComponents", "type": { - "text": "'small' | 'medium' | 'large'" + "text": "string | undefined" }, - "default": "'medium'" + "description": "Comma-separated list of allowed component tags for this slot.\nUsed by CMS to filter available components." }, { "kind": "field", - "name": "selected", + "name": "multiple", "type": { "text": "boolean" }, - "default": "false" + "default": "true", + "description": "Whether multiple components can be dropped in this slot." }, { "kind": "field", - "name": "fullWidth", + "name": "required", "type": { "text": "boolean" }, - "default": "false" + "default": "false", + "description": "Whether this slot is required to have content." }, { "kind": "field", - "name": "iconOnly", + "name": "placeholder", "type": { - "text": "string | Node | undefined" - } + "text": "string | undefined" + }, + "description": "Placeholder text for text/textarea inputs in admin mode." }, { "kind": "field", - "name": "iconStart", + "name": "tag", "type": { - "text": "string | Node | undefined" - } + "text": "string | undefined" + }, + "description": "The HTML tag to create when there's no slotted element.\nUsed with type=\"text\" or type=\"textarea\" to auto-create elements." }, { "kind": "field", - "name": "iconEnd", + "name": "slotStyle", "type": { - "text": "string | Node | undefined" - } + "text": "string | undefined" + }, + "description": "CSS styles for the slot dropzone container.\nUseful for layouts - e.g., \"flex-direction: row\" for horizontal stacks.\nOnly applies in admin mode for type=\"slot\"." }, { "kind": "field", - "name": "type", + "name": "adminMode", "type": { - "text": "'button' | 'submit' | 'reset'" + "text": "boolean" }, - "default": "'button'" + "privacy": "private", + "default": "false", + "description": "Internal state to track admin mode" }, { "kind": "field", - "name": "href", + "name": "textValue", "type": { - "text": "string | undefined" - } + "text": "string" + }, + "privacy": "private", + "default": "''", + "description": "Internal state for text input value (synced from slot content)" }, { "kind": "field", - "name": "target", + "name": "isValidHtml", "type": { - "text": "string | undefined" - } + "text": "boolean" + }, + "privacy": "private", + "default": "true", + "description": "Whether the current textValue contains valid HTML" }, { "kind": "field", - "name": "align", + "name": "availableComponents", "type": { - "text": "'start' | 'center' | 'space-between' | 'end'" + "text": "ComponentInfo[]" }, - "default": "'center'" + "privacy": "private", + "default": "[]", + "description": "Available components loaded from Custom Elements Manifest" }, { "kind": "field", - "name": "shortcutSpec", + "name": "pickerOpen", "type": { - "text": "ShortcutSpec | undefined" + "text": "boolean" }, - "privacy": "private" + "privacy": "private", + "default": "false", + "description": "Whether the component picker popover is open" }, { "kind": "field", - "name": "expanded", + "name": "slotRef", "type": { - "text": "boolean | undefined" + "text": "HTMLSlotElement | undefined" }, - "privacy": "private" + "privacy": "private", + "description": "Reference to the slot element to access assignedNodes" }, { "kind": "field", - "name": "buttonEl", + "name": "slottedElement", "type": { - "text": "HTMLElement | undefined" + "text": "Element | undefined" }, - "privacy": "private" + "privacy": "private", + "description": "The original slotted element (e.g.,

)" }, { "kind": "field", - "name": "forwardedNodes", + "name": "disconnectModeObserver", "type": { - "text": "ChildNode[] | undefined" + "text": "() => void | undefined" }, "privacy": "private" }, { - "kind": "method", - "name": "onShortcutChanged", - "privacy": "protected" + "kind": "field", + "name": "isUpdating", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false", + "description": "Flag to prevent re-reading content right after we updated it" }, { "kind": "method", - "name": "syncShortcutListener", - "privacy": "private" + "name": "readSlottedContent", + "privacy": "private", + "description": "Read content from slotted elements via assignedNodes()" }, { "kind": "method", - "name": "getResolvedPanelId", + "name": "validateHtml", "privacy": "private", "return": { "type": { - "text": "string | undefined" + "text": "boolean" } - } - }, - { - "kind": "method", - "name": "emitRequest", - "privacy": "private" - }, - { - "kind": "field", - "name": "onDocumentKeyDown", - "privacy": "private" + }, + "parameters": [ + { + "name": "html", + "type": { + "text": "string" + } + } + ], + "description": "Validates if a string contains valid HTML" }, { "kind": "field", - "name": "onPanelStateChange", + "name": "handleTextInput", "privacy": "private" }, { "kind": "method", - "name": "syncForwardedNodesIntoButton", - "privacy": "private" + "name": "createSlottedElement", + "privacy": "private", + "description": "Create a new slotted element when none exists.\nThe element is appended to the host component's light DOM." }, { "kind": "method", - "name": "syncAriaExpanded", - "privacy": "private" + "name": "loadAvailableComponents", + "privacy": "private", + "description": "Load available components from Custom Elements Manifest" }, { "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "panel-id", - "fieldName": "panelId", - "description": "Optional id used to target a specific panel.", - "type": { - "text": "string" - } - }, - { - "name": "action", - "fieldName": "action", - "default": "'toggle'", - "description": "Action to emit. Default toggles the panel.", - "type": { - "text": "LeSidePanelToggleAction" - } - }, - { - "name": "shortcut", - "fieldName": "shortcut", - "description": "Optional keyboard shortcut like `Mod+B` or `Alt+N`.", - "type": { - "text": "string" - } - }, - { - "name": "disabled", - "fieldName": "disabled", - "default": "false", - "description": "Disables the toggle.", - "type": { - "text": "boolean" - } + "name": "formatComponentName", + "privacy": "private", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "tagName", + "type": { + "text": "string" + } + } + ], + "description": "Format a tag name into a display name\ne.g., 'le-card' -> 'Card'" }, { - "name": "mode", - "fieldName": "mode", - "default": "'default'", - "type": { - "text": "'default' | 'admin'" - } + "kind": "method", + "name": "addComponent", + "privacy": "private", + "parameters": [ + { + "name": "tagName", + "type": { + "text": "string" + } + } + ], + "description": "Add a new component to the slot" }, { - "name": "variant", - "fieldName": "variant", - "default": "'solid'", - "type": { - "text": "'solid' | 'outlined' | 'clear' | 'system'" - } + "kind": "field", + "name": "handleSlotChange", + "privacy": "private", + "description": "Handle slot change event to re-read content when nodes are assigned" }, { - "name": "color", - "fieldName": "color", - "default": "'primary'", - "type": { - "text": "'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'" - } + "kind": "method", + "name": "render" }, { - "name": "size", - "fieldName": "size", - "default": "'medium'", + "kind": "method", + "name": "renderContent", + "privacy": "private" + } + ], + "attributes": [ + { + "name": "type", + "fieldName": "type", + "default": "'slot'", + "description": "The type of slot content.\n- `slot`: Default, shows a dropzone for components (default)\n- `text`: Shows a single-line text input\n- `textarea`: Shows a multi-line text area", "type": { - "text": "'small' | 'medium' | 'large'" + "text": "'slot' | 'text' | 'textarea'" } }, { - "name": "selected", - "fieldName": "selected", - "default": "false", + "name": "name", + "fieldName": "name", + "default": "''", + "description": "The name of the slot this placeholder represents.\nShould match the slot name in the parent component.", "type": { - "text": "boolean" + "text": "string" } }, { - "name": "full-width", - "fieldName": "fullWidth", - "default": "false", + "name": "label", + "fieldName": "label", + "description": "Label to display in admin mode.\nIf not provided, the slot name will be used.", "type": { - "text": "boolean" + "text": "string" } }, { - "name": "icon-only", - "fieldName": "iconOnly", + "name": "description", + "fieldName": "description", + "description": "Description of what content this slot accepts.\nShown in admin mode to guide content editors.", "type": { - "text": "string | Node" + "text": "string" } }, { - "name": "icon-start", - "fieldName": "iconStart", + "name": "allowed-components", + "fieldName": "allowedComponents", + "description": "Comma-separated list of allowed component tags for this slot.\nUsed by CMS to filter available components.", "type": { - "text": "string | Node" + "text": "string" } }, { - "name": "icon-end", - "fieldName": "iconEnd", + "name": "multiple", + "fieldName": "multiple", + "default": "true", + "description": "Whether multiple components can be dropped in this slot.", "type": { - "text": "string | Node" + "text": "boolean" } }, { - "name": "type", - "fieldName": "type", - "default": "'button'", + "name": "required", + "fieldName": "required", + "default": "false", + "description": "Whether this slot is required to have content.", "type": { - "text": "'button' | 'submit' | 'reset'" + "text": "boolean" } }, { - "name": "href", - "fieldName": "href", + "name": "placeholder", + "fieldName": "placeholder", + "description": "Placeholder text for text/textarea inputs in admin mode.", "type": { "text": "string" } }, { - "name": "target", - "fieldName": "target", + "name": "tag", + "fieldName": "tag", + "description": "The HTML tag to create when there's no slotted element.\nUsed with type=\"text\" or type=\"textarea\" to auto-create elements.", "type": { "text": "string" } }, { - "name": "align", - "fieldName": "align", - "default": "'center'", + "name": "slot-style", + "fieldName": "slotStyle", + "description": "CSS styles for the slot dropzone container.\nUseful for layouts - e.g., \"flex-direction: row\" for horizontal stacks.\nOnly applies in admin mode for type=\"slot\".", "type": { - "text": "'start' | 'center' | 'space-between' | 'end'" + "text": "string" } } ], - "tagName": "le-side-panel-toggle", + "tagName": "le-slot", "events": [ { - "name": "leSidePanelRequestToggle", + "name": "leSlotChange", "type": { - "text": "EventEmitter" - } + "text": "EventEmitter<{ name: string; value: string; isValid: boolean }>" + }, + "description": "Emitted when text content changes in admin mode.\nThe event detail contains the new text value and validity." } ], "customElement": true @@ -13222,33 +13623,45 @@ "exports": [ { "kind": "js", - "name": "LeSidePanelToggle", + "name": "LeSlot", "declaration": { - "name": "LeSidePanelToggle", - "module": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx" + "name": "LeSlot", + "module": "src/components/le-slot/le-slot.tsx" } }, { "kind": "custom-element-definition", - "name": "le-side-panel-toggle", + "name": "le-slot", "declaration": { - "name": "LeSidePanelToggle", - "module": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx" + "name": "LeSlot", + "module": "src/components/le-slot/le-slot.tsx" } } ] }, { "kind": "javascript-module", - "path": "src/components/le-slot/le-slot.tsx", + "path": "src/components/le-stack/le-stack.tsx", "declarations": [ { "kind": "class", - "description": "Slot placeholder component for admin/CMS mode.\n\nThis component renders a visual placeholder for slots when in admin mode,\nallowing CMS systems to show available drop zones for content or inline editing.\n\nIn non-admin mode, this component renders nothing and acts as a passthrough.", - "name": "LeSlot", + "description": "A flexible stack layout component using CSS flexbox.\n\n`le-stack` arranges its children in a row (horizontal) or column (vertical)\nwith configurable spacing, alignment, and wrapping behavior. Perfect for\ncreating responsive layouts.", + "name": "LeStack", + "cssProperties": [ + { + "description": "Gap between items (defaults to var(--le-space-md))", + "name": "--le-stack-gap" + } + ], + "cssParts": [ + { + "description": "The main stack container", + "name": "stack" + } + ], "slots": [ { - "description": "Default slot for placeholder content or drop zone UI", + "description": "Default slot for stack items (le-box components recommended)", "name": "" } ], @@ -13262,407 +13675,309 @@ }, { "kind": "field", - "name": "type", - "type": { - "text": "'slot' | 'text' | 'textarea'" - }, - "default": "'slot'", - "description": "The type of slot content.\n- `slot`: Default, shows a dropzone for components (default)\n- `text`: Shows a single-line text input\n- `textarea`: Shows a multi-line text area" - }, - { - "kind": "field", - "name": "name", - "type": { - "text": "string" - }, - "default": "''", - "description": "The name of the slot this placeholder represents.\nShould match the slot name in the parent component." - }, - { - "kind": "field", - "name": "label", - "type": { - "text": "string | undefined" - }, - "description": "Label to display in admin mode.\nIf not provided, the slot name will be used." - }, - { - "kind": "field", - "name": "description", - "type": { - "text": "string | undefined" - }, - "description": "Description of what content this slot accepts.\nShown in admin mode to guide content editors." - }, - { - "kind": "field", - "name": "allowedComponents", - "type": { - "text": "string | undefined" - }, - "description": "Comma-separated list of allowed component tags for this slot.\nUsed by CMS to filter available components." - }, - { - "kind": "field", - "name": "multiple", - "type": { - "text": "boolean" - }, - "default": "true", - "description": "Whether multiple components can be dropped in this slot." - }, - { - "kind": "field", - "name": "required", + "name": "direction", "type": { - "text": "boolean" + "text": "'horizontal' | 'vertical'" }, - "default": "false", - "description": "Whether this slot is required to have content." + "default": "'horizontal'", + "description": "Direction of the stack layout" }, { "kind": "field", - "name": "placeholder", + "name": "gap", "type": { "text": "string | undefined" }, - "description": "Placeholder text for text/textarea inputs in admin mode." + "description": "Gap between items (CSS value like '8px', '1rem', 'var(--le-space-md)')" }, { "kind": "field", - "name": "tag", + "name": "align", "type": { - "text": "string | undefined" + "text": "'start' | 'center' | 'end' | 'stretch' | 'baseline'" }, - "description": "The HTML tag to create when there's no slotted element.\nUsed with type=\"text\" or type=\"textarea\" to auto-create elements." + "default": "'stretch'", + "description": "Alignment of items on the cross axis" }, { "kind": "field", - "name": "slotStyle", + "name": "justify", "type": { - "text": "string | undefined" + "text": "'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly'" }, - "description": "CSS styles for the slot dropzone container.\nUseful for layouts - e.g., \"flex-direction: row\" for horizontal stacks.\nOnly applies in admin mode for type=\"slot\"." + "default": "'start'", + "description": "Distribution of items on the main axis" }, { "kind": "field", - "name": "adminMode", + "name": "wrap", "type": { "text": "boolean" }, - "privacy": "private", "default": "false", - "description": "Internal state to track admin mode" - }, - { - "kind": "field", - "name": "textValue", - "type": { - "text": "string" - }, - "privacy": "private", - "default": "''", - "description": "Internal state for text input value (synced from slot content)" - }, - { - "kind": "field", - "name": "isValidHtml", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "true", - "description": "Whether the current textValue contains valid HTML" + "description": "Whether items should wrap to multiple lines" }, { "kind": "field", - "name": "availableComponents", + "name": "alignContent", "type": { - "text": "ComponentInfo[]" + "text": "'start' | 'center' | 'end' | 'stretch' | 'space-between' | 'space-around'" }, - "privacy": "private", - "default": "[]", - "description": "Available components loaded from Custom Elements Manifest" + "default": "'stretch'", + "description": "Alignment of wrapped lines (only applies when wrap is true)" }, { "kind": "field", - "name": "pickerOpen", + "name": "reverse", "type": { "text": "boolean" }, - "privacy": "private", "default": "false", - "description": "Whether the component picker popover is open" - }, - { - "kind": "field", - "name": "slotRef", - "type": { - "text": "HTMLSlotElement | undefined" - }, - "privacy": "private", - "description": "Reference to the slot element to access assignedNodes" + "description": "Whether to reverse the order of items" }, { "kind": "field", - "name": "slottedElement", + "name": "maxItems", "type": { - "text": "Element | undefined" + "text": "number | undefined" }, - "privacy": "private", - "description": "The original slotted element (e.g.,

)" + "description": "Maximum number of items allowed in the stack (for CMS validation)" }, { "kind": "field", - "name": "disconnectModeObserver", + "name": "fullWidth", "type": { - "text": "() => void | undefined" + "text": "boolean" }, - "privacy": "private" + "default": "false", + "description": "Whether the stack should take full width of its container" }, { "kind": "field", - "name": "isUpdating", + "name": "fullHeight", "type": { "text": "boolean" }, - "privacy": "private", "default": "false", - "description": "Flag to prevent re-reading content right after we updated it" + "description": "Whether the stack should take full height of its container" }, { - "kind": "method", - "name": "readSlottedContent", - "privacy": "private", - "description": "Read content from slotted elements via assignedNodes()" + "kind": "field", + "name": "padding", + "type": { + "text": "string | undefined" + }, + "description": "Padding inside the stack container (CSS value)" }, { "kind": "method", - "name": "validateHtml", + "name": "getFlexDirection", "privacy": "private", "return": { "type": { - "text": "boolean" - } - }, - "parameters": [ - { - "name": "html", - "type": { - "text": "string" - } + "text": "string" } - ], - "description": "Validates if a string contains valid HTML" - }, - { - "kind": "field", - "name": "handleTextInput", - "privacy": "private" - }, - { - "kind": "method", - "name": "createSlottedElement", - "privacy": "private", - "description": "Create a new slotted element when none exists.\nThe element is appended to the host component's light DOM." + } }, { "kind": "method", - "name": "loadAvailableComponents", + "name": "getAlignItems", "privacy": "private", - "description": "Load available components from Custom Elements Manifest" + "return": { + "type": { + "text": "string" + } + } }, { "kind": "method", - "name": "formatComponentName", + "name": "getJustifyContent", "privacy": "private", "return": { "type": { "text": "string" } - }, - "parameters": [ - { - "name": "tagName", - "type": { - "text": "string" - } - } - ], - "description": "Format a tag name into a display name\ne.g., 'le-card' -> 'Card'" + } }, { "kind": "method", - "name": "addComponent", + "name": "getAlignContent", "privacy": "private", - "parameters": [ - { - "name": "tagName", - "type": { - "text": "string" - } + "return": { + "type": { + "text": "string" } - ], - "description": "Add a new component to the slot" - }, - { - "kind": "field", - "name": "handleSlotChange", - "privacy": "private", - "description": "Handle slot change event to re-read content when nodes are assigned" + } }, { "kind": "method", "name": "render" - }, - { - "kind": "method", - "name": "renderContent", - "privacy": "private" } ], "attributes": [ { - "name": "type", - "fieldName": "type", - "default": "'slot'", - "description": "The type of slot content.\n- `slot`: Default, shows a dropzone for components (default)\n- `text`: Shows a single-line text input\n- `textarea`: Shows a multi-line text area", + "name": "direction", + "fieldName": "direction", + "default": "'horizontal'", + "description": "Direction of the stack layout", "type": { - "text": "'slot' | 'text' | 'textarea'" + "text": "'horizontal' | 'vertical'" } }, { - "name": "name", - "fieldName": "name", - "default": "''", - "description": "The name of the slot this placeholder represents.\nShould match the slot name in the parent component.", + "name": "gap", + "fieldName": "gap", + "description": "Gap between items (CSS value like '8px', '1rem', 'var(--le-space-md)')", "type": { "text": "string" } }, { - "name": "label", - "fieldName": "label", - "description": "Label to display in admin mode.\nIf not provided, the slot name will be used.", + "name": "align", + "fieldName": "align", + "default": "'stretch'", + "description": "Alignment of items on the cross axis", "type": { - "text": "string" + "text": "'start' | 'center' | 'end' | 'stretch' | 'baseline'" } }, { - "name": "description", - "fieldName": "description", - "description": "Description of what content this slot accepts.\nShown in admin mode to guide content editors.", + "name": "justify", + "fieldName": "justify", + "default": "'start'", + "description": "Distribution of items on the main axis", "type": { - "text": "string" + "text": "'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly'" } }, { - "name": "allowed-components", - "fieldName": "allowedComponents", - "description": "Comma-separated list of allowed component tags for this slot.\nUsed by CMS to filter available components.", + "name": "wrap", + "fieldName": "wrap", + "default": "false", + "description": "Whether items should wrap to multiple lines", "type": { - "text": "string" + "text": "boolean" } }, { - "name": "multiple", - "fieldName": "multiple", - "default": "true", - "description": "Whether multiple components can be dropped in this slot.", + "name": "align-content", + "fieldName": "alignContent", + "default": "'stretch'", + "description": "Alignment of wrapped lines (only applies when wrap is true)", "type": { - "text": "boolean" + "text": "'start' | 'center' | 'end' | 'stretch' | 'space-between' | 'space-around'" } }, { - "name": "required", - "fieldName": "required", + "name": "reverse", + "fieldName": "reverse", "default": "false", - "description": "Whether this slot is required to have content.", + "description": "Whether to reverse the order of items", "type": { "text": "boolean" } }, { - "name": "placeholder", - "fieldName": "placeholder", - "description": "Placeholder text for text/textarea inputs in admin mode.", + "name": "max-items", + "fieldName": "maxItems", + "description": "Maximum number of items allowed in the stack (for CMS validation)", "type": { - "text": "string" + "text": "number" } }, { - "name": "tag", - "fieldName": "tag", - "description": "The HTML tag to create when there's no slotted element.\nUsed with type=\"text\" or type=\"textarea\" to auto-create elements.", + "name": "full-width", + "fieldName": "fullWidth", + "default": "false", + "description": "Whether the stack should take full width of its container", "type": { - "text": "string" + "text": "boolean" } }, { - "name": "slot-style", - "fieldName": "slotStyle", - "description": "CSS styles for the slot dropzone container.\nUseful for layouts - e.g., \"flex-direction: row\" for horizontal stacks.\nOnly applies in admin mode for type=\"slot\".", + "name": "full-height", + "fieldName": "fullHeight", + "default": "false", + "description": "Whether the stack should take full height of its container", "type": { - "text": "string" + "text": "boolean" } - } - ], - "tagName": "le-slot", - "events": [ + }, { - "name": "leSlotChange", + "name": "padding", + "fieldName": "padding", + "description": "Padding inside the stack container (CSS value)", "type": { - "text": "EventEmitter<{ name: string; value: string; isValid: boolean }>" - }, - "description": "Emitted when text content changes in admin mode.\nThe event detail contains the new text value and validity." + "text": "string" + } } ], + "tagName": "le-stack", + "events": [], "customElement": true } ], "exports": [ { "kind": "js", - "name": "LeSlot", + "name": "LeStack", "declaration": { - "name": "LeSlot", - "module": "src/components/le-slot/le-slot.tsx" + "name": "LeStack", + "module": "src/components/le-stack/le-stack.tsx" } }, { "kind": "custom-element-definition", - "name": "le-slot", + "name": "le-stack", "declaration": { - "name": "LeSlot", - "module": "src/components/le-slot/le-slot.tsx" + "name": "LeStack", + "module": "src/components/le-stack/le-stack.tsx" } } ] }, { "kind": "javascript-module", - "path": "src/components/le-stack/le-stack.tsx", + "path": "src/components/le-tab-bar/le-tab-bar.tsx", "declarations": [ { "kind": "class", - "description": "A flexible stack layout component using CSS flexbox.\n\n`le-stack` arranges its children in a row (horizontal) or column (vertical)\nwith configurable spacing, alignment, and wrapping behavior. Perfect for\ncreating responsive layouts.", - "name": "LeStack", + "description": "A presentational tab bar component without panels.\n\nUse this for navigation/routing scenarios where you manage the content\nexternally based on the selection events. For tabs with built-in panels,\nuse `le-tabs` instead.", + "name": "LeTabBar", "cssProperties": [ { - "description": "Gap between items (defaults to var(--le-space-md))", - "name": "--le-stack-gap" + "description": "Border color", + "name": "--le-tab-bar-border-color" + }, + { + "description": "Gap between tabs", + "name": "--le-tab-bar-gap" + }, + { + "description": "Active indicator color", + "name": "--le-tab-bar-indicator-color" + }, + { + "description": "Horizontal padding for tabs", + "name": "--le-tab-bar-padding-x" + }, + { + "description": "Vertical padding for tabs", + "name": "--le-tab-bar-padding-y" } ], "cssParts": [ { - "description": "The main stack container", - "name": "stack" - } - ], - "slots": [ + "description": "The tab button container", + "name": "tablist" + }, { - "description": "Default slot for stack items (le-box components recommended)", - "name": "" + "description": "Individual tab buttons", + "name": "tab" + }, + { + "description": "The currently active tab", + "name": "tab-active" } ], "members": [ @@ -13675,137 +13990,223 @@ }, { "kind": "field", - "name": "direction", + "name": "tabs", "type": { - "text": "'horizontal' | 'vertical'" + "text": "LeOption[]" }, - "default": "'horizontal'", - "description": "Direction of the stack layout" + "default": "[]", + "description": "Array of tab options defining the tabs to display." }, { "kind": "field", - "name": "gap", + "name": "selected", "type": { - "text": "string | undefined" + "text": "LeOptionValue | undefined" }, - "description": "Gap between items (CSS value like '8px', '1rem', 'var(--le-space-md)')" + "description": "The value of the currently selected tab." }, { "kind": "field", - "name": "align", + "name": "fullWidth", "type": { - "text": "'start' | 'center' | 'end' | 'stretch' | 'baseline'" + "text": "boolean" }, - "default": "'stretch'", - "description": "Alignment of items on the cross axis" + "default": "true", + "description": "Whether tabs should stretch to fill available width." }, { "kind": "field", - "name": "justify", + "name": "showLabels", "type": { - "text": "'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly'" + "text": "boolean" }, - "default": "'start'", - "description": "Distribution of items on the main axis" + "default": "false", + "description": "Whether to show labels in icon-only mode." }, { "kind": "field", - "name": "wrap", + "name": "position", "type": { - "text": "boolean" + "text": "'top' | 'bottom'" }, - "default": "false", - "description": "Whether items should wrap to multiple lines" + "default": "'top'", + "description": "Position of the tab bar." }, { "kind": "field", - "name": "alignContent", + "name": "size", "type": { - "text": "'start' | 'center' | 'end' | 'stretch' | 'space-between' | 'space-around'" + "text": "'small' | 'medium' | 'large'" }, - "default": "'stretch'", - "description": "Alignment of wrapped lines (only applies when wrap is true)" + "default": "'medium'", + "description": "Size of the tabs." }, { "kind": "field", - "name": "reverse", + "name": "bordered", "type": { "text": "boolean" }, - "default": "false", - "description": "Whether to reverse the order of items" + "default": "true", + "description": "Whether to show a border below the tab bar." }, { "kind": "field", - "name": "maxItems", + "name": "tabConfigs", "type": { - "text": "number | undefined" + "text": "TabConfig[]" }, - "description": "Maximum number of items allowed in the stack (for CMS validation)" + "privacy": "private", + "default": "[]", + "description": "Internal tab configurations (built from children or tabs prop)" }, { "kind": "field", - "name": "fullWidth", + "name": "isDeclarativeMode", "type": { "text": "boolean" }, + "privacy": "private", "default": "false", - "description": "Whether the stack should take full width of its container" + "description": "Whether we're using declarative mode (le-tab-panel children)" }, { "kind": "field", - "name": "fullHeight", + "name": "focusedIndex", "type": { - "text": "boolean" + "text": "number" }, - "default": "false", - "description": "Whether the stack should take full height of its container" + "privacy": "private", + "default": "0", + "description": "Internal state for focused tab index (for keyboard navigation)" }, { "kind": "field", - "name": "padding", + "name": "mutationObserver", "type": { - "text": "string | undefined" + "text": "MutationObserver | undefined" }, - "description": "Padding inside the stack container (CSS value)" + "privacy": "private" }, { "kind": "method", - "name": "getFlexDirection", + "name": "selectedChanged", + "parameters": [ + { + "name": "newValue", + "type": { + "text": "LeOptionValue" + } + } + ] + }, + { + "kind": "method", + "name": "tabsChanged" + }, + { + "kind": "method", + "name": "handleSlotChange" + }, + { + "kind": "method", + "name": "buildTabConfigs", + "privacy": "private" + }, + { + "kind": "method", + "name": "getTabValue", "privacy": "private", "return": { "type": { - "text": "string" + "text": "LeOptionValue" } - } + }, + "parameters": [ + { + "name": "tab", + "type": { + "text": "LeOption" + } + } + ] }, { "kind": "method", - "name": "getAlignItems", + "name": "getTabIndex", "privacy": "private", "return": { "type": { - "text": "string" + "text": "number" } - } + }, + "parameters": [ + { + "name": "value", + "type": { + "text": "LeOptionValue" + } + } + ] }, { "kind": "method", - "name": "getJustifyContent", + "name": "selectTab", + "privacy": "private", + "parameters": [ + { + "name": "tab", + "type": { + "text": "LeOption" + } + } + ] + }, + { + "kind": "field", + "name": "handleTabClick", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleKeyDown", + "privacy": "private" + }, + { + "kind": "method", + "name": "findNextEnabledTab", "privacy": "private", "return": { "type": { - "text": "string" + "text": "number" + } + }, + "parameters": [ + { + "name": "direction", + "type": { + "text": "1 | -1" + } + } + ] + }, + { + "kind": "method", + "name": "findFirstEnabledTab", + "privacy": "private", + "return": { + "type": { + "text": "number" } } }, { "kind": "method", - "name": "getAlignContent", + "name": "findLastEnabledTab", "privacy": "private", "return": { "type": { - "text": "string" + "text": "number" } } }, @@ -13816,122 +14217,96 @@ ], "attributes": [ { - "name": "direction", - "fieldName": "direction", - "default": "'horizontal'", - "description": "Direction of the stack layout", - "type": { - "text": "'horizontal' | 'vertical'" - } - }, - { - "name": "gap", - "fieldName": "gap", - "description": "Gap between items (CSS value like '8px', '1rem', 'var(--le-space-md)')", - "type": { - "text": "string" - } - }, - { - "name": "align", - "fieldName": "align", - "default": "'stretch'", - "description": "Alignment of items on the cross axis", + "name": "tabs", + "fieldName": "tabs", + "default": "[]", + "description": "Array of tab options defining the tabs to display.", "type": { - "text": "'start' | 'center' | 'end' | 'stretch' | 'baseline'" + "text": "LeOption[]" } }, { - "name": "justify", - "fieldName": "justify", - "default": "'start'", - "description": "Distribution of items on the main axis", + "name": "selected", + "fieldName": "selected", + "description": "The value of the currently selected tab.", "type": { - "text": "'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly'" + "text": "LeOptionValue" } }, { - "name": "wrap", - "fieldName": "wrap", - "default": "false", - "description": "Whether items should wrap to multiple lines", + "name": "full-width", + "fieldName": "fullWidth", + "default": "true", + "description": "Whether tabs should stretch to fill available width.", "type": { "text": "boolean" } }, { - "name": "align-content", - "fieldName": "alignContent", - "default": "'stretch'", - "description": "Alignment of wrapped lines (only applies when wrap is true)", - "type": { - "text": "'start' | 'center' | 'end' | 'stretch' | 'space-between' | 'space-around'" - } - }, - { - "name": "reverse", - "fieldName": "reverse", + "name": "show-labels", + "fieldName": "showLabels", "default": "false", - "description": "Whether to reverse the order of items", + "description": "Whether to show labels in icon-only mode.", "type": { "text": "boolean" } }, { - "name": "max-items", - "fieldName": "maxItems", - "description": "Maximum number of items allowed in the stack (for CMS validation)", + "name": "position", + "fieldName": "position", + "default": "'top'", + "description": "Position of the tab bar.", "type": { - "text": "number" + "text": "'top' | 'bottom'" } }, { - "name": "full-width", - "fieldName": "fullWidth", - "default": "false", - "description": "Whether the stack should take full width of its container", + "name": "size", + "fieldName": "size", + "default": "'medium'", + "description": "Size of the tabs.", "type": { - "text": "boolean" + "text": "'small' | 'medium' | 'large'" } }, { - "name": "full-height", - "fieldName": "fullHeight", - "default": "false", - "description": "Whether the stack should take full height of its container", + "name": "bordered", + "fieldName": "bordered", + "default": "true", + "description": "Whether to show a border below the tab bar.", "type": { "text": "boolean" } - }, + } + ], + "tagName": "le-tab-bar", + "events": [ { - "name": "padding", - "fieldName": "padding", - "description": "Padding inside the stack container (CSS value)", + "name": "leTabChange", "type": { - "text": "string" - } + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the selected tab changes." } ], - "tagName": "le-stack", - "events": [], "customElement": true } ], "exports": [ { "kind": "js", - "name": "LeStack", + "name": "LeTabBar", "declaration": { - "name": "LeStack", - "module": "src/components/le-stack/le-stack.tsx" + "name": "LeTabBar", + "module": "src/components/le-tab-bar/le-tab-bar.tsx" } }, { "kind": "custom-element-definition", - "name": "le-stack", + "name": "le-tab-bar", "declaration": { - "name": "LeStack", - "module": "src/components/le-stack/le-stack.tsx" + "name": "LeTabBar", + "module": "src/components/le-tab-bar/le-tab-bar.tsx" } } ] @@ -14781,37 +15156,37 @@ }, { "kind": "javascript-module", - "path": "src/components/le-tab-bar/le-tab-bar.tsx", + "path": "src/components/le-tabs/le-tabs.tsx", "declarations": [ { "kind": "class", - "description": "A presentational tab bar component without panels.\n\nUse this for navigation/routing scenarios where you manage the content\nexternally based on the selection events. For tabs with built-in panels,\nuse `le-tabs` instead.", - "name": "LeTabBar", + "description": "A flexible tabs component for organizing content into tabbed panels.\n\nSupports two modes:\n1. **Declarative**: Use `` children to define tabs and content\n2. **Programmatic**: Use the `tabs` prop with named slots for content\n\nFull keyboard navigation and ARIA support included.", + "name": "LeTabs", "cssProperties": [ { - "description": "Border color", - "name": "--le-tab-bar-border-color" + "description": "Border color for tab list", + "name": "--le-tabs-border-color" }, { "description": "Gap between tabs", - "name": "--le-tab-bar-gap" + "name": "--le-tabs-gap" }, { - "description": "Active indicator color", - "name": "--le-tab-bar-indicator-color" + "description": "Active tab indicator color", + "name": "--le-tabs-indicator-color" }, { - "description": "Horizontal padding for tabs", - "name": "--le-tab-bar-padding-x" + "description": "Horizontal padding for tab buttons", + "name": "--le-tabs-padding-x" }, { - "description": "Vertical padding for tabs", - "name": "--le-tab-bar-padding-y" + "description": "Vertical padding for tab buttons", + "name": "--le-tabs-padding-y" } ], "cssParts": [ { - "description": "The tab button container", + "description": "The tab button container (role=\"tablist\")", "name": "tablist" }, { @@ -14821,6 +15196,24 @@ { "description": "The currently active tab", "name": "tab-active" + }, + { + "description": "Container for panel content", + "name": "panels" + }, + { + "description": "Individual panel containers", + "name": "panel" + } + ], + "slots": [ + { + "description": "Default slot for le-tab-panel children (declarative mode)", + "name": "" + }, + { + "description": "Named slots for panel content (programmatic mode)", + "name": "panel-{value}" } ], "members": [ @@ -14838,7 +15231,7 @@ "text": "LeOption[]" }, "default": "[]", - "description": "Array of tab options defining the tabs to display." + "description": "Array of tab options (programmatic mode).\nIf le-tab-panel children exist, they take precedence." }, { "kind": "field", @@ -14846,34 +15239,43 @@ "type": { "text": "LeOptionValue | undefined" }, - "description": "The value of the currently selected tab." + "description": "The value of the currently selected tab.\nIf not provided, defaults to the first tab." }, { "kind": "field", - "name": "fullWidth", + "name": "orientation", "type": { - "text": "boolean" + "text": "'horizontal' | 'vertical'" }, - "default": "true", - "description": "Whether tabs should stretch to fill available width." + "default": "'horizontal'", + "description": "Orientation of the tabs." }, { "kind": "field", - "name": "showLabels", + "name": "position", "type": { - "text": "boolean" + "text": "'start' | 'end'" }, - "default": "false", - "description": "Whether to show labels in icon-only mode." + "default": "'start'", + "description": "Position of the tabs relative to the panels." }, { "kind": "field", - "name": "position", + "name": "variant", "type": { - "text": "'top' | 'bottom'" + "text": "'underlined' | 'solid' | 'pills' | 'enclosed' | 'icon-only'" }, - "default": "'top'", - "description": "Position of the tab bar." + "default": "'underlined'", + "description": "Tab variant style." + }, + { + "kind": "field", + "name": "fullWidth", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether tabs should stretch to fill available width." }, { "kind": "field", @@ -14886,12 +15288,21 @@ }, { "kind": "field", - "name": "bordered", + "name": "wrap", "type": { "text": "boolean" }, - "default": "true", - "description": "Whether to show a border below the tab bar." + "default": "false", + "description": "Wrap the tabs if they exceed container width." + }, + { + "kind": "field", + "name": "overflow", + "type": { + "text": "'auto' | 'hidden' | 'visible' | 'scroll'" + }, + "default": "'auto'", + "description": "Scroll behavior for overflowing tabs." }, { "kind": "field", @@ -14905,23 +15316,23 @@ }, { "kind": "field", - "name": "isDeclarativeMode", + "name": "focusedIndex", "type": { - "text": "boolean" + "text": "number" }, "privacy": "private", - "default": "false", - "description": "Whether we're using declarative mode (le-tab-panel children)" + "default": "0", + "description": "Internal state for focused tab index (for keyboard navigation)" }, { "kind": "field", - "name": "focusedIndex", + "name": "isDeclarativeMode", "type": { - "text": "number" + "text": "boolean" }, "privacy": "private", - "default": "0", - "description": "Internal state for focused tab index (for keyboard navigation)" + "default": "false", + "description": "Whether we're using declarative mode (le-tab-panel children)" }, { "kind": "field", @@ -14958,39 +15369,8 @@ }, { "kind": "method", - "name": "getTabValue", - "privacy": "private", - "return": { - "type": { - "text": "LeOptionValue" - } - }, - "parameters": [ - { - "name": "tab", - "type": { - "text": "LeOption" - } - } - ] - }, - { - "kind": "method", - "name": "getTabIndex", - "privacy": "private", - "return": { - "type": { - "text": "number" - } - }, - "parameters": [ - { - "name": "value", - "type": { - "text": "LeOptionValue" - } - } - ] + "name": "updatePanelStates", + "privacy": "private" }, { "kind": "method", @@ -14998,9 +15378,9 @@ "privacy": "private", "parameters": [ { - "name": "tab", + "name": "config", "type": { - "text": "LeOption" + "text": "TabConfig" } } ] @@ -15053,6 +15433,19 @@ } } }, + { + "kind": "method", + "name": "focusTab", + "privacy": "private", + "parameters": [ + { + "name": "index", + "type": { + "text": "number" + } + } + ] + }, { "kind": "method", "name": "render" @@ -15063,7 +15456,7 @@ "name": "tabs", "fieldName": "tabs", "default": "[]", - "description": "Array of tab options defining the tabs to display.", + "description": "Array of tab options (programmatic mode).\nIf le-tab-panel children exist, they take precedence.", "type": { "text": "LeOption[]" } @@ -15071,36 +15464,45 @@ { "name": "selected", "fieldName": "selected", - "description": "The value of the currently selected tab.", + "description": "The value of the currently selected tab.\nIf not provided, defaults to the first tab.", "type": { "text": "LeOptionValue" } }, { - "name": "full-width", - "fieldName": "fullWidth", - "default": "true", - "description": "Whether tabs should stretch to fill available width.", + "name": "orientation", + "fieldName": "orientation", + "default": "'horizontal'", + "description": "Orientation of the tabs.", "type": { - "text": "boolean" + "text": "'horizontal' | 'vertical'" } }, { - "name": "show-labels", - "fieldName": "showLabels", - "default": "false", - "description": "Whether to show labels in icon-only mode.", + "name": "position", + "fieldName": "position", + "default": "'start'", + "description": "Position of the tabs relative to the panels.", "type": { - "text": "boolean" + "text": "'start' | 'end'" } }, { - "name": "position", - "fieldName": "position", - "default": "'top'", - "description": "Position of the tab bar.", + "name": "variant", + "fieldName": "variant", + "default": "'underlined'", + "description": "Tab variant style.", "type": { - "text": "'top' | 'bottom'" + "text": "'underlined' | 'solid' | 'pills' | 'enclosed' | 'icon-only'" + } + }, + { + "name": "full-width", + "fieldName": "fullWidth", + "default": "false", + "description": "Whether tabs should stretch to fill available width.", + "type": { + "text": "boolean" } }, { @@ -15113,16 +15515,25 @@ } }, { - "name": "bordered", - "fieldName": "bordered", - "default": "true", - "description": "Whether to show a border below the tab bar.", + "name": "wrap", + "fieldName": "wrap", + "default": "false", + "description": "Wrap the tabs if they exceed container width.", + "type": { + "text": "boolean" + } + }, + { + "name": "overflow", + "fieldName": "overflow", + "default": "'auto'", + "description": "Scroll behavior for overflowing tabs.", "type": { - "text": "boolean" + "text": "'auto' | 'hidden' | 'visible' | 'scroll'" } } ], - "tagName": "le-tab-bar", + "tagName": "le-tabs", "events": [ { "name": "leTabChange", @@ -15138,18 +15549,18 @@ "exports": [ { "kind": "js", - "name": "LeTabBar", + "name": "LeTabs", "declaration": { - "name": "LeTabBar", - "module": "src/components/le-tab-bar/le-tab-bar.tsx" + "name": "LeTabs", + "module": "src/components/le-tabs/le-tabs.tsx" } }, { "kind": "custom-element-definition", - "name": "le-tab-bar", + "name": "le-tabs", "declaration": { - "name": "LeTabBar", - "module": "src/components/le-tab-bar/le-tab-bar.tsx" + "name": "LeTabs", + "module": "src/components/le-tabs/le-tabs.tsx" } } ] @@ -15386,307 +15797,57 @@ "path": "src/components/le-tag/le-tag.tsx", "declarations": [ { - "kind": "class", - "description": "A tag/chip component for displaying labels with optional dismiss functionality.", - "name": "LeTag", - "slots": [ - { - "description": "Default slot for custom content (overrides label prop)", - "name": "" - } - ], - "members": [ - { - "kind": "field", - "name": "label", - "type": { - "text": "string | undefined" - }, - "description": "The text label to display in the tag." - }, - { - "kind": "field", - "name": "mode", - "type": { - "text": "'default' | 'admin' | undefined" - }, - "description": "Mode of the popover should be 'default' for internal use" - }, - { - "kind": "field", - "name": "icon", - "type": { - "text": "string | undefined" - }, - "description": "Icon to display before the label.\nCan be an emoji, URL, or icon name." - }, - { - "kind": "field", - "name": "dismissible", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Whether the tag can be dismissed (shows close button)." - }, - { - "kind": "field", - "name": "disabled", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Whether the tag is disabled." - }, - { - "kind": "field", - "name": "size", - "type": { - "text": "'small' | 'medium' | 'large'" - }, - "default": "'medium'", - "description": "The size of the tag." - }, - { - "kind": "field", - "name": "color", - "type": { - "text": "| 'default'\n | 'primary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'secondary'\n | 'info'" - }, - "default": "'default'", - "description": "The color of the tag." - }, - { - "kind": "field", - "name": "handleDismiss", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderIcon", - "privacy": "private" - }, - { - "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "label", - "fieldName": "label", - "description": "The text label to display in the tag.", - "type": { - "text": "string" - } - }, - { - "name": "mode", - "fieldName": "mode", - "description": "Mode of the popover should be 'default' for internal use", - "type": { - "text": "'default' | 'admin'" - } - }, - { - "name": "icon", - "fieldName": "icon", - "description": "Icon to display before the label.\nCan be an emoji, URL, or icon name.", - "type": { - "text": "string" - } - }, - { - "name": "dismissible", - "fieldName": "dismissible", - "default": "false", - "description": "Whether the tag can be dismissed (shows close button).", - "type": { - "text": "boolean" - } - }, - { - "name": "disabled", - "fieldName": "disabled", - "default": "false", - "description": "Whether the tag is disabled.", - "type": { - "text": "boolean" - } - }, - { - "name": "size", - "fieldName": "size", - "default": "'medium'", - "description": "The size of the tag.", - "type": { - "text": "'small' | 'medium' | 'large'" - } - }, - { - "name": "color", - "fieldName": "color", - "default": "'default'", - "description": "The color of the tag.", - "type": { - "text": "| 'default'\n | 'primary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'secondary'\n | 'info'" - } - } - ], - "tagName": "le-tag", - "events": [ - { - "name": "leDismiss", - "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the dismiss button is clicked." - } - ], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeTag", - "declaration": { - "name": "LeTag", - "module": "src/components/le-tag/le-tag.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-tag", - "declaration": { - "name": "LeTag", - "module": "src/components/le-tag/le-tag.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-tabs/le-tabs.tsx", - "declarations": [ - { - "kind": "class", - "description": "A flexible tabs component for organizing content into tabbed panels.\n\nSupports two modes:\n1. **Declarative**: Use `` children to define tabs and content\n2. **Programmatic**: Use the `tabs` prop with named slots for content\n\nFull keyboard navigation and ARIA support included.", - "name": "LeTabs", - "cssProperties": [ - { - "description": "Border color for tab list", - "name": "--le-tabs-border-color" - }, - { - "description": "Gap between tabs", - "name": "--le-tabs-gap" - }, - { - "description": "Active tab indicator color", - "name": "--le-tabs-indicator-color" - }, - { - "description": "Horizontal padding for tab buttons", - "name": "--le-tabs-padding-x" - }, - { - "description": "Vertical padding for tab buttons", - "name": "--le-tabs-padding-y" - } - ], - "cssParts": [ - { - "description": "The tab button container (role=\"tablist\")", - "name": "tablist" - }, - { - "description": "Individual tab buttons", - "name": "tab" - }, - { - "description": "The currently active tab", - "name": "tab-active" - }, - { - "description": "Container for panel content", - "name": "panels" - }, - { - "description": "Individual panel containers", - "name": "panel" - } - ], + "kind": "class", + "description": "A tag/chip component for displaying labels with optional dismiss functionality.", + "name": "LeTag", "slots": [ { - "description": "Default slot for le-tab-panel children (declarative mode)", + "description": "Default slot for custom content (overrides label prop)", "name": "" - }, - { - "description": "Named slots for panel content (programmatic mode)", - "name": "panel-{value}" } ], "members": [ { "kind": "field", - "name": "el", - "type": { - "text": "HTMLElement" - } - }, - { - "kind": "field", - "name": "tabs", - "type": { - "text": "LeOption[]" - }, - "default": "[]", - "description": "Array of tab options (programmatic mode).\nIf le-tab-panel children exist, they take precedence." - }, - { - "kind": "field", - "name": "selected", + "name": "label", "type": { - "text": "LeOptionValue | undefined" + "text": "string | undefined" }, - "description": "The value of the currently selected tab.\nIf not provided, defaults to the first tab." + "description": "The text label to display in the tag." }, { "kind": "field", - "name": "orientation", + "name": "mode", "type": { - "text": "'horizontal' | 'vertical'" + "text": "'default' | 'admin' | undefined" }, - "default": "'horizontal'", - "description": "Orientation of the tabs." + "description": "Mode of the popover should be 'default' for internal use" }, { "kind": "field", - "name": "position", + "name": "icon", "type": { - "text": "'start' | 'end'" + "text": "string | undefined" }, - "default": "'start'", - "description": "Position of the tabs relative to the panels." + "description": "Icon to display before the label.\nCan be an emoji, URL, or icon name." }, { "kind": "field", - "name": "variant", + "name": "dismissible", "type": { - "text": "'underlined' | 'solid' | 'pills' | 'enclosed' | 'icon-only'" + "text": "boolean" }, - "default": "'underlined'", - "description": "Tab variant style." + "default": "false", + "description": "Whether the tag can be dismissed (shows close button)." }, { "kind": "field", - "name": "fullWidth", + "name": "disabled", "type": { "text": "boolean" }, "default": "false", - "description": "Whether tabs should stretch to fill available width." + "description": "Whether the tag is disabled." }, { "kind": "field", @@ -15695,168 +15856,27 @@ "text": "'small' | 'medium' | 'large'" }, "default": "'medium'", - "description": "Size of the tabs." - }, - { - "kind": "field", - "name": "wrap", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Wrap the tabs if they exceed container width." - }, - { - "kind": "field", - "name": "overflow", - "type": { - "text": "'auto' | 'hidden' | 'visible' | 'scroll'" - }, - "default": "'auto'", - "description": "Scroll behavior for overflowing tabs." - }, - { - "kind": "field", - "name": "tabConfigs", - "type": { - "text": "TabConfig[]" - }, - "privacy": "private", - "default": "[]", - "description": "Internal tab configurations (built from children or tabs prop)" - }, - { - "kind": "field", - "name": "focusedIndex", - "type": { - "text": "number" - }, - "privacy": "private", - "default": "0", - "description": "Internal state for focused tab index (for keyboard navigation)" + "description": "The size of the tag." }, { "kind": "field", - "name": "isDeclarativeMode", + "name": "color", "type": { - "text": "boolean" + "text": "| 'default'\n | 'primary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'secondary'\n | 'info'" }, - "privacy": "private", - "default": "false", - "description": "Whether we're using declarative mode (le-tab-panel children)" + "default": "'default'", + "description": "The color of the tag." }, { "kind": "field", - "name": "mutationObserver", - "type": { - "text": "MutationObserver | undefined" - }, - "privacy": "private" - }, - { - "kind": "method", - "name": "selectedChanged", - "parameters": [ - { - "name": "newValue", - "type": { - "text": "LeOptionValue" - } - } - ] - }, - { - "kind": "method", - "name": "tabsChanged" - }, - { - "kind": "method", - "name": "handleSlotChange" - }, - { - "kind": "method", - "name": "buildTabConfigs", - "privacy": "private" - }, - { - "kind": "method", - "name": "updatePanelStates", + "name": "handleDismiss", "privacy": "private" }, { "kind": "method", - "name": "selectTab", - "privacy": "private", - "parameters": [ - { - "name": "config", - "type": { - "text": "TabConfig" - } - } - ] - }, - { - "kind": "field", - "name": "handleTabClick", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleKeyDown", + "name": "renderIcon", "privacy": "private" }, - { - "kind": "method", - "name": "findNextEnabledTab", - "privacy": "private", - "return": { - "type": { - "text": "number" - } - }, - "parameters": [ - { - "name": "direction", - "type": { - "text": "1 | -1" - } - } - ] - }, - { - "kind": "method", - "name": "findFirstEnabledTab", - "privacy": "private", - "return": { - "type": { - "text": "number" - } - } - }, - { - "kind": "method", - "name": "findLastEnabledTab", - "privacy": "private", - "return": { - "type": { - "text": "number" - } - } - }, - { - "kind": "method", - "name": "focusTab", - "privacy": "private", - "parameters": [ - { - "name": "index", - "type": { - "text": "number" - } - } - ] - }, { "kind": "method", "name": "render" @@ -15864,54 +15884,43 @@ ], "attributes": [ { - "name": "tabs", - "fieldName": "tabs", - "default": "[]", - "description": "Array of tab options (programmatic mode).\nIf le-tab-panel children exist, they take precedence.", - "type": { - "text": "LeOption[]" - } - }, - { - "name": "selected", - "fieldName": "selected", - "description": "The value of the currently selected tab.\nIf not provided, defaults to the first tab.", + "name": "label", + "fieldName": "label", + "description": "The text label to display in the tag.", "type": { - "text": "LeOptionValue" + "text": "string" } }, { - "name": "orientation", - "fieldName": "orientation", - "default": "'horizontal'", - "description": "Orientation of the tabs.", + "name": "mode", + "fieldName": "mode", + "description": "Mode of the popover should be 'default' for internal use", "type": { - "text": "'horizontal' | 'vertical'" + "text": "'default' | 'admin'" } }, { - "name": "position", - "fieldName": "position", - "default": "'start'", - "description": "Position of the tabs relative to the panels.", + "name": "icon", + "fieldName": "icon", + "description": "Icon to display before the label.\nCan be an emoji, URL, or icon name.", "type": { - "text": "'start' | 'end'" + "text": "string" } }, { - "name": "variant", - "fieldName": "variant", - "default": "'underlined'", - "description": "Tab variant style.", + "name": "dismissible", + "fieldName": "dismissible", + "default": "false", + "description": "Whether the tag can be dismissed (shows close button).", "type": { - "text": "'underlined' | 'solid' | 'pills' | 'enclosed' | 'icon-only'" + "text": "boolean" } }, { - "name": "full-width", - "fieldName": "fullWidth", + "name": "disabled", + "fieldName": "disabled", "default": "false", - "description": "Whether tabs should stretch to fill available width.", + "description": "Whether the tag is disabled.", "type": { "text": "boolean" } @@ -15920,38 +15929,29 @@ "name": "size", "fieldName": "size", "default": "'medium'", - "description": "Size of the tabs.", + "description": "The size of the tag.", "type": { "text": "'small' | 'medium' | 'large'" } }, { - "name": "wrap", - "fieldName": "wrap", - "default": "false", - "description": "Wrap the tabs if they exceed container width.", - "type": { - "text": "boolean" - } - }, - { - "name": "overflow", - "fieldName": "overflow", - "default": "'auto'", - "description": "Scroll behavior for overflowing tabs.", + "name": "color", + "fieldName": "color", + "default": "'default'", + "description": "The color of the tag.", "type": { - "text": "'auto' | 'hidden' | 'visible' | 'scroll'" + "text": "| 'default'\n | 'primary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'secondary'\n | 'info'" } } ], - "tagName": "le-tabs", + "tagName": "le-tag", "events": [ { - "name": "leTabChange", + "name": "leDismiss", "type": { - "text": "EventEmitter | undefined" + "text": "EventEmitter | undefined" }, - "description": "Emitted when the selected tab changes." + "description": "Emitted when the dismiss button is clicked." } ], "customElement": true @@ -15960,18 +15960,18 @@ "exports": [ { "kind": "js", - "name": "LeTabs", + "name": "LeTag", "declaration": { - "name": "LeTabs", - "module": "src/components/le-tabs/le-tabs.tsx" + "name": "LeTag", + "module": "src/components/le-tag/le-tag.tsx" } }, { "kind": "custom-element-definition", - "name": "le-tabs", + "name": "le-tag", "declaration": { - "name": "LeTabs", - "module": "src/components/le-tabs/le-tabs.tsx" + "name": "LeTag", + "module": "src/components/le-tag/le-tag.tsx" } } ] @@ -16344,6 +16344,110 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx", + "declarations": [ + { + "kind": "class", + "description": "Flexible spacer for le-toolbar layouts.\n\nDefault behavior (no width): occupies available free space and shrinks naturally.\nWith numeric `width`: behaves as a fixed-width spacer that can be collapsed by le-toolbar.", + "name": "LeToolbarSpacer", + "members": [ + { + "kind": "field", + "name": "width", + "type": { + "text": "number | string | undefined" + }, + "description": "Optional fixed width.\nNumeric values (e.g. `24`) are treated as px.\nString values may be any valid CSS width (e.g. `2rem`, `var(--le-spacing-2)`)." + }, + { + "kind": "method", + "name": "isValidCssWidth", + "privacy": "private", + "return": { + "type": { + "text": "boolean" + } + }, + "parameters": [ + { + "name": "value", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "method", + "name": "getFixedWidthValue", + "privacy": "private", + "return": { + "type": { + "text": "string | undefined" + } + } + }, + { + "kind": "method", + "name": "isFixedSpacer", + "privacy": "private", + "return": { + "type": { + "text": "boolean" + } + } + }, + { + "kind": "method", + "name": "getCollapseMeta", + "return": { + "type": { + "text": "Promise" + } + }, + "description": "Returns collapse meta for toolbar integration." + }, + { + "kind": "method", + "name": "render" + } + ], + "attributes": [ + { + "name": "width", + "fieldName": "width", + "description": "Optional fixed width.\nNumeric values (e.g. `24`) are treated as px.\nString values may be any valid CSS width (e.g. `2rem`, `var(--le-spacing-2)`).", + "type": { + "text": "number | string" + } + } + ], + "tagName": "le-toolbar-spacer", + "events": [], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeToolbarSpacer", + "declaration": { + "name": "LeToolbarSpacer", + "module": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-toolbar-spacer", + "declaration": { + "name": "LeToolbarSpacer", + "module": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx" + } + } + ] + }, { "kind": "javascript-module", "path": "src/components/le-toolbar/le-toolbar.tsx", @@ -17935,110 +18039,6 @@ } ] }, - { - "kind": "javascript-module", - "path": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx", - "declarations": [ - { - "kind": "class", - "description": "Flexible spacer for le-toolbar layouts.\n\nDefault behavior (no width): occupies available free space and shrinks naturally.\nWith numeric `width`: behaves as a fixed-width spacer that can be collapsed by le-toolbar.", - "name": "LeToolbarSpacer", - "members": [ - { - "kind": "field", - "name": "width", - "type": { - "text": "number | string | undefined" - }, - "description": "Optional fixed width.\nNumeric values (e.g. `24`) are treated as px.\nString values may be any valid CSS width (e.g. `2rem`, `var(--le-spacing-2)`)." - }, - { - "kind": "method", - "name": "isValidCssWidth", - "privacy": "private", - "return": { - "type": { - "text": "boolean" - } - }, - "parameters": [ - { - "name": "value", - "type": { - "text": "string" - } - } - ] - }, - { - "kind": "method", - "name": "getFixedWidthValue", - "privacy": "private", - "return": { - "type": { - "text": "string | undefined" - } - } - }, - { - "kind": "method", - "name": "isFixedSpacer", - "privacy": "private", - "return": { - "type": { - "text": "boolean" - } - } - }, - { - "kind": "method", - "name": "getCollapseMeta", - "return": { - "type": { - "text": "Promise" - } - }, - "description": "Returns collapse meta for toolbar integration." - }, - { - "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "width", - "fieldName": "width", - "description": "Optional fixed width.\nNumeric values (e.g. `24`) are treated as px.\nString values may be any valid CSS width (e.g. `2rem`, `var(--le-spacing-2)`).", - "type": { - "text": "number | string" - } - } - ], - "tagName": "le-toolbar-spacer", - "events": [], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeToolbarSpacer", - "declaration": { - "name": "LeToolbarSpacer", - "module": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-toolbar-spacer", - "declaration": { - "name": "LeToolbarSpacer", - "module": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx" - } - } - ] - }, { "kind": "javascript-module", "path": "src/components/le-visibility/le-visibility.tsx", diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index 2a814cc..c25cb99 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -815,8 +815,8 @@ export namespace Components { */ "open": boolean; /** - * Behavior of the menu on page scroll: - 'blocked': blocks page scroll - 'menu-close': closes the menu automatically on scroll - 'fixed-menu': menu scrolls with the page (default) - * @default 'fixed-menu' + * Behavior of the menu on page scroll: - 'blocked': blocks page scroll - 'menu-close': closes the menu automatically on scroll (default) - 'fixed-menu': menu scrolls with the page + * @default 'menu-close' */ "pageScrollBehavior": 'blocked' | 'menu-close' | 'fixed-menu'; /** @@ -4922,8 +4922,8 @@ declare namespace LocalJSX { */ "open"?: boolean; /** - * Behavior of the menu on page scroll: - 'blocked': blocks page scroll - 'menu-close': closes the menu automatically on scroll - 'fixed-menu': menu scrolls with the page (default) - * @default 'fixed-menu' + * Behavior of the menu on page scroll: - 'blocked': blocks page scroll - 'menu-close': closes the menu automatically on scroll (default) - 'fixed-menu': menu scrolls with the page + * @default 'menu-close' */ "pageScrollBehavior"?: 'blocked' | 'menu-close' | 'fixed-menu'; /** diff --git a/packages/core/src/components/le-context-menu/le-context-menu.css b/packages/core/src/components/le-context-menu/le-context-menu.css index 4189282..e153b9a 100644 --- a/packages/core/src/components/le-context-menu/le-context-menu.css +++ b/packages/core/src/components/le-context-menu/le-context-menu.css @@ -12,9 +12,6 @@ left: 0; width: 100vw; height: 100vh; - background: rgba(0, 0, 0, 0.45); - backdrop-filter: blur(5px); - -webkit-backdrop-filter: blur(5px); z-index: 9990; opacity: 0; pointer-events: none; diff --git a/packages/core/src/components/le-context-menu/le-context-menu.tsx b/packages/core/src/components/le-context-menu/le-context-menu.tsx index c2f7329..4488aee 100644 --- a/packages/core/src/components/le-context-menu/le-context-menu.tsx +++ b/packages/core/src/components/le-context-menu/le-context-menu.tsx @@ -12,6 +12,7 @@ import { } from '@stencil/core'; import type { LeOption } from '../../types/options'; import { parseOptionInput } from '../../utils/utils'; +import { LONG_PRESS_DURATION, LONG_PRESS_MOVE_THRESHOLD } from '../../utils/constants'; import type { LeNavigationItemSelectDetail } from '../le-navigation/le-navigation'; export interface LeContextMenuSelectDetail { @@ -43,8 +44,6 @@ export class LeContextMenu { private startX = 0; private startY = 0; private isLongPressActive = false; - private readonly LONG_PRESS_DURATION = 500; // ms - private readonly MOVE_THRESHOLD = 10; // px private initialTriggerRect?: DOMRect; private initialCoords = { x: 0, y: 0 }; @@ -73,10 +72,10 @@ export class LeContextMenu { /** * Behavior of the menu on page scroll: * - 'blocked': blocks page scroll - * - 'menu-close': closes the menu automatically on scroll - * - 'fixed-menu': menu scrolls with the page (default) + * - 'menu-close': closes the menu automatically on scroll (default) + * - 'fixed-menu': menu scrolls with the page */ - @Prop() pageScrollBehavior: 'blocked' | 'menu-close' | 'fixed-menu' = 'fixed-menu'; + @Prop() pageScrollBehavior: 'blocked' | 'menu-close' | 'fixed-menu' = 'menu-close'; /** * Position of the menu relative to the trigger. @@ -298,7 +297,7 @@ export class LeContextMenu { this.touchTimeout = setTimeout(() => { this.isLongPressActive = true; this.triggerMenu(touch.clientX, touch.clientY, e); - }, this.LONG_PRESS_DURATION); + }, LONG_PRESS_DURATION); }; private handleTouchMove = (e: TouchEvent) => { @@ -307,7 +306,7 @@ export class LeContextMenu { const dx = touch.clientX - this.startX; const dy = touch.clientY - this.startY; - if (Math.hypot(dx, dy) > this.MOVE_THRESHOLD) { + if (Math.hypot(dx, dy) > LONG_PRESS_MOVE_THRESHOLD) { this.clearTouchTimeout(); } }; @@ -408,7 +407,7 @@ export class LeContextMenu { {this.backdrop && (
this.hide()} /> )} diff --git a/packages/core/src/components/le-navigation/le-navigation.tsx b/packages/core/src/components/le-navigation/le-navigation.tsx index aab9241..821660f 100644 --- a/packages/core/src/components/le-navigation/le-navigation.tsx +++ b/packages/core/src/components/le-navigation/le-navigation.tsx @@ -221,7 +221,6 @@ export class LeNavigation { } private renderIcon(icon: string) { - console.log('Rendering icon:', icon); if (icon.includes('<')) { return ; } diff --git a/packages/core/src/themes/index.css b/packages/core/src/themes/index.css index 0699902..e86355c 100644 --- a/packages/core/src/themes/index.css +++ b/packages/core/src/themes/index.css @@ -21,3 +21,10 @@ .header-is-shrunk .hidden-on-shrink { display: none; } + +/* Shared backdrop utility class */ +.le-backdrop-background { + background: var(--le-color-backdrop, rgba(0, 0, 0, 0.5)); + backdrop-filter: blur(5px); + -webkit-backdrop-filter: blur(5px); +} diff --git a/packages/core/src/utils/constants.ts b/packages/core/src/utils/constants.ts new file mode 100644 index 0000000..4ecc873 --- /dev/null +++ b/packages/core/src/utils/constants.ts @@ -0,0 +1,13 @@ +/** + * Global constants for touch and pointer interactions. + */ + +/** + * Duration in milliseconds a user must hold down a touch pointer before it is recognized as a long-press. + */ +export const LONG_PRESS_DURATION = 500; + +/** + * Distance in pixels a user's touch pointer can move before cancelling a long-press. + */ +export const LONG_PRESS_MOVE_THRESHOLD = 10; From 9ab76c66fb5fcb2614f3ed1fb882f0d159ee31bb Mon Sep 17 00:00:00 2001 From: Andrey Lechev Date: Sun, 7 Jun 2026 16:08:38 +0200 Subject: [PATCH 4/7] Fix for the backdrop colors --- .../src/components/le-context-menu/le-context-menu.css | 7 +++++++ packages/core/src/components/le-popup/le-popup.css | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/core/src/components/le-context-menu/le-context-menu.css b/packages/core/src/components/le-context-menu/le-context-menu.css index e153b9a..228a6a9 100644 --- a/packages/core/src/components/le-context-menu/le-context-menu.css +++ b/packages/core/src/components/le-context-menu/le-context-menu.css @@ -23,6 +23,13 @@ pointer-events: auto; } +/* Shared backdrop style for Shadow DOM */ +.le-backdrop-background { + background: var(--le-color-backdrop, rgba(0, 0, 0, 0.5)); + backdrop-filter: blur(5px); + -webkit-backdrop-filter: blur(5px); +} + :host([has-backdrop]) ::slotted(.le-context-menu-active-item) { position: relative !important; z-index: 9995 !important; diff --git a/packages/core/src/components/le-popup/le-popup.css b/packages/core/src/components/le-popup/le-popup.css index 453433e..e3ba367 100644 --- a/packages/core/src/components/le-popup/le-popup.css +++ b/packages/core/src/components/le-popup/le-popup.css @@ -35,7 +35,9 @@ /* Backdrop styling (native ::backdrop pseudo-element) */ .le-popup-dialog::backdrop { - background: var(--le-popup-backdrop-color, rgba(0, 0, 0, 0.5)); + background: var(--le-popup-backdrop-color, var(--le-color-backdrop, rgba(0, 0, 0, 0.5))); + backdrop-filter: blur(5px); + -webkit-backdrop-filter: blur(5px); animation: le-popup-backdrop-fade 0.2s ease-out; } From dd18556987f30ddb6c8e5be2120982e898fd2965 Mon Sep 17 00:00:00 2001 From: Andrey Lechev Date: Sun, 7 Jun 2026 16:09:23 +0200 Subject: [PATCH 5/7] Update : make `menu-close` the default option for the page scroll behavior --- .../src/components/le-context-menu/le-context-menu.spec.tsx | 2 +- packages/core/src/components/le-context-menu/readme.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/components/le-context-menu/le-context-menu.spec.tsx b/packages/core/src/components/le-context-menu/le-context-menu.spec.tsx index 9a1eef2..1867400 100644 --- a/packages/core/src/components/le-context-menu/le-context-menu.spec.tsx +++ b/packages/core/src/components/le-context-menu/le-context-menu.spec.tsx @@ -23,7 +23,7 @@ describe('le-context-menu', () => { const host = page.root as any; expect(host).not.toBeNull(); expect(host.backdrop).toBe(false); - expect(host.pageScrollBehavior).toBe('fixed-menu'); + expect(host.pageScrollBehavior).toBe('menu-close'); expect(host.position).toBe('mouse'); expect(host.align).toBe('start'); diff --git a/packages/core/src/components/le-context-menu/readme.md b/packages/core/src/components/le-context-menu/readme.md index c8159b7..027deba 100644 --- a/packages/core/src/components/le-context-menu/readme.md +++ b/packages/core/src/components/le-context-menu/readme.md @@ -19,7 +19,7 @@ when the user right-clicks or long-presses on its children. | `disabled` | `disabled` | Disables right-click and touch interactions. | `boolean` | `false` | | `items` | `items` | List of menu items represented as options. | `LeOption[] \| string` | `[]` | | `open` | `open` | Whether the context menu is open. | `boolean` | `false` | -| `pageScrollBehavior` | `page-scroll-behavior` | Behavior of the menu on page scroll: - 'blocked': blocks page scroll - 'menu-close': closes the menu automatically on scroll - 'fixed-menu': menu scrolls with the page (default) | `"blocked" \| "fixed-menu" \| "menu-close"` | `'fixed-menu'` | +| `pageScrollBehavior` | `page-scroll-behavior` | Behavior of the menu on page scroll: - 'blocked': blocks page scroll - 'menu-close': closes the menu automatically on scroll (default) - 'fixed-menu': menu scrolls with the page | `"blocked" \| "fixed-menu" \| "menu-close"` | `'menu-close'` | | `position` | `position` | Position of the menu relative to the trigger. If 'mouse', positions next to mouse/touch coords. | `"bottom" \| "left" \| "mouse" \| "right" \| "top"` | `'mouse'` | From 4bc0e4b44cf9f6b3af7d672cea743e3c0b01a4ee Mon Sep 17 00:00:00 2001 From: Andrey Lechev Date: Sun, 7 Jun 2026 16:09:41 +0200 Subject: [PATCH 6/7] Version up to 0.7.1 --- packages/core/LLM_CONTEXT.md | 2 +- packages/core/package.json | 2 +- packages/core/src/assets/custom-elements.json | 8412 ++++++++--------- 3 files changed, 4198 insertions(+), 4218 deletions(-) diff --git a/packages/core/LLM_CONTEXT.md b/packages/core/LLM_CONTEXT.md index 0849a04..31e357f 100644 --- a/packages/core/LLM_CONTEXT.md +++ b/packages/core/LLM_CONTEXT.md @@ -589,7 +589,7 @@ when the user right-clicks or long-presses on its children. | `disabled` | `boolean` | `false` | Disables right-click and touch interactions. | | `items` | `LeOption[] \| string` | `[]` | List of menu items represented as options. | | `backdrop` | `boolean` | `false` | Whether to show a backdrop behind the menu, lifting the active item. | -| `pageScrollBehavior` | `'blocked' \| 'menu-close' \| 'fixed-menu'` | `'fixed-menu'` | Behavior of the menu on page scroll: - 'blocked': blocks page scroll - 'menu-close': closes the menu automatically on scroll - 'fixed-menu': menu scrolls with the page (default) | +| `pageScrollBehavior` | `'blocked' \| 'menu-close' \| 'fixed-menu'` | `'menu-close'` | Behavior of the menu on page scroll: - 'blocked': blocks page scroll - 'menu-close': closes the menu automatically on scroll (default) - 'fixed-menu': menu scrolls with the page | | `position` | `'top' \| 'bottom' \| 'left' \| 'right' \| 'mouse'` | `'mouse'` | Position of the menu relative to the trigger. If 'mouse', positions next to mouse/touch coords. | | `align` | `'start' \| 'center' \| 'end'` | `'start'` | Alignment of the menu relative to the trigger. | diff --git a/packages/core/package.json b/packages/core/package.json index 9c530ae..28bafcc 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "le-kit", - "version": "0.7.0", + "version": "0.7.1", "description": "Themable web components library with CMS admin mode support", "main": "dist/index.cjs.js", "module": "dist/index.js", diff --git a/packages/core/src/assets/custom-elements.json b/packages/core/src/assets/custom-elements.json index dc877ed..f39c07b 100644 --- a/packages/core/src/assets/custom-elements.json +++ b/packages/core/src/assets/custom-elements.json @@ -1269,62 +1269,12 @@ }, { "kind": "javascript-module", - "path": "src/components/le-button/le-button.tsx", + "path": "src/components/le-breadcrumbs/le-breadcrumbs.tsx", "declarations": [ { "kind": "class", - "description": "A flexible button component with multiple variants and states.", - "name": "LeButton", - "cssProperties": [ - { - "description": "Button background color", - "name": "--le-button-bg" - }, - { - "description": "Button text color", - "name": "--le-button-color" - }, - { - "description": "Button border radius", - "name": "--le-button-border-radius" - }, - { - "description": "Button horizontal padding", - "name": "--le-button-padding-x" - }, - { - "description": "Button vertical padding", - "name": "--le-button-padding-y" - } - ], - "cssParts": [ - { - "description": "The native button element", - "name": "button" - }, - { - "description": "The button content wrapper", - "name": "content" - }, - { - "description": "The start icon slot", - "name": "icon-start" - }, - { - "description": "The end icon slot", - "name": "icon-end" - } - ], - "slots": [ - { - "description": "Button text content", - "name": "" - }, - { - "description": "Icon for icon-only buttons", - "name": "icon-only" - } - ], + "description": "", + "name": "LeBreadcrumbs", "members": [ { "kind": "field", @@ -1335,273 +1285,256 @@ }, { "kind": "field", - "name": "hasIconStartSlot", + "name": "items", "type": { - "text": "boolean" + "text": "LeOption[] | string" }, - "privacy": "private", - "default": "false" + "default": "[]", + "description": "Breadcrumb items (supports JSON string)." }, { "kind": "field", - "name": "hasIconEndSlot", + "name": "label", "type": { - "text": "boolean" + "text": "string" }, - "privacy": "private", - "default": "false" + "default": "'Breadcrumbs'", + "description": "Accessible label for the breadcrumbs navigation." }, { "kind": "field", - "name": "hasIconOnlySlot", + "name": "separatorIcon", "type": { - "text": "boolean" + "text": "string" }, - "privacy": "private", - "default": "false" + "default": "'chevron-right'", + "description": "Separator icon name (used if no separator slot is provided)." }, { "kind": "field", - "name": "disconnectSlotObserver", + "name": "overflowMode", "type": { - "text": "() => void | undefined" + "text": "'collapse' | 'wrap' | 'scroll'" }, - "privacy": "private" + "default": "'collapse'", + "description": "Overflow behavior: collapse (default), wrap, or scroll." }, { "kind": "field", - "name": "mode", + "name": "minVisibleItems", "type": { - "text": "'default' | 'admin' | undefined" + "text": "number" }, - "description": "Mode of the popover should be 'default' for internal use" + "default": "2", + "description": "Minimum visible items before collapsing." }, { "kind": "field", - "name": "variant", + "name": "hiddenIndices", "type": { - "text": "'solid' | 'outlined' | 'clear' | 'system'" + "text": "number[]" }, - "default": "'outlined'", - "description": "Button variant style" + "privacy": "private", + "default": "[]" }, { "kind": "field", - "name": "color", + "name": "separatorTemplate", "type": { - "text": "| 'primary'\n | 'secondary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'info'\n | 'transparent' | undefined" + "text": "string" }, - "description": "Button color theme (uses theme semantic colors)" + "privacy": "private", + "default": "''" }, { "kind": "field", - "name": "size", + "name": "declarativeItems", "type": { - "text": "'small' | 'medium' | 'large'" + "text": "LeOption[]" }, - "default": "'medium'", - "description": "Button size" + "privacy": "private", + "default": "[]" }, { "kind": "field", - "name": "selected", + "name": "isDeclarativeMode", "type": { "text": "boolean" }, - "default": "false", - "description": "Whether the button is in a selected/active state" + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "label", + "name": "listEl", "type": { - "text": "string | undefined" + "text": "HTMLElement | undefined" }, - "description": "Optional label for the button,\nused for accessibility and tooltips when the button is icon-only." + "privacy": "private" }, { "kind": "field", - "name": "tooltip", + "name": "resizeObserver", "type": { - "text": "string | undefined" + "text": "ResizeObserver | undefined" }, - "description": "Tooltip text to show on hover" + "privacy": "private" }, { "kind": "field", - "name": "tooltipPosition", + "name": "instanceId", "type": { - "text": "TooltipPlacement" + "text": "string" }, - "default": "'top'", - "description": "Tooltip position around the button" + "privacy": "private" }, { "kind": "field", - "name": "fullWidth", + "name": "recomputeQueued", "type": { "text": "boolean" }, - "default": "false", - "description": "Whether the button takes full width of its container" + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "visibility", + "name": "mutationObserver", "type": { - "text": "'visible' | 'collapsing' | 'collapsed' | 'expanding'" + "text": "MutationObserver | undefined" }, - "default": "'visible'", - "description": "Visibility state used by responsive containers to animate show/hide transitions." + "privacy": "private" }, { - "kind": "field", - "name": "groupShape", - "type": { - "text": "'start' | 'middle' | 'end' | 'single'" - }, - "default": "'single'", - "description": "Shape of the button when rendered inside grouped containers." + "kind": "method", + "name": "handleGeneralSlotChange", + "parameters": [ + { + "name": "ev", + "type": { + "text": "Event" + } + } + ] }, { - "kind": "field", - "name": "motionPreset", - "type": { - "text": "'none' | 'soft' | 'fluid' | 'spring' | undefined" - }, - "description": "Optional per-instance motion preset override." + "kind": "method", + "name": "buildDeclarativeItems", + "privacy": "private" }, { - "kind": "field", - "name": "iconOnly", - "type": { - "text": "string | Node | undefined" - }, - "description": "Icon only button image or emoji\nif this prop is set, the button will render only the icon slot" + "kind": "method", + "name": "handleInputsChange" }, { - "kind": "field", - "name": "iconStart", - "type": { - "text": "string | Node | undefined" - }, - "description": "Start icon image or emoji" + "kind": "method", + "name": "setupResizeObserver", + "privacy": "private" }, { "kind": "field", - "name": "collapsible", + "name": "parsedItems", "type": { - "text": "boolean" + "text": "LeOption[]" }, - "default": "false", - "description": "Enables responsive collapse to icon-only when the toolbar applies\n`collapse=\"icon\"`." + "privacy": "private", + "readonly": true }, { - "kind": "field", - "name": "collapse", - "type": { - "text": "string | undefined" + "kind": "method", + "name": "getItemId", + "privacy": "private", + "return": { + "type": { + "text": "string" + } }, - "description": "Runtime collapse state controlled by responsive containers." + "parameters": [ + { + "name": "item", + "type": { + "text": "LeOption" + } + }, + { + "name": "index", + "type": { + "text": "number" + } + } + ] }, { "kind": "field", - "name": "collapsePriorityOffset", - "type": { - "text": "number" - }, - "default": "100", - "description": "Relative collapse priority offset for toolbar stepping.\nHigher numbers collapse earlier while keeping the button visible longer." + "name": "handleSeparatorSlotChange", + "privacy": "private" }, { - "kind": "field", - "name": "iconEnd", - "type": { - "text": "string | Node | undefined" - }, - "description": "End icon image or emoji" + "kind": "method", + "name": "scheduleOverflowRecompute", + "privacy": "private" }, { - "kind": "field", - "name": "disabled", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Whether the button is disabled" - }, - { - "kind": "field", - "name": "type", - "type": { - "text": "'button' | 'submit' | 'reset'" - }, - "default": "'button'", - "description": "The button type attribute" - }, - { - "kind": "field", - "name": "href", - "type": { - "text": "string | undefined" - }, - "description": "Optional href to make the button act as a link" + "kind": "method", + "name": "nextFrame", + "privacy": "private", + "return": { + "type": { + "text": "Promise" + } + } }, { - "kind": "field", - "name": "target", - "type": { - "text": "string | undefined" - }, - "description": "Link target when href is set" + "kind": "method", + "name": "recomputeOverflow", + "privacy": "private" }, { "kind": "field", - "name": "align", - "type": { - "text": "'start' | 'center' | 'space-between' | 'end'" - }, - "default": "'center'", - "description": "Alignment of the button label without the end icon" + "name": "handleItemClick", + "privacy": "private" }, { "kind": "field", - "name": "handleClick", + "name": "handleKeyDown", "privacy": "private" }, { "kind": "method", - "name": "getCollapseMeta", - "return": { - "type": { - "text": "Promise" - } - }, - "description": "Returns collapse meta for toolbar integration." - }, - { - "kind": "method", - "name": "initSlotObserver", + "name": "renderSeparator", "privacy": "private" }, { "kind": "method", - "name": "getOption", - "return": { - "type": { - "text": "Promise" + "name": "renderItem", + "privacy": "private", + "parameters": [ + { + "name": "item", + "type": { + "text": "LeOption" + } + }, + { + "name": "index", + "type": { + "text": "number" + } } - } + ] }, { "kind": "method", - "name": "getResolvedLabel", + "name": "renderMore", "privacy": "private", - "return": { - "type": { - "text": "string | undefined" + "parameters": [ + { + "name": "hiddenItems", + "type": { + "text": "LeOption[]" + } } - } + ] }, { "kind": "method", @@ -1610,502 +1543,418 @@ ], "attributes": [ { - "name": "mode", - "fieldName": "mode", - "description": "Mode of the popover should be 'default' for internal use", + "name": "items", + "fieldName": "items", + "default": "[]", + "description": "Breadcrumb items (supports JSON string).", "type": { - "text": "'default' | 'admin'" + "text": "LeOption[] | string" } }, { - "name": "variant", - "fieldName": "variant", - "default": "'outlined'", - "description": "Button variant style", + "name": "label", + "fieldName": "label", + "default": "'Breadcrumbs'", + "description": "Accessible label for the breadcrumbs navigation.", "type": { - "text": "'solid' | 'outlined' | 'clear' | 'system'" + "text": "string" } }, { - "name": "color", - "fieldName": "color", - "description": "Button color theme (uses theme semantic colors)", + "name": "separator-icon", + "fieldName": "separatorIcon", + "default": "'chevron-right'", + "description": "Separator icon name (used if no separator slot is provided).", "type": { - "text": "| 'primary'\n | 'secondary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'info'\n | 'transparent'" + "text": "string" } }, { - "name": "size", - "fieldName": "size", - "default": "'medium'", - "description": "Button size", + "name": "overflow-mode", + "fieldName": "overflowMode", + "default": "'collapse'", + "description": "Overflow behavior: collapse (default), wrap, or scroll.", "type": { - "text": "'small' | 'medium' | 'large'" + "text": "'collapse' | 'wrap' | 'scroll'" } }, { - "name": "selected", - "fieldName": "selected", - "default": "false", - "description": "Whether the button is in a selected/active state", + "name": "min-visible-items", + "fieldName": "minVisibleItems", + "default": "2", + "description": "Minimum visible items before collapsing.", "type": { - "text": "boolean" + "text": "number" } - }, + } + ], + "tagName": "le-breadcrumbs", + "events": [ { - "name": "label", - "fieldName": "label", - "description": "Optional label for the button,\nused for accessibility and tooltips when the button is icon-only.", + "name": "leBreadcrumbSelect", "type": { - "text": "string" - } - }, + "text": "EventEmitter" + }, + "description": "Emitted when a breadcrumb item is selected." + } + ], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeBreadcrumbs", + "declaration": { + "name": "LeBreadcrumbs", + "module": "src/components/le-breadcrumbs/le-breadcrumbs.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-breadcrumbs", + "declaration": { + "name": "LeBreadcrumbs", + "module": "src/components/le-breadcrumbs/le-breadcrumbs.tsx" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/components/le-button/le-button.tsx", + "declarations": [ + { + "kind": "class", + "description": "A flexible button component with multiple variants and states.", + "name": "LeButton", + "cssProperties": [ { - "name": "tooltip", - "fieldName": "tooltip", - "description": "Tooltip text to show on hover", - "type": { - "text": "string" - } + "description": "Button background color", + "name": "--le-button-bg" }, { - "name": "tooltip-position", - "fieldName": "tooltipPosition", - "default": "'top'", - "description": "Tooltip position around the button", - "type": { - "text": "TooltipPlacement" - } + "description": "Button text color", + "name": "--le-button-color" }, { - "name": "full-width", - "fieldName": "fullWidth", - "default": "false", - "description": "Whether the button takes full width of its container", - "type": { - "text": "boolean" - } + "description": "Button border radius", + "name": "--le-button-border-radius" }, { - "name": "visibility", - "fieldName": "visibility", - "default": "'visible'", - "description": "Visibility state used by responsive containers to animate show/hide transitions.", - "type": { - "text": "'visible' | 'collapsing' | 'collapsed' | 'expanding'" - } + "description": "Button horizontal padding", + "name": "--le-button-padding-x" }, { - "name": "group-shape", - "fieldName": "groupShape", - "default": "'single'", - "description": "Shape of the button when rendered inside grouped containers.", - "type": { - "text": "'start' | 'middle' | 'end' | 'single'" - } + "description": "Button vertical padding", + "name": "--le-button-padding-y" + } + ], + "cssParts": [ + { + "description": "The native button element", + "name": "button" }, { - "name": "motion-preset", - "fieldName": "motionPreset", - "description": "Optional per-instance motion preset override.", - "type": { - "text": "'none' | 'soft' | 'fluid' | 'spring'" - } + "description": "The button content wrapper", + "name": "content" }, { - "name": "icon-only", - "fieldName": "iconOnly", - "description": "Icon only button image or emoji\nif this prop is set, the button will render only the icon slot", - "type": { - "text": "string | Node" - } + "description": "The start icon slot", + "name": "icon-start" }, { - "name": "icon-start", - "fieldName": "iconStart", - "description": "Start icon image or emoji", - "type": { - "text": "string | Node" - } - }, + "description": "The end icon slot", + "name": "icon-end" + } + ], + "slots": [ { - "name": "collapsible", - "fieldName": "collapsible", - "default": "false", - "description": "Enables responsive collapse to icon-only when the toolbar applies\n`collapse=\"icon\"`.", - "type": { - "text": "boolean" - } + "description": "Button text content", + "name": "" }, { - "name": "collapse", - "fieldName": "collapse", - "description": "Runtime collapse state controlled by responsive containers.", - "type": { - "text": "string" - } - }, + "description": "Icon for icon-only buttons", + "name": "icon-only" + } + ], + "members": [ { - "name": "collapse-priority-offset", - "fieldName": "collapsePriorityOffset", - "default": "100", - "description": "Relative collapse priority offset for toolbar stepping.\nHigher numbers collapse earlier while keeping the button visible longer.", + "kind": "field", + "name": "el", "type": { - "text": "number" + "text": "HTMLElement" } }, { - "name": "icon-end", - "fieldName": "iconEnd", - "description": "End icon image or emoji", + "kind": "field", + "name": "hasIconStartSlot", "type": { - "text": "string | Node" - } + "text": "boolean" + }, + "privacy": "private", + "default": "false" }, { - "name": "disabled", - "fieldName": "disabled", - "default": "false", - "description": "Whether the button is disabled", + "kind": "field", + "name": "hasIconEndSlot", "type": { "text": "boolean" - } + }, + "privacy": "private", + "default": "false" }, { - "name": "type", - "fieldName": "type", - "default": "'button'", - "description": "The button type attribute", + "kind": "field", + "name": "hasIconOnlySlot", "type": { - "text": "'button' | 'submit' | 'reset'" - } + "text": "boolean" + }, + "privacy": "private", + "default": "false" }, { - "name": "href", - "fieldName": "href", - "description": "Optional href to make the button act as a link", + "kind": "field", + "name": "disconnectSlotObserver", "type": { - "text": "string" - } + "text": "() => void | undefined" + }, + "privacy": "private" }, { - "name": "target", - "fieldName": "target", - "description": "Link target when href is set", + "kind": "field", + "name": "mode", "type": { - "text": "string" - } + "text": "'default' | 'admin' | undefined" + }, + "description": "Mode of the popover should be 'default' for internal use" }, { - "name": "align", - "fieldName": "align", - "default": "'center'", - "description": "Alignment of the button label without the end icon", + "kind": "field", + "name": "variant", "type": { - "text": "'start' | 'center' | 'space-between' | 'end'" - } - } - ], - "tagName": "le-button", - "events": [ + "text": "'solid' | 'outlined' | 'clear' | 'system'" + }, + "default": "'outlined'", + "description": "Button variant style" + }, { - "name": "click", + "kind": "field", + "name": "color", "type": { - "text": "EventEmitter" + "text": "| 'primary'\n | 'secondary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'info'\n | 'transparent' | undefined" }, - "description": "Emitted when the button is clicked.\nThis is a custom event that wraps the native click but ensures the target is the le-button." - } - ], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeButton", - "declaration": { - "name": "LeButton", - "module": "src/components/le-button/le-button.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-button", - "declaration": { - "name": "LeButton", - "module": "src/components/le-button/le-button.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-breadcrumbs/le-breadcrumbs.tsx", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "LeBreadcrumbs", - "members": [ + "description": "Button color theme (uses theme semantic colors)" + }, { "kind": "field", - "name": "el", + "name": "size", "type": { - "text": "HTMLElement" - } + "text": "'small' | 'medium' | 'large'" + }, + "default": "'medium'", + "description": "Button size" }, { "kind": "field", - "name": "items", + "name": "selected", "type": { - "text": "LeOption[] | string" + "text": "boolean" }, - "default": "[]", - "description": "Breadcrumb items (supports JSON string)." + "default": "false", + "description": "Whether the button is in a selected/active state" }, { "kind": "field", "name": "label", "type": { - "text": "string" + "text": "string | undefined" }, - "default": "'Breadcrumbs'", - "description": "Accessible label for the breadcrumbs navigation." + "description": "Optional label for the button,\nused for accessibility and tooltips when the button is icon-only." }, { "kind": "field", - "name": "separatorIcon", + "name": "tooltip", "type": { - "text": "string" + "text": "string | undefined" }, - "default": "'chevron-right'", - "description": "Separator icon name (used if no separator slot is provided)." + "description": "Tooltip text to show on hover" }, { "kind": "field", - "name": "overflowMode", + "name": "tooltipPosition", "type": { - "text": "'collapse' | 'wrap' | 'scroll'" + "text": "TooltipPlacement" }, - "default": "'collapse'", - "description": "Overflow behavior: collapse (default), wrap, or scroll." + "default": "'top'", + "description": "Tooltip position around the button" }, { "kind": "field", - "name": "minVisibleItems", + "name": "fullWidth", "type": { - "text": "number" + "text": "boolean" }, - "default": "2", - "description": "Minimum visible items before collapsing." + "default": "false", + "description": "Whether the button takes full width of its container" }, { "kind": "field", - "name": "hiddenIndices", + "name": "visibility", "type": { - "text": "number[]" + "text": "'visible' | 'collapsing' | 'collapsed' | 'expanding'" }, - "privacy": "private", - "default": "[]" + "default": "'visible'", + "description": "Visibility state used by responsive containers to animate show/hide transitions." }, { "kind": "field", - "name": "separatorTemplate", + "name": "groupShape", "type": { - "text": "string" + "text": "'start' | 'middle' | 'end' | 'single'" }, - "privacy": "private", - "default": "''" + "default": "'single'", + "description": "Shape of the button when rendered inside grouped containers." }, { "kind": "field", - "name": "declarativeItems", + "name": "motionPreset", "type": { - "text": "LeOption[]" + "text": "'none' | 'soft' | 'fluid' | 'spring' | undefined" }, - "privacy": "private", - "default": "[]" + "description": "Optional per-instance motion preset override." }, { "kind": "field", - "name": "isDeclarativeMode", + "name": "iconOnly", "type": { - "text": "boolean" + "text": "string | Node | undefined" }, - "privacy": "private", - "default": "false" + "description": "Icon only button image or emoji\nif this prop is set, the button will render only the icon slot" }, { "kind": "field", - "name": "listEl", + "name": "iconStart", "type": { - "text": "HTMLElement | undefined" + "text": "string | Node | undefined" }, - "privacy": "private" + "description": "Start icon image or emoji" }, { "kind": "field", - "name": "resizeObserver", + "name": "collapsible", "type": { - "text": "ResizeObserver | undefined" + "text": "boolean" }, - "privacy": "private" + "default": "false", + "description": "Enables responsive collapse to icon-only when the toolbar applies\n`collapse=\"icon\"`." }, { "kind": "field", - "name": "instanceId", + "name": "collapse", "type": { - "text": "string" + "text": "string | undefined" }, - "privacy": "private" + "description": "Runtime collapse state controlled by responsive containers." }, { "kind": "field", - "name": "recomputeQueued", + "name": "collapsePriorityOffset", "type": { - "text": "boolean" + "text": "number" }, - "privacy": "private", - "default": "false" + "default": "100", + "description": "Relative collapse priority offset for toolbar stepping.\nHigher numbers collapse earlier while keeping the button visible longer." }, { "kind": "field", - "name": "mutationObserver", + "name": "iconEnd", "type": { - "text": "MutationObserver | undefined" + "text": "string | Node | undefined" }, - "privacy": "private" + "description": "End icon image or emoji" }, { - "kind": "method", - "name": "handleGeneralSlotChange", - "parameters": [ - { - "name": "ev", - "type": { - "text": "Event" - } - } - ] - }, - { - "kind": "method", - "name": "buildDeclarativeItems", - "privacy": "private" - }, - { - "kind": "method", - "name": "handleInputsChange" + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether the button is disabled" }, { - "kind": "method", - "name": "setupResizeObserver", - "privacy": "private" + "kind": "field", + "name": "type", + "type": { + "text": "'button' | 'submit' | 'reset'" + }, + "default": "'button'", + "description": "The button type attribute" }, { "kind": "field", - "name": "parsedItems", + "name": "href", "type": { - "text": "LeOption[]" + "text": "string | undefined" }, - "privacy": "private", - "readonly": true + "description": "Optional href to make the button act as a link" }, { - "kind": "method", - "name": "getItemId", - "privacy": "private", - "return": { - "type": { - "text": "string" - } + "kind": "field", + "name": "target", + "type": { + "text": "string | undefined" }, - "parameters": [ - { - "name": "item", - "type": { - "text": "LeOption" - } - }, - { - "name": "index", - "type": { - "text": "number" - } - } - ] + "description": "Link target when href is set" }, { "kind": "field", - "name": "handleSeparatorSlotChange", - "privacy": "private" + "name": "align", + "type": { + "text": "'start' | 'center' | 'space-between' | 'end'" + }, + "default": "'center'", + "description": "Alignment of the button label without the end icon" }, { - "kind": "method", - "name": "scheduleOverflowRecompute", + "kind": "field", + "name": "handleClick", "privacy": "private" }, { "kind": "method", - "name": "nextFrame", - "privacy": "private", + "name": "getCollapseMeta", "return": { "type": { - "text": "Promise" + "text": "Promise" } - } - }, - { - "kind": "method", - "name": "recomputeOverflow", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleItemClick", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleKeyDown", - "privacy": "private" + }, + "description": "Returns collapse meta for toolbar integration." }, { "kind": "method", - "name": "renderSeparator", + "name": "initSlotObserver", "privacy": "private" }, { "kind": "method", - "name": "renderItem", - "privacy": "private", - "parameters": [ - { - "name": "item", - "type": { - "text": "LeOption" - } - }, - { - "name": "index", - "type": { - "text": "number" - } + "name": "getOption", + "return": { + "type": { + "text": "Promise" } - ] + } }, { "kind": "method", - "name": "renderMore", + "name": "getResolvedLabel", "privacy": "private", - "parameters": [ - { - "name": "hiddenItems", - "type": { - "text": "LeOption[]" - } + "return": { + "type": { + "text": "string | undefined" } - ] + } }, { "kind": "method", @@ -2114,212 +1963,230 @@ ], "attributes": [ { - "name": "items", - "fieldName": "items", - "default": "[]", - "description": "Breadcrumb items (supports JSON string).", + "name": "mode", + "fieldName": "mode", + "description": "Mode of the popover should be 'default' for internal use", "type": { - "text": "LeOption[] | string" + "text": "'default' | 'admin'" } }, { - "name": "label", - "fieldName": "label", - "default": "'Breadcrumbs'", - "description": "Accessible label for the breadcrumbs navigation.", + "name": "variant", + "fieldName": "variant", + "default": "'outlined'", + "description": "Button variant style", "type": { - "text": "string" + "text": "'solid' | 'outlined' | 'clear' | 'system'" } }, { - "name": "separator-icon", - "fieldName": "separatorIcon", - "default": "'chevron-right'", - "description": "Separator icon name (used if no separator slot is provided).", + "name": "color", + "fieldName": "color", + "description": "Button color theme (uses theme semantic colors)", "type": { - "text": "string" + "text": "| 'primary'\n | 'secondary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'info'\n | 'transparent'" } }, { - "name": "overflow-mode", - "fieldName": "overflowMode", - "default": "'collapse'", - "description": "Overflow behavior: collapse (default), wrap, or scroll.", + "name": "size", + "fieldName": "size", + "default": "'medium'", + "description": "Button size", "type": { - "text": "'collapse' | 'wrap' | 'scroll'" + "text": "'small' | 'medium' | 'large'" } }, { - "name": "min-visible-items", - "fieldName": "minVisibleItems", - "default": "2", - "description": "Minimum visible items before collapsing.", + "name": "selected", + "fieldName": "selected", + "default": "false", + "description": "Whether the button is in a selected/active state", "type": { - "text": "number" + "text": "boolean" } - } - ], - "tagName": "le-breadcrumbs", - "events": [ + }, { - "name": "leBreadcrumbSelect", + "name": "label", + "fieldName": "label", + "description": "Optional label for the button,\nused for accessibility and tooltips when the button is icon-only.", "type": { - "text": "EventEmitter" - }, - "description": "Emitted when a breadcrumb item is selected." - } - ], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeBreadcrumbs", - "declaration": { - "name": "LeBreadcrumbs", - "module": "src/components/le-breadcrumbs/le-breadcrumbs.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-breadcrumbs", - "declaration": { - "name": "LeBreadcrumbs", - "module": "src/components/le-breadcrumbs/le-breadcrumbs.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-card/le-card.tsx", - "declarations": [ - { - "kind": "class", - "description": "A flexible card component with header, content, and footer slots.\n\nThe card uses le-slot wrappers for each slot area. In admin mode,\nle-slot shows placeholders for CMS editing. In default mode,\nle-slot acts as a transparent passthrough.", - "name": "LeCard", - "cssProperties": [ - { - "description": "Card background color", - "name": "--le-card-bg" + "text": "string" + } }, { - "description": "Card border radius", - "name": "--le-card-border-radius" + "name": "tooltip", + "fieldName": "tooltip", + "description": "Tooltip text to show on hover", + "type": { + "text": "string" + } }, { - "description": "Card box shadow", - "name": "--le-card-shadow" + "name": "tooltip-position", + "fieldName": "tooltipPosition", + "default": "'top'", + "description": "Tooltip position around the button", + "type": { + "text": "TooltipPlacement" + } }, { - "description": "Card content padding", - "name": "--le-card-padding" - } - ], - "cssParts": [ + "name": "full-width", + "fieldName": "fullWidth", + "default": "false", + "description": "Whether the button takes full width of its container", + "type": { + "text": "boolean" + } + }, { - "description": "The main card container", - "name": "card" + "name": "visibility", + "fieldName": "visibility", + "default": "'visible'", + "description": "Visibility state used by responsive containers to animate show/hide transitions.", + "type": { + "text": "'visible' | 'collapsing' | 'collapsed' | 'expanding'" + } }, { - "description": "The card header section", - "name": "header" + "name": "group-shape", + "fieldName": "groupShape", + "default": "'single'", + "description": "Shape of the button when rendered inside grouped containers.", + "type": { + "text": "'start' | 'middle' | 'end' | 'single'" + } }, { - "description": "The card content section", - "name": "content" + "name": "motion-preset", + "fieldName": "motionPreset", + "description": "Optional per-instance motion preset override.", + "type": { + "text": "'none' | 'soft' | 'fluid' | 'spring'" + } }, { - "description": "The card footer section", - "name": "footer" - } - ], - "slots": [ + "name": "icon-only", + "fieldName": "iconOnly", + "description": "Icon only button image or emoji\nif this prop is set, the button will render only the icon slot", + "type": { + "text": "string | Node" + } + }, { - "description": "Card header content (title, actions)", - "name": "header" + "name": "icon-start", + "fieldName": "iconStart", + "description": "Start icon image or emoji", + "type": { + "text": "string | Node" + } }, { - "description": "Default slot for main card content", - "name": "" + "name": "collapsible", + "fieldName": "collapsible", + "default": "false", + "description": "Enables responsive collapse to icon-only when the toolbar applies\n`collapse=\"icon\"`.", + "type": { + "text": "boolean" + } }, { - "description": "Card footer content (buttons, links)", - "name": "footer" - } - ], - "members": [ + "name": "collapse", + "fieldName": "collapse", + "description": "Runtime collapse state controlled by responsive containers.", + "type": { + "text": "string" + } + }, { - "kind": "field", - "name": "el", + "name": "collapse-priority-offset", + "fieldName": "collapsePriorityOffset", + "default": "100", + "description": "Relative collapse priority offset for toolbar stepping.\nHigher numbers collapse earlier while keeping the button visible longer.", "type": { - "text": "HTMLElement" + "text": "number" } }, { - "kind": "field", - "name": "variant", + "name": "icon-end", + "fieldName": "iconEnd", + "description": "End icon image or emoji", "type": { - "text": "'default' | 'outlined' | 'elevated'" - }, - "default": "'default'", - "description": "Card variant style" + "text": "string | Node" + } }, { - "kind": "field", - "name": "interactive", + "name": "disabled", + "fieldName": "disabled", + "default": "false", + "description": "Whether the button is disabled", "type": { "text": "boolean" - }, - "default": "false", - "description": "Whether the card is interactive (clickable)" + } }, { - "kind": "method", - "name": "render" - } - ], - "attributes": [ + "name": "type", + "fieldName": "type", + "default": "'button'", + "description": "The button type attribute", + "type": { + "text": "'button' | 'submit' | 'reset'" + } + }, { - "name": "variant", - "fieldName": "variant", - "default": "'default'", - "description": "Card variant style", + "name": "href", + "fieldName": "href", + "description": "Optional href to make the button act as a link", "type": { - "text": "'default' | 'outlined' | 'elevated'" + "text": "string" } }, { - "name": "interactive", - "fieldName": "interactive", - "default": "false", - "description": "Whether the card is interactive (clickable)", + "name": "target", + "fieldName": "target", + "description": "Link target when href is set", "type": { - "text": "boolean" + "text": "string" + } + }, + { + "name": "align", + "fieldName": "align", + "default": "'center'", + "description": "Alignment of the button label without the end icon", + "type": { + "text": "'start' | 'center' | 'space-between' | 'end'" } } ], - "tagName": "le-card", - "events": [], + "tagName": "le-button", + "events": [ + { + "name": "click", + "type": { + "text": "EventEmitter" + }, + "description": "Emitted when the button is clicked.\nThis is a custom event that wraps the native click but ensures the target is the le-button." + } + ], "customElement": true } ], "exports": [ { "kind": "js", - "name": "LeCard", + "name": "LeButton", "declaration": { - "name": "LeCard", - "module": "src/components/le-card/le-card.tsx" + "name": "LeButton", + "module": "src/components/le-button/le-button.tsx" } }, { "kind": "custom-element-definition", - "name": "le-card", + "name": "le-button", "declaration": { - "name": "LeCard", - "module": "src/components/le-card/le-card.tsx" + "name": "LeButton", + "module": "src/components/le-button/le-button.tsx" } } ] @@ -3004,46 +2871,60 @@ }, { "kind": "javascript-module", - "path": "src/components/le-code-input/le-code-input.tsx", + "path": "src/components/le-card/le-card.tsx", "declarations": [ { "kind": "class", - "description": "A one-time code input component with individual frames for each character.\nSupports standard copy/paste and range selection behaviors.", - "name": "LeCodeInput", + "description": "A flexible card component with header, content, and footer slots.\n\nThe card uses le-slot wrappers for each slot area. In admin mode,\nle-slot shows placeholders for CMS editing. In default mode,\nle-slot acts as a transparent passthrough.", + "name": "LeCard", "cssProperties": [ { - "description": "Size of each character box (default: 40px width, 48px height)", - "name": "--le-code-box-size" + "description": "Card background color", + "name": "--le-card-bg" }, { - "description": "Input background color", - "name": "--le-input-bg" + "description": "Card border radius", + "name": "--le-card-border-radius" }, { - "description": "Input text color", - "name": "--le-input-color" + "description": "Card box shadow", + "name": "--le-card-shadow" }, { - "description": "Input border style", - "name": "--le-input-border" + "description": "Card content padding", + "name": "--le-card-padding" + } + ], + "cssParts": [ + { + "description": "The main card container", + "name": "card" }, { - "description": "Input border style when focused", - "name": "--le-input-border-focus" + "description": "The card header section", + "name": "header" }, { - "description": "Input border style when invalid", - "name": "--le-input-border-error" + "description": "The card content section", + "name": "content" }, { - "description": "Input border radius", - "name": "--le-input-radius" + "description": "The card footer section", + "name": "footer" } ], "slots": [ { - "description": "Additional description text displayed below the input", - "name": "description" + "description": "Card header content (title, actions)", + "name": "header" + }, + { + "description": "Default slot for main card content", + "name": "" + }, + { + "description": "Card footer content (buttons, links)", + "name": "footer" } ], "members": [ @@ -3056,33 +2937,152 @@ }, { "kind": "field", - "name": "value", + "name": "variant", "type": { - "text": "string" + "text": "'default' | 'outlined' | 'elevated'" }, - "default": "''", - "description": "The value of the input" + "default": "'default'", + "description": "Card variant style" }, { "kind": "field", - "name": "name", + "name": "interactive", "type": { - "text": "string | undefined" + "text": "boolean" }, - "description": "The name of the input" + "default": "false", + "description": "Whether the card is interactive (clickable)" }, { - "kind": "field", - "name": "label", + "kind": "method", + "name": "render" + } + ], + "attributes": [ + { + "name": "variant", + "fieldName": "variant", + "default": "'default'", + "description": "Card variant style", "type": { - "text": "string | undefined" - }, - "description": "Label for the input" + "text": "'default' | 'outlined' | 'elevated'" + } }, { - "kind": "field", - "name": "length", - "type": { + "name": "interactive", + "fieldName": "interactive", + "default": "false", + "description": "Whether the card is interactive (clickable)", + "type": { + "text": "boolean" + } + } + ], + "tagName": "le-card", + "events": [], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeCard", + "declaration": { + "name": "LeCard", + "module": "src/components/le-card/le-card.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-card", + "declaration": { + "name": "LeCard", + "module": "src/components/le-card/le-card.tsx" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/components/le-code-input/le-code-input.tsx", + "declarations": [ + { + "kind": "class", + "description": "A one-time code input component with individual frames for each character.\nSupports standard copy/paste and range selection behaviors.", + "name": "LeCodeInput", + "cssProperties": [ + { + "description": "Size of each character box (default: 40px width, 48px height)", + "name": "--le-code-box-size" + }, + { + "description": "Input background color", + "name": "--le-input-bg" + }, + { + "description": "Input text color", + "name": "--le-input-color" + }, + { + "description": "Input border style", + "name": "--le-input-border" + }, + { + "description": "Input border style when focused", + "name": "--le-input-border-focus" + }, + { + "description": "Input border style when invalid", + "name": "--le-input-border-error" + }, + { + "description": "Input border radius", + "name": "--le-input-radius" + } + ], + "slots": [ + { + "description": "Additional description text displayed below the input", + "name": "description" + } + ], + "members": [ + { + "kind": "field", + "name": "el", + "type": { + "text": "HTMLElement" + } + }, + { + "kind": "field", + "name": "value", + "type": { + "text": "string" + }, + "default": "''", + "description": "The value of the input" + }, + { + "kind": "field", + "name": "name", + "type": { + "text": "string | undefined" + }, + "description": "The name of the input" + }, + { + "kind": "field", + "name": "label", + "type": { + "text": "string | undefined" + }, + "description": "Label for the input" + }, + { + "kind": "field", + "name": "length", + "type": { "text": "number" }, "default": "6", @@ -4007,112 +4007,6 @@ } ] }, - { - "kind": "javascript-module", - "path": "src/components/le-current-heading/le-current-heading.tsx", - "declarations": [ - { - "kind": "class", - "description": "Shows a \"smart\" header title based on what has scrolled out of view.\n\nWhen `selector` matches multiple elements, the title becomes the last element\n(top-to-bottom) that has fully scrolled out above the viewport.", - "name": "LeCurrentHeading", - "cssParts": [ - { - "description": "The rendered title", - "name": "title" - } - ], - "slots": [ - { - "description": "Optional fallback content if no watched title is active", - "name": "" - } - ], - "members": [ - { - "kind": "field", - "name": "el", - "type": { - "text": "HTMLElement" - } - }, - { - "kind": "field", - "name": "selector", - "type": { - "text": "string" - }, - "default": "''", - "description": "CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`)." - }, - { - "kind": "field", - "name": "activeText", - "type": { - "text": "string | null" - }, - "privacy": "private", - "default": "null" - }, - { - "kind": "method", - "name": "onSelectorChange", - "privacy": "protected" - }, - { - "kind": "method", - "name": "onScroll", - "privacy": "protected" - }, - { - "kind": "method", - "name": "onResize", - "privacy": "protected" - }, - { - "kind": "method", - "name": "updateActiveTitle", - "privacy": "private" - }, - { - "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "selector", - "fieldName": "selector", - "default": "''", - "description": "CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`).", - "type": { - "text": "string" - } - } - ], - "tagName": "le-current-heading", - "events": [], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeCurrentHeading", - "declaration": { - "name": "LeCurrentHeading", - "module": "src/components/le-current-heading/le-current-heading.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-current-heading", - "declaration": { - "name": "LeCurrentHeading", - "module": "src/components/le-current-heading/le-current-heading.tsx" - } - } - ] - }, { "kind": "javascript-module", "path": "src/components/le-component/le-component.tsx", @@ -4519,26 +4413,6 @@ "privacy": "private", "default": "false" }, - { - "kind": "field", - "name": "LONG_PRESS_DURATION", - "type": { - "text": "number" - }, - "privacy": "private", - "readonly": true, - "default": "500" - }, - { - "kind": "field", - "name": "MOVE_THRESHOLD", - "type": { - "text": "number" - }, - "privacy": "private", - "readonly": true, - "default": "10" - }, { "kind": "field", "name": "initialTriggerRect", @@ -4607,8 +4481,8 @@ "type": { "text": "'blocked' | 'menu-close' | 'fixed-menu'" }, - "default": "'fixed-menu'", - "description": "Behavior of the menu on page scroll:\n- 'blocked': blocks page scroll\n- 'menu-close': closes the menu automatically on scroll\n- 'fixed-menu': menu scrolls with the page (default)" + "default": "'menu-close'", + "description": "Behavior of the menu on page scroll:\n- 'blocked': blocks page scroll\n- 'menu-close': closes the menu automatically on scroll (default)\n- 'fixed-menu': menu scrolls with the page" }, { "kind": "field", @@ -4850,8 +4724,8 @@ { "name": "page-scroll-behavior", "fieldName": "pageScrollBehavior", - "default": "'fixed-menu'", - "description": "Behavior of the menu on page scroll:\n- 'blocked': blocks page scroll\n- 'menu-close': closes the menu automatically on scroll\n- 'fixed-menu': menu scrolls with the page (default)", + "default": "'menu-close'", + "description": "Behavior of the menu on page scroll:\n- 'blocked': blocks page scroll\n- 'menu-close': closes the menu automatically on scroll (default)\n- 'fixed-menu': menu scrolls with the page", "type": { "text": "'blocked' | 'menu-close' | 'fixed-menu'" } @@ -4916,36 +4790,69 @@ }, { "kind": "javascript-module", - "path": "src/components/le-drag-handle/le-drag-handle.tsx", + "path": "src/components/le-current-heading/le-current-heading.tsx", "declarations": [ { "kind": "class", - "description": "Reusable drag handle used by resizable components.", - "name": "LeDragHandle", + "description": "Shows a \"smart\" header title based on what has scrolled out of view.\n\nWhen `selector` matches multiple elements, the title becomes the last element\n(top-to-bottom) that has fully scrolled out above the viewport.", + "name": "LeCurrentHeading", + "cssParts": [ + { + "description": "The rendered title", + "name": "title" + } + ], "slots": [ { - "description": "Optional assistive text for screen readers.", + "description": "Optional fallback content if no watched title is active", "name": "" } ], "members": [ { "kind": "field", - "name": "orientation", + "name": "el", "type": { - "text": "LeDragHandleOrientation" - }, - "default": "'vertical'", - "description": "Handle orientation (vertical = width drag, horizontal = height drag)." + "text": "HTMLElement" + } }, { "kind": "field", - "name": "placement", + "name": "selector", "type": { - "text": "LeDragHandlePlacement" + "text": "string" }, - "default": "'end'", - "description": "Handle position on the owning edge." + "default": "''", + "description": "CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`)." + }, + { + "kind": "field", + "name": "activeText", + "type": { + "text": "string | null" + }, + "privacy": "private", + "default": "null" + }, + { + "kind": "method", + "name": "onSelectorChange", + "privacy": "protected" + }, + { + "kind": "method", + "name": "onScroll", + "privacy": "protected" + }, + { + "kind": "method", + "name": "onResize", + "privacy": "protected" + }, + { + "kind": "method", + "name": "updateActiveTitle", + "privacy": "private" }, { "kind": "method", @@ -4954,25 +4861,16 @@ ], "attributes": [ { - "name": "orientation", - "fieldName": "orientation", - "default": "'vertical'", - "description": "Handle orientation (vertical = width drag, horizontal = height drag).", - "type": { - "text": "LeDragHandleOrientation" - } - }, - { - "name": "placement", - "fieldName": "placement", - "default": "'end'", - "description": "Handle position on the owning edge.", + "name": "selector", + "fieldName": "selector", + "default": "''", + "description": "CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`).", "type": { - "text": "LeDragHandlePlacement" + "text": "string" } } ], - "tagName": "le-drag-handle", + "tagName": "le-current-heading", "events": [], "customElement": true } @@ -4980,43 +4878,81 @@ "exports": [ { "kind": "js", - "name": "LeDragHandle", + "name": "LeCurrentHeading", "declaration": { - "name": "LeDragHandle", - "module": "src/components/le-drag-handle/le-drag-handle.tsx" + "name": "LeCurrentHeading", + "module": "src/components/le-current-heading/le-current-heading.tsx" } }, { "kind": "custom-element-definition", - "name": "le-drag-handle", + "name": "le-current-heading", "declaration": { - "name": "LeDragHandle", - "module": "src/components/le-drag-handle/le-drag-handle.tsx" + "name": "LeCurrentHeading", + "module": "src/components/le-current-heading/le-current-heading.tsx" } } ] }, { "kind": "javascript-module", - "path": "src/components/le-header-placeholder/le-header-placeholder.tsx", + "path": "src/components/le-drag-handle/le-drag-handle.tsx", "declarations": [ { "kind": "class", - "description": "Placeholder for `le-header`.\n\nReserves space using the global CSS variable `--le-header-height`.\nThe header component updates that variable when it renders.", - "name": "LeHeaderPlaceholder", - "cssProperties": [ + "description": "Reusable drag handle used by resizable components.", + "name": "LeDragHandle", + "slots": [ { - "description": "Published header height (px)", - "name": "--le-header-height" + "description": "Optional assistive text for screen readers.", + "name": "" } ], "members": [ + { + "kind": "field", + "name": "orientation", + "type": { + "text": "LeDragHandleOrientation" + }, + "default": "'vertical'", + "description": "Handle orientation (vertical = width drag, horizontal = height drag)." + }, + { + "kind": "field", + "name": "placement", + "type": { + "text": "LeDragHandlePlacement" + }, + "default": "'end'", + "description": "Handle position on the owning edge." + }, { "kind": "method", "name": "render" } ], - "tagName": "le-header-placeholder", + "attributes": [ + { + "name": "orientation", + "fieldName": "orientation", + "default": "'vertical'", + "description": "Handle orientation (vertical = width drag, horizontal = height drag).", + "type": { + "text": "LeDragHandleOrientation" + } + }, + { + "name": "placement", + "fieldName": "placement", + "default": "'end'", + "description": "Handle position on the owning edge.", + "type": { + "text": "LeDragHandlePlacement" + } + } + ], + "tagName": "le-drag-handle", "events": [], "customElement": true } @@ -5024,18 +4960,18 @@ "exports": [ { "kind": "js", - "name": "LeHeaderPlaceholder", + "name": "LeDragHandle", "declaration": { - "name": "LeHeaderPlaceholder", - "module": "src/components/le-header-placeholder/le-header-placeholder.tsx" + "name": "LeDragHandle", + "module": "src/components/le-drag-handle/le-drag-handle.tsx" } }, { "kind": "custom-element-definition", - "name": "le-header-placeholder", + "name": "le-drag-handle", "declaration": { - "name": "LeHeaderPlaceholder", - "module": "src/components/le-header-placeholder/le-header-placeholder.tsx" + "name": "LeDragHandle", + "module": "src/components/le-drag-handle/le-drag-handle.tsx" } } ] @@ -6170,6 +6106,50 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/components/le-header-placeholder/le-header-placeholder.tsx", + "declarations": [ + { + "kind": "class", + "description": "Placeholder for `le-header`.\n\nReserves space using the global CSS variable `--le-header-height`.\nThe header component updates that variable when it renders.", + "name": "LeHeaderPlaceholder", + "cssProperties": [ + { + "description": "Published header height (px)", + "name": "--le-header-height" + } + ], + "members": [ + { + "kind": "method", + "name": "render" + } + ], + "tagName": "le-header-placeholder", + "events": [], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeHeaderPlaceholder", + "declaration": { + "name": "LeHeaderPlaceholder", + "module": "src/components/le-header-placeholder/le-header-placeholder.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-header-placeholder", + "declaration": { + "name": "LeHeaderPlaceholder", + "module": "src/components/le-header-placeholder/le-header-placeholder.tsx" + } + } + ] + }, { "kind": "javascript-module", "path": "src/components/le-icon/le-icon.tsx", @@ -8954,66 +8934,63 @@ }, { "kind": "javascript-module", - "path": "src/components/le-popover/le-popover.tsx", + "path": "src/components/le-overflow-menu/le-overflow-menu.tsx", "declarations": [ { "kind": "class", - "description": "A popover component for displaying floating content.\n\nUses the native HTML Popover API for proper layering with dialogs\nand other top-layer elements. Falls back gracefully in older browsers.", - "name": "LePopover", - "cssParts": [ + "description": "", + "name": "LeOverflowMenu", + "members": [ { - "description": "The popover trigger element", - "name": "trigger" + "kind": "field", + "name": "popoverEl", + "type": { + "text": "HTMLLePopoverElement | undefined" + }, + "privacy": "private" }, { - "description": "The popover content wrapper", - "name": "content" - } - ], - "slots": [ - { - "description": "Content to display inside the popover", - "name": "" + "kind": "field", + "name": "navigationEl", + "type": { + "text": "HTMLLeNavigationElement | undefined" + }, + "privacy": "private" }, - { - "description": "Element that triggers the popover (optional)", - "name": "trigger" - } - ], - "members": [ { "kind": "field", - "name": "el", + "name": "triggerEl", "type": { - "text": "HTMLElement" - } + "text": "HTMLElement | undefined" + }, + "privacy": "private" }, { "kind": "field", - "name": "mode", + "name": "open", "type": { - "text": "'default' | 'admin'" + "text": "boolean" }, - "default": "'default'", - "description": "Mode of the popover should be 'default' for internal use" + "default": "false", + "description": "Whether the menu popover is open." }, { "kind": "field", - "name": "open", + "name": "disabled", "type": { "text": "boolean" }, "default": "false", - "description": "Whether the popover is currently open" + "description": "Disables trigger interactions." }, { "kind": "field", "name": "position", "type": { - "text": "'top' | 'bottom' | 'left' | 'right' | 'auto'" + "text": "'top' | 'right' | 'bottom' | 'left'" }, "default": "'bottom'", - "description": "Position of the popover relative to its trigger" + "description": "Popover position." }, { "kind": "field", @@ -9021,153 +8998,62 @@ "type": { "text": "'start' | 'center' | 'end'" }, - "default": "'start'", - "description": "Alignment of the popover" + "default": "'end'", + "description": "Popover alignment relative to trigger." }, { "kind": "field", - "name": "popoverTitle", + "name": "offset", "type": { - "text": "string | undefined" + "text": "number" }, - "description": "Optional title for the popover header" + "default": "8", + "description": "Popover offset in px." }, { "kind": "field", - "name": "showClose", + "name": "minWidth", "type": { - "text": "boolean" + "text": "string" }, - "default": "true", - "description": "Whether to show a close button in the header" - }, - { - "kind": "field", - "name": "closeOnClickOutside", - "type": { - "text": "boolean" - }, - "default": "true", - "description": "Whether clicking outside closes the popover" - }, - { - "kind": "field", - "name": "closeOnEscape", - "type": { - "text": "boolean" - }, - "default": "true", - "description": "Whether pressing Escape closes the popover" - }, - { - "kind": "field", - "name": "offset", - "type": { - "text": "number" - }, - "default": "8", - "description": "Offset from the trigger element (in pixels)" - }, - { - "kind": "field", - "name": "width", - "type": { - "text": "string | undefined" - }, - "description": "Fixed width for the popover (e.g., '300px', '20rem')" - }, - { - "kind": "field", - "name": "minWidth", - "type": { - "text": "string | undefined" - }, - "default": "'200px'", - "description": "Minimum width for the popover (e.g., '200px', '15rem')" - }, - { - "kind": "field", - "name": "maxWidth", - "type": { - "text": "string | undefined" - }, - "description": "Maximum width for the popover (e.g., '400px', '25rem')" - }, - { - "kind": "field", - "name": "triggerFullWidth", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Should the popover's trigger take full width of its container" - }, - { - "kind": "method", - "name": "updatePosition", - "description": "Method to update the popover position from a parent component" - }, - { - "kind": "field", - "name": "isPositioned", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" - }, - { - "kind": "field", - "name": "triggerEl", - "type": { - "text": "HTMLElement | undefined" - }, - "privacy": "private" + "default": "'160px'", + "description": "Minimum popover width." }, { "kind": "field", - "name": "popoverEl", + "name": "icon", "type": { - "text": "HTMLElement | undefined" + "text": "string" }, - "privacy": "private" + "default": "'ellipsis-horizontal'", + "description": "Fallback icon name for trigger." }, { "kind": "field", - "name": "uniqueId", + "name": "triggerAriaLabel", "type": { "text": "string" }, - "privacy": "private", - "default": "`le-popover-${Math.random().toString(36).substr(2, 9)}`" + "default": "'Open menu'", + "description": "Aria label for fallback trigger button." }, { "kind": "field", - "name": "scrollParents", + "name": "triggerPart", "type": { - "text": "Element[]" + "text": "string" }, - "privacy": "private", - "default": "[]" + "default": "'trigger-button'", + "description": "Part name for fallback trigger button." }, { "kind": "field", - "name": "isListeningForDismiss", + "name": "items", "type": { - "text": "boolean" + "text": "LeOverflowMenuItem[] | string" }, - "privacy": "private", - "default": "false" - }, - { - "kind": "method", - "name": "isNativePopoverOpen", - "privacy": "private", - "return": { - "type": { - "text": "boolean" - } - } + "default": "[]", + "description": "List of menu items represented as options." }, { "kind": "method", @@ -9181,158 +9067,68 @@ } ] }, - { - "kind": "field", - "name": "supportsPopoverApi", - "type": { - "text": "boolean" - }, - "privacy": "private", - "readonly": true - }, { "kind": "method", - "name": "shadowContains", - "privacy": "private", - "return": { - "type": { - "text": "boolean" - } - }, - "parameters": [ - { - "name": "container", - "type": { - "text": "HTMLElement" - } - }, - { - "name": "node", - "type": { - "text": "HTMLElement" - } - } - ] + "name": "show" }, { "kind": "method", - "name": "addDismissListeners", - "privacy": "private" + "name": "hide" }, { "kind": "method", - "name": "removeDismissListeners", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleDocumentPointerDown", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleDocumentKeyDown", - "privacy": "private" + "name": "toggle" }, { "kind": "method", - "name": "getScrollParents", + "name": "parseItems", "privacy": "private", "return": { "type": { - "text": "Element[]" + "text": "LeOverflowMenuItem[]" } }, "parameters": [ { - "name": "element", + "name": "input", "type": { - "text": "Element" + "text": "LeOverflowMenuItem[] | string" } } - ], - "description": "Find all scrollable parent elements" - }, - { - "kind": "method", - "name": "addScrollListeners", - "privacy": "private", - "description": "Add scroll listeners to all scrollable parents" - }, - { - "kind": "method", - "name": "removeScrollListeners", - "privacy": "private", - "description": "Remove scroll listeners" + ] }, { "kind": "field", - "name": "handleScroll", - "privacy": "private" - }, - { - "kind": "method", - "name": "handleOpened", - "privacy": "private" - }, - { - "kind": "method", - "name": "handleClosed", + "name": "handlePopoverOpen", "privacy": "private" }, { "kind": "field", - "name": "handlePopoverToggle", + "name": "handlePopoverClose", "privacy": "private" }, { "kind": "field", - "name": "handleOtherPopoverOpen", + "name": "handleItemClick", "privacy": "private" }, - { - "kind": "method", - "name": "show", - "description": "Opens the popover" - }, - { - "kind": "method", - "name": "hide", - "description": "Closes the popover" - }, - { - "kind": "method", - "name": "toggle", - "description": "Toggles the popover" - }, { "kind": "field", - "name": "handleTriggerClick", + "name": "handleNavigationSelect", "privacy": "private" }, { "kind": "method", - "name": "getUnscaledPopoverSize", + "name": "renderItems", "privacy": "private", - "return": { - "type": { - "text": "{ width: number; height: number }" - } - }, "parameters": [ { - "name": "rect", + "name": "items", "type": { - "text": "DOMRect" + "text": "LeOverflowMenuItem[]" } } - ], - "description": "During opening animation we scale the popover (e.g. 0.95 -> 1).\ngetBoundingClientRect() returns transformed dimensions, so for initial\npositioning we compensate back to the unscaled size." - }, - { - "kind": "method", - "name": "_updatePosition", - "privacy": "private" + ] }, { "kind": "method", @@ -9341,19 +9137,19 @@ ], "attributes": [ { - "name": "mode", - "fieldName": "mode", - "default": "'default'", - "description": "Mode of the popover should be 'default' for internal use", + "name": "open", + "fieldName": "open", + "default": "false", + "description": "Whether the menu popover is open.", "type": { - "text": "'default' | 'admin'" + "text": "boolean" } }, { - "name": "open", - "fieldName": "open", + "name": "disabled", + "fieldName": "disabled", "default": "false", - "description": "Whether the popover is currently open", + "description": "Disables trigger interactions.", "type": { "text": "boolean" } @@ -9362,114 +9158,88 @@ "name": "position", "fieldName": "position", "default": "'bottom'", - "description": "Position of the popover relative to its trigger", + "description": "Popover position.", "type": { - "text": "'top' | 'bottom' | 'left' | 'right' | 'auto'" + "text": "'top' | 'right' | 'bottom' | 'left'" } }, { "name": "align", "fieldName": "align", - "default": "'start'", - "description": "Alignment of the popover", + "default": "'end'", + "description": "Popover alignment relative to trigger.", "type": { "text": "'start' | 'center' | 'end'" } }, - { - "name": "popover-title", - "fieldName": "popoverTitle", - "description": "Optional title for the popover header", - "type": { - "text": "string" - } - }, - { - "name": "show-close", - "fieldName": "showClose", - "default": "true", - "description": "Whether to show a close button in the header", - "type": { - "text": "boolean" - } - }, - { - "name": "close-on-click-outside", - "fieldName": "closeOnClickOutside", - "default": "true", - "description": "Whether clicking outside closes the popover", - "type": { - "text": "boolean" - } - }, - { - "name": "close-on-escape", - "fieldName": "closeOnEscape", - "default": "true", - "description": "Whether pressing Escape closes the popover", - "type": { - "text": "boolean" - } - }, { "name": "offset", "fieldName": "offset", "default": "8", - "description": "Offset from the trigger element (in pixels)", + "description": "Popover offset in px.", "type": { "text": "number" } }, { - "name": "width", - "fieldName": "width", - "description": "Fixed width for the popover (e.g., '300px', '20rem')", + "name": "min-width", + "fieldName": "minWidth", + "default": "'160px'", + "description": "Minimum popover width.", "type": { "text": "string" } }, { - "name": "min-width", - "fieldName": "minWidth", - "default": "'200px'", - "description": "Minimum width for the popover (e.g., '200px', '15rem')", + "name": "icon", + "fieldName": "icon", + "default": "'ellipsis-horizontal'", + "description": "Fallback icon name for trigger.", "type": { "text": "string" } }, { - "name": "max-width", - "fieldName": "maxWidth", - "description": "Maximum width for the popover (e.g., '400px', '25rem')", + "name": "trigger-aria-label", + "fieldName": "triggerAriaLabel", + "default": "'Open menu'", + "description": "Aria label for fallback trigger button.", "type": { "text": "string" } }, { - "name": "trigger-full-width", - "fieldName": "triggerFullWidth", - "default": "false", - "description": "Should the popover's trigger take full width of its container", + "name": "trigger-part", + "fieldName": "triggerPart", + "default": "'trigger-button'", + "description": "Part name for fallback trigger button.", "type": { - "text": "boolean" + "text": "string" + } + }, + { + "name": "items", + "fieldName": "items", + "default": "[]", + "description": "List of menu items represented as options.", + "type": { + "text": "LeOverflowMenuItem[] | string" } } ], - "tagName": "le-popover", + "tagName": "le-overflow-menu", "events": [ { - "name": "lePopoverOpen", + "name": "leOverflowMenuItemSelect", "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the popover opens" + "text": "EventEmitter" + } }, { - "name": "lePopoverClose", + "name": "leOverflowMenuClose", "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the popover closes" + "text": "EventEmitter" + } } ], "customElement": true @@ -9478,81 +9248,84 @@ "exports": [ { "kind": "js", - "name": "LePopover", + "name": "LeOverflowMenu", "declaration": { - "name": "LePopover", - "module": "src/components/le-popover/le-popover.tsx" + "name": "LeOverflowMenu", + "module": "src/components/le-overflow-menu/le-overflow-menu.tsx" } }, { "kind": "custom-element-definition", - "name": "le-popover", + "name": "le-overflow-menu", "declaration": { - "name": "LePopover", - "module": "src/components/le-popover/le-popover.tsx" + "name": "LeOverflowMenu", + "module": "src/components/le-overflow-menu/le-overflow-menu.tsx" } } ] }, { "kind": "javascript-module", - "path": "src/components/le-overflow-menu/le-overflow-menu.tsx", + "path": "src/components/le-popover/le-popover.tsx", "declarations": [ { "kind": "class", - "description": "", - "name": "LeOverflowMenu", - "members": [ + "description": "A popover component for displaying floating content.\n\nUses the native HTML Popover API for proper layering with dialogs\nand other top-layer elements. Falls back gracefully in older browsers.", + "name": "LePopover", + "cssParts": [ { - "kind": "field", - "name": "popoverEl", - "type": { - "text": "HTMLLePopoverElement | undefined" - }, - "privacy": "private" + "description": "The popover trigger element", + "name": "trigger" }, { - "kind": "field", - "name": "navigationEl", - "type": { - "text": "HTMLLeNavigationElement | undefined" - }, - "privacy": "private" + "description": "The popover content wrapper", + "name": "content" + } + ], + "slots": [ + { + "description": "Content to display inside the popover", + "name": "" }, + { + "description": "Element that triggers the popover (optional)", + "name": "trigger" + } + ], + "members": [ { "kind": "field", - "name": "triggerEl", + "name": "el", "type": { - "text": "HTMLElement | undefined" - }, - "privacy": "private" + "text": "HTMLElement" + } }, { "kind": "field", - "name": "open", + "name": "mode", "type": { - "text": "boolean" + "text": "'default' | 'admin'" }, - "default": "false", - "description": "Whether the menu popover is open." + "default": "'default'", + "description": "Mode of the popover should be 'default' for internal use" }, { "kind": "field", - "name": "disabled", + "name": "open", "type": { "text": "boolean" }, "default": "false", - "description": "Disables trigger interactions." + "description": "Whether the popover is currently open" }, { "kind": "field", "name": "position", "type": { - "text": "'top' | 'right' | 'bottom' | 'left'" + "text": "'top' | 'bottom' | 'left' | 'right' | 'auto'" }, "default": "'bottom'", - "description": "Popover position." + "description": "Position of the popover relative to its trigger" }, { "kind": "field", @@ -9560,137 +9333,318 @@ "type": { "text": "'start' | 'center' | 'end'" }, - "default": "'end'", - "description": "Popover alignment relative to trigger." + "default": "'start'", + "description": "Alignment of the popover" }, { "kind": "field", - "name": "offset", + "name": "popoverTitle", "type": { - "text": "number" + "text": "string | undefined" }, - "default": "8", - "description": "Popover offset in px." + "description": "Optional title for the popover header" }, { "kind": "field", - "name": "minWidth", + "name": "showClose", "type": { - "text": "string" + "text": "boolean" }, - "default": "'160px'", - "description": "Minimum popover width." + "default": "true", + "description": "Whether to show a close button in the header" }, { "kind": "field", - "name": "icon", + "name": "closeOnClickOutside", "type": { - "text": "string" + "text": "boolean" }, - "default": "'ellipsis-horizontal'", - "description": "Fallback icon name for trigger." + "default": "true", + "description": "Whether clicking outside closes the popover" }, { "kind": "field", - "name": "triggerAriaLabel", + "name": "closeOnEscape", "type": { - "text": "string" + "text": "boolean" }, - "default": "'Open menu'", - "description": "Aria label for fallback trigger button." + "default": "true", + "description": "Whether pressing Escape closes the popover" }, { "kind": "field", - "name": "triggerPart", + "name": "offset", "type": { - "text": "string" + "text": "number" }, - "default": "'trigger-button'", - "description": "Part name for fallback trigger button." + "default": "8", + "description": "Offset from the trigger element (in pixels)" }, { "kind": "field", - "name": "items", + "name": "width", "type": { - "text": "LeOverflowMenuItem[] | string" + "text": "string | undefined" }, - "default": "[]", - "description": "List of menu items represented as options." + "description": "Fixed width for the popover (e.g., '300px', '20rem')" }, { - "kind": "method", - "name": "handleOpenChange", - "parameters": [ - { - "name": "nextOpen", - "type": { - "text": "boolean" - } - } - ] + "kind": "field", + "name": "minWidth", + "type": { + "text": "string | undefined" + }, + "default": "'200px'", + "description": "Minimum width for the popover (e.g., '200px', '15rem')" }, { - "kind": "method", - "name": "show" + "kind": "field", + "name": "maxWidth", + "type": { + "text": "string | undefined" + }, + "description": "Maximum width for the popover (e.g., '400px', '25rem')" }, { - "kind": "method", - "name": "hide" + "kind": "field", + "name": "triggerFullWidth", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Should the popover's trigger take full width of its container" }, { "kind": "method", - "name": "toggle" + "name": "updatePosition", + "description": "Method to update the popover position from a parent component" + }, + { + "kind": "field", + "name": "isPositioned", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "field", + "name": "triggerEl", + "type": { + "text": "HTMLElement | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "popoverEl", + "type": { + "text": "HTMLElement | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "uniqueId", + "type": { + "text": "string" + }, + "privacy": "private", + "default": "`le-popover-${Math.random().toString(36).substr(2, 9)}`" + }, + { + "kind": "field", + "name": "scrollParents", + "type": { + "text": "Element[]" + }, + "privacy": "private", + "default": "[]" + }, + { + "kind": "field", + "name": "isListeningForDismiss", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" }, { "kind": "method", - "name": "parseItems", + "name": "isNativePopoverOpen", "privacy": "private", "return": { "type": { - "text": "LeOverflowMenuItem[]" + "text": "boolean" + } + } + }, + { + "kind": "method", + "name": "handleOpenChange", + "parameters": [ + { + "name": "nextOpen", + "type": { + "text": "boolean" + } + } + ] + }, + { + "kind": "field", + "name": "supportsPopoverApi", + "type": { + "text": "boolean" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "shadowContains", + "privacy": "private", + "return": { + "type": { + "text": "boolean" } }, "parameters": [ { - "name": "input", + "name": "container", "type": { - "text": "LeOverflowMenuItem[] | string" + "text": "HTMLElement" + } + }, + { + "name": "node", + "type": { + "text": "HTMLElement" } } ] }, + { + "kind": "method", + "name": "addDismissListeners", + "privacy": "private" + }, + { + "kind": "method", + "name": "removeDismissListeners", + "privacy": "private" + }, { "kind": "field", - "name": "handlePopoverOpen", + "name": "handleDocumentPointerDown", "privacy": "private" }, { "kind": "field", - "name": "handlePopoverClose", + "name": "handleDocumentKeyDown", + "privacy": "private" + }, + { + "kind": "method", + "name": "getScrollParents", + "privacy": "private", + "return": { + "type": { + "text": "Element[]" + } + }, + "parameters": [ + { + "name": "element", + "type": { + "text": "Element" + } + } + ], + "description": "Find all scrollable parent elements" + }, + { + "kind": "method", + "name": "addScrollListeners", + "privacy": "private", + "description": "Add scroll listeners to all scrollable parents" + }, + { + "kind": "method", + "name": "removeScrollListeners", + "privacy": "private", + "description": "Remove scroll listeners" + }, + { + "kind": "field", + "name": "handleScroll", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleOpened", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleClosed", "privacy": "private" }, { "kind": "field", - "name": "handleItemClick", + "name": "handlePopoverToggle", "privacy": "private" }, { "kind": "field", - "name": "handleNavigationSelect", + "name": "handleOtherPopoverOpen", "privacy": "private" }, { "kind": "method", - "name": "renderItems", + "name": "show", + "description": "Opens the popover" + }, + { + "kind": "method", + "name": "hide", + "description": "Closes the popover" + }, + { + "kind": "method", + "name": "toggle", + "description": "Toggles the popover" + }, + { + "kind": "field", + "name": "handleTriggerClick", + "privacy": "private" + }, + { + "kind": "method", + "name": "getUnscaledPopoverSize", "privacy": "private", + "return": { + "type": { + "text": "{ width: number; height: number }" + } + }, "parameters": [ { - "name": "items", + "name": "rect", "type": { - "text": "LeOverflowMenuItem[]" + "text": "DOMRect" } } - ] + ], + "description": "During opening animation we scale the popover (e.g. 0.95 -> 1).\ngetBoundingClientRect() returns transformed dimensions, so for initial\npositioning we compensate back to the unscaled size." + }, + { + "kind": "method", + "name": "_updatePosition", + "privacy": "private" }, { "kind": "method", @@ -9699,19 +9653,19 @@ ], "attributes": [ { - "name": "open", - "fieldName": "open", - "default": "false", - "description": "Whether the menu popover is open.", + "name": "mode", + "fieldName": "mode", + "default": "'default'", + "description": "Mode of the popover should be 'default' for internal use", "type": { - "text": "boolean" + "text": "'default' | 'admin'" } }, { - "name": "disabled", - "fieldName": "disabled", + "name": "open", + "fieldName": "open", "default": "false", - "description": "Disables trigger interactions.", + "description": "Whether the popover is currently open", "type": { "text": "boolean" } @@ -9720,88 +9674,114 @@ "name": "position", "fieldName": "position", "default": "'bottom'", - "description": "Popover position.", + "description": "Position of the popover relative to its trigger", "type": { - "text": "'top' | 'right' | 'bottom' | 'left'" + "text": "'top' | 'bottom' | 'left' | 'right' | 'auto'" } }, { "name": "align", "fieldName": "align", - "default": "'end'", - "description": "Popover alignment relative to trigger.", + "default": "'start'", + "description": "Alignment of the popover", "type": { "text": "'start' | 'center' | 'end'" } }, { - "name": "offset", - "fieldName": "offset", - "default": "8", - "description": "Popover offset in px.", + "name": "popover-title", + "fieldName": "popoverTitle", + "description": "Optional title for the popover header", "type": { - "text": "number" + "text": "string" } }, { - "name": "min-width", - "fieldName": "minWidth", - "default": "'160px'", - "description": "Minimum popover width.", + "name": "show-close", + "fieldName": "showClose", + "default": "true", + "description": "Whether to show a close button in the header", "type": { - "text": "string" + "text": "boolean" } }, { - "name": "icon", - "fieldName": "icon", - "default": "'ellipsis-horizontal'", - "description": "Fallback icon name for trigger.", + "name": "close-on-click-outside", + "fieldName": "closeOnClickOutside", + "default": "true", + "description": "Whether clicking outside closes the popover", + "type": { + "text": "boolean" + } + }, + { + "name": "close-on-escape", + "fieldName": "closeOnEscape", + "default": "true", + "description": "Whether pressing Escape closes the popover", + "type": { + "text": "boolean" + } + }, + { + "name": "offset", + "fieldName": "offset", + "default": "8", + "description": "Offset from the trigger element (in pixels)", + "type": { + "text": "number" + } + }, + { + "name": "width", + "fieldName": "width", + "description": "Fixed width for the popover (e.g., '300px', '20rem')", "type": { "text": "string" } }, { - "name": "trigger-aria-label", - "fieldName": "triggerAriaLabel", - "default": "'Open menu'", - "description": "Aria label for fallback trigger button.", + "name": "min-width", + "fieldName": "minWidth", + "default": "'200px'", + "description": "Minimum width for the popover (e.g., '200px', '15rem')", "type": { "text": "string" } }, { - "name": "trigger-part", - "fieldName": "triggerPart", - "default": "'trigger-button'", - "description": "Part name for fallback trigger button.", + "name": "max-width", + "fieldName": "maxWidth", + "description": "Maximum width for the popover (e.g., '400px', '25rem')", "type": { "text": "string" } }, { - "name": "items", - "fieldName": "items", - "default": "[]", - "description": "List of menu items represented as options.", + "name": "trigger-full-width", + "fieldName": "triggerFullWidth", + "default": "false", + "description": "Should the popover's trigger take full width of its container", "type": { - "text": "LeOverflowMenuItem[] | string" + "text": "boolean" } } ], - "tagName": "le-overflow-menu", + "tagName": "le-popover", "events": [ { - "name": "leOverflowMenuItemSelect", + "name": "lePopoverOpen", "type": { - "text": "EventEmitter" - } + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the popover opens" }, { - "name": "leOverflowMenuClose", + "name": "lePopoverClose", "type": { - "text": "EventEmitter" - } + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the popover closes" } ], "customElement": true @@ -9810,18 +9790,18 @@ "exports": [ { "kind": "js", - "name": "LeOverflowMenu", + "name": "LePopover", "declaration": { - "name": "LeOverflowMenu", - "module": "src/components/le-overflow-menu/le-overflow-menu.tsx" + "name": "LePopover", + "module": "src/components/le-popover/le-popover.tsx" } }, { "kind": "custom-element-definition", - "name": "le-overflow-menu", + "name": "le-popover", "declaration": { - "name": "LeOverflowMenu", - "module": "src/components/le-overflow-menu/le-overflow-menu.tsx" + "name": "LePopover", + "module": "src/components/le-popover/le-popover.tsx" } } ] @@ -10975,6 +10955,172 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/components/le-round-progress/le-round-progress.tsx", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "LeRoundProgress", + "members": [ + { + "kind": "field", + "name": "el", + "type": { + "text": "HTMLElement" + } + }, + { + "kind": "field", + "name": "value", + "type": { + "text": "number" + }, + "default": "0" + }, + { + "kind": "method", + "name": "updateValue", + "parameters": [ + { + "name": "newValue", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "field", + "name": "padding", + "type": { + "text": "number" + }, + "default": "0" + }, + { + "kind": "method", + "name": "updatePadding", + "parameters": [ + { + "name": "newValue", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "field", + "name": "paths", + "type": { + "text": "string" + } + }, + { + "kind": "method", + "name": "updateProgressBackgrounds", + "parameters": [ + { + "name": "newValue", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "field", + "name": "progressPaths", + "type": { + "text": "any[]" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "params", + "type": { + "text": "{\n width: number;\n diameter: number;\n circumference: number;\n }" + } + }, + { + "kind": "method", + "name": "calcParams" + }, + { + "kind": "method", + "name": "getViewBox", + "description": "Returns the viewPath attribute value for the SVG\nbased on the width of the parent element" + }, + { + "kind": "method", + "name": "getPath", + "description": "Returns the circular path for the progress stroke\nand additional paths in the background" + }, + { + "kind": "method", + "name": "getStrokeDashArray" + }, + { + "kind": "method", + "name": "getPaths" + }, + { + "kind": "method", + "name": "render" + } + ], + "attributes": [ + { + "name": "value", + "fieldName": "value", + "default": "0", + "type": { + "text": "number" + } + }, + { + "name": "padding", + "fieldName": "padding", + "default": "0", + "type": { + "text": "number" + } + }, + { + "name": "paths", + "fieldName": "paths", + "type": { + "text": "string" + } + } + ], + "tagName": "le-round-progress", + "events": [], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeRoundProgress", + "declaration": { + "name": "LeRoundProgress", + "module": "src/components/le-round-progress/le-round-progress.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-round-progress", + "declaration": { + "name": "LeRoundProgress", + "module": "src/components/le-round-progress/le-round-progress.tsx" + } + } + ] + }, { "kind": "javascript-module", "path": "src/components/le-scroll-progress/le-scroll-progress.tsx", @@ -11163,173 +11309,7 @@ }, { "kind": "javascript-module", - "path": "src/components/le-round-progress/le-round-progress.tsx", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "LeRoundProgress", - "members": [ - { - "kind": "field", - "name": "el", - "type": { - "text": "HTMLElement" - } - }, - { - "kind": "field", - "name": "value", - "type": { - "text": "number" - }, - "default": "0" - }, - { - "kind": "method", - "name": "updateValue", - "parameters": [ - { - "name": "newValue", - "type": { - "text": "string" - } - } - ] - }, - { - "kind": "field", - "name": "padding", - "type": { - "text": "number" - }, - "default": "0" - }, - { - "kind": "method", - "name": "updatePadding", - "parameters": [ - { - "name": "newValue", - "type": { - "text": "string" - } - } - ] - }, - { - "kind": "field", - "name": "paths", - "type": { - "text": "string" - } - }, - { - "kind": "method", - "name": "updateProgressBackgrounds", - "parameters": [ - { - "name": "newValue", - "type": { - "text": "string" - } - } - ] - }, - { - "kind": "field", - "name": "progressPaths", - "type": { - "text": "any[]" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "params", - "type": { - "text": "{\n width: number;\n diameter: number;\n circumference: number;\n }" - } - }, - { - "kind": "method", - "name": "calcParams" - }, - { - "kind": "method", - "name": "getViewBox", - "description": "Returns the viewPath attribute value for the SVG\nbased on the width of the parent element" - }, - { - "kind": "method", - "name": "getPath", - "description": "Returns the circular path for the progress stroke\nand additional paths in the background" - }, - { - "kind": "method", - "name": "getStrokeDashArray" - }, - { - "kind": "method", - "name": "getPaths" - }, - { - "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "value", - "fieldName": "value", - "default": "0", - "type": { - "text": "number" - } - }, - { - "name": "padding", - "fieldName": "padding", - "default": "0", - "type": { - "text": "number" - } - }, - { - "name": "paths", - "fieldName": "paths", - "type": { - "text": "string" - } - } - ], - "tagName": "le-round-progress", - "events": [], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeRoundProgress", - "declaration": { - "name": "LeRoundProgress", - "module": "src/components/le-round-progress/le-round-progress.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-round-progress", - "declaration": { - "name": "LeRoundProgress", - "module": "src/components/le-round-progress/le-round-progress.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-segmented-control/le-segmented-control.tsx", + "path": "src/components/le-segmented-control/le-segmented-control.tsx", "declarations": [ { "kind": "class", @@ -11701,12 +11681,12 @@ }, { "kind": "javascript-module", - "path": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx", + "path": "src/components/le-select/le-select.tsx", "declarations": [ { "kind": "class", - "description": "", - "name": "LeSidePanelToggle", + "description": "A select dropdown component for single selection.", + "name": "LeSelect", "members": [ { "kind": "field", @@ -11717,28 +11697,29 @@ }, { "kind": "field", - "name": "panelId", + "name": "options", "type": { - "text": "string | undefined" + "text": "LeOption[] | string" }, - "description": "Optional id used to target a specific panel." + "default": "[]", + "description": "The options to display in the dropdown." }, { "kind": "field", - "name": "action", + "name": "value", "type": { - "text": "LeSidePanelToggleAction" + "text": "LeOptionValue | undefined" }, - "default": "'toggle'", - "description": "Action to emit. Default toggles the panel." + "description": "The currently selected value." }, { "kind": "field", - "name": "shortcut", + "name": "placeholder", "type": { - "text": "string | undefined" + "text": "string" }, - "description": "Optional keyboard shortcut like `Mod+B` or `Alt+N`." + "default": "'Select an option'", + "description": "Placeholder text when no option is selected." }, { "kind": "field", @@ -11747,31 +11728,24 @@ "text": "boolean" }, "default": "false", - "description": "Disables the toggle." - }, - { - "kind": "field", - "name": "mode", - "type": { - "text": "'default' | 'admin'" - }, - "default": "'default'" + "description": "Whether the select is disabled." }, { "kind": "field", - "name": "variant", + "name": "required", "type": { - "text": "'solid' | 'outlined' | 'clear' | 'system'" + "text": "boolean" }, - "default": "'solid'" + "default": "false", + "description": "Whether selection is required." }, { "kind": "field", - "name": "color", + "name": "name", "type": { - "text": "'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'" + "text": "string | undefined" }, - "default": "'primary'" + "description": "Name attribute for form submission." }, { "kind": "field", @@ -11779,151 +11753,152 @@ "type": { "text": "'small' | 'medium' | 'large'" }, - "default": "'medium'" + "default": "'medium'", + "description": "Size variant of the select." }, { "kind": "field", - "name": "selected", + "name": "variant", "type": { - "text": "boolean" + "text": "'default' | 'outlined' | 'solid'" }, - "default": "false" + "default": "'default'", + "description": "Visual variant of the select." }, { "kind": "field", - "name": "fullWidth", + "name": "open", "type": { "text": "boolean" }, - "default": "false" + "default": "false", + "description": "Whether the dropdown is currently open." }, { "kind": "field", - "name": "iconOnly", + "name": "selectedOption", "type": { - "text": "string | Node | undefined" - } + "text": "LeOption | undefined" + }, + "privacy": "private" }, { "kind": "field", - "name": "iconStart", + "name": "declarativeOptions", "type": { - "text": "string | Node | undefined" - } + "text": "LeOption[]" + }, + "privacy": "private", + "default": "[]" }, { "kind": "field", - "name": "iconEnd", + "name": "isDeclarativeMode", "type": { - "text": "string | Node | undefined" - } + "text": "boolean" + }, + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "type", + "name": "dropdownEl", "type": { - "text": "'button' | 'submit' | 'reset'" + "text": "HTMLLeDropdownBaseElement | undefined" }, - "default": "'button'" + "privacy": "private" }, { "kind": "field", - "name": "href", + "name": "mutationObserver", "type": { - "text": "string | undefined" - } + "text": "MutationObserver | undefined" + }, + "privacy": "private" }, { - "kind": "field", - "name": "target", - "type": { - "text": "string | undefined" - } + "kind": "method", + "name": "handleValueChange" }, { - "kind": "field", - "name": "align", - "type": { - "text": "'start' | 'center' | 'space-between' | 'end'" - }, - "default": "'center'" + "kind": "method", + "name": "handleOptionsChange" }, { - "kind": "field", - "name": "shortcutSpec", - "type": { - "text": "ShortcutSpec | undefined" - }, - "privacy": "private" + "kind": "method", + "name": "handleSlotChange" }, { - "kind": "field", - "name": "expanded", - "type": { - "text": "boolean | undefined" - }, + "kind": "method", + "name": "syncDeclarativeOptionsAndSelection", "privacy": "private" }, { - "kind": "field", - "name": "buttonEl", - "type": { - "text": "HTMLElement | undefined" - }, + "kind": "method", + "name": "buildDeclarativeOptions", "privacy": "private" }, { "kind": "field", - "name": "forwardedNodes", + "name": "parsedOptions", "type": { - "text": "ChildNode[] | undefined" + "text": "LeOption[]" }, - "privacy": "private" + "privacy": "private", + "readonly": true }, { "kind": "method", - "name": "onShortcutChanged", - "privacy": "protected" + "name": "updateSelectedOption", + "privacy": "private" }, { - "kind": "method", - "name": "syncShortcutListener", + "kind": "field", + "name": "handleOptionSelect", "privacy": "private" }, { - "kind": "method", - "name": "getResolvedPanelId", - "privacy": "private", - "return": { - "type": { - "text": "string | undefined" - } - } + "kind": "field", + "name": "handleDropdownOpen", + "privacy": "private" }, { - "kind": "method", - "name": "emitRequest", + "kind": "field", + "name": "handleDropdownClose", "privacy": "private" }, { "kind": "field", - "name": "onDocumentKeyDown", + "name": "handleTriggerClick", "privacy": "private" }, { "kind": "field", - "name": "onPanelStateChange", + "name": "handleTriggerKeyDown", "privacy": "private" }, { "kind": "method", - "name": "syncForwardedNodesIntoButton", - "privacy": "private" + "name": "showDropdown", + "description": "Opens the dropdown." }, { "kind": "method", - "name": "syncAriaExpanded", - "privacy": "private" + "name": "hideDropdown", + "description": "Closes the dropdown." + }, + { + "kind": "method", + "name": "renderIcon", + "privacy": "private", + "parameters": [ + { + "name": "icon", + "type": { + "text": "string | undefined" + } + } + ] }, { "kind": "method", @@ -11932,26 +11907,27 @@ ], "attributes": [ { - "name": "panel-id", - "fieldName": "panelId", - "description": "Optional id used to target a specific panel.", + "name": "options", + "fieldName": "options", + "default": "[]", + "description": "The options to display in the dropdown.", "type": { - "text": "string" + "text": "LeOption[] | string" } }, { - "name": "action", - "fieldName": "action", - "default": "'toggle'", - "description": "Action to emit. Default toggles the panel.", + "name": "value", + "fieldName": "value", + "description": "The currently selected value.", "type": { - "text": "LeSidePanelToggleAction" + "text": "LeOptionValue" } }, { - "name": "shortcut", - "fieldName": "shortcut", - "description": "Optional keyboard shortcut like `Mod+B` or `Alt+N`.", + "name": "placeholder", + "fieldName": "placeholder", + "default": "'Select an option'", + "description": "Placeholder text when no option is selected.", "type": { "text": "string" } @@ -11960,118 +11936,78 @@ "name": "disabled", "fieldName": "disabled", "default": "false", - "description": "Disables the toggle.", + "description": "Whether the select is disabled.", "type": { "text": "boolean" } }, { - "name": "mode", - "fieldName": "mode", - "default": "'default'", - "type": { - "text": "'default' | 'admin'" - } - }, - { - "name": "variant", - "fieldName": "variant", - "default": "'solid'", + "name": "required", + "fieldName": "required", + "default": "false", + "description": "Whether selection is required.", "type": { - "text": "'solid' | 'outlined' | 'clear' | 'system'" + "text": "boolean" } }, { - "name": "color", - "fieldName": "color", - "default": "'primary'", + "name": "name", + "fieldName": "name", + "description": "Name attribute for form submission.", "type": { - "text": "'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'" + "text": "string" } }, { "name": "size", "fieldName": "size", "default": "'medium'", + "description": "Size variant of the select.", "type": { "text": "'small' | 'medium' | 'large'" } }, { - "name": "selected", - "fieldName": "selected", - "default": "false", + "name": "variant", + "fieldName": "variant", + "default": "'default'", + "description": "Visual variant of the select.", "type": { - "text": "boolean" + "text": "'default' | 'outlined' | 'solid'" } }, { - "name": "full-width", - "fieldName": "fullWidth", + "name": "open", + "fieldName": "open", "default": "false", + "description": "Whether the dropdown is currently open.", "type": { "text": "boolean" } - }, - { - "name": "icon-only", - "fieldName": "iconOnly", - "type": { - "text": "string | Node" - } - }, - { - "name": "icon-start", - "fieldName": "iconStart", - "type": { - "text": "string | Node" - } - }, - { - "name": "icon-end", - "fieldName": "iconEnd", - "type": { - "text": "string | Node" - } - }, - { - "name": "type", - "fieldName": "type", - "default": "'button'", - "type": { - "text": "'button' | 'submit' | 'reset'" - } - }, + } + ], + "tagName": "le-select", + "events": [ { - "name": "href", - "fieldName": "href", + "name": "leChange", "type": { - "text": "string" - } + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the selected value changes." }, { - "name": "target", - "fieldName": "target", + "name": "leOpen", "type": { - "text": "string" - } + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the dropdown opens." }, { - "name": "align", - "fieldName": "align", - "default": "'center'", - "type": { - "text": "'start' | 'center' | 'space-between' | 'end'" - } - } - ], - "tagName": "le-side-panel-toggle", - "events": [ - { - "name": "leSidePanelRequestToggle", + "name": "leClose", "type": { - "text": "EventEmitter" - } + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the dropdown closes." } ], "customElement": true @@ -12080,30 +12016,30 @@ "exports": [ { "kind": "js", - "name": "LeSidePanelToggle", + "name": "LeSelect", "declaration": { - "name": "LeSidePanelToggle", - "module": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx" + "name": "LeSelect", + "module": "src/components/le-select/le-select.tsx" } }, { "kind": "custom-element-definition", - "name": "le-side-panel-toggle", + "name": "le-select", "declaration": { - "name": "LeSidePanelToggle", - "module": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx" + "name": "LeSelect", + "module": "src/components/le-select/le-select.tsx" } } ] }, { "kind": "javascript-module", - "path": "src/components/le-select/le-select.tsx", + "path": "src/components/le-side-panel/le-side-panel.tsx", "declarations": [ { "kind": "class", - "description": "A select dropdown component for single selection.", - "name": "LeSelect", + "description": "", + "name": "LeSidePanel", "members": [ { "kind": "field", @@ -12114,725 +12050,372 @@ }, { "kind": "field", - "name": "options", + "name": "panelId", "type": { - "text": "LeOption[] | string" + "text": "string | undefined" }, - "default": "[]", - "description": "The options to display in the dropdown." + "description": "Optional id used to match toggle requests.\nIf set, the panel only responds to toggle events with the same `panelId`." }, { "kind": "field", - "name": "value", + "name": "side", "type": { - "text": "LeOptionValue | undefined" + "text": "LeSidePanelSide" }, - "description": "The currently selected value." + "default": "'start'", + "description": "Which side the panel is attached to." }, { "kind": "field", - "name": "placeholder", + "name": "collapseAt", "type": { - "text": "string" + "text": "string | undefined" }, - "default": "'Select an option'", - "description": "Placeholder text when no option is selected." + "description": "Width breakpoint (in px or a CSS var like `--le-breakpoint-md`) below which the panel enters \"narrow\" mode." }, { "kind": "field", - "name": "disabled", + "name": "narrowBehavior", "type": { - "text": "boolean" + "text": "LeSidePanelNarrowBehavior" }, - "default": "false", - "description": "Whether the select is disabled." + "default": "'overlay'", + "description": "Behavior when in narrow mode." }, { "kind": "field", - "name": "required", + "name": "sticky", "type": { "text": "boolean" }, "default": "false", - "description": "Whether selection is required." + "description": "Whether the panel is sticky (remains visible when scrolling)." }, { "kind": "field", - "name": "name", + "name": "minPanelHeight", "type": { - "text": "string | undefined" + "text": "number" }, - "description": "Name attribute for form submission." + "default": "200", + "description": "Minimum panel height (px) when sticky full-height logic is active." }, { "kind": "field", - "name": "size", + "name": "top", "type": { - "text": "'small' | 'medium' | 'large'" + "text": "number | 'under-header'" }, - "default": "'medium'", - "description": "Size variant of the select." + "default": "0", + "description": "Top offset for the sticky panel." }, { "kind": "field", - "name": "variant", + "name": "bottom", "type": { - "text": "'default' | 'outlined' | 'solid'" + "text": "number | 'under-footer'" }, - "default": "'default'", - "description": "Visual variant of the select." + "default": "0", + "description": "Bottom offset for sticky full-height calculations." }, { "kind": "field", - "name": "open", + "name": "fullHeight", "type": { "text": "boolean" }, "default": "false", - "description": "Whether the dropdown is currently open." + "description": "Whether the sticky panel should stretch to full height." }, { "kind": "field", - "name": "selectedOption", + "name": "margin", "type": { - "text": "LeOption | undefined" + "text": "string | number | undefined" }, - "privacy": "private" + "description": "Optional panel margin override. Accepts CSS length (e.g. `16px`, `1rem`, `var(--space-4)`)." }, { "kind": "field", - "name": "declarativeOptions", + "name": "open", "type": { - "text": "LeOption[]" + "text": "boolean" }, - "privacy": "private", - "default": "[]" + "default": "false", + "description": "Panel open state for narrow mode.\n- overlay: controls modal drawer visibility\n- push: controls whether panel is shown (non-modal)" }, { "kind": "field", - "name": "isDeclarativeMode", + "name": "collapsed", "type": { "text": "boolean" }, - "privacy": "private", - "default": "false" + "default": "false", + "description": "Panel collapsed state for wide mode (fully hidden)." }, { "kind": "field", - "name": "dropdownEl", + "name": "panelWidth", "type": { - "text": "HTMLLeDropdownBaseElement | undefined" + "text": "number" }, - "privacy": "private" + "default": "280", + "description": "Default panel width in pixels." }, { "kind": "field", - "name": "mutationObserver", + "name": "minPanelWidth", "type": { - "text": "MutationObserver | undefined" + "text": "number" }, - "privacy": "private" + "default": "220", + "description": "Minimum allowed width when resizable." }, { - "kind": "method", - "name": "handleValueChange" + "kind": "field", + "name": "maxPanelWidth", + "type": { + "text": "number" + }, + "default": "420", + "description": "Maximum allowed width when resizable." }, { - "kind": "method", - "name": "handleOptionsChange" + "kind": "field", + "name": "resizable", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Allows users to resize the panel by dragging its edge." }, { - "kind": "method", - "name": "handleSlotChange" + "kind": "field", + "name": "persistKey", + "type": { + "text": "string | undefined" + }, + "description": "When set, panel width + collapsed state are persisted in localStorage." }, { - "kind": "method", - "name": "syncDeclarativeOptionsAndSelection", - "privacy": "private" + "kind": "field", + "name": "showCloseButton", + "type": { + "text": "boolean" + }, + "default": "true", + "description": "Show a close button inside the panel (primarily used in narrow overlay mode)." }, { - "kind": "method", - "name": "buildDeclarativeOptions", - "privacy": "private" + "kind": "field", + "name": "autoShowOnWide", + "type": { + "text": "boolean" + }, + "default": "true", + "description": "When crossing to wide mode, automatically show the panel (collapsed=false)." }, { "kind": "field", - "name": "parsedOptions", + "name": "autoHideOnNarrow", "type": { - "text": "LeOption[]" + "text": "boolean" }, - "privacy": "private", - "readonly": true + "default": "true", + "description": "When crossing to narrow mode, automatically hide the panel (open=false)." }, { - "kind": "method", - "name": "updateSelectedOption", - "privacy": "private" + "kind": "field", + "name": "panelLabel", + "type": { + "text": "string" + }, + "default": "'Navigation'", + "description": "Accessible label for the panel navigation region." }, { "kind": "field", - "name": "handleOptionSelect", - "privacy": "private" + "name": "isNarrow", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "handleDropdownOpen", - "privacy": "private" + "name": "responsiveReady", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "handleDropdownClose", - "privacy": "private" + "name": "overlayMounted", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "handleTriggerClick", - "privacy": "private" + "name": "overlayVisible", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "handleTriggerKeyDown", + "name": "currentWidthPx", + "type": { + "text": "number" + }, "privacy": "private" }, { - "kind": "method", - "name": "showDropdown", - "description": "Opens the dropdown." - }, - { - "kind": "method", - "name": "hideDropdown", - "description": "Closes the dropdown." - }, - { - "kind": "method", - "name": "renderIcon", + "kind": "field", + "name": "resizing", + "type": { + "text": "boolean" + }, "privacy": "private", - "parameters": [ - { - "name": "icon", - "type": { - "text": "string | undefined" - } - } - ] + "default": "false" }, { - "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "options", - "fieldName": "options", - "default": "[]", - "description": "The options to display in the dropdown.", + "kind": "field", + "name": "suppressAnimation", "type": { - "text": "LeOption[] | string" - } + "text": "boolean" + }, + "privacy": "private", + "default": "true" }, { - "name": "value", - "fieldName": "value", - "description": "The currently selected value.", + "kind": "field", + "name": "resizeObserver", "type": { - "text": "LeOptionValue" - } + "text": "ResizeObserver | undefined" + }, + "privacy": "private" }, { - "name": "placeholder", - "fieldName": "placeholder", - "default": "'Select an option'", - "description": "Placeholder text when no option is selected.", + "kind": "field", + "name": "panelEl", "type": { - "text": "string" - } - }, - { - "name": "disabled", - "fieldName": "disabled", - "default": "false", - "description": "Whether the select is disabled.", - "type": { - "text": "boolean" - } - }, - { - "name": "required", - "fieldName": "required", - "default": "false", - "description": "Whether selection is required.", - "type": { - "text": "boolean" - } - }, - { - "name": "name", - "fieldName": "name", - "description": "Name attribute for form submission.", - "type": { - "text": "string" - } - }, - { - "name": "size", - "fieldName": "size", - "default": "'medium'", - "description": "Size variant of the select.", - "type": { - "text": "'small' | 'medium' | 'large'" - } - }, - { - "name": "variant", - "fieldName": "variant", - "default": "'default'", - "description": "Visual variant of the select.", - "type": { - "text": "'default' | 'outlined' | 'solid'" - } - }, - { - "name": "open", - "fieldName": "open", - "default": "false", - "description": "Whether the dropdown is currently open.", - "type": { - "text": "boolean" - } - } - ], - "tagName": "le-select", - "events": [ - { - "name": "leChange", - "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the selected value changes." - }, - { - "name": "leOpen", - "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the dropdown opens." - }, - { - "name": "leClose", - "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the dropdown closes." - } - ], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeSelect", - "declaration": { - "name": "LeSelect", - "module": "src/components/le-select/le-select.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-select", - "declaration": { - "name": "LeSelect", - "module": "src/components/le-select/le-select.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-side-panel/le-side-panel.tsx", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "LeSidePanel", - "members": [ - { - "kind": "field", - "name": "el", - "type": { - "text": "HTMLElement" - } + "text": "HTMLElement | undefined" + }, + "privacy": "private" }, { "kind": "field", - "name": "panelId", + "name": "overlayWrapEl", "type": { - "text": "string | undefined" + "text": "HTMLElement | undefined" }, - "description": "Optional id used to match toggle requests.\nIf set, the panel only responds to toggle events with the same `panelId`." + "privacy": "private" }, { "kind": "field", - "name": "side", + "name": "focusedBeforeOpen", "type": { - "text": "LeSidePanelSide" + "text": "HTMLElement | null | undefined" }, - "default": "'start'", - "description": "Which side the panel is attached to." + "privacy": "private" }, { "kind": "field", - "name": "collapseAt", + "name": "stickyMetricsFrame", "type": { - "text": "string | undefined" + "text": "number | undefined" }, - "description": "Width breakpoint (in px or a CSS var like `--le-breakpoint-md`) below which the panel enters \"narrow\" mode." + "privacy": "private" }, { "kind": "field", - "name": "narrowBehavior", + "name": "dragPointerId", "type": { - "text": "LeSidePanelNarrowBehavior" + "text": "number | undefined" }, - "default": "'overlay'", - "description": "Behavior when in narrow mode." + "privacy": "private" }, { "kind": "field", - "name": "sticky", + "name": "dragStartX", "type": { - "text": "boolean" + "text": "number | undefined" }, - "default": "false", - "description": "Whether the panel is sticky (remains visible when scrolling)." + "privacy": "private" }, { "kind": "field", - "name": "minPanelHeight", + "name": "dragStartWidth", "type": { - "text": "number" + "text": "number | undefined" }, - "default": "200", - "description": "Minimum panel height (px) when sticky full-height logic is active." + "privacy": "private" }, { - "kind": "field", - "name": "top", - "type": { - "text": "number | 'under-header'" - }, - "default": "0", - "description": "Top offset for the sticky panel." + "kind": "method", + "name": "isModalOverlayActive", + "privacy": "private", + "return": { + "type": { + "text": "boolean" + } + } }, { - "kind": "field", - "name": "bottom", - "type": { - "text": "number | 'under-footer'" - }, - "default": "0", - "description": "Bottom offset for sticky full-height calculations." + "kind": "method", + "name": "syncOverlayToState", + "privacy": "private" }, { - "kind": "field", - "name": "fullHeight", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Whether the sticky panel should stretch to full height." + "kind": "method", + "name": "onPanelWidthChanged", + "privacy": "protected" }, { - "kind": "field", - "name": "margin", - "type": { - "text": "string | number | undefined" - }, - "description": "Optional panel margin override. Accepts CSS length (e.g. `16px`, `1rem`, `var(--space-4)`)." + "kind": "method", + "name": "onCollapsedChanged", + "privacy": "protected" }, { - "kind": "field", - "name": "open", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Panel open state for narrow mode.\n- overlay: controls modal drawer visibility\n- push: controls whether panel is shown (non-modal)" + "kind": "method", + "name": "onOpenChanged", + "privacy": "protected", + "parameters": [ + { + "name": "newValue", + "type": { + "text": "boolean" + } + } + ] }, { - "kind": "field", - "name": "collapsed", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Panel collapsed state for wide mode (fully hidden)." + "kind": "method", + "name": "onResponsivePropChanged", + "privacy": "protected" }, { - "kind": "field", - "name": "panelWidth", - "type": { - "text": "number" - }, - "default": "280", - "description": "Default panel width in pixels." + "kind": "method", + "name": "onStickyLayoutPropChanged", + "privacy": "protected" }, { "kind": "field", - "name": "minPanelWidth", - "type": { - "text": "number" - }, - "default": "220", - "description": "Minimum allowed width when resizable." + "name": "onWindowViewportChange", + "privacy": "private" }, { - "kind": "field", - "name": "maxPanelWidth", - "type": { - "text": "number" - }, - "default": "420", - "description": "Maximum allowed width when resizable." - }, - { - "kind": "field", - "name": "resizable", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Allows users to resize the panel by dragging its edge." - }, - { - "kind": "field", - "name": "persistKey", - "type": { - "text": "string | undefined" - }, - "description": "When set, panel width + collapsed state are persisted in localStorage." - }, - { - "kind": "field", - "name": "showCloseButton", - "type": { - "text": "boolean" - }, - "default": "true", - "description": "Show a close button inside the panel (primarily used in narrow overlay mode)." - }, - { - "kind": "field", - "name": "autoShowOnWide", - "type": { - "text": "boolean" - }, - "default": "true", - "description": "When crossing to wide mode, automatically show the panel (collapsed=false)." - }, - { - "kind": "field", - "name": "autoHideOnNarrow", - "type": { - "text": "boolean" - }, - "default": "true", - "description": "When crossing to narrow mode, automatically hide the panel (open=false)." - }, - { - "kind": "field", - "name": "panelLabel", - "type": { - "text": "string" - }, - "default": "'Navigation'", - "description": "Accessible label for the panel navigation region." - }, - { - "kind": "field", - "name": "isNarrow", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" - }, - { - "kind": "field", - "name": "responsiveReady", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" - }, - { - "kind": "field", - "name": "overlayMounted", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" - }, - { - "kind": "field", - "name": "overlayVisible", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" - }, - { - "kind": "field", - "name": "currentWidthPx", - "type": { - "text": "number" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "resizing", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" - }, - { - "kind": "field", - "name": "suppressAnimation", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "true" - }, - { - "kind": "field", - "name": "resizeObserver", - "type": { - "text": "ResizeObserver | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "panelEl", - "type": { - "text": "HTMLElement | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "overlayWrapEl", - "type": { - "text": "HTMLElement | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "focusedBeforeOpen", - "type": { - "text": "HTMLElement | null | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "stickyMetricsFrame", - "type": { - "text": "number | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "dragPointerId", - "type": { - "text": "number | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "dragStartX", - "type": { - "text": "number | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "dragStartWidth", - "type": { - "text": "number | undefined" - }, - "privacy": "private" - }, - { - "kind": "method", - "name": "isModalOverlayActive", - "privacy": "private", - "return": { - "type": { - "text": "boolean" - } - } - }, - { - "kind": "method", - "name": "syncOverlayToState", - "privacy": "private" - }, - { - "kind": "method", - "name": "onPanelWidthChanged", - "privacy": "protected" - }, - { - "kind": "method", - "name": "onCollapsedChanged", - "privacy": "protected" - }, - { - "kind": "method", - "name": "onOpenChanged", - "privacy": "protected", - "parameters": [ - { - "name": "newValue", - "type": { - "text": "boolean" - } - } - ] - }, - { - "kind": "method", - "name": "onResponsivePropChanged", - "privacy": "protected" - }, - { - "kind": "method", - "name": "onStickyLayoutPropChanged", - "privacy": "protected" - }, - { - "kind": "field", - "name": "onWindowViewportChange", - "privacy": "private" - }, - { - "kind": "method", - "name": "clearStickyMetricsFrame", - "privacy": "private" + "kind": "method", + "name": "clearStickyMetricsFrame", + "privacy": "private" }, { "kind": "method", @@ -12917,303 +12500,1101 @@ ] }, { - "kind": "method", - "name": "recomputeNarrow", - "privacy": "private" + "kind": "method", + "name": "recomputeNarrow", + "privacy": "private" + }, + { + "kind": "method", + "name": "restorePersistedState", + "privacy": "private" + }, + { + "kind": "method", + "name": "persistState", + "privacy": "private" + }, + { + "kind": "method", + "name": "focusFirstInsidePanel", + "privacy": "private" + }, + { + "kind": "method", + "name": "getFocusableElements", + "privacy": "private", + "return": { + "type": { + "text": "HTMLElement[]" + } + }, + "parameters": [ + { + "name": "root", + "type": { + "text": "HTMLElement" + } + } + ] + }, + { + "kind": "method", + "name": "restoreFocusAfterClose", + "privacy": "private" + }, + { + "kind": "field", + "name": "onOverlayTransitionEnd", + "privacy": "private" + }, + { + "kind": "field", + "name": "onOverlayPointerDown", + "privacy": "private" + }, + { + "kind": "field", + "name": "startResizeDrag", + "privacy": "private" + }, + { + "kind": "field", + "name": "onResizeDragMove", + "privacy": "private" + }, + { + "kind": "field", + "name": "onResizeDragEnd", + "privacy": "private" + }, + { + "kind": "method", + "name": "teardownDragListeners", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderPanelInner", + "privacy": "private", + "parameters": [ + { + "name": "opts", + "optional": true, + "type": { + "text": "{ renderPanelSlot?: boolean }" + } + } + ] + }, + { + "kind": "method", + "name": "render" + } + ], + "attributes": [ + { + "name": "panel-id", + "fieldName": "panelId", + "description": "Optional id used to match toggle requests.\nIf set, the panel only responds to toggle events with the same `panelId`.", + "type": { + "text": "string" + } + }, + { + "name": "side", + "fieldName": "side", + "default": "'start'", + "description": "Which side the panel is attached to.", + "type": { + "text": "LeSidePanelSide" + } + }, + { + "name": "collapse-at", + "fieldName": "collapseAt", + "description": "Width breakpoint (in px or a CSS var like `--le-breakpoint-md`) below which the panel enters \"narrow\" mode.", + "type": { + "text": "string" + } + }, + { + "name": "narrow-behavior", + "fieldName": "narrowBehavior", + "default": "'overlay'", + "description": "Behavior when in narrow mode.", + "type": { + "text": "LeSidePanelNarrowBehavior" + } + }, + { + "name": "sticky", + "fieldName": "sticky", + "default": "false", + "description": "Whether the panel is sticky (remains visible when scrolling).", + "type": { + "text": "boolean" + } + }, + { + "name": "min-panel-height", + "fieldName": "minPanelHeight", + "default": "200", + "description": "Minimum panel height (px) when sticky full-height logic is active.", + "type": { + "text": "number" + } + }, + { + "name": "top", + "fieldName": "top", + "default": "0", + "description": "Top offset for the sticky panel.", + "type": { + "text": "number | 'under-header'" + } + }, + { + "name": "bottom", + "fieldName": "bottom", + "default": "0", + "description": "Bottom offset for sticky full-height calculations.", + "type": { + "text": "number | 'under-footer'" + } + }, + { + "name": "full-height", + "fieldName": "fullHeight", + "default": "false", + "description": "Whether the sticky panel should stretch to full height.", + "type": { + "text": "boolean" + } + }, + { + "name": "margin", + "fieldName": "margin", + "description": "Optional panel margin override. Accepts CSS length (e.g. `16px`, `1rem`, `var(--space-4)`).", + "type": { + "text": "string | number" + } + }, + { + "name": "open", + "fieldName": "open", + "default": "false", + "description": "Panel open state for narrow mode.\n- overlay: controls modal drawer visibility\n- push: controls whether panel is shown (non-modal)", + "type": { + "text": "boolean" + } + }, + { + "name": "collapsed", + "fieldName": "collapsed", + "default": "false", + "description": "Panel collapsed state for wide mode (fully hidden).", + "type": { + "text": "boolean" + } + }, + { + "name": "panel-width", + "fieldName": "panelWidth", + "default": "280", + "description": "Default panel width in pixels.", + "type": { + "text": "number" + } + }, + { + "name": "min-panel-width", + "fieldName": "minPanelWidth", + "default": "220", + "description": "Minimum allowed width when resizable.", + "type": { + "text": "number" + } + }, + { + "name": "max-panel-width", + "fieldName": "maxPanelWidth", + "default": "420", + "description": "Maximum allowed width when resizable.", + "type": { + "text": "number" + } + }, + { + "name": "resizable", + "fieldName": "resizable", + "default": "false", + "description": "Allows users to resize the panel by dragging its edge.", + "type": { + "text": "boolean" + } + }, + { + "name": "persist-key", + "fieldName": "persistKey", + "description": "When set, panel width + collapsed state are persisted in localStorage.", + "type": { + "text": "string" + } + }, + { + "name": "show-close-button", + "fieldName": "showCloseButton", + "default": "true", + "description": "Show a close button inside the panel (primarily used in narrow overlay mode).", + "type": { + "text": "boolean" + } + }, + { + "name": "auto-show-on-wide", + "fieldName": "autoShowOnWide", + "default": "true", + "description": "When crossing to wide mode, automatically show the panel (collapsed=false).", + "type": { + "text": "boolean" + } + }, + { + "name": "auto-hide-on-narrow", + "fieldName": "autoHideOnNarrow", + "default": "true", + "description": "When crossing to narrow mode, automatically hide the panel (open=false).", + "type": { + "text": "boolean" + } + }, + { + "name": "panel-label", + "fieldName": "panelLabel", + "default": "'Navigation'", + "description": "Accessible label for the panel navigation region.", + "type": { + "text": "string" + } + } + ], + "tagName": "le-side-panel", + "events": [ + { + "name": "leSidePanelOpenChange", + "type": { + "text": "EventEmitter<{ open: boolean; panelId?: string }>" + } + }, + { + "name": "leSidePanelCollapsedChange", + "type": { + "text": "EventEmitter<{ collapsed: boolean; panelId?: string }>" + } + }, + { + "name": "leSidePanelWidthChange", + "type": { + "text": "EventEmitter<{ width: number; panelId?: string }>" + } + } + ], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeSidePanel", + "declaration": { + "name": "LeSidePanel", + "module": "src/components/le-side-panel/le-side-panel.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-side-panel", + "declaration": { + "name": "LeSidePanel", + "module": "src/components/le-side-panel/le-side-panel.tsx" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "LeSidePanelToggle", + "members": [ + { + "kind": "field", + "name": "el", + "type": { + "text": "HTMLElement" + } + }, + { + "kind": "field", + "name": "panelId", + "type": { + "text": "string | undefined" + }, + "description": "Optional id used to target a specific panel." + }, + { + "kind": "field", + "name": "action", + "type": { + "text": "LeSidePanelToggleAction" + }, + "default": "'toggle'", + "description": "Action to emit. Default toggles the panel." + }, + { + "kind": "field", + "name": "shortcut", + "type": { + "text": "string | undefined" + }, + "description": "Optional keyboard shortcut like `Mod+B` or `Alt+N`." + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Disables the toggle." + }, + { + "kind": "field", + "name": "mode", + "type": { + "text": "'default' | 'admin'" + }, + "default": "'default'" + }, + { + "kind": "field", + "name": "variant", + "type": { + "text": "'solid' | 'outlined' | 'clear' | 'system'" + }, + "default": "'solid'" + }, + { + "kind": "field", + "name": "color", + "type": { + "text": "'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'" + }, + "default": "'primary'" + }, + { + "kind": "field", + "name": "size", + "type": { + "text": "'small' | 'medium' | 'large'" + }, + "default": "'medium'" + }, + { + "kind": "field", + "name": "selected", + "type": { + "text": "boolean" + }, + "default": "false" + }, + { + "kind": "field", + "name": "fullWidth", + "type": { + "text": "boolean" + }, + "default": "false" + }, + { + "kind": "field", + "name": "iconOnly", + "type": { + "text": "string | Node | undefined" + } + }, + { + "kind": "field", + "name": "iconStart", + "type": { + "text": "string | Node | undefined" + } + }, + { + "kind": "field", + "name": "iconEnd", + "type": { + "text": "string | Node | undefined" + } + }, + { + "kind": "field", + "name": "type", + "type": { + "text": "'button' | 'submit' | 'reset'" + }, + "default": "'button'" + }, + { + "kind": "field", + "name": "href", + "type": { + "text": "string | undefined" + } + }, + { + "kind": "field", + "name": "target", + "type": { + "text": "string | undefined" + } + }, + { + "kind": "field", + "name": "align", + "type": { + "text": "'start' | 'center' | 'space-between' | 'end'" + }, + "default": "'center'" + }, + { + "kind": "field", + "name": "shortcutSpec", + "type": { + "text": "ShortcutSpec | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "expanded", + "type": { + "text": "boolean | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "buttonEl", + "type": { + "text": "HTMLElement | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "forwardedNodes", + "type": { + "text": "ChildNode[] | undefined" + }, + "privacy": "private" + }, + { + "kind": "method", + "name": "onShortcutChanged", + "privacy": "protected" + }, + { + "kind": "method", + "name": "syncShortcutListener", + "privacy": "private" + }, + { + "kind": "method", + "name": "getResolvedPanelId", + "privacy": "private", + "return": { + "type": { + "text": "string | undefined" + } + } + }, + { + "kind": "method", + "name": "emitRequest", + "privacy": "private" + }, + { + "kind": "field", + "name": "onDocumentKeyDown", + "privacy": "private" + }, + { + "kind": "field", + "name": "onPanelStateChange", + "privacy": "private" + }, + { + "kind": "method", + "name": "syncForwardedNodesIntoButton", + "privacy": "private" + }, + { + "kind": "method", + "name": "syncAriaExpanded", + "privacy": "private" + }, + { + "kind": "method", + "name": "render" + } + ], + "attributes": [ + { + "name": "panel-id", + "fieldName": "panelId", + "description": "Optional id used to target a specific panel.", + "type": { + "text": "string" + } + }, + { + "name": "action", + "fieldName": "action", + "default": "'toggle'", + "description": "Action to emit. Default toggles the panel.", + "type": { + "text": "LeSidePanelToggleAction" + } + }, + { + "name": "shortcut", + "fieldName": "shortcut", + "description": "Optional keyboard shortcut like `Mod+B` or `Alt+N`.", + "type": { + "text": "string" + } + }, + { + "name": "disabled", + "fieldName": "disabled", + "default": "false", + "description": "Disables the toggle.", + "type": { + "text": "boolean" + } + }, + { + "name": "mode", + "fieldName": "mode", + "default": "'default'", + "type": { + "text": "'default' | 'admin'" + } + }, + { + "name": "variant", + "fieldName": "variant", + "default": "'solid'", + "type": { + "text": "'solid' | 'outlined' | 'clear' | 'system'" + } + }, + { + "name": "color", + "fieldName": "color", + "default": "'primary'", + "type": { + "text": "'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'" + } + }, + { + "name": "size", + "fieldName": "size", + "default": "'medium'", + "type": { + "text": "'small' | 'medium' | 'large'" + } + }, + { + "name": "selected", + "fieldName": "selected", + "default": "false", + "type": { + "text": "boolean" + } + }, + { + "name": "full-width", + "fieldName": "fullWidth", + "default": "false", + "type": { + "text": "boolean" + } + }, + { + "name": "icon-only", + "fieldName": "iconOnly", + "type": { + "text": "string | Node" + } + }, + { + "name": "icon-start", + "fieldName": "iconStart", + "type": { + "text": "string | Node" + } + }, + { + "name": "icon-end", + "fieldName": "iconEnd", + "type": { + "text": "string | Node" + } + }, + { + "name": "type", + "fieldName": "type", + "default": "'button'", + "type": { + "text": "'button' | 'submit' | 'reset'" + } + }, + { + "name": "href", + "fieldName": "href", + "type": { + "text": "string" + } + }, + { + "name": "target", + "fieldName": "target", + "type": { + "text": "string" + } + }, + { + "name": "align", + "fieldName": "align", + "default": "'center'", + "type": { + "text": "'start' | 'center' | 'space-between' | 'end'" + } + } + ], + "tagName": "le-side-panel-toggle", + "events": [ + { + "name": "leSidePanelRequestToggle", + "type": { + "text": "EventEmitter" + } + } + ], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeSidePanelToggle", + "declaration": { + "name": "LeSidePanelToggle", + "module": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-side-panel-toggle", + "declaration": { + "name": "LeSidePanelToggle", + "module": "src/components/le-side-panel-toggle/le-side-panel-toggle.tsx" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/components/le-slot/le-slot.tsx", + "declarations": [ + { + "kind": "class", + "description": "Slot placeholder component for admin/CMS mode.\n\nThis component renders a visual placeholder for slots when in admin mode,\nallowing CMS systems to show available drop zones for content or inline editing.\n\nIn non-admin mode, this component renders nothing and acts as a passthrough.", + "name": "LeSlot", + "slots": [ + { + "description": "Default slot for placeholder content or drop zone UI", + "name": "" + } + ], + "members": [ + { + "kind": "field", + "name": "el", + "type": { + "text": "HTMLElement" + } + }, + { + "kind": "field", + "name": "type", + "type": { + "text": "'slot' | 'text' | 'textarea'" + }, + "default": "'slot'", + "description": "The type of slot content.\n- `slot`: Default, shows a dropzone for components (default)\n- `text`: Shows a single-line text input\n- `textarea`: Shows a multi-line text area" }, { - "kind": "method", - "name": "restorePersistedState", - "privacy": "private" + "kind": "field", + "name": "name", + "type": { + "text": "string" + }, + "default": "''", + "description": "The name of the slot this placeholder represents.\nShould match the slot name in the parent component." }, { - "kind": "method", - "name": "persistState", - "privacy": "private" + "kind": "field", + "name": "label", + "type": { + "text": "string | undefined" + }, + "description": "Label to display in admin mode.\nIf not provided, the slot name will be used." }, { - "kind": "method", - "name": "focusFirstInsidePanel", - "privacy": "private" + "kind": "field", + "name": "description", + "type": { + "text": "string | undefined" + }, + "description": "Description of what content this slot accepts.\nShown in admin mode to guide content editors." }, { - "kind": "method", - "name": "getFocusableElements", - "privacy": "private", - "return": { - "type": { - "text": "HTMLElement[]" - } + "kind": "field", + "name": "allowedComponents", + "type": { + "text": "string | undefined" }, - "parameters": [ - { - "name": "root", - "type": { - "text": "HTMLElement" - } - } - ] + "description": "Comma-separated list of allowed component tags for this slot.\nUsed by CMS to filter available components." }, { - "kind": "method", - "name": "restoreFocusAfterClose", - "privacy": "private" + "kind": "field", + "name": "multiple", + "type": { + "text": "boolean" + }, + "default": "true", + "description": "Whether multiple components can be dropped in this slot." }, { "kind": "field", - "name": "onOverlayTransitionEnd", - "privacy": "private" + "name": "required", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether this slot is required to have content." }, { "kind": "field", - "name": "onOverlayPointerDown", - "privacy": "private" + "name": "placeholder", + "type": { + "text": "string | undefined" + }, + "description": "Placeholder text for text/textarea inputs in admin mode." }, { "kind": "field", - "name": "startResizeDrag", - "privacy": "private" + "name": "tag", + "type": { + "text": "string | undefined" + }, + "description": "The HTML tag to create when there's no slotted element.\nUsed with type=\"text\" or type=\"textarea\" to auto-create elements." }, { "kind": "field", - "name": "onResizeDragMove", - "privacy": "private" + "name": "slotStyle", + "type": { + "text": "string | undefined" + }, + "description": "CSS styles for the slot dropzone container.\nUseful for layouts - e.g., \"flex-direction: row\" for horizontal stacks.\nOnly applies in admin mode for type=\"slot\"." }, { "kind": "field", - "name": "onResizeDragEnd", - "privacy": "private" + "name": "adminMode", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false", + "description": "Internal state to track admin mode" }, { - "kind": "method", - "name": "teardownDragListeners", - "privacy": "private" + "kind": "field", + "name": "textValue", + "type": { + "text": "string" + }, + "privacy": "private", + "default": "''", + "description": "Internal state for text input value (synced from slot content)" }, { - "kind": "method", - "name": "renderPanelInner", + "kind": "field", + "name": "isValidHtml", + "type": { + "text": "boolean" + }, "privacy": "private", - "parameters": [ - { - "name": "opts", - "optional": true, - "type": { - "text": "{ renderPanelSlot?: boolean }" - } - } - ] + "default": "true", + "description": "Whether the current textValue contains valid HTML" }, { - "kind": "method", - "name": "render" - } - ], - "attributes": [ + "kind": "field", + "name": "availableComponents", + "type": { + "text": "ComponentInfo[]" + }, + "privacy": "private", + "default": "[]", + "description": "Available components loaded from Custom Elements Manifest" + }, { - "name": "panel-id", - "fieldName": "panelId", - "description": "Optional id used to match toggle requests.\nIf set, the panel only responds to toggle events with the same `panelId`.", + "kind": "field", + "name": "pickerOpen", "type": { - "text": "string" - } + "text": "boolean" + }, + "privacy": "private", + "default": "false", + "description": "Whether the component picker popover is open" }, { - "name": "side", - "fieldName": "side", - "default": "'start'", - "description": "Which side the panel is attached to.", + "kind": "field", + "name": "slotRef", "type": { - "text": "LeSidePanelSide" - } + "text": "HTMLSlotElement | undefined" + }, + "privacy": "private", + "description": "Reference to the slot element to access assignedNodes" }, { - "name": "collapse-at", - "fieldName": "collapseAt", - "description": "Width breakpoint (in px or a CSS var like `--le-breakpoint-md`) below which the panel enters \"narrow\" mode.", + "kind": "field", + "name": "slottedElement", "type": { - "text": "string" - } + "text": "Element | undefined" + }, + "privacy": "private", + "description": "The original slotted element (e.g.,

)" }, { - "name": "narrow-behavior", - "fieldName": "narrowBehavior", - "default": "'overlay'", - "description": "Behavior when in narrow mode.", + "kind": "field", + "name": "disconnectModeObserver", "type": { - "text": "LeSidePanelNarrowBehavior" - } + "text": "() => void | undefined" + }, + "privacy": "private" }, { - "name": "sticky", - "fieldName": "sticky", - "default": "false", - "description": "Whether the panel is sticky (remains visible when scrolling).", + "kind": "field", + "name": "isUpdating", "type": { "text": "boolean" - } + }, + "privacy": "private", + "default": "false", + "description": "Flag to prevent re-reading content right after we updated it" }, { - "name": "min-panel-height", - "fieldName": "minPanelHeight", - "default": "200", - "description": "Minimum panel height (px) when sticky full-height logic is active.", - "type": { - "text": "number" - } + "kind": "method", + "name": "readSlottedContent", + "privacy": "private", + "description": "Read content from slotted elements via assignedNodes()" }, { - "name": "top", - "fieldName": "top", - "default": "0", - "description": "Top offset for the sticky panel.", - "type": { - "text": "number | 'under-header'" - } + "kind": "method", + "name": "validateHtml", + "privacy": "private", + "return": { + "type": { + "text": "boolean" + } + }, + "parameters": [ + { + "name": "html", + "type": { + "text": "string" + } + } + ], + "description": "Validates if a string contains valid HTML" }, { - "name": "bottom", - "fieldName": "bottom", - "default": "0", - "description": "Bottom offset for sticky full-height calculations.", - "type": { - "text": "number | 'under-footer'" - } + "kind": "field", + "name": "handleTextInput", + "privacy": "private" + }, + { + "kind": "method", + "name": "createSlottedElement", + "privacy": "private", + "description": "Create a new slotted element when none exists.\nThe element is appended to the host component's light DOM." }, { - "name": "full-height", - "fieldName": "fullHeight", - "default": "false", - "description": "Whether the sticky panel should stretch to full height.", - "type": { - "text": "boolean" - } + "kind": "method", + "name": "loadAvailableComponents", + "privacy": "private", + "description": "Load available components from Custom Elements Manifest" }, { - "name": "margin", - "fieldName": "margin", - "description": "Optional panel margin override. Accepts CSS length (e.g. `16px`, `1rem`, `var(--space-4)`).", - "type": { - "text": "string | number" - } + "kind": "method", + "name": "formatComponentName", + "privacy": "private", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "tagName", + "type": { + "text": "string" + } + } + ], + "description": "Format a tag name into a display name\ne.g., 'le-card' -> 'Card'" }, { - "name": "open", - "fieldName": "open", - "default": "false", - "description": "Panel open state for narrow mode.\n- overlay: controls modal drawer visibility\n- push: controls whether panel is shown (non-modal)", - "type": { - "text": "boolean" - } + "kind": "method", + "name": "addComponent", + "privacy": "private", + "parameters": [ + { + "name": "tagName", + "type": { + "text": "string" + } + } + ], + "description": "Add a new component to the slot" }, { - "name": "collapsed", - "fieldName": "collapsed", - "default": "false", - "description": "Panel collapsed state for wide mode (fully hidden).", - "type": { - "text": "boolean" - } + "kind": "field", + "name": "handleSlotChange", + "privacy": "private", + "description": "Handle slot change event to re-read content when nodes are assigned" }, { - "name": "panel-width", - "fieldName": "panelWidth", - "default": "280", - "description": "Default panel width in pixels.", - "type": { - "text": "number" - } + "kind": "method", + "name": "render" }, { - "name": "min-panel-width", - "fieldName": "minPanelWidth", - "default": "220", - "description": "Minimum allowed width when resizable.", + "kind": "method", + "name": "renderContent", + "privacy": "private" + } + ], + "attributes": [ + { + "name": "type", + "fieldName": "type", + "default": "'slot'", + "description": "The type of slot content.\n- `slot`: Default, shows a dropzone for components (default)\n- `text`: Shows a single-line text input\n- `textarea`: Shows a multi-line text area", "type": { - "text": "number" + "text": "'slot' | 'text' | 'textarea'" } }, { - "name": "max-panel-width", - "fieldName": "maxPanelWidth", - "default": "420", - "description": "Maximum allowed width when resizable.", + "name": "name", + "fieldName": "name", + "default": "''", + "description": "The name of the slot this placeholder represents.\nShould match the slot name in the parent component.", "type": { - "text": "number" + "text": "string" } }, { - "name": "resizable", - "fieldName": "resizable", - "default": "false", - "description": "Allows users to resize the panel by dragging its edge.", + "name": "label", + "fieldName": "label", + "description": "Label to display in admin mode.\nIf not provided, the slot name will be used.", "type": { - "text": "boolean" + "text": "string" } }, { - "name": "persist-key", - "fieldName": "persistKey", - "description": "When set, panel width + collapsed state are persisted in localStorage.", + "name": "description", + "fieldName": "description", + "description": "Description of what content this slot accepts.\nShown in admin mode to guide content editors.", "type": { "text": "string" } }, { - "name": "show-close-button", - "fieldName": "showCloseButton", - "default": "true", - "description": "Show a close button inside the panel (primarily used in narrow overlay mode).", + "name": "allowed-components", + "fieldName": "allowedComponents", + "description": "Comma-separated list of allowed component tags for this slot.\nUsed by CMS to filter available components.", "type": { - "text": "boolean" + "text": "string" } }, { - "name": "auto-show-on-wide", - "fieldName": "autoShowOnWide", + "name": "multiple", + "fieldName": "multiple", "default": "true", - "description": "When crossing to wide mode, automatically show the panel (collapsed=false).", + "description": "Whether multiple components can be dropped in this slot.", "type": { "text": "boolean" } }, { - "name": "auto-hide-on-narrow", - "fieldName": "autoHideOnNarrow", - "default": "true", - "description": "When crossing to narrow mode, automatically hide the panel (open=false).", + "name": "required", + "fieldName": "required", + "default": "false", + "description": "Whether this slot is required to have content.", "type": { "text": "boolean" } }, { - "name": "panel-label", - "fieldName": "panelLabel", - "default": "'Navigation'", - "description": "Accessible label for the panel navigation region.", + "name": "placeholder", + "fieldName": "placeholder", + "description": "Placeholder text for text/textarea inputs in admin mode.", "type": { "text": "string" } - } - ], - "tagName": "le-side-panel", - "events": [ + }, { - "name": "leSidePanelOpenChange", + "name": "tag", + "fieldName": "tag", + "description": "The HTML tag to create when there's no slotted element.\nUsed with type=\"text\" or type=\"textarea\" to auto-create elements.", "type": { - "text": "EventEmitter<{ open: boolean; panelId?: string }>" + "text": "string" } }, { - "name": "leSidePanelCollapsedChange", + "name": "slot-style", + "fieldName": "slotStyle", + "description": "CSS styles for the slot dropzone container.\nUseful for layouts - e.g., \"flex-direction: row\" for horizontal stacks.\nOnly applies in admin mode for type=\"slot\".", "type": { - "text": "EventEmitter<{ collapsed: boolean; panelId?: string }>" + "text": "string" } - }, + } + ], + "tagName": "le-slot", + "events": [ { - "name": "leSidePanelWidthChange", + "name": "leSlotChange", "type": { - "text": "EventEmitter<{ width: number; panelId?: string }>" - } + "text": "EventEmitter<{ name: string; value: string; isValid: boolean }>" + }, + "description": "Emitted when text content changes in admin mode.\nThe event detail contains the new text value and validity." } ], "customElement": true @@ -13222,447 +13603,375 @@ "exports": [ { "kind": "js", - "name": "LeSidePanel", + "name": "LeSlot", "declaration": { - "name": "LeSidePanel", - "module": "src/components/le-side-panel/le-side-panel.tsx" + "name": "LeSlot", + "module": "src/components/le-slot/le-slot.tsx" } }, { "kind": "custom-element-definition", - "name": "le-side-panel", + "name": "le-slot", "declaration": { - "name": "LeSidePanel", - "module": "src/components/le-side-panel/le-side-panel.tsx" + "name": "LeSlot", + "module": "src/components/le-slot/le-slot.tsx" } } ] }, { "kind": "javascript-module", - "path": "src/components/le-slot/le-slot.tsx", + "path": "src/components/le-stack/le-stack.tsx", "declarations": [ { "kind": "class", - "description": "Slot placeholder component for admin/CMS mode.\n\nThis component renders a visual placeholder for slots when in admin mode,\nallowing CMS systems to show available drop zones for content or inline editing.\n\nIn non-admin mode, this component renders nothing and acts as a passthrough.", - "name": "LeSlot", - "slots": [ + "description": "A flexible stack layout component using CSS flexbox.\n\n`le-stack` arranges its children in a row (horizontal) or column (vertical)\nwith configurable spacing, alignment, and wrapping behavior. Perfect for\ncreating responsive layouts.", + "name": "LeStack", + "cssProperties": [ { - "description": "Default slot for placeholder content or drop zone UI", - "name": "" + "description": "Gap between items (defaults to var(--le-space-md))", + "name": "--le-stack-gap" } ], - "members": [ - { - "kind": "field", - "name": "el", - "type": { - "text": "HTMLElement" - } - }, - { - "kind": "field", - "name": "type", - "type": { - "text": "'slot' | 'text' | 'textarea'" - }, - "default": "'slot'", - "description": "The type of slot content.\n- `slot`: Default, shows a dropzone for components (default)\n- `text`: Shows a single-line text input\n- `textarea`: Shows a multi-line text area" - }, - { - "kind": "field", - "name": "name", - "type": { - "text": "string" - }, - "default": "''", - "description": "The name of the slot this placeholder represents.\nShould match the slot name in the parent component." - }, - { - "kind": "field", - "name": "label", - "type": { - "text": "string | undefined" - }, - "description": "Label to display in admin mode.\nIf not provided, the slot name will be used." - }, - { - "kind": "field", - "name": "description", - "type": { - "text": "string | undefined" - }, - "description": "Description of what content this slot accepts.\nShown in admin mode to guide content editors." - }, + "cssParts": [ { - "kind": "field", - "name": "allowedComponents", - "type": { - "text": "string | undefined" - }, - "description": "Comma-separated list of allowed component tags for this slot.\nUsed by CMS to filter available components." - }, + "description": "The main stack container", + "name": "stack" + } + ], + "slots": [ + { + "description": "Default slot for stack items (le-box components recommended)", + "name": "" + } + ], + "members": [ { "kind": "field", - "name": "multiple", + "name": "el", "type": { - "text": "boolean" - }, - "default": "true", - "description": "Whether multiple components can be dropped in this slot." + "text": "HTMLElement" + } }, { "kind": "field", - "name": "required", + "name": "direction", "type": { - "text": "boolean" + "text": "'horizontal' | 'vertical'" }, - "default": "false", - "description": "Whether this slot is required to have content." + "default": "'horizontal'", + "description": "Direction of the stack layout" }, { "kind": "field", - "name": "placeholder", + "name": "gap", "type": { "text": "string | undefined" }, - "description": "Placeholder text for text/textarea inputs in admin mode." + "description": "Gap between items (CSS value like '8px', '1rem', 'var(--le-space-md)')" }, { "kind": "field", - "name": "tag", + "name": "align", "type": { - "text": "string | undefined" + "text": "'start' | 'center' | 'end' | 'stretch' | 'baseline'" }, - "description": "The HTML tag to create when there's no slotted element.\nUsed with type=\"text\" or type=\"textarea\" to auto-create elements." + "default": "'stretch'", + "description": "Alignment of items on the cross axis" }, { "kind": "field", - "name": "slotStyle", + "name": "justify", "type": { - "text": "string | undefined" + "text": "'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly'" }, - "description": "CSS styles for the slot dropzone container.\nUseful for layouts - e.g., \"flex-direction: row\" for horizontal stacks.\nOnly applies in admin mode for type=\"slot\"." + "default": "'start'", + "description": "Distribution of items on the main axis" }, { "kind": "field", - "name": "adminMode", + "name": "wrap", "type": { "text": "boolean" }, - "privacy": "private", "default": "false", - "description": "Internal state to track admin mode" + "description": "Whether items should wrap to multiple lines" }, { "kind": "field", - "name": "textValue", + "name": "alignContent", "type": { - "text": "string" + "text": "'start' | 'center' | 'end' | 'stretch' | 'space-between' | 'space-around'" }, - "privacy": "private", - "default": "''", - "description": "Internal state for text input value (synced from slot content)" + "default": "'stretch'", + "description": "Alignment of wrapped lines (only applies when wrap is true)" }, { "kind": "field", - "name": "isValidHtml", + "name": "reverse", "type": { "text": "boolean" }, - "privacy": "private", - "default": "true", - "description": "Whether the current textValue contains valid HTML" + "default": "false", + "description": "Whether to reverse the order of items" }, { "kind": "field", - "name": "availableComponents", + "name": "maxItems", "type": { - "text": "ComponentInfo[]" + "text": "number | undefined" }, - "privacy": "private", - "default": "[]", - "description": "Available components loaded from Custom Elements Manifest" + "description": "Maximum number of items allowed in the stack (for CMS validation)" }, { "kind": "field", - "name": "pickerOpen", + "name": "fullWidth", "type": { "text": "boolean" }, - "privacy": "private", "default": "false", - "description": "Whether the component picker popover is open" - }, - { - "kind": "field", - "name": "slotRef", - "type": { - "text": "HTMLSlotElement | undefined" - }, - "privacy": "private", - "description": "Reference to the slot element to access assignedNodes" - }, - { - "kind": "field", - "name": "slottedElement", - "type": { - "text": "Element | undefined" - }, - "privacy": "private", - "description": "The original slotted element (e.g.,

)" + "description": "Whether the stack should take full width of its container" }, { "kind": "field", - "name": "disconnectModeObserver", + "name": "fullHeight", "type": { - "text": "() => void | undefined" + "text": "boolean" }, - "privacy": "private" + "default": "false", + "description": "Whether the stack should take full height of its container" }, { "kind": "field", - "name": "isUpdating", + "name": "padding", "type": { - "text": "boolean" + "text": "string | undefined" }, - "privacy": "private", - "default": "false", - "description": "Flag to prevent re-reading content right after we updated it" - }, - { - "kind": "method", - "name": "readSlottedContent", - "privacy": "private", - "description": "Read content from slotted elements via assignedNodes()" + "description": "Padding inside the stack container (CSS value)" }, { "kind": "method", - "name": "validateHtml", + "name": "getFlexDirection", "privacy": "private", "return": { "type": { - "text": "boolean" - } - }, - "parameters": [ - { - "name": "html", - "type": { - "text": "string" - } + "text": "string" } - ], - "description": "Validates if a string contains valid HTML" - }, - { - "kind": "field", - "name": "handleTextInput", - "privacy": "private" - }, - { - "kind": "method", - "name": "createSlottedElement", - "privacy": "private", - "description": "Create a new slotted element when none exists.\nThe element is appended to the host component's light DOM." + } }, { "kind": "method", - "name": "loadAvailableComponents", + "name": "getAlignItems", "privacy": "private", - "description": "Load available components from Custom Elements Manifest" + "return": { + "type": { + "text": "string" + } + } }, { "kind": "method", - "name": "formatComponentName", + "name": "getJustifyContent", "privacy": "private", "return": { "type": { "text": "string" } - }, - "parameters": [ - { - "name": "tagName", - "type": { - "text": "string" - } - } - ], - "description": "Format a tag name into a display name\ne.g., 'le-card' -> 'Card'" + } }, { "kind": "method", - "name": "addComponent", + "name": "getAlignContent", "privacy": "private", - "parameters": [ - { - "name": "tagName", - "type": { - "text": "string" - } + "return": { + "type": { + "text": "string" } - ], - "description": "Add a new component to the slot" - }, - { - "kind": "field", - "name": "handleSlotChange", - "privacy": "private", - "description": "Handle slot change event to re-read content when nodes are assigned" + } }, { "kind": "method", "name": "render" - }, - { - "kind": "method", - "name": "renderContent", - "privacy": "private" } ], "attributes": [ { - "name": "type", - "fieldName": "type", - "default": "'slot'", - "description": "The type of slot content.\n- `slot`: Default, shows a dropzone for components (default)\n- `text`: Shows a single-line text input\n- `textarea`: Shows a multi-line text area", + "name": "direction", + "fieldName": "direction", + "default": "'horizontal'", + "description": "Direction of the stack layout", "type": { - "text": "'slot' | 'text' | 'textarea'" + "text": "'horizontal' | 'vertical'" } }, { - "name": "name", - "fieldName": "name", - "default": "''", - "description": "The name of the slot this placeholder represents.\nShould match the slot name in the parent component.", + "name": "gap", + "fieldName": "gap", + "description": "Gap between items (CSS value like '8px', '1rem', 'var(--le-space-md)')", "type": { "text": "string" } }, { - "name": "label", - "fieldName": "label", - "description": "Label to display in admin mode.\nIf not provided, the slot name will be used.", + "name": "align", + "fieldName": "align", + "default": "'stretch'", + "description": "Alignment of items on the cross axis", "type": { - "text": "string" + "text": "'start' | 'center' | 'end' | 'stretch' | 'baseline'" } }, { - "name": "description", - "fieldName": "description", - "description": "Description of what content this slot accepts.\nShown in admin mode to guide content editors.", + "name": "justify", + "fieldName": "justify", + "default": "'start'", + "description": "Distribution of items on the main axis", "type": { - "text": "string" + "text": "'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly'" } }, { - "name": "allowed-components", - "fieldName": "allowedComponents", - "description": "Comma-separated list of allowed component tags for this slot.\nUsed by CMS to filter available components.", + "name": "wrap", + "fieldName": "wrap", + "default": "false", + "description": "Whether items should wrap to multiple lines", "type": { - "text": "string" + "text": "boolean" } }, { - "name": "multiple", - "fieldName": "multiple", - "default": "true", - "description": "Whether multiple components can be dropped in this slot.", + "name": "align-content", + "fieldName": "alignContent", + "default": "'stretch'", + "description": "Alignment of wrapped lines (only applies when wrap is true)", "type": { - "text": "boolean" + "text": "'start' | 'center' | 'end' | 'stretch' | 'space-between' | 'space-around'" } }, { - "name": "required", - "fieldName": "required", + "name": "reverse", + "fieldName": "reverse", "default": "false", - "description": "Whether this slot is required to have content.", + "description": "Whether to reverse the order of items", "type": { "text": "boolean" } }, { - "name": "placeholder", - "fieldName": "placeholder", - "description": "Placeholder text for text/textarea inputs in admin mode.", + "name": "max-items", + "fieldName": "maxItems", + "description": "Maximum number of items allowed in the stack (for CMS validation)", + "type": { + "text": "number" + } + }, + { + "name": "full-width", + "fieldName": "fullWidth", + "default": "false", + "description": "Whether the stack should take full width of its container", "type": { - "text": "string" + "text": "boolean" } }, { - "name": "tag", - "fieldName": "tag", - "description": "The HTML tag to create when there's no slotted element.\nUsed with type=\"text\" or type=\"textarea\" to auto-create elements.", + "name": "full-height", + "fieldName": "fullHeight", + "default": "false", + "description": "Whether the stack should take full height of its container", "type": { - "text": "string" + "text": "boolean" } }, { - "name": "slot-style", - "fieldName": "slotStyle", - "description": "CSS styles for the slot dropzone container.\nUseful for layouts - e.g., \"flex-direction: row\" for horizontal stacks.\nOnly applies in admin mode for type=\"slot\".", + "name": "padding", + "fieldName": "padding", + "description": "Padding inside the stack container (CSS value)", "type": { "text": "string" } } ], - "tagName": "le-slot", - "events": [ - { - "name": "leSlotChange", - "type": { - "text": "EventEmitter<{ name: string; value: string; isValid: boolean }>" - }, - "description": "Emitted when text content changes in admin mode.\nThe event detail contains the new text value and validity." - } - ], + "tagName": "le-stack", + "events": [], "customElement": true } ], "exports": [ { "kind": "js", - "name": "LeSlot", + "name": "LeStack", "declaration": { - "name": "LeSlot", - "module": "src/components/le-slot/le-slot.tsx" + "name": "LeStack", + "module": "src/components/le-stack/le-stack.tsx" } }, { "kind": "custom-element-definition", - "name": "le-slot", + "name": "le-stack", "declaration": { - "name": "LeSlot", - "module": "src/components/le-slot/le-slot.tsx" + "name": "LeStack", + "module": "src/components/le-stack/le-stack.tsx" } } ] }, { "kind": "javascript-module", - "path": "src/components/le-stack/le-stack.tsx", + "path": "src/components/le-tab/le-tab.tsx", "declarations": [ { "kind": "class", - "description": "A flexible stack layout component using CSS flexbox.\n\n`le-stack` arranges its children in a row (horizontal) or column (vertical)\nwith configurable spacing, alignment, and wrapping behavior. Perfect for\ncreating responsive layouts.", - "name": "LeStack", + "description": "A flexible tab component with multiple variants and states.", + "name": "LeTab", "cssProperties": [ { - "description": "Gap between items (defaults to var(--le-space-md))", - "name": "--le-stack-gap" + "description": "Tab background color", + "name": "--le-tab-bg" + }, + { + "description": "Tab text color", + "name": "--le-tab-color" + }, + { + "description": "Tab border radius", + "name": "--le-tab-border-radius" + }, + { + "description": "Tab horizontal padding", + "name": "--le-tab-padding-x" + }, + { + "description": "Tab vertical padding", + "name": "--le-tab-padding-y" } ], "cssParts": [ { - "description": "The main stack container", - "name": "stack" + "description": "The native button element", + "name": "button" + }, + { + "description": "The tab content wrapper", + "name": "content" + }, + { + "description": "The start icon slot", + "name": "icon-start" + }, + { + "description": "The end icon slot", + "name": "icon-end" } ], "slots": [ { - "description": "Default slot for stack items (le-box components recommended)", + "description": "Tab text content", "name": "" + }, + { + "description": "Icon for icon-only tabs", + "name": "icon-only" } ], "members": [ @@ -13675,263 +13984,346 @@ }, { "kind": "field", - "name": "direction", + "name": "mode", "type": { - "text": "'horizontal' | 'vertical'" + "text": "'default' | 'admin'" }, - "default": "'horizontal'", - "description": "Direction of the stack layout" + "default": "'default'", + "description": "Mode of the popover should be 'default' for internal use" }, { "kind": "field", - "name": "gap", + "name": "label", "type": { "text": "string | undefined" }, - "description": "Gap between items (CSS value like '8px', '1rem', 'var(--le-space-md)')" + "description": "Label if it is not provided via slot" }, { "kind": "field", - "name": "align", + "name": "value", "type": { - "text": "'start' | 'center' | 'end' | 'stretch' | 'baseline'" + "text": "string | undefined" }, - "default": "'stretch'", - "description": "Alignment of items on the cross axis" + "description": "Value of the tab, defaults to label if not provided" }, { "kind": "field", - "name": "justify", + "name": "variant", "type": { - "text": "'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly'" + "text": "'underlined' | 'solid' | 'pills' | 'enclosed' | 'icon-only'" }, - "default": "'start'", - "description": "Distribution of items on the main axis" + "default": "'underlined'", + "description": "Tab variant style" }, { "kind": "field", - "name": "wrap", + "name": "position", + "type": { + "text": "'top' | 'bottom' | 'start' | 'end'" + }, + "default": "'top'", + "description": "Position of the tabs when used within a le-tabs component" + }, + { + "kind": "field", + "name": "size", + "type": { + "text": "'small' | 'medium' | 'large'" + }, + "default": "'medium'", + "description": "Tab size" + }, + { + "kind": "field", + "name": "focusable", "type": { "text": "boolean" }, - "default": "false", - "description": "Whether items should wrap to multiple lines" + "default": "true", + "description": "Whether the tab can get focus\nneeded for accessibility when used in custom tab implementations" }, { "kind": "field", - "name": "alignContent", + "name": "selected", "type": { - "text": "'start' | 'center' | 'end' | 'stretch' | 'space-between' | 'space-around'" + "text": "boolean" }, - "default": "'stretch'", - "description": "Alignment of wrapped lines (only applies when wrap is true)" + "default": "false", + "description": "Whether the tab is in a selected/active state" }, { "kind": "field", - "name": "reverse", + "name": "fullWidth", "type": { "text": "boolean" }, "default": "false", - "description": "Whether to reverse the order of items" + "description": "Whether the tab takes full width of its container" }, { "kind": "field", - "name": "maxItems", + "name": "icon", "type": { - "text": "number | undefined" + "text": "string | Node | undefined" }, - "description": "Maximum number of items allowed in the stack (for CMS validation)" + "description": "Icon only tab image or emoji\nif this prop is set, the tab will render only the icon slot" }, { "kind": "field", - "name": "fullWidth", + "name": "showLabel", "type": { "text": "boolean" }, "default": "false", - "description": "Whether the stack should take full width of its container" + "description": "Whether to show the label when in icon-only mode" }, { "kind": "field", - "name": "fullHeight", + "name": "iconStart", + "type": { + "text": "string | Node | undefined" + }, + "description": "Start icon image or emoji" + }, + { + "kind": "field", + "name": "iconEnd", + "type": { + "text": "string | Node | undefined" + }, + "description": "End icon image or emoji" + }, + { + "kind": "field", + "name": "disabled", "type": { "text": "boolean" }, "default": "false", - "description": "Whether the stack should take full height of its container" + "description": "Whether the tab is disabled" }, { "kind": "field", - "name": "padding", + "name": "href", "type": { "text": "string | undefined" }, - "description": "Padding inside the stack container (CSS value)" + "description": "Optional href to make the tab act as a link" + }, + { + "kind": "field", + "name": "target", + "type": { + "text": "string | undefined" + }, + "description": "Link target when href is set" + }, + { + "kind": "field", + "name": "align", + "type": { + "text": "'start' | 'center' | 'space-between' | 'end'" + }, + "default": "'center'", + "description": "Alignment of the tab label without the end icon" }, { "kind": "method", - "name": "getFlexDirection", - "privacy": "private", + "name": "getTabConfig", "return": { "type": { - "text": "string" + "text": "Promise<{\n label?: string;\n value?: string;\n icon?: string | Node;\n iconStart?: string | Node;\n iconEnd?: string | Node;\n disabled: boolean;\n }>" } - } + }, + "description": "Get tab configuration for parent component" + }, + { + "kind": "field", + "name": "handleClick", + "privacy": "private" }, { "kind": "method", - "name": "getAlignItems", - "privacy": "private", - "return": { - "type": { - "text": "string" - } + "name": "render" + } + ], + "attributes": [ + { + "name": "mode", + "fieldName": "mode", + "default": "'default'", + "description": "Mode of the popover should be 'default' for internal use", + "type": { + "text": "'default' | 'admin'" } }, { - "kind": "method", - "name": "getJustifyContent", - "privacy": "private", - "return": { - "type": { - "text": "string" - } + "name": "label", + "fieldName": "label", + "description": "Label if it is not provided via slot", + "type": { + "text": "string" + } + }, + { + "name": "value", + "fieldName": "value", + "description": "Value of the tab, defaults to label if not provided", + "type": { + "text": "string" } }, { - "kind": "method", - "name": "getAlignContent", - "privacy": "private", - "return": { - "type": { - "text": "string" - } + "name": "variant", + "fieldName": "variant", + "default": "'underlined'", + "description": "Tab variant style", + "type": { + "text": "'underlined' | 'solid' | 'pills' | 'enclosed' | 'icon-only'" } }, { - "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "direction", - "fieldName": "direction", - "default": "'horizontal'", - "description": "Direction of the stack layout", + "name": "position", + "fieldName": "position", + "default": "'top'", + "description": "Position of the tabs when used within a le-tabs component", "type": { - "text": "'horizontal' | 'vertical'" + "text": "'top' | 'bottom' | 'start' | 'end'" } }, { - "name": "gap", - "fieldName": "gap", - "description": "Gap between items (CSS value like '8px', '1rem', 'var(--le-space-md)')", + "name": "size", + "fieldName": "size", + "default": "'medium'", + "description": "Tab size", "type": { - "text": "string" + "text": "'small' | 'medium' | 'large'" } }, { - "name": "align", - "fieldName": "align", - "default": "'stretch'", - "description": "Alignment of items on the cross axis", + "name": "focusable", + "fieldName": "focusable", + "default": "true", + "description": "Whether the tab can get focus\nneeded for accessibility when used in custom tab implementations", "type": { - "text": "'start' | 'center' | 'end' | 'stretch' | 'baseline'" + "text": "boolean" } }, { - "name": "justify", - "fieldName": "justify", - "default": "'start'", - "description": "Distribution of items on the main axis", + "name": "selected", + "fieldName": "selected", + "default": "false", + "description": "Whether the tab is in a selected/active state", "type": { - "text": "'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly'" + "text": "boolean" } }, { - "name": "wrap", - "fieldName": "wrap", + "name": "full-width", + "fieldName": "fullWidth", "default": "false", - "description": "Whether items should wrap to multiple lines", + "description": "Whether the tab takes full width of its container", "type": { "text": "boolean" } }, { - "name": "align-content", - "fieldName": "alignContent", - "default": "'stretch'", - "description": "Alignment of wrapped lines (only applies when wrap is true)", + "name": "icon", + "fieldName": "icon", + "description": "Icon only tab image or emoji\nif this prop is set, the tab will render only the icon slot", "type": { - "text": "'start' | 'center' | 'end' | 'stretch' | 'space-between' | 'space-around'" + "text": "string | Node" } }, { - "name": "reverse", - "fieldName": "reverse", + "name": "show-label", + "fieldName": "showLabel", "default": "false", - "description": "Whether to reverse the order of items", + "description": "Whether to show the label when in icon-only mode", "type": { "text": "boolean" } }, { - "name": "max-items", - "fieldName": "maxItems", - "description": "Maximum number of items allowed in the stack (for CMS validation)", + "name": "icon-start", + "fieldName": "iconStart", + "description": "Start icon image or emoji", "type": { - "text": "number" + "text": "string | Node" } }, { - "name": "full-width", - "fieldName": "fullWidth", - "default": "false", - "description": "Whether the stack should take full width of its container", + "name": "icon-end", + "fieldName": "iconEnd", + "description": "End icon image or emoji", "type": { - "text": "boolean" + "text": "string | Node" } }, { - "name": "full-height", - "fieldName": "fullHeight", + "name": "disabled", + "fieldName": "disabled", "default": "false", - "description": "Whether the stack should take full height of its container", + "description": "Whether the tab is disabled", "type": { "text": "boolean" } }, { - "name": "padding", - "fieldName": "padding", - "description": "Padding inside the stack container (CSS value)", + "name": "href", + "fieldName": "href", + "description": "Optional href to make the tab act as a link", + "type": { + "text": "string" + } + }, + { + "name": "target", + "fieldName": "target", + "description": "Link target when href is set", "type": { "text": "string" } + }, + { + "name": "align", + "fieldName": "align", + "default": "'center'", + "description": "Alignment of the tab label without the end icon", + "type": { + "text": "'start' | 'center' | 'space-between' | 'end'" + } + } + ], + "tagName": "le-tab", + "events": [ + { + "name": "click", + "type": { + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the tab is clicked.\nThis is a custom event that wraps the native click but ensures the target is the le-tab." } ], - "tagName": "le-stack", - "events": [], "customElement": true } ], "exports": [ { "kind": "js", - "name": "LeStack", + "name": "LeTab", "declaration": { - "name": "LeStack", - "module": "src/components/le-stack/le-stack.tsx" + "name": "LeTab", + "module": "src/components/le-tab/le-tab.tsx" } }, { "kind": "custom-element-definition", - "name": "le-stack", + "name": "le-tab", "declaration": { - "name": "LeStack", - "module": "src/components/le-stack/le-stack.tsx" + "name": "LeTab", + "module": "src/components/le-tab/le-tab.tsx" } } ] @@ -14744,60 +15136,16 @@ }, { "kind": "javascript-module", - "path": "src/components/le-tab/le-tab.tsx", + "path": "src/components/le-tab-panel/le-tab-panel.tsx", "declarations": [ { "kind": "class", - "description": "A flexible tab component with multiple variants and states.", - "name": "LeTab", - "cssProperties": [ - { - "description": "Tab background color", - "name": "--le-tab-bg" - }, - { - "description": "Tab text color", - "name": "--le-tab-color" - }, - { - "description": "Tab border radius", - "name": "--le-tab-border-radius" - }, - { - "description": "Tab horizontal padding", - "name": "--le-tab-padding-x" - }, - { - "description": "Tab vertical padding", - "name": "--le-tab-padding-y" - } - ], - "cssParts": [ - { - "description": "The native button element", - "name": "button" - }, - { - "description": "The tab content wrapper", - "name": "content" - }, - { - "description": "The start icon slot", - "name": "icon-start" - }, - { - "description": "The end icon slot", - "name": "icon-end" - } - ], + "description": "A tab panel component used as a child of le-tabs.\n\nEach le-tab-panel defines both the tab button label and the panel content.\nThe parent le-tabs component automatically reads these panels and creates\nthe tab interface.", + "name": "LeTabPanel", "slots": [ { - "description": "Tab text content", + "description": "Default slot for panel content", "name": "" - }, - { - "description": "Icon for icon-only tabs", - "name": "icon-only" } ], "members": [ @@ -14805,169 +15153,132 @@ "kind": "field", "name": "el", "type": { - "text": "HTMLElement" + "text": "HTMLLeTabPanelElement" } }, { "kind": "field", - "name": "mode", - "type": { - "text": "'default' | 'admin'" - }, - "default": "'default'", - "description": "Mode of the popover should be 'default' for internal use" - }, - { - "kind": "field", - "name": "label", - "type": { - "text": "string | undefined" - }, - "description": "Label if it is not provided via slot" - }, - { - "kind": "field", - "name": "value", - "type": { - "text": "string | undefined" - }, - "description": "Value of the tab, defaults to label if not provided" - }, - { - "kind": "field", - "name": "variant", - "type": { - "text": "'underlined' | 'solid' | 'pills' | 'enclosed' | 'icon-only'" - }, - "default": "'underlined'", - "description": "Tab variant style" - }, - { - "kind": "field", - "name": "position", - "type": { - "text": "'top' | 'bottom' | 'start' | 'end'" - }, - "default": "'top'", - "description": "Position of the tabs when used within a le-tabs component" - }, - { - "kind": "field", - "name": "size", - "type": { - "text": "'small' | 'medium' | 'large'" - }, - "default": "'medium'", - "description": "Tab size" - }, - { - "kind": "field", - "name": "focusable", + "name": "label", "type": { - "text": "boolean" + "text": "string" }, - "default": "true", - "description": "Whether the tab can get focus\nneeded for accessibility when used in custom tab implementations" + "description": "The label displayed in the tab button." }, { "kind": "field", - "name": "selected", + "name": "value", "type": { - "text": "boolean" + "text": "string | undefined" }, - "default": "false", - "description": "Whether the tab is in a selected/active state" + "description": "The value used to identify this tab.\nDefaults to the label if not provided." }, { "kind": "field", - "name": "fullWidth", + "name": "iconStart", "type": { - "text": "boolean" + "text": "string | undefined" }, - "default": "false", - "description": "Whether the tab takes full width of its container" + "description": "Icon displayed at the start of the tab button.\nCan be an emoji, URL, or icon class." }, { "kind": "field", - "name": "icon", + "name": "iconEnd", "type": { - "text": "string | Node | undefined" + "text": "string | undefined" }, - "description": "Icon only tab image or emoji\nif this prop is set, the tab will render only the icon slot" + "description": "Icon displayed at the end of the tab button." }, { "kind": "field", - "name": "showLabel", + "name": "disabled", "type": { "text": "boolean" }, "default": "false", - "description": "Whether to show the label when in icon-only mode" - }, - { - "kind": "field", - "name": "iconStart", - "type": { - "text": "string | Node | undefined" - }, - "description": "Start icon image or emoji" + "description": "Whether this tab is disabled." }, { "kind": "field", - "name": "iconEnd", + "name": "lazy", "type": { - "text": "string | Node | undefined" + "text": "boolean" }, - "description": "End icon image or emoji" + "default": "false", + "description": "Whether to render the panel content only when active (lazy loading).\nWhen true, content is not rendered until the tab is first selected.\nWhen false (default), content is always in DOM but hidden when inactive." }, { "kind": "field", - "name": "disabled", + "name": "active", "type": { "text": "boolean" }, "default": "false", - "description": "Whether the tab is disabled" + "description": "Internal: Whether this panel is currently active (set by parent le-tabs)" }, { "kind": "field", - "name": "href", + "name": "hasBeenActive", "type": { - "text": "string | undefined" + "text": "boolean" }, - "description": "Optional href to make the tab act as a link" + "default": "false", + "description": "Internal: Track if panel has ever been activated (for lazy rendering)" }, { - "kind": "field", - "name": "target", - "type": { - "text": "string | undefined" - }, - "description": "Link target when href is set" + "kind": "method", + "name": "activeChanged", + "parameters": [ + { + "name": "isActive", + "type": { + "text": "boolean" + } + } + ] }, { - "kind": "field", - "name": "align", - "type": { - "text": "'start' | 'center' | 'space-between' | 'end'" + "kind": "method", + "name": "getValue", + "return": { + "type": { + "text": "Promise" + } }, - "default": "'center'", - "description": "Alignment of the tab label without the end icon" + "description": "Get the effective value (value or label as fallback)" }, { "kind": "method", "name": "getTabConfig", "return": { "type": { - "text": "Promise<{\n label?: string;\n value?: string;\n icon?: string | Node;\n iconStart?: string | Node;\n iconEnd?: string | Node;\n disabled: boolean;\n }>" + "text": "Promise<{\n label: string;\n value: string;\n iconStart?: string;\n iconEnd?: string;\n disabled: boolean;\n }>" } }, "description": "Get tab configuration for parent component" }, { - "kind": "field", - "name": "handleClick", - "privacy": "private" + "kind": "method", + "name": "setActive", + "parameters": [ + { + "name": "isActive", + "type": { + "text": "boolean" + } + } + ], + "description": "Set the active state (called by parent le-tabs)" + }, + { + "kind": "method", + "name": "shouldRenderContent", + "privacy": "private", + "return": { + "type": { + "text": "boolean" + } + }, + "description": "Check if panel should render content" }, { "kind": "method", @@ -14975,19 +15286,10 @@ } ], "attributes": [ - { - "name": "mode", - "fieldName": "mode", - "default": "'default'", - "description": "Mode of the popover should be 'default' for internal use", - "type": { - "text": "'default' | 'admin'" - } - }, { "name": "label", "fieldName": "label", - "description": "Label if it is not provided via slot", + "description": "The label displayed in the tab button.", "type": { "text": "string" } @@ -14995,161 +15297,66 @@ { "name": "value", "fieldName": "value", - "description": "Value of the tab, defaults to label if not provided", + "description": "The value used to identify this tab.\nDefaults to the label if not provided.", "type": { "text": "string" } }, - { - "name": "variant", - "fieldName": "variant", - "default": "'underlined'", - "description": "Tab variant style", - "type": { - "text": "'underlined' | 'solid' | 'pills' | 'enclosed' | 'icon-only'" - } - }, - { - "name": "position", - "fieldName": "position", - "default": "'top'", - "description": "Position of the tabs when used within a le-tabs component", - "type": { - "text": "'top' | 'bottom' | 'start' | 'end'" - } - }, - { - "name": "size", - "fieldName": "size", - "default": "'medium'", - "description": "Tab size", - "type": { - "text": "'small' | 'medium' | 'large'" - } - }, - { - "name": "focusable", - "fieldName": "focusable", - "default": "true", - "description": "Whether the tab can get focus\nneeded for accessibility when used in custom tab implementations", - "type": { - "text": "boolean" - } - }, - { - "name": "selected", - "fieldName": "selected", - "default": "false", - "description": "Whether the tab is in a selected/active state", - "type": { - "text": "boolean" - } - }, - { - "name": "full-width", - "fieldName": "fullWidth", - "default": "false", - "description": "Whether the tab takes full width of its container", - "type": { - "text": "boolean" - } - }, - { - "name": "icon", - "fieldName": "icon", - "description": "Icon only tab image or emoji\nif this prop is set, the tab will render only the icon slot", - "type": { - "text": "string | Node" - } - }, - { - "name": "show-label", - "fieldName": "showLabel", - "default": "false", - "description": "Whether to show the label when in icon-only mode", - "type": { - "text": "boolean" - } - }, { "name": "icon-start", "fieldName": "iconStart", - "description": "Start icon image or emoji", + "description": "Icon displayed at the start of the tab button.\nCan be an emoji, URL, or icon class.", "type": { - "text": "string | Node" + "text": "string" } }, { "name": "icon-end", "fieldName": "iconEnd", - "description": "End icon image or emoji", + "description": "Icon displayed at the end of the tab button.", "type": { - "text": "string | Node" + "text": "string" } }, { "name": "disabled", "fieldName": "disabled", "default": "false", - "description": "Whether the tab is disabled", + "description": "Whether this tab is disabled.", "type": { "text": "boolean" } }, { - "name": "href", - "fieldName": "href", - "description": "Optional href to make the tab act as a link", - "type": { - "text": "string" - } - }, - { - "name": "target", - "fieldName": "target", - "description": "Link target when href is set", - "type": { - "text": "string" - } - }, - { - "name": "align", - "fieldName": "align", - "default": "'center'", - "description": "Alignment of the tab label without the end icon", + "name": "lazy", + "fieldName": "lazy", + "default": "false", + "description": "Whether to render the panel content only when active (lazy loading).\nWhen true, content is not rendered until the tab is first selected.\nWhen false (default), content is always in DOM but hidden when inactive.", "type": { - "text": "'start' | 'center' | 'space-between' | 'end'" + "text": "boolean" } } ], - "tagName": "le-tab", - "events": [ - { - "name": "click", - "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the tab is clicked.\nThis is a custom event that wraps the native click but ensures the target is the le-tab." - } - ], + "tagName": "le-tab-panel", + "events": [], "customElement": true } ], "exports": [ { "kind": "js", - "name": "LeTab", + "name": "LeTabPanel", "declaration": { - "name": "LeTab", - "module": "src/components/le-tab/le-tab.tsx" + "name": "LeTabPanel", + "module": "src/components/le-tab-panel/le-tab-panel.tsx" } }, { "kind": "custom-element-definition", - "name": "le-tab", + "name": "le-tab-panel", "declaration": { - "name": "LeTab", - "module": "src/components/le-tab/le-tab.tsx" + "name": "LeTabPanel", + "module": "src/components/le-tab-panel/le-tab-panel.tsx" } } ] @@ -15425,291 +15632,26 @@ }, { "kind": "method", - "name": "findLastEnabledTab", - "privacy": "private", - "return": { - "type": { - "text": "number" - } - } - }, - { - "kind": "method", - "name": "focusTab", - "privacy": "private", - "parameters": [ - { - "name": "index", - "type": { - "text": "number" - } - } - ] - }, - { - "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "tabs", - "fieldName": "tabs", - "default": "[]", - "description": "Array of tab options (programmatic mode).\nIf le-tab-panel children exist, they take precedence.", - "type": { - "text": "LeOption[]" - } - }, - { - "name": "selected", - "fieldName": "selected", - "description": "The value of the currently selected tab.\nIf not provided, defaults to the first tab.", - "type": { - "text": "LeOptionValue" - } - }, - { - "name": "orientation", - "fieldName": "orientation", - "default": "'horizontal'", - "description": "Orientation of the tabs.", - "type": { - "text": "'horizontal' | 'vertical'" - } - }, - { - "name": "position", - "fieldName": "position", - "default": "'start'", - "description": "Position of the tabs relative to the panels.", - "type": { - "text": "'start' | 'end'" - } - }, - { - "name": "variant", - "fieldName": "variant", - "default": "'underlined'", - "description": "Tab variant style.", - "type": { - "text": "'underlined' | 'solid' | 'pills' | 'enclosed' | 'icon-only'" - } - }, - { - "name": "full-width", - "fieldName": "fullWidth", - "default": "false", - "description": "Whether tabs should stretch to fill available width.", - "type": { - "text": "boolean" - } - }, - { - "name": "size", - "fieldName": "size", - "default": "'medium'", - "description": "Size of the tabs.", - "type": { - "text": "'small' | 'medium' | 'large'" - } - }, - { - "name": "wrap", - "fieldName": "wrap", - "default": "false", - "description": "Wrap the tabs if they exceed container width.", - "type": { - "text": "boolean" - } - }, - { - "name": "overflow", - "fieldName": "overflow", - "default": "'auto'", - "description": "Scroll behavior for overflowing tabs.", - "type": { - "text": "'auto' | 'hidden' | 'visible' | 'scroll'" - } - } - ], - "tagName": "le-tabs", - "events": [ - { - "name": "leTabChange", - "type": { - "text": "EventEmitter | undefined" - }, - "description": "Emitted when the selected tab changes." - } - ], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeTabs", - "declaration": { - "name": "LeTabs", - "module": "src/components/le-tabs/le-tabs.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-tabs", - "declaration": { - "name": "LeTabs", - "module": "src/components/le-tabs/le-tabs.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-tab-panel/le-tab-panel.tsx", - "declarations": [ - { - "kind": "class", - "description": "A tab panel component used as a child of le-tabs.\n\nEach le-tab-panel defines both the tab button label and the panel content.\nThe parent le-tabs component automatically reads these panels and creates\nthe tab interface.", - "name": "LeTabPanel", - "slots": [ - { - "description": "Default slot for panel content", - "name": "" - } - ], - "members": [ - { - "kind": "field", - "name": "el", - "type": { - "text": "HTMLLeTabPanelElement" - } - }, - { - "kind": "field", - "name": "label", - "type": { - "text": "string" - }, - "description": "The label displayed in the tab button." - }, - { - "kind": "field", - "name": "value", - "type": { - "text": "string | undefined" - }, - "description": "The value used to identify this tab.\nDefaults to the label if not provided." - }, - { - "kind": "field", - "name": "iconStart", - "type": { - "text": "string | undefined" - }, - "description": "Icon displayed at the start of the tab button.\nCan be an emoji, URL, or icon class." - }, - { - "kind": "field", - "name": "iconEnd", - "type": { - "text": "string | undefined" - }, - "description": "Icon displayed at the end of the tab button." - }, - { - "kind": "field", - "name": "disabled", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Whether this tab is disabled." - }, - { - "kind": "field", - "name": "lazy", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Whether to render the panel content only when active (lazy loading).\nWhen true, content is not rendered until the tab is first selected.\nWhen false (default), content is always in DOM but hidden when inactive." - }, - { - "kind": "field", - "name": "active", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Internal: Whether this panel is currently active (set by parent le-tabs)" - }, - { - "kind": "field", - "name": "hasBeenActive", - "type": { - "text": "boolean" - }, - "default": "false", - "description": "Internal: Track if panel has ever been activated (for lazy rendering)" - }, - { - "kind": "method", - "name": "activeChanged", - "parameters": [ - { - "name": "isActive", - "type": { - "text": "boolean" - } - } - ] - }, - { - "kind": "method", - "name": "getValue", - "return": { - "type": { - "text": "Promise" - } - }, - "description": "Get the effective value (value or label as fallback)" - }, - { - "kind": "method", - "name": "getTabConfig", + "name": "findLastEnabledTab", + "privacy": "private", "return": { "type": { - "text": "Promise<{\n label: string;\n value: string;\n iconStart?: string;\n iconEnd?: string;\n disabled: boolean;\n }>" + "text": "number" } - }, - "description": "Get tab configuration for parent component" + } }, { "kind": "method", - "name": "setActive", + "name": "focusTab", + "privacy": "private", "parameters": [ { - "name": "isActive", + "name": "index", "type": { - "text": "boolean" + "text": "number" } } - ], - "description": "Set the active state (called by parent le-tabs)" - }, - { - "kind": "method", - "name": "shouldRenderContent", - "privacy": "private", - "return": { - "type": { - "text": "boolean" - } - }, - "description": "Check if panel should render content" + ] }, { "kind": "method", @@ -15718,410 +15660,412 @@ ], "attributes": [ { - "name": "label", - "fieldName": "label", - "description": "The label displayed in the tab button.", + "name": "tabs", + "fieldName": "tabs", + "default": "[]", + "description": "Array of tab options (programmatic mode).\nIf le-tab-panel children exist, they take precedence.", "type": { - "text": "string" + "text": "LeOption[]" } }, { - "name": "value", - "fieldName": "value", - "description": "The value used to identify this tab.\nDefaults to the label if not provided.", + "name": "selected", + "fieldName": "selected", + "description": "The value of the currently selected tab.\nIf not provided, defaults to the first tab.", "type": { - "text": "string" + "text": "LeOptionValue" } }, { - "name": "icon-start", - "fieldName": "iconStart", - "description": "Icon displayed at the start of the tab button.\nCan be an emoji, URL, or icon class.", + "name": "orientation", + "fieldName": "orientation", + "default": "'horizontal'", + "description": "Orientation of the tabs.", "type": { - "text": "string" + "text": "'horizontal' | 'vertical'" } }, { - "name": "icon-end", - "fieldName": "iconEnd", - "description": "Icon displayed at the end of the tab button.", + "name": "position", + "fieldName": "position", + "default": "'start'", + "description": "Position of the tabs relative to the panels.", "type": { - "text": "string" + "text": "'start' | 'end'" } }, { - "name": "disabled", - "fieldName": "disabled", + "name": "variant", + "fieldName": "variant", + "default": "'underlined'", + "description": "Tab variant style.", + "type": { + "text": "'underlined' | 'solid' | 'pills' | 'enclosed' | 'icon-only'" + } + }, + { + "name": "full-width", + "fieldName": "fullWidth", "default": "false", - "description": "Whether this tab is disabled.", + "description": "Whether tabs should stretch to fill available width.", "type": { "text": "boolean" } }, { - "name": "lazy", - "fieldName": "lazy", + "name": "size", + "fieldName": "size", + "default": "'medium'", + "description": "Size of the tabs.", + "type": { + "text": "'small' | 'medium' | 'large'" + } + }, + { + "name": "wrap", + "fieldName": "wrap", "default": "false", - "description": "Whether to render the panel content only when active (lazy loading).\nWhen true, content is not rendered until the tab is first selected.\nWhen false (default), content is always in DOM but hidden when inactive.", + "description": "Wrap the tabs if they exceed container width.", "type": { "text": "boolean" } + }, + { + "name": "overflow", + "fieldName": "overflow", + "default": "'auto'", + "description": "Scroll behavior for overflowing tabs.", + "type": { + "text": "'auto' | 'hidden' | 'visible' | 'scroll'" + } + } + ], + "tagName": "le-tabs", + "events": [ + { + "name": "leTabChange", + "type": { + "text": "EventEmitter | undefined" + }, + "description": "Emitted when the selected tab changes." } ], - "tagName": "le-tab-panel", - "events": [], "customElement": true } ], "exports": [ { "kind": "js", - "name": "LeTabPanel", + "name": "LeTabs", "declaration": { - "name": "LeTabPanel", - "module": "src/components/le-tab-panel/le-tab-panel.tsx" + "name": "LeTabs", + "module": "src/components/le-tabs/le-tabs.tsx" } }, { "kind": "custom-element-definition", - "name": "le-tab-panel", + "name": "le-tabs", "declaration": { - "name": "LeTabPanel", - "module": "src/components/le-tab-panel/le-tab-panel.tsx" + "name": "LeTabs", + "module": "src/components/le-tabs/le-tabs.tsx" } } ] }, { "kind": "javascript-module", - "path": "src/components/le-tag/le-tag.tsx", + "path": "src/components/le-toolbar/le-toolbar.tsx", "declarations": [ { "kind": "class", - "description": "A tag/chip component for displaying labels with optional dismiss functionality.", - "name": "LeTag", + "description": "A priority-aware, overflow-safe toolbar component.\n\nItems are slotted light-DOM children. Each item may carry a\n`priority` attribute (lower = more important). When there\nisn't enough space, lower-priority items move to an overflow menu.\n\nCollapsible `le-button-group` children are asked to reduce their own\nfootprint first before their contents are overflowed entirely.", + "name": "LeToolbar", + "cssParts": [ + { + "description": "The main flex row", + "name": "container" + }, + { + "description": "The \"more\" button wrapper", + "name": "overflow-trigger" + } + ], "slots": [ { - "description": "Default slot for custom content (overrides label prop)", + "description": "Toolbar items", "name": "" + }, + { + "description": "Custom content for the overflow trigger button", + "name": "more" } ], "members": [ { "kind": "field", - "name": "label", + "name": "el", "type": { - "text": "string | undefined" - }, - "description": "The text label to display in the tag." + "text": "HTMLElement" + } }, { "kind": "field", - "name": "mode", + "name": "items", "type": { - "text": "'default' | 'admin' | undefined" + "text": "unknown | undefined" }, - "description": "Mode of the popover should be 'default' for internal use" + "description": "Optional declarative items input.\n\nThe current implementation is slot-driven, but when this prop changes we\nstill invalidate the slotted-items cache and recompute layout." }, { "kind": "field", - "name": "icon", + "name": "alignItems", "type": { - "text": "string | undefined" + "text": "'start' | 'center' | 'end' | 'stretch'" }, - "description": "Icon to display before the label.\nCan be an emoji, URL, or icon name." + "default": "'start'", + "description": "Alignment of items along the main axis." }, { "kind": "field", - "name": "dismissible", + "name": "itemGap", "type": { - "text": "boolean" + "text": "string" }, - "default": "false", - "description": "Whether the tag can be dismissed (shows close button)." + "default": "'var(--le-toolbar-gap, var(--le-spacing-1, 4px))'", + "description": "Spacing between top-level toolbar items.\nAccepts any valid CSS length (e.g. `8px`, `0.5rem`, `var(--le-spacing-2)`)." }, { "kind": "field", - "name": "disabled", + "name": "overflowIcon", "type": { - "text": "boolean" + "text": "string" }, - "default": "false", - "description": "Whether the tag is disabled." + "default": "'ellipsis-horizontal'", + "description": "Icon for the overflow trigger button when no custom slot content is provided." }, { "kind": "field", - "name": "size", + "name": "overflowLabel", "type": { - "text": "'small' | 'medium' | 'large'" + "text": "string" }, - "default": "'medium'", - "description": "The size of the tag." + "default": "'More'", + "description": "Accessible label for the overflow trigger button." }, { "kind": "field", - "name": "color", + "name": "disablePopover", "type": { - "text": "| 'default'\n | 'primary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'secondary'\n | 'info'" + "text": "boolean" }, - "default": "'default'", - "description": "The color of the tag." + "default": "false", + "description": "Disable the built-in overflow popover.\nThe toolbar will still compute overflow state and emit events, but\nwon't render its own menu. Useful for custom overflow handling." }, { "kind": "field", - "name": "handleDismiss", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderIcon", - "privacy": "private" + "name": "debugVirtualToolbar", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Temporary debug mode: render the virtual toolbar visibly above\nthe live toolbar so collapse measurements can be inspected." }, { - "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "label", - "fieldName": "label", - "description": "The text label to display in the tag.", + "kind": "field", + "name": "debugPauseBeforeMeasure", "type": { - "text": "string" - } + "text": "boolean" + }, + "default": "false", + "description": "Temporary debug mode: stop before measuring virtual widths so the\nvirtual DOM can be inspected before collapse simulation mutates it." }, { - "name": "mode", - "fieldName": "mode", - "description": "Mode of the popover should be 'default' for internal use", + "kind": "field", + "name": "solverOutput", "type": { - "text": "'default' | 'admin'" - } + "text": "SolverOutput" + }, + "privacy": "private", + "default": "{ visibleIds: new Set(), collapsedGroupIds: new Set(), overflowIds: new Set(), showTrigger: false, }" }, { - "name": "icon", - "fieldName": "icon", - "description": "Icon to display before the label.\nCan be an emoji, URL, or icon name.", + "kind": "field", + "name": "overflowMenuItems", "type": { - "text": "string" - } + "text": "LeOption[]" + }, + "privacy": "private", + "default": "[]" }, { - "name": "dismissible", - "fieldName": "dismissible", - "default": "false", - "description": "Whether the tag can be dismissed (shows close button).", + "kind": "field", + "name": "itemSlots", "type": { - "text": "boolean" - } + "text": "Array<{ id: string; slotName: string }>" + }, + "privacy": "private", + "default": "[]" }, { - "name": "disabled", - "fieldName": "disabled", - "default": "false", - "description": "Whether the tag is disabled.", + "kind": "field", + "name": "initializingLayout", "type": { "text": "boolean" - } + }, + "privacy": "private", + "default": "true" }, { - "name": "size", - "fieldName": "size", - "default": "'medium'", - "description": "The size of the tag.", + "kind": "field", + "name": "debugStepIndex", "type": { - "text": "'small' | 'medium' | 'large'" - } + "text": "number" + }, + "privacy": "private", + "default": "0" }, { - "name": "color", - "fieldName": "color", - "default": "'default'", - "description": "The color of the tag.", + "kind": "field", + "name": "debugStepMeasuredWidth", "type": { - "text": "| 'default'\n | 'primary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'secondary'\n | 'info'" - } - } - ], - "tagName": "le-tag", - "events": [ + "text": "number" + }, + "privacy": "private", + "default": "0" + }, { - "name": "leDismiss", + "kind": "field", + "name": "virtualTriggerVisible", "type": { - "text": "EventEmitter | undefined" + "text": "boolean" }, - "description": "Emitted when the dismiss button is clicked." - } - ], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeTag", - "declaration": { - "name": "LeTag", - "module": "src/components/le-tag/le-tag.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-tag", - "declaration": { - "name": "LeTag", - "module": "src/components/le-tag/le-tag.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-text/le-text.tsx", - "declarations": [ - { - "kind": "class", - "description": "A text component with rich text editing capabilities in admin mode.\n\n`le-text` renders semantic text elements (headings, paragraphs, code, quotes)\nand provides a Notion-like rich text editor in admin mode with formatting\ntoolbar for bold, italic, links, and paragraph type selection.", - "name": "LeText", - "cssProperties": [ - { - "description": "Text color", - "name": "--le-text-color" + "privacy": "private", + "default": "false" }, { - "description": "Font size", - "name": "--le-text-font-size" + "kind": "field", + "name": "hasPreparedInitialLayout", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" }, { - "description": "Line height", - "name": "--le-text-line-height" + "kind": "field", + "name": "instanceId", + "type": { + "text": "string" + }, + "privacy": "private" }, - { - "description": "Font weight", - "name": "--le-text-font-weight" - } - ], - "cssParts": [ - { - "description": "The text container element", - "name": "text" - } - ], - "slots": [ - { - "description": "Default slot for text content", - "name": "" - } - ], - "members": [ { "kind": "field", - "name": "el", + "name": "toolbarHostEl", "type": { - "text": "HTMLElement" - } + "text": "HTMLElement | null | undefined" + }, + "privacy": "private", + "description": "Toolbar host element (follows the width of the parent element)." }, { "kind": "field", - "name": "variant", + "name": "toolbarContainerEl", "type": { - "text": "| 'p'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'h4'\n | 'h5'\n | 'h6'\n | 'code'\n | 'quote'\n | 'label'\n | 'small'" + "text": "HTMLElement | null | undefined" }, - "default": "'p'", - "description": "The semantic variant/type of text element" + "privacy": "private", + "description": "Live toolbar items container." }, { "kind": "field", - "name": "align", + "name": "virtualToolbarEl", "type": { - "text": "'left' | 'center' | 'right' | 'justify'" + "text": "HTMLElement | undefined" }, - "default": "'left'", - "description": "Text alignment" + "privacy": "private", + "description": "Hidden virtual toolbar container used for browser-native overflow checks." }, { "kind": "field", - "name": "color", + "name": "virtualItemsEl", "type": { - "text": "string | undefined" + "text": "HTMLElement | undefined" }, - "description": "Text color (CSS value or theme token)" + "privacy": "private", + "description": "Virtual row where cloned participants are mounted for simulation." }, { "kind": "field", - "name": "truncate", + "name": "virtualTriggerEl", "type": { - "text": "boolean" + "text": "HTMLElement | undefined" }, - "default": "false", - "description": "Whether the text should truncate with ellipsis" + "privacy": "private", + "description": "Virtual trigger element that participates in layout when overflow exists." }, { "kind": "field", - "name": "maxLines", + "name": "resizeObserver", "type": { - "text": "number | undefined" + "text": "ResizeObserver | undefined" }, - "description": "Maximum number of lines before truncating (requires truncate=true)" + "privacy": "private" }, { "kind": "field", - "name": "adminMode", + "name": "mutationObserver", "type": { - "text": "boolean" + "text": "MutationObserver | undefined" }, - "privacy": "private", - "default": "false", - "description": "Internal state to track admin mode" + "privacy": "private" }, { "kind": "field", - "name": "content", + "name": "pendingRecalc", "type": { - "text": "string" + "text": "number | null" }, "privacy": "private", - "default": "''", - "description": "The HTML content being edited" + "default": "null" }, { "kind": "field", - "name": "isFocused", + "name": "debugVirtualWidth", "type": { - "text": "boolean" + "text": "number" }, "privacy": "private", - "default": "false", - "description": "Whether the editor is focused (shows toolbar)" + "default": "0" }, { "kind": "field", - "name": "selectionState", + "name": "observersAttached", "type": { - "text": "SelectionState" + "text": "boolean" }, "privacy": "private", - "default": "{ isBold: false, isItalic: false, isUnderline: false, isStrikethrough: false, isLink: false, blockType: 'p', }", - "description": "Current selection state for toolbar button highlighting" + "default": "false", + "description": "Prevent double-attach on rapid connect/disconnect cycles." }, { "kind": "field", - "name": "editorRef", + "name": "itemMap", "type": { - "text": "HTMLDivElement | undefined" + "text": "Map" }, "privacy": "private", - "description": "Reference to the contenteditable element" + "default": "new Map()", + "description": "Map from ID → original light-DOM element plus virtual clone." }, { "kind": "field", - "name": "slotRef", + "name": "collapseSteps", "type": { - "text": "HTMLSlotElement | undefined" + "text": "CollapseStep[]" }, "privacy": "private", - "description": "Reference to the slot element" + "default": "[]" }, { "kind": "field", @@ -16133,281 +16077,287 @@ }, { "kind": "method", - "name": "onVariantChange" + "name": "handleAlignChange" }, { "kind": "method", - "name": "readSlottedContent", - "privacy": "private", - "description": "Read content from slotted elements" + "name": "handleGapChange", + "parameters": [ + { + "name": "newValue", + "type": { + "text": "string" + } + } + ] }, { "kind": "method", - "name": "syncContentToSlot", - "privacy": "private", - "description": "Sync edited content back to the slot" + "name": "handleItemsChange" }, { - "kind": "field", - "name": "handleInput", - "privacy": "private", - "description": "Handle input in the contenteditable" + "kind": "method", + "name": "handleSlotChange" }, { - "kind": "field", - "name": "handleFocus", - "privacy": "private", - "description": "Handle focus on the editor" + "kind": "method", + "name": "resetToolbar", + "description": "Reset the toolbar's internal layout state and recalculate item visibility from scratch." + }, + { + "kind": "method", + "name": "recalculate", + "description": "Force a layout recalculation." + }, + { + "kind": "method", + "name": "attachObservers", + "privacy": "private" + }, + { + "kind": "method", + "name": "detachObservers", + "privacy": "private" }, { - "kind": "field", - "name": "handleBlur", + "kind": "method", + "name": "observeContainer", "privacy": "private", - "description": "Handle blur on the editor" + "parameters": [ + { + "name": "el", + "optional": true, + "type": { + "text": "HTMLElement | null" + } + } + ] }, { - "kind": "field", - "name": "handleSelectionChange", - "privacy": "private", - "description": "Handle selection change to update toolbar state" + "kind": "method", + "name": "scheduleRecalc", + "privacy": "private" }, { "kind": "method", - "name": "updateSelectionState", + "name": "getItemId", "privacy": "private", - "description": "Update the selection state for toolbar highlighting" + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "el", + "type": { + "text": "HTMLElement" + } + }, + { + "name": "index", + "type": { + "text": "number" + } + } + ] }, { "kind": "method", - "name": "isSelectionInLink", + "name": "getItemPriority", "privacy": "private", "return": { "type": { - "text": "boolean" + "text": "number" } }, "parameters": [ { - "name": "selection", + "name": "el", "type": { - "text": "Selection" + "text": "HTMLElement" + } + }, + { + "name": "index", + "type": { + "text": "number" } } - ], - "description": "Check if current selection is within a link" + ] }, { "kind": "method", - "name": "execCommand", + "name": "buildOverflowOption", "privacy": "private", + "return": { + "type": { + "text": "Promise" + } + }, "parameters": [ { - "name": "command", + "name": "item", "type": { - "text": "string" + "text": "HTMLElement" } }, { - "name": "value", - "optional": true, + "name": "id", "type": { "text": "string" } } - ], - "description": "Execute a formatting command" + ] }, { - "kind": "field", - "name": "toggleBold", + "kind": "method", + "name": "setVirtualTriggerVisible", "privacy": "private", - "description": "Toggle bold formatting" + "parameters": [ + { + "name": "visible", + "type": { + "text": "boolean" + } + } + ] }, { - "kind": "field", - "name": "toggleItalic", + "kind": "method", + "name": "getAuthoredVirtualCollapse", "privacy": "private", - "description": "Toggle italic formatting" + "return": { + "type": { + "text": "string | undefined" + } + }, + "parameters": [ + { + "name": "record", + "type": { + "text": "ToolbarItemRecord" + } + } + ] }, { - "kind": "field", - "name": "toggleUnderline", - "privacy": "private", - "description": "Toggle underline formatting" + "kind": "method", + "name": "resetVirtualState", + "privacy": "private" }, { - "kind": "field", - "name": "toggleStrikethrough", - "privacy": "private", - "description": "Toggle strikethrough formatting" + "kind": "method", + "name": "initializeDebugMeasurementState", + "privacy": "private" }, { - "kind": "field", - "name": "toggleLink", - "privacy": "private", - "description": "Add or edit a link" + "kind": "method", + "name": "runDebugMeasurementStep" }, { "kind": "field", - "name": "changeVariant", - "privacy": "private", - "description": "Change the block type/variant" + "name": "handleVirtualDebugClick", + "privacy": "private" }, { "kind": "method", - "name": "renderToolbar", - "privacy": "private", - "description": "Render the formatting toolbar" + "name": "clearVirtualMeasurements", + "privacy": "private" }, { "kind": "method", - "name": "getTag", + "name": "settleVirtualItem", "privacy": "private", - "return": { - "type": { - "text": "string" + "parameters": [ + { + "name": "element", + "optional": true, + "type": { + "text": "HTMLElement" + } } - }, - "description": "Get the semantic tag for the current variant" + ] }, { "kind": "method", - "name": "render" - } - ], - "attributes": [ - { - "name": "variant", - "fieldName": "variant", - "default": "'p'", - "description": "The semantic variant/type of text element", - "type": { - "text": "| 'p'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'h4'\n | 'h5'\n | 'h6'\n | 'code'\n | 'quote'\n | 'label'\n | 'small'" - } - }, - { - "name": "align", - "fieldName": "align", - "default": "'left'", - "description": "Text alignment", - "type": { - "text": "'left' | 'center' | 'right' | 'justify'" - } - }, - { - "name": "color", - "fieldName": "color", - "description": "Text color (CSS value or theme token)", - "type": { - "text": "string" - } + "name": "waitForNestedCustomElements", + "privacy": "private", + "parameters": [ + { + "name": "root", + "type": { + "text": "HTMLElement" + } + } + ] }, { - "name": "truncate", - "fieldName": "truncate", - "default": "false", - "description": "Whether the text should truncate with ellipsis", - "type": { - "text": "boolean" - } + "kind": "method", + "name": "syncVirtualTriggerContent", + "privacy": "private" }, { - "name": "max-lines", - "fieldName": "maxLines", - "description": "Maximum number of lines before truncating (requires truncate=true)", - "type": { - "text": "number" - } - } - ], - "tagName": "le-text", - "events": [], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeText", - "declaration": { - "name": "LeText", - "module": "src/components/le-text/le-text.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-text", - "declaration": { - "name": "LeText", - "module": "src/components/le-text/le-text.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx", - "declarations": [ - { - "kind": "class", - "description": "Flexible spacer for le-toolbar layouts.\n\nDefault behavior (no width): occupies available free space and shrinks naturally.\nWith numeric `width`: behaves as a fixed-width spacer that can be collapsed by le-toolbar.", - "name": "LeToolbarSpacer", - "members": [ - { - "kind": "field", - "name": "width", - "type": { - "text": "number | string | undefined" - }, - "description": "Optional fixed width.\nNumeric values (e.g. `24`) are treated as px.\nString values may be any valid CSS width (e.g. `2rem`, `var(--le-spacing-2)`)." + "kind": "method", + "name": "prepareToolbarItems", + "privacy": "private" }, { "kind": "method", - "name": "isValidCssWidth", + "name": "getVisibilityState", "privacy": "private", "return": { "type": { - "text": "boolean" + "text": "'visible' | 'collapsed'" } }, "parameters": [ { "name": "value", "type": { - "text": "string" + "text": "string | null" } } ] }, { "kind": "method", - "name": "getFixedWidthValue", - "privacy": "private", - "return": { - "type": { - "text": "string | undefined" - } - } + "name": "calculateLayoutWidths", + "privacy": "private" }, { "kind": "method", - "name": "isFixedSpacer", + "name": "computeLayout", + "privacy": "private" + }, + { + "kind": "method", + "name": "applyOutput", "privacy": "private", - "return": { - "type": { - "text": "boolean" + "parameters": [ + { + "name": "output", + "type": { + "text": "SolverOutput" + } + }, + { + "name": "overflowItems", + "type": { + "text": "LeOption[]" + } } - } + ] + }, + { + "kind": "field", + "name": "handleOverflowSelect", + "privacy": "private" }, { "kind": "method", - "name": "getCollapseMeta", - "return": { - "type": { - "text": "Promise" - } - }, - "description": "Returns collapse meta for toolbar integration." + "name": "renderVirtualToolbar", + "privacy": "private" }, { "kind": "method", @@ -16416,332 +16366,379 @@ ], "attributes": [ { - "name": "width", - "fieldName": "width", - "description": "Optional fixed width.\nNumeric values (e.g. `24`) are treated as px.\nString values may be any valid CSS width (e.g. `2rem`, `var(--le-spacing-2)`).", + "name": "items", + "fieldName": "items", + "description": "Optional declarative items input.\n\nThe current implementation is slot-driven, but when this prop changes we\nstill invalidate the slotted-items cache and recompute layout.", "type": { - "text": "number | string" + "text": "unknown" } - } - ], - "tagName": "le-toolbar-spacer", - "events": [], - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "LeToolbarSpacer", - "declaration": { - "name": "LeToolbarSpacer", - "module": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx" - } - }, - { - "kind": "custom-element-definition", - "name": "le-toolbar-spacer", - "declaration": { - "name": "LeToolbarSpacer", - "module": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/components/le-toolbar/le-toolbar.tsx", - "declarations": [ - { - "kind": "class", - "description": "A priority-aware, overflow-safe toolbar component.\n\nItems are slotted light-DOM children. Each item may carry a\n`priority` attribute (lower = more important). When there\nisn't enough space, lower-priority items move to an overflow menu.\n\nCollapsible `le-button-group` children are asked to reduce their own\nfootprint first before their contents are overflowed entirely.", - "name": "LeToolbar", - "cssParts": [ - { - "description": "The main flex row", - "name": "container" - }, - { - "description": "The \"more\" button wrapper", - "name": "overflow-trigger" - } - ], - "slots": [ - { - "description": "Toolbar items", - "name": "" }, { - "description": "Custom content for the overflow trigger button", - "name": "more" - } - ], - "members": [ - { - "kind": "field", - "name": "el", + "name": "align-items", + "fieldName": "alignItems", + "default": "'start'", + "description": "Alignment of items along the main axis.", "type": { - "text": "HTMLElement" + "text": "'start' | 'center' | 'end' | 'stretch'" } }, { - "kind": "field", - "name": "items", - "type": { - "text": "unknown | undefined" - }, - "description": "Optional declarative items input.\n\nThe current implementation is slot-driven, but when this prop changes we\nstill invalidate the slotted-items cache and recompute layout." - }, - { - "kind": "field", - "name": "alignItems", + "name": "item-gap", + "fieldName": "itemGap", + "default": "'var(--le-toolbar-gap, var(--le-spacing-1, 4px))'", + "description": "Spacing between top-level toolbar items.\nAccepts any valid CSS length (e.g. `8px`, `0.5rem`, `var(--le-spacing-2)`).", "type": { - "text": "'start' | 'center' | 'end' | 'stretch'" - }, - "default": "'start'", - "description": "Alignment of items along the main axis." + "text": "string" + } }, { - "kind": "field", - "name": "itemGap", + "name": "overflow-icon", + "fieldName": "overflowIcon", + "default": "'ellipsis-horizontal'", + "description": "Icon for the overflow trigger button when no custom slot content is provided.", "type": { "text": "string" - }, - "default": "'var(--le-toolbar-gap, var(--le-spacing-1, 4px))'", - "description": "Spacing between top-level toolbar items.\nAccepts any valid CSS length (e.g. `8px`, `0.5rem`, `var(--le-spacing-2)`)." + } }, { - "kind": "field", - "name": "overflowIcon", + "name": "overflow-label", + "fieldName": "overflowLabel", + "default": "'More'", + "description": "Accessible label for the overflow trigger button.", "type": { "text": "string" - }, - "default": "'ellipsis-horizontal'", - "description": "Icon for the overflow trigger button when no custom slot content is provided." + } }, { - "kind": "field", - "name": "overflowLabel", + "name": "disable-popover", + "fieldName": "disablePopover", + "default": "false", + "description": "Disable the built-in overflow popover.\nThe toolbar will still compute overflow state and emit events, but\nwon't render its own menu. Useful for custom overflow handling.", "type": { - "text": "string" - }, - "default": "'More'", - "description": "Accessible label for the overflow trigger button." + "text": "boolean" + } }, { - "kind": "field", - "name": "disablePopover", + "name": "debug-virtual-toolbar", + "fieldName": "debugVirtualToolbar", + "default": "false", + "description": "Temporary debug mode: render the virtual toolbar visibly above\nthe live toolbar so collapse measurements can be inspected.", "type": { "text": "boolean" - }, - "default": "false", - "description": "Disable the built-in overflow popover.\nThe toolbar will still compute overflow state and emit events, but\nwon't render its own menu. Useful for custom overflow handling." + } }, { - "kind": "field", - "name": "debugVirtualToolbar", + "name": "debug-pause-before-measure", + "fieldName": "debugPauseBeforeMeasure", + "default": "false", + "description": "Temporary debug mode: stop before measuring virtual widths so the\nvirtual DOM can be inspected before collapse simulation mutates it.", "type": { "text": "boolean" + } + } + ], + "tagName": "le-toolbar", + "events": [ + { + "name": "leToolbarOverflowChange", + "type": { + "text": "EventEmitter | undefined" }, - "default": "false", - "description": "Temporary debug mode: render the virtual toolbar visibly above\nthe live toolbar so collapse measurements can be inspected." - }, + "description": "Emitted when the overflow state changes." + } + ], + "customElement": true + }, + { + "kind": "variable", + "name": "slotName", + "default": "`__le-toolbar-item-${index}`" + }, + { + "kind": "variable", + "name": "priority" + }, + { + "kind": "variable", + "name": "kind", + "type": { + "text": "ToolbarItemRecord['kind']" + } + }, + { + "kind": "variable", + "name": "overflowOption" + } + ], + "exports": [ + { + "kind": "js", + "name": "LeToolbar", + "declaration": { + "name": "LeToolbar", + "module": "src/components/le-toolbar/le-toolbar.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-toolbar", + "declaration": { + "name": "LeToolbar", + "module": "src/components/le-toolbar/le-toolbar.tsx" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx", + "declarations": [ + { + "kind": "class", + "description": "Flexible spacer for le-toolbar layouts.\n\nDefault behavior (no width): occupies available free space and shrinks naturally.\nWith numeric `width`: behaves as a fixed-width spacer that can be collapsed by le-toolbar.", + "name": "LeToolbarSpacer", + "members": [ { "kind": "field", - "name": "debugPauseBeforeMeasure", + "name": "width", "type": { - "text": "boolean" + "text": "number | string | undefined" }, - "default": "false", - "description": "Temporary debug mode: stop before measuring virtual widths so the\nvirtual DOM can be inspected before collapse simulation mutates it." + "description": "Optional fixed width.\nNumeric values (e.g. `24`) are treated as px.\nString values may be any valid CSS width (e.g. `2rem`, `var(--le-spacing-2)`)." }, { - "kind": "field", - "name": "solverOutput", - "type": { - "text": "SolverOutput" - }, + "kind": "method", + "name": "isValidCssWidth", "privacy": "private", - "default": "{ visibleIds: new Set(), collapsedGroupIds: new Set(), overflowIds: new Set(), showTrigger: false, }" - }, - { - "kind": "field", - "name": "overflowMenuItems", - "type": { - "text": "LeOption[]" + "return": { + "type": { + "text": "boolean" + } }, - "privacy": "private", - "default": "[]" + "parameters": [ + { + "name": "value", + "type": { + "text": "string" + } + } + ] }, { - "kind": "field", - "name": "itemSlots", - "type": { - "text": "Array<{ id: string; slotName: string }>" - }, + "kind": "method", + "name": "getFixedWidthValue", "privacy": "private", - "default": "[]" + "return": { + "type": { + "text": "string | undefined" + } + } }, { - "kind": "field", - "name": "initializingLayout", - "type": { - "text": "boolean" - }, + "kind": "method", + "name": "isFixedSpacer", "privacy": "private", - "default": "true" + "return": { + "type": { + "text": "boolean" + } + } }, { - "kind": "field", - "name": "debugStepIndex", - "type": { - "text": "number" + "kind": "method", + "name": "getCollapseMeta", + "return": { + "type": { + "text": "Promise" + } }, - "privacy": "private", - "default": "0" + "description": "Returns collapse meta for toolbar integration." }, { - "kind": "field", - "name": "debugStepMeasuredWidth", - "type": { - "text": "number" - }, - "privacy": "private", - "default": "0" - }, + "kind": "method", + "name": "render" + } + ], + "attributes": [ { - "kind": "field", - "name": "virtualTriggerVisible", + "name": "width", + "fieldName": "width", + "description": "Optional fixed width.\nNumeric values (e.g. `24`) are treated as px.\nString values may be any valid CSS width (e.g. `2rem`, `var(--le-spacing-2)`).", "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" + "text": "number | string" + } + } + ], + "tagName": "le-toolbar-spacer", + "events": [], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeToolbarSpacer", + "declaration": { + "name": "LeToolbarSpacer", + "module": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-toolbar-spacer", + "declaration": { + "name": "LeToolbarSpacer", + "module": "src/components/le-toolbar-spacer/le-toolbar-spacer.tsx" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/components/le-text/le-text.tsx", + "declarations": [ + { + "kind": "class", + "description": "A text component with rich text editing capabilities in admin mode.\n\n`le-text` renders semantic text elements (headings, paragraphs, code, quotes)\nand provides a Notion-like rich text editor in admin mode with formatting\ntoolbar for bold, italic, links, and paragraph type selection.", + "name": "LeText", + "cssProperties": [ + { + "description": "Text color", + "name": "--le-text-color" }, { - "kind": "field", - "name": "hasPreparedInitialLayout", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" + "description": "Font size", + "name": "--le-text-font-size" }, { - "kind": "field", - "name": "instanceId", - "type": { - "text": "string" - }, - "privacy": "private" + "description": "Line height", + "name": "--le-text-line-height" }, + { + "description": "Font weight", + "name": "--le-text-font-weight" + } + ], + "cssParts": [ + { + "description": "The text container element", + "name": "text" + } + ], + "slots": [ + { + "description": "Default slot for text content", + "name": "" + } + ], + "members": [ { "kind": "field", - "name": "toolbarHostEl", + "name": "el", "type": { - "text": "HTMLElement | null | undefined" - }, - "privacy": "private", - "description": "Toolbar host element (follows the width of the parent element)." + "text": "HTMLElement" + } }, { "kind": "field", - "name": "toolbarContainerEl", + "name": "variant", "type": { - "text": "HTMLElement | null | undefined" + "text": "| 'p'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'h4'\n | 'h5'\n | 'h6'\n | 'code'\n | 'quote'\n | 'label'\n | 'small'" }, - "privacy": "private", - "description": "Live toolbar items container." + "default": "'p'", + "description": "The semantic variant/type of text element" }, { "kind": "field", - "name": "virtualToolbarEl", + "name": "align", "type": { - "text": "HTMLElement | undefined" + "text": "'left' | 'center' | 'right' | 'justify'" }, - "privacy": "private", - "description": "Hidden virtual toolbar container used for browser-native overflow checks." + "default": "'left'", + "description": "Text alignment" }, { "kind": "field", - "name": "virtualItemsEl", + "name": "color", "type": { - "text": "HTMLElement | undefined" + "text": "string | undefined" }, - "privacy": "private", - "description": "Virtual row where cloned participants are mounted for simulation." + "description": "Text color (CSS value or theme token)" }, { "kind": "field", - "name": "virtualTriggerEl", + "name": "truncate", "type": { - "text": "HTMLElement | undefined" + "text": "boolean" }, - "privacy": "private", - "description": "Virtual trigger element that participates in layout when overflow exists." + "default": "false", + "description": "Whether the text should truncate with ellipsis" }, { "kind": "field", - "name": "resizeObserver", + "name": "maxLines", "type": { - "text": "ResizeObserver | undefined" + "text": "number | undefined" }, - "privacy": "private" + "description": "Maximum number of lines before truncating (requires truncate=true)" }, { "kind": "field", - "name": "mutationObserver", + "name": "adminMode", "type": { - "text": "MutationObserver | undefined" + "text": "boolean" }, - "privacy": "private" + "privacy": "private", + "default": "false", + "description": "Internal state to track admin mode" }, { "kind": "field", - "name": "pendingRecalc", + "name": "content", "type": { - "text": "number | null" + "text": "string" }, "privacy": "private", - "default": "null" + "default": "''", + "description": "The HTML content being edited" }, { "kind": "field", - "name": "debugVirtualWidth", + "name": "isFocused", "type": { - "text": "number" + "text": "boolean" }, "privacy": "private", - "default": "0" + "default": "false", + "description": "Whether the editor is focused (shows toolbar)" }, { "kind": "field", - "name": "observersAttached", + "name": "selectionState", "type": { - "text": "boolean" + "text": "SelectionState" }, "privacy": "private", - "default": "false", - "description": "Prevent double-attach on rapid connect/disconnect cycles." + "default": "{ isBold: false, isItalic: false, isUnderline: false, isStrikethrough: false, isLink: false, blockType: 'p', }", + "description": "Current selection state for toolbar button highlighting" }, { "kind": "field", - "name": "itemMap", + "name": "editorRef", "type": { - "text": "Map" + "text": "HTMLDivElement | undefined" }, "privacy": "private", - "default": "new Map()", - "description": "Map from ID → original light-DOM element plus virtual clone." + "description": "Reference to the contenteditable element" }, { "kind": "field", - "name": "collapseSteps", + "name": "slotRef", "type": { - "text": "CollapseStep[]" + "text": "HTMLSlotElement | undefined" }, "privacy": "private", - "default": "[]" + "description": "Reference to the slot element" }, { "kind": "field", @@ -16753,286 +16750,300 @@ }, { "kind": "method", - "name": "handleAlignChange" - }, - { - "kind": "method", - "name": "handleGapChange", - "parameters": [ - { - "name": "newValue", - "type": { - "text": "string" - } - } - ] - }, - { - "kind": "method", - "name": "handleItemsChange" + "name": "onVariantChange" }, { "kind": "method", - "name": "handleSlotChange" + "name": "readSlottedContent", + "privacy": "private", + "description": "Read content from slotted elements" }, { "kind": "method", - "name": "resetToolbar", - "description": "Reset the toolbar's internal layout state and recalculate item visibility from scratch." + "name": "syncContentToSlot", + "privacy": "private", + "description": "Sync edited content back to the slot" }, { - "kind": "method", - "name": "recalculate", - "description": "Force a layout recalculation." + "kind": "field", + "name": "handleInput", + "privacy": "private", + "description": "Handle input in the contenteditable" }, { - "kind": "method", - "name": "attachObservers", - "privacy": "private" + "kind": "field", + "name": "handleFocus", + "privacy": "private", + "description": "Handle focus on the editor" }, { - "kind": "method", - "name": "detachObservers", - "privacy": "private" + "kind": "field", + "name": "handleBlur", + "privacy": "private", + "description": "Handle blur on the editor" }, { - "kind": "method", - "name": "observeContainer", + "kind": "field", + "name": "handleSelectionChange", "privacy": "private", - "parameters": [ - { - "name": "el", - "optional": true, - "type": { - "text": "HTMLElement | null" - } - } - ] + "description": "Handle selection change to update toolbar state" }, { "kind": "method", - "name": "scheduleRecalc", - "privacy": "private" + "name": "updateSelectionState", + "privacy": "private", + "description": "Update the selection state for toolbar highlighting" }, { "kind": "method", - "name": "getItemId", + "name": "isSelectionInLink", "privacy": "private", "return": { "type": { - "text": "string" + "text": "boolean" } }, "parameters": [ { - "name": "el", - "type": { - "text": "HTMLElement" - } - }, - { - "name": "index", + "name": "selection", "type": { - "text": "number" + "text": "Selection" } } - ] + ], + "description": "Check if current selection is within a link" }, { "kind": "method", - "name": "getItemPriority", + "name": "execCommand", "privacy": "private", - "return": { - "type": { - "text": "number" - } - }, "parameters": [ { - "name": "el", + "name": "command", "type": { - "text": "HTMLElement" + "text": "string" } }, { - "name": "index", + "name": "value", + "optional": true, "type": { - "text": "number" + "text": "string" } } - ] + ], + "description": "Execute a formatting command" }, { - "kind": "method", - "name": "buildOverflowOption", + "kind": "field", + "name": "toggleBold", "privacy": "private", - "return": { - "type": { - "text": "Promise" - } - }, - "parameters": [ - { - "name": "item", - "type": { - "text": "HTMLElement" - } - }, - { - "name": "id", - "type": { - "text": "string" - } - } - ] + "description": "Toggle bold formatting" + }, + { + "kind": "field", + "name": "toggleItalic", + "privacy": "private", + "description": "Toggle italic formatting" + }, + { + "kind": "field", + "name": "toggleUnderline", + "privacy": "private", + "description": "Toggle underline formatting" + }, + { + "kind": "field", + "name": "toggleStrikethrough", + "privacy": "private", + "description": "Toggle strikethrough formatting" + }, + { + "kind": "field", + "name": "toggleLink", + "privacy": "private", + "description": "Add or edit a link" + }, + { + "kind": "field", + "name": "changeVariant", + "privacy": "private", + "description": "Change the block type/variant" }, { "kind": "method", - "name": "setVirtualTriggerVisible", + "name": "renderToolbar", "privacy": "private", - "parameters": [ - { - "name": "visible", - "type": { - "text": "boolean" - } - } - ] + "description": "Render the formatting toolbar" }, { "kind": "method", - "name": "getAuthoredVirtualCollapse", + "name": "getTag", "privacy": "private", "return": { "type": { - "text": "string | undefined" + "text": "string" } }, - "parameters": [ - { - "name": "record", - "type": { - "text": "ToolbarItemRecord" - } - } - ] + "description": "Get the semantic tag for the current variant" }, { "kind": "method", - "name": "resetVirtualState", - "privacy": "private" + "name": "render" + } + ], + "attributes": [ + { + "name": "variant", + "fieldName": "variant", + "default": "'p'", + "description": "The semantic variant/type of text element", + "type": { + "text": "| 'p'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'h4'\n | 'h5'\n | 'h6'\n | 'code'\n | 'quote'\n | 'label'\n | 'small'" + } }, { - "kind": "method", - "name": "initializeDebugMeasurementState", - "privacy": "private" + "name": "align", + "fieldName": "align", + "default": "'left'", + "description": "Text alignment", + "type": { + "text": "'left' | 'center' | 'right' | 'justify'" + } + }, + { + "name": "color", + "fieldName": "color", + "description": "Text color (CSS value or theme token)", + "type": { + "text": "string" + } + }, + { + "name": "truncate", + "fieldName": "truncate", + "default": "false", + "description": "Whether the text should truncate with ellipsis", + "type": { + "text": "boolean" + } }, { - "kind": "method", - "name": "runDebugMeasurementStep" - }, + "name": "max-lines", + "fieldName": "maxLines", + "description": "Maximum number of lines before truncating (requires truncate=true)", + "type": { + "text": "number" + } + } + ], + "tagName": "le-text", + "events": [], + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "LeText", + "declaration": { + "name": "LeText", + "module": "src/components/le-text/le-text.tsx" + } + }, + { + "kind": "custom-element-definition", + "name": "le-text", + "declaration": { + "name": "LeText", + "module": "src/components/le-text/le-text.tsx" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/components/le-tag/le-tag.tsx", + "declarations": [ + { + "kind": "class", + "description": "A tag/chip component for displaying labels with optional dismiss functionality.", + "name": "LeTag", + "slots": [ + { + "description": "Default slot for custom content (overrides label prop)", + "name": "" + } + ], + "members": [ { "kind": "field", - "name": "handleVirtualDebugClick", - "privacy": "private" - }, - { - "kind": "method", - "name": "clearVirtualMeasurements", - "privacy": "private" - }, - { - "kind": "method", - "name": "settleVirtualItem", - "privacy": "private", - "parameters": [ - { - "name": "element", - "optional": true, - "type": { - "text": "HTMLElement" - } - } - ] - }, - { - "kind": "method", - "name": "waitForNestedCustomElements", - "privacy": "private", - "parameters": [ - { - "name": "root", - "type": { - "text": "HTMLElement" - } - } - ] + "name": "label", + "type": { + "text": "string | undefined" + }, + "description": "The text label to display in the tag." }, { - "kind": "method", - "name": "syncVirtualTriggerContent", - "privacy": "private" + "kind": "field", + "name": "mode", + "type": { + "text": "'default' | 'admin' | undefined" + }, + "description": "Mode of the popover should be 'default' for internal use" }, { - "kind": "method", - "name": "prepareToolbarItems", - "privacy": "private" + "kind": "field", + "name": "icon", + "type": { + "text": "string | undefined" + }, + "description": "Icon to display before the label.\nCan be an emoji, URL, or icon name." }, { - "kind": "method", - "name": "getVisibilityState", - "privacy": "private", - "return": { - "type": { - "text": "'visible' | 'collapsed'" - } + "kind": "field", + "name": "dismissible", + "type": { + "text": "boolean" }, - "parameters": [ - { - "name": "value", - "type": { - "text": "string | null" - } - } - ] + "default": "false", + "description": "Whether the tag can be dismissed (shows close button)." }, { - "kind": "method", - "name": "calculateLayoutWidths", - "privacy": "private" + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether the tag is disabled." }, { - "kind": "method", - "name": "computeLayout", - "privacy": "private" + "kind": "field", + "name": "size", + "type": { + "text": "'small' | 'medium' | 'large'" + }, + "default": "'medium'", + "description": "The size of the tag." }, { - "kind": "method", - "name": "applyOutput", - "privacy": "private", - "parameters": [ - { - "name": "output", - "type": { - "text": "SolverOutput" - } - }, - { - "name": "overflowItems", - "type": { - "text": "LeOption[]" - } - } - ] + "kind": "field", + "name": "color", + "type": { + "text": "| 'default'\n | 'primary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'secondary'\n | 'info'" + }, + "default": "'default'", + "description": "The color of the tag." }, { "kind": "field", - "name": "handleOverflowSelect", + "name": "handleDismiss", "privacy": "private" }, { "kind": "method", - "name": "renderVirtualToolbar", + "name": "renderIcon", "privacy": "private" }, { @@ -17042,125 +17053,94 @@ ], "attributes": [ { - "name": "items", - "fieldName": "items", - "description": "Optional declarative items input.\n\nThe current implementation is slot-driven, but when this prop changes we\nstill invalidate the slotted-items cache and recompute layout.", - "type": { - "text": "unknown" - } - }, - { - "name": "align-items", - "fieldName": "alignItems", - "default": "'start'", - "description": "Alignment of items along the main axis.", + "name": "label", + "fieldName": "label", + "description": "The text label to display in the tag.", "type": { - "text": "'start' | 'center' | 'end' | 'stretch'" + "text": "string" } }, { - "name": "item-gap", - "fieldName": "itemGap", - "default": "'var(--le-toolbar-gap, var(--le-spacing-1, 4px))'", - "description": "Spacing between top-level toolbar items.\nAccepts any valid CSS length (e.g. `8px`, `0.5rem`, `var(--le-spacing-2)`).", + "name": "mode", + "fieldName": "mode", + "description": "Mode of the popover should be 'default' for internal use", "type": { - "text": "string" + "text": "'default' | 'admin'" } }, { - "name": "overflow-icon", - "fieldName": "overflowIcon", - "default": "'ellipsis-horizontal'", - "description": "Icon for the overflow trigger button when no custom slot content is provided.", + "name": "icon", + "fieldName": "icon", + "description": "Icon to display before the label.\nCan be an emoji, URL, or icon name.", "type": { "text": "string" } }, { - "name": "overflow-label", - "fieldName": "overflowLabel", - "default": "'More'", - "description": "Accessible label for the overflow trigger button.", + "name": "dismissible", + "fieldName": "dismissible", + "default": "false", + "description": "Whether the tag can be dismissed (shows close button).", "type": { - "text": "string" + "text": "boolean" } }, { - "name": "disable-popover", - "fieldName": "disablePopover", + "name": "disabled", + "fieldName": "disabled", "default": "false", - "description": "Disable the built-in overflow popover.\nThe toolbar will still compute overflow state and emit events, but\nwon't render its own menu. Useful for custom overflow handling.", + "description": "Whether the tag is disabled.", "type": { "text": "boolean" } }, { - "name": "debug-virtual-toolbar", - "fieldName": "debugVirtualToolbar", - "default": "false", - "description": "Temporary debug mode: render the virtual toolbar visibly above\nthe live toolbar so collapse measurements can be inspected.", + "name": "size", + "fieldName": "size", + "default": "'medium'", + "description": "The size of the tag.", "type": { - "text": "boolean" + "text": "'small' | 'medium' | 'large'" } }, { - "name": "debug-pause-before-measure", - "fieldName": "debugPauseBeforeMeasure", - "default": "false", - "description": "Temporary debug mode: stop before measuring virtual widths so the\nvirtual DOM can be inspected before collapse simulation mutates it.", + "name": "color", + "fieldName": "color", + "default": "'default'", + "description": "The color of the tag.", "type": { - "text": "boolean" + "text": "| 'default'\n | 'primary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'secondary'\n | 'info'" } } ], - "tagName": "le-toolbar", + "tagName": "le-tag", "events": [ { - "name": "leToolbarOverflowChange", + "name": "leDismiss", "type": { - "text": "EventEmitter | undefined" + "text": "EventEmitter | undefined" }, - "description": "Emitted when the overflow state changes." + "description": "Emitted when the dismiss button is clicked." } ], "customElement": true - }, - { - "kind": "variable", - "name": "slotName", - "default": "`__le-toolbar-item-${index}`" - }, - { - "kind": "variable", - "name": "priority" - }, - { - "kind": "variable", - "name": "kind", - "type": { - "text": "ToolbarItemRecord['kind']" - } - }, - { - "kind": "variable", - "name": "overflowOption" } ], "exports": [ { "kind": "js", - "name": "LeToolbar", + "name": "LeTag", "declaration": { - "name": "LeToolbar", - "module": "src/components/le-toolbar/le-toolbar.tsx" + "name": "LeTag", + "module": "src/components/le-tag/le-tag.tsx" } }, { "kind": "custom-element-definition", - "name": "le-toolbar", + "name": "le-tag", "declaration": { - "name": "LeToolbar", - "module": "src/components/le-toolbar/le-toolbar.tsx" + "name": "LeTag", + "module": "src/components/le-tag/le-tag.tsx" } } ] From 562b7993eb222e9915faf6b312f4860bdc528778 Mon Sep 17 00:00:00 2001 From: Andrey Lechev Date: Sun, 7 Jun 2026 16:09:55 +0200 Subject: [PATCH 7/7] Add docs for --- apps/docs/src/data/navigation.ts | 1 + .../pages/components/le-context-menu.astro | 305 ++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 apps/docs/src/pages/components/le-context-menu.astro diff --git a/apps/docs/src/data/navigation.ts b/apps/docs/src/data/navigation.ts index 1161f20..b51f2a4 100644 --- a/apps/docs/src/data/navigation.ts +++ b/apps/docs/src/data/navigation.ts @@ -120,6 +120,7 @@ export const componentsNavigationItems: NavItem[] = [ children: [ { label: "Popover", href: "/components/le-popover" }, { label: "Popup", href: "/components/le-popup" }, + { label: "Context Menu", href: "/components/le-context-menu" }, ], }, { diff --git a/apps/docs/src/pages/components/le-context-menu.astro b/apps/docs/src/pages/components/le-context-menu.astro new file mode 100644 index 0000000..66cdd89 --- /dev/null +++ b/apps/docs/src/pages/components/le-context-menu.astro @@ -0,0 +1,305 @@ +--- +import ComponentsPage from "../../layouts/ComponentsPage.astro"; +import CodeBlock from "../../components/CodeBlock.astro"; +--- + + +

<le-context-menu>

+

+ A custom component that triggers a vertical navigation menu upon right-clicking (mouse/desktop) + or long-pressing (touch/mobile) its children. It is built on top of <le-popover> + and <le-navigation>. +

+ +

Examples

+ +

Standard Right-Click Menu

+

+ Right-click inside the dashed area below to trigger the context menu. By default, the menu positions itself next to the mouse click. +

+ +
+ +
+ Right-click here to open the menu. +
+
+ + +
+ + +
Right-click here.
+
+ + +`} + /> + +

iOS-Style Touch Long-Press with Backdrop

+

+ On touch interfaces, long-pressing triggers the menu. The backdrop property dims the screen and lifts the active item above the backdrop overlay, matching native mobile UI patterns. +

+ +
+ +
+ Long-press (touch) or right-click here. +
+
+
+ + +
Long-press or right-click here.
+ +`} + /> + +

Page Scroll Behavior

+

+ You can customize what happens to the menu when the user scrolls the page. Use the page-scroll-behavior property: +

+
    +
  • menu-close (default) — Closes the context menu automatically when page scrolling is detected.
  • +
  • fixed-menu — The context menu remains open and moves relative to the scrolling page/trigger.
  • +
  • blocked — Blocks scroll interactions on the document body entirely while the menu is open.
  • +
+ +
+
+ + Scroll: Close (menu-close) + + + + Scroll: Follow (fixed-menu) + + + + Scroll: Blocked (blocked) + +
+
+ + + + Scroll Close + + + + + Scroll Follow + + + + + Scroll Blocked + +`} + /> + +

Positioning and Alignment Options

+

+ When you specify a layout position other than mouse, the menu aligns itself relative to the trigger element's bounding box. You can configure both position (top, bottom, left, right) and align (start, center, end): +

+ +
+
+ + Top Center + + + + Bottom End + + + + Right Start + +
+
+ + + + Top Center + + + + + Bottom End + + + + + Right Start + +`} + /> + +

Properties / Attributes

+ +

@open

+

+ Controls the visibility of the menu. Reflects as an attribute. Can be toggled programmatically. +

+
    +
  • Type: boolean
  • +
  • Default: false
  • +
+ +

@disabled

+

+ When present or set to true, blocks right-click and touch long-press triggers. +

+
    +
  • Type: boolean
  • +
  • Default: false
  • +
+ +

@items

+

+ An array of menu options to display. Supports nested icons, actions, selection states (checkmarks), and disabling. Passed as a JSON string in HTML or an array in frameworks. +

+
    +
  • Type: LeOption[] | string
  • +
  • Default: []
  • +
+ +

@backdrop

+

+ Whether to show a dimming overlay behind the menu, lifting the active trigger item above the backdrop overlay. +

+
    +
  • Type: boolean
  • +
  • Default: false
  • +
+ +

@page-scroll-behavior

+

+ Determines how the menu reacts when the page is scrolled: +

+
    +
  • menu-close (default) — Closes the context menu automatically when page scrolling is detected.
  • +
  • fixed-menu — The context menu remains open and smoothly scrolls/moves along with the page.
  • +
  • blocked — Blocks scroll interactions on the document body entirely while the menu is open.
  • +
+ +

@position

+

+ Placement direction relative to the trigger container. +

+
    +
  • mouse (default) — Dynamic placement following the click coordinate. Falls back to bottom alignment on touch devices.
  • +
  • top, bottom, left, right — Align next to the specified side of the trigger boundary box.
  • +
+ +

@align

+

+ Alignment relative to the target boundary: start (default), center, or end. +

+ +

Slots

+ +

Default Slot

+

+ The trigger content. Any DOM nodes placed in this slot will act as the right-click/long-press trigger zone. +

+ +

Events

+ +

leContextMenuSelect

+

+ Fired when a menu navigation item is selected. +

+ + +

leContextMenuClose

+

+ Fired when the context menu is closed. +

+