import { RawParams, TargetState, Transition, TransitionOptions } from "@uirouter/core"; import { noChange, ElementPart } from "lit"; import { PartInfo } from "lit/directive.js"; import type { DirectiveResult } from "lit/directive.js"; import { AsyncDirective } from "lit/async-directive.js"; import { UIRouterLit } from "./core.js"; import { UiSrefElement, UiSrefTargetEvent } from "./ui-sref.js"; import { UiView } from "./ui-view.js"; /** @internal */ interface TransEvt { evt: string; trans: Transition; status?: SrefStatus; } /** * Event name dispatched when a transition state changes. * @internal */ export declare const TRANSITION_STATE_CHANGE_EVENT = "transitionStateChange"; /** * Enum representing the different stages of a transition. * @internal */ export declare enum TransitionStateChange { /** Transition has started */ start = "start", /** Transition completed successfully */ success = "success", /** Transition failed with an error */ error = "error" } /** * Status object representing the active state of a uiSref link. * * This interface describes the relationship between a link (or container * with links) and the current router state. * * @see {@link uiSrefActive} * @see [[TargetState]] * * @category types */ export interface SrefStatus { /** The sref's target state (or one of its children) is currently active */ active: boolean; /** The sref's target state is currently active */ exact: boolean; /** A transition is entering the sref's target state */ entering: boolean; /** A transition is exiting the sref's target state */ exiting: boolean; /** The enclosed sref(s) target state(s) */ targetStates: TargetState[]; } /** @internal */ export declare function mergeSrefStatus(left: SrefStatus, right: SrefStatus): SrefStatus; /** * Valid `aria-current` token values. * * @see {@link UiSrefActiveParams.ariaCurrentValue} * @see [WAI-ARIA `aria-current`](https://www.w3.org/TR/wai-aria-1.2/#aria-current) * * @category types */ export type AriaCurrentValue = "page" | "step" | "location" | "date" | "time" | "true"; /** * Per-state `aria-current` values, for the rare nav that wants to mark an * ancestor as well as the current page. * * Unlike `activeClasses` and `exactClasses` — which both land in `class` when a * link is exactly active — `aria-current` is one attribute with one value, so * these do not combine: on an exactly-active element `exact` wins and `active` * is not consulted. Each key falls back to its own default when omitted. * * @see {@link UiSrefActiveParams.ariaCurrentValue} * * @category types */ export interface AriaCurrentValues { /** Applied when the exact state is active. Defaults to `'page'` on links. */ exact?: AriaCurrentValue | false; /** * Applied when a child state is active but this one is not the exact match — * `'location'` is the token meant for this. Defaults to `false`. */ active?: AriaCurrentValue | false; } /** * Parameters for the uiSrefActive directive. * * @see {@link uiSrefActive} * * @category types */ export interface UiSrefActiveParams { /** CSS classes to add when the state (or a child state) is active */ activeClasses: string[]; /** CSS classes to add only when the exact state is active */ exactClasses: string[]; /** * The `aria-current` value to set when the **exact** state is active — the * same binding Vue Router's `ariaCurrentValue` uses. * * Defaults to `'page'` on link elements (``, ``, `[role="link"]`). * Pass a value explicitly to apply it to any element; pass `false` to leave * `aria-current` untouched. * * Pass an object to also mark ancestors, which is otherwise off: * `{ exact: 'page', active: 'location' }`. See {@link AriaCurrentValues} — * the two do not combine the way `activeClasses` and `exactClasses` do. * * The directive only removes an `aria-current` it set itself, so a value * authored in the template survives until the directive first writes one of * its own — after that it owns the attribute and clears it when inactive, * warning once. Use `false` to keep an authored value for good. */ ariaCurrentValue?: AriaCurrentValue | false | AriaCurrentValues; /** The state name to check for active status */ state: string; /** State parameters to match */ params?: RawParams; /** Transition options */ options?: TransitionOptions; /** Target states from nested uiSref directives */ targetStates: TargetState[]; } type deregisterFn = () => void; /** * Directive class that adds CSS classes based on active state. * * This directive is used internally by the {@link uiSrefActive} directive function. * It watches the current router state and applies CSS classes to elements * when their associated states are active. * * The directive can operate in two modes: * 1. **Explicit state**: Provide a state name to watch * 2. **Container mode**: Automatically watch nested uiSref directives * * @see {@link uiSrefActive} for the public API * @see [[AsyncDirective]] * @see {@link SrefStatus} * * @category directives */ export declare class UiSrefActiveDirective extends AsyncDirective { element: Element | null; uiRouter: UIRouterLit | undefined; /** @internal */ seekRouter(): void; parentView: UiView | null; /** @internal */ seekParentView(): void; activeClasses: string[]; exactClasses: string[]; /** undefined = default (on for link elements) */ ariaCurrentValue: AriaCurrentValue | false | AriaCurrentValues | undefined; /** * Whether the `aria-current` currently on the element was written by this * directive. Guards against clearing one authored in the template. * * @internal */ private ownsAriaCurrent; /** * Whether the takeover warning has already been emitted. Instance state * rather than a module-level element registry: the directive instance already * lives as long as its part, so this costs nothing extra and pins nothing. * * @internal */ private warnedAriaCurrentTakeover; state: string | undefined; params: RawParams; options: TransitionOptions; active: boolean | undefined; exact: boolean | undefined; entering: boolean | undefined; exiting: boolean | undefined; targetStates: Set; uiSrefs: WeakMap; /** @internal */ _deregisterOnStart: deregisterFn | undefined; /** @internal */ _deregisterOnStatesChanged: deregisterFn | undefined; /** @internal */ constructor(partInfo: PartInfo); /** @internal */ render({ activeClasses, exactClasses, ariaCurrentValue }: Partial): typeof noChange; /** * Resolves one `aria-current` value for the element's current state, or * `false` for none. * * `exact` and `active` are branches of a single decision here, not the union * `classList` gets: an exactly-active element takes the `exact` value and * never falls through to `active`. * * @internal */ private resolveAriaCurrent; /** * Writes, rewrites, or clears `aria-current`. * * Resolving to a single value first is what keeps "no opinion", "explicitly * off" and "not applicable" from each needing their own branch here. * * @internal */ private applyAriaCurrent; /** * Warns the first time this directive takes over an `aria-current` it did not * write. Taking over is deliberate — restoring the previous value when the * state goes inactive would leave an inactive link asserting * `aria-current="page"` — but it is silent, and the loss only surfaces a * navigation later, so it is worth naming once. * * Development builds only, like `uiSref`'s `assignHref` warning. * * @internal */ private warnAriaCurrentTakeover; /** @internal */ getOptions(): TransitionOptions; /** * Given a TransEvt (Transition event: started, success, error) * and a UISref Target State, return a SrefStatus object * which represents the current status of that Sref: * active, activeEq (exact match), entering, exiting * * @internal */ getSrefStatus(event: TransEvt | undefined, srefTarget: TargetState): SrefStatus; /** @internal */ update(part: ElementPart, [{ activeClasses, exactClasses, ariaCurrentValue, state, params, options, targetStates }]: [UiSrefActiveParams]): Promise; /** @internal */ doRender: () => typeof noChange; /** @internal */ _firstUpdated: boolean; /** @internal */ firstUpdated({ targetStates }: Partial): void; /** @internal */ disconnected(): void; /** @internal */ createTransitionStateChangeEvent(evt: TransitionStateChange, trans: Transition): CustomEvent; /** @internal */ onUiSrefTargetEvent: (event: UiSrefTargetEvent) => void; /** @internal */ onTransitionStateChange: (e: Event) => void; /** @internal */ getStatus(transEvt?: TransEvt): SrefStatus | undefined; /** @internal */ onTransitionStart: (trans: Transition) => void; /** @internal */ onStatesChanged: () => void; } /** * Directive that adds CSS classes based on active router state. * * The `uiSrefActive` directive watches the current router state and applies * CSS classes to elements when their associated states are active. It supports * both "active" classes (applied when the state or any child state is active) * and "exact" classes (applied only when the exact state is active). * * On link elements (``, ``, `[role="link"]`) it also sets * `aria-current="page"` while the *exact* state is active, and removes the * attribute otherwise, so assistive technology gets the same "you are here" * signal as the active CSS class. Other elements opt in by passing * `ariaCurrentValue` explicitly. * * **Arguments:** * - `params` - Configuration object (see [[UiSrefActiveParams]]) with activeClasses, exactClasses, ariaCurrentValue, and optional state/params * * @example Basic usage with nested uiSref * ```ts * import { uiSref, uiSrefActive } from 'lit-ui-router'; * import { html } from 'lit'; * * html` * * Home * * ` * ``` * * @example With exact matching * ```ts * html` * * Users * * ` * ``` * * @example Container mode (watches nested uiSref directives) * ```ts * html` * * ` * ``` * * @example Customizing or disabling `aria-current` * ```ts * html` * * * Payment * * * * * * * * * Home * * * * * Users * * * * * Users * * ` * ``` * * Only an `aria-current` this directive wrote is removed again. A template-authored * value therefore survives right up until the directive first writes one of its own — * from that point the directive owns the attribute and will clear it on the next * inactive render. Pair a template-authored value with `ariaCurrentValue: false` to * keep it for good. * * @example Explicit state (without nested uiSref) * ```ts * html` *
* Dashboard content *
* ` * ``` * * @see {@link SrefStatus} * @see {@link UiSrefActiveParams} * @see [[DirectiveResult]] * * @category directives */ export declare const uiSrefActive: (params: Partial) => DirectiveResult; export {}; //# sourceMappingURL=ui-sref-active.d.ts.map