import { $Container, $ContainerContentType, $ContainerOptions, $EventManager } from "elexis"; export interface $RouteOptions extends $ContainerOptions {} export class $Route> extends $Container { #path: $RoutePathType = ''; #builder?: (record: $RouteRecord) => OrMatrix<$ContainerContentType>; events = new $EventManager<$RouteEventMap>().register('opened', 'closed') readonly rendered: boolean = false; constructor(options?: $RouteOptions) { super('route', options); } path(): $RoutePathType; path

(pathname: P): $Route

: ''>; path(pathname?: $RoutePathType): $RoutePathType | $Route { return $.fluent(this, arguments, () => this.#path, () => this.#path = pathname ?? this.#path ) } builder(builder: (record: $RouteRecord) => OrMatrix<$ContainerContentType>) { this.#builder = builder; return this; } render(options: {params: Path}) { if (this.#builder) this.content(this.#builder({ $route: this, params: options.params })); (this as Mutable<$Route>).rendered = true; return this; } build(options: {params: Path}) { return new $Route({dom: this.dom.cloneNode() as HTMLElement}).self(($route) => { if (this.#builder) $route.builder(this.#builder as any).render({params: options.params as any}) }) } } interface $RouteRecord { $route: $Route; params: Path } interface $RouteEventMap { opened: []; closed: [] } export type $RoutePathType = string | string[]; type PathParams = Path extends `${infer Segment}/${infer Rest}` ? Segment extends `${string}:${infer Param}` ? Record & PathParams : PathParams : Path extends `${string}:${infer Param}` ? Record : {}