import{type PropertyValues,type TemplateResult}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';export interface LyraAppRailGroupToggleDetail{open:boolean;}export interface LyraAppRailGroupEventMap{'lr-toggle-request':CustomEvent;'lr-toggle':CustomEvent;} /** * `` — a titled section of navigation items inside ``. * * Grouping is by COMPOSITION: a group holds whatever it is given (``s, nested * groups, anything else a consumer slots), and has no items array, no renderer callback and no * model of its own. Nothing about its contents is described twice, so a group can never disagree * with what is actually rendered inside it. * * The group names itself with a real heading landmark (`role="heading"` plus a settable * `aria-level`, not a hard-wired `

` whose level would be wrong in half the pages that embed a * rail), and labels its own `role="group"` container from that same heading — so a screen-reader * user reaches "Workspaces, group" instead of an unnamed run of links. * * `collapsible` opts in the standard disclosure shape: the heading's own text becomes a button * carrying `aria-expanded` and `aria-controls`, exactly as the accordion pattern prescribes, * rather than a separate unlabeled chevron next to an inert title. Collapsing goes through the * library's request/commit pair, so a consumer can veto it (`preventDefault()`) or resolve it * itself by assigning `open` from the request listener. * * The owning rail marks a slotted group `icon-only` the same way it marks a slotted item, and the * group forwards that to the items and nested groups it DIRECTLY owns — including ones appended * later — so composition survives the rail's icon-only presentation without the rail having to * reach through it. A nested group re-forwards in turn, so exactly one element ever writes * `icon-only` onto any given node and a nested group clips its own heading too. * * @customElement lr-app-rail-group * @slot - The group's navigation items. `` and nested `` * children mirror the group's `icon-only` state automatically; anything else is rendered as * given. * @slot heading - Rich heading content, replacing the `heading` property. Becomes the collapse * control's own accessible name while `collapsible` is set. * @slot header-actions - Controls rendered beside the heading — an "add" button, an overflow menu. * A SIBLING of the heading (and so of the collapse control inside it), matching ``'s * header-actions shape, so activating one never toggles the group. * @event lr-toggle-request - Cancelable proposal emitted before `open` changes from the built-in * collapse control. Call `preventDefault()` to keep the current state, or assign `open` from the * listener to resolve it yourself — a write during the dispatch suppresses the default commit * even when it assigns the value the property already held. Not emitted for a direct `open` * write. `detail: LyraAppRailGroupToggleDetail`. * @event lr-toggle - The group finished opening or closing. Non-cancelable, emitted after `open` * is written, and never emitted for a vetoed or listener-resolved request. * `detail: LyraAppRailGroupToggleDetail`. * @csspart base - The `role="group"` container. * @csspart header - The row holding the heading and any header actions. * @csspart heading - The heading landmark. Carries `role="heading"` and `aria-level`. * @csspart heading-text - The wrapper around the heading text/slot; visually clipped while * `icon-only`, keeping the group's accessible name intact. * @csspart toggle - The collapse control, only rendered while `collapsible` is set. Renders * `aria-expanded` in both states and takes its accessible name from the heading text. Resolves * to a square hit target (matching the icon-button footprint used elsewhere in this library) * while `icon-only`, instead of stretching across the header row. * @csspart toggle-icon - The wrapper around the collapse chevron. Direction-aware through this * wrapper's own `transform`, never a second mirrored glyph. * @csspart header-actions - The wrapper around the `header-actions` slot. Hidden while empty. * @csspart content - The collapsible region holding the default slot. * @cssprop [--lr-app-rail-group-gap=var(--lr-space-xs)] - Gap between the group's own items. * @cssprop [--lr-app-rail-group-padding-block=var(--lr-space-xs)] - Block padding around * `[part="base"]`. * @cssprop [--lr-app-rail-group-heading-color=var(--lr-color-text-quiet)] - Heading text color. * @cssprop [--lr-app-rail-group-heading-font-size=var(--lr-font-size-sm)] - Heading font size. * @cssprop [--lr-app-rail-group-hover-bg=var(--lr-color-brand-quiet)] - Collapse-control hover * background. * @cssprop [--lr-app-rail-group-hover-color=var(--lr-color-brand)] - Collapse-control hover * foreground. * @cssprop --lr-app-rail-group-active-bg - Collapse-control pressed background; defaults to the * same brand-quiet active mix the rest of the rail uses. * @cssprop [--lr-app-rail-group-active-color=var(--lr-color-brand)] - Collapse-control pressed * foreground. * * @example * ```html * * * One * Two * * * ``` * @status experimental * @since 16.0.0 */ export declare class LyraAppRailGroup extends LyraElement{static styles:import("lit").CSSResultGroup[];static get observedAttributes():string[]; /** The group's heading text. The `heading` slot replaces it when populated. */ heading:string; /** The `aria-level` the heading landmark reports. A rail sits at a different depth in every * page that embeds it, so the level is settable rather than baked into a fixed `

`. * Clamped to the 1-6 range a heading can actually carry, and rounded; a non-finite value falls * back to the default. * @default 3 */ headingLevel:number; /** Opts in the built-in collapse control. `false` (the default) renders the heading as inert * text, exactly as a plain section title. `open` still governs whether the content renders, so * a consumer can drive collapse entirely from its own chrome without opting in here. */ collapsible:boolean; /** Whether the group's content is shown. `true` by default — a nav section that hid itself on * first paint would be the surprising default — which is why it carries * `trueDefaultBooleanConverter`: Lit's presence-based boolean converter cannot parse * `open="false"`, so without it the property would be unsettable from markup. * @default true */ get open():boolean;set open(next:boolean);private _open;private readonly toggleGuard;private hasHeadingSlot;private hasHeaderActionsSlot;private headingSlot?;private headerActionsSlot?;private readonly headingId;private readonly contentId;private get safeHeadingLevel();connectedCallback():void;attributeChangedCallback(name:string,oldValue:string|null,newValue:string|null):void;protected updated(changed:PropertyValues):void;protected firstUpdated(changed:PropertyValues):void; /** Mirrors this group's `icon-only` state onto every `` and nested * `` it DIRECTLY owns. The rail cannot reach these itself: * `assignedElements({ flatten: true })` expands nested `` elements, not element children, * so a group's contents never appear in the rail's own assignment list. * * One owner per node, exactly as the rail already treats its own top level. A deep * `querySelectorAll` would let an outer group write `icon-only` onto items a nested group also * writes -- and because that selector matched only items, the nested group never received * `icon-only` itself, so its own next sync (it runs from `connectedCallback`, `updated` and the * default slot's `slotchange`) read `false` and stripped the attribute the outer group had just * set, unclipping every label inside it in a narrow rail. Marking the nested group instead * cascades through that group's own `attributeChangedCallback`, which also gets its heading * clipped -- something the item-only selector could never do. * * Gated on `isConnected` so a detached group stops claiming ownership of nodes appended to it * afterwards. */ private syncOwnedItems; /** `assignedNodes({ flatten: true })` returns a slot's FALLBACK content when nothing is assigned * to it -- and this slot's fallback IS `this.heading`. Reading only the flattened list made the * state oscillate: fallback present -> `hasHeadingSlot` -> render `nothing` as the fallback -> * list empty -> `hasHeadingSlot` false -> render the heading again, forever. WebKit fires * `slotchange` for a fallback-content mutation where Chromium and Firefox do not, so the first * `heading` write after mount hung the page outright there (a microtask loop, so no timer ever * ran again). Gate on the UNFLATTENED list first -- it never contains fallback -- and flatten * only once something really is assigned, which still resolves a consumer's forwarding * `` down to its own (possibly empty) content. */ private onHeadingSlotChange;private applyHeadingSlotPresence;private onHeaderActionsSlotChange;private applyHeaderActionsSlotPresence;private onContentSlotChange;private onToggleClick;render():TemplateResult;}declare global{interface HTMLElementTagNameMap{'lr-app-rail-group':LyraAppRailGroup;}}