/** * Owns everything about moving between closed / open / hidden. * * The host's `state` property changes the instant it is assigned; what the DOM * shows lags behind it for as long as the transition animation runs. That * lagging value is `renderedState`, and the render functions key off it — so a * panel animating out is still in the DOM while `state` already reads 'closed'. * * @implements {ReactiveController} */ export class StateController implements ReactiveController { /** * @param {LitElement & { state: ChatState }} host * @param {StateControllerOptions} options */ constructor(host: LitElement & { state: ChatState; }, { animation, keepsLauncher, onOpened }: StateControllerOptions); /** @returns {ChatState} What the DOM currently shows. */ get renderedState(): ChatState; /** @returns {boolean} True while the host's own setter must not call us back. */ get applying(): boolean; hostConnected(): void; hostDisconnected(): void; hostUpdated(): void; /** * Move to `to`, running the before-event, the animations and the completion * events in order. * * @param {ChatState} to * @param {Trigger} trigger * @returns {Promise} false when a listener cancelled it, or when a * later transition superseded this one. */ request(to: ChatState, trigger: Trigger): Promise; #private; } export type AnimationSpec = { effect: Effect; duration: number; }; export type AnimationResolver = (from: ChatState, to: ChatState, phase: "enter" | "exit") => AnimationSpec; export type StateControllerOptions = { /** * Which effect and duration to play. */ animation: AnimationResolver; /** * True when the launcher stays visible behind an open panel. */ keepsLauncher: () => boolean; /** * Called once the panel is open and settled. */ onOpened: () => void; }; import type { ReactiveController } from 'lit'; import type { ChatState } from '../types.js'; import type { Trigger } from '../types.js'; import type { LitElement } from 'lit'; import type { Effect } from '../types.js';