import { html, LitElement } from 'lit';
import type { TemplateResult } from 'lit';
import { property } from 'lit/decorators.js';
import { UIRouterLit } from './core.js';
interface UiRouterContextEventDetail {
uiRouter?: UIRouterLit;
}
/**
* @internal
*/
export type UiRouterContextEvent = CustomEvent;
/**
* @hideconstructor
*
* @slot - <ui-router> renders slotted content.
*
* @fires {CustomEvent} ui-router-context
*
* <ui-router> listens to the
* ui-router-context event
* and provides the uiRouter instance.
*
* @summary
*
* This is the root ui-router component.
*
*/
export class UIRouterLitElement extends LitElement {
/**
* Root uiRouter singleton.
* If not provided, the element creates and assigns a new instance.
*/
@property({ attribute: false })
uiRouter: UIRouterLit | undefined;
/** @internal */
static uiRouterContextEventName = 'ui-router-context';
/** @internal */
static uiRouterContextEvent(uiRouter?: UIRouterLit): UiRouterContextEvent {
return new CustomEvent(this.uiRouterContextEventName, {
bubbles: true,
composed: true,
detail: {
uiRouter,
},
});
}
/**
* Discovers the {@link UIRouterLit} instance provided by the nearest
* enclosing <ui-router> element.
*
* Dispatches a bubbling, composed ui-router-context event from
* the candidate element; the enclosing <ui-router>
* answers it with its router instance. Returns undefined when
* the candidate is not inside a <ui-router> (e.g. not
* yet connected).
*
* This is the dependency-injection primitive for integrating external
* reactivity systems (state stores, controllers) with the router context —
* call it from hostConnected() / connectedCallback()
* instead of prop-drilling the router instance.
*/
static seekRouter(candidate: Element): UIRouterLit | undefined {
const uiRouterContextEvent = this.uiRouterContextEvent();
candidate.dispatchEvent(uiRouterContextEvent);
return uiRouterContextEvent.detail.uiRouter;
}
/** @internal */
static onUiRouterContextEvent(
uiRouter?: UIRouterLit,
): (event: UiRouterContextEvent) => void {
return (event: UiRouterContextEvent) => {
event.stopPropagation();
event.detail.uiRouter = uiRouter;
};
}
private readonly onUiRouterContextEvent = (event: UiRouterContextEvent) => {
this.constructor.onUiRouterContextEvent(this.uiRouter)(event);
};
/** @internal */
connectedCallback(): void {
super.connectedCallback();
this.uiRouter = this.uiRouter || new UIRouterLit();
this.addEventListener(
this.constructor.uiRouterContextEventName,
this.onUiRouterContextEvent as EventListener,
);
this.dispatchEvent(this.constructor.uiRouterContextEvent(this.uiRouter));
}
/** @internal */
render(): TemplateResult {
return html``;
}
}
export interface UIRouterLitElement {
/** @internal */
constructor: typeof UIRouterLitElement;
}