UNPKG

@bespunky/angular-zen

Version:

The Angular tools you always wished were there.

128 lines (120 loc) 6.03 kB
import { filter, Observable, switchMap, merge, map, shareReplay } from 'rxjs'; import { inject } from '@angular/core'; import { Router, ActivatedRoute, NavigationEnd } from '@angular/router'; import { RouterOutletComponentBus } from '@bespunky/angular-zen/router-x'; /** * Creates an observable which emits only the specified routing event. * * @export * @template T The type of router event to observe. * @param {Type<T>} eventType The type of router event to observe. * @return {Observable<T>} An observable which emits only the specified routing event. */ function useRouterEvent(eventType) { const router = inject(Router); return router.events.pipe(filter((event) => event instanceof eventType)); } /** * Recoursively runs a processing function on the route and its children. * Scan is done from parent to child, meaning the parent is the first to process. * * @export * @param {(RouterOutletComponentBus | null)} componentBus The instance of the component bus. * @param {ActivatedRouteSnapshot} route The top route on which to apply the processing function. * @param {RouteProcessFunction} process The function to run on the route and its children. * The function receives a `route` argument which reflects the route being processed, * and a `component` argument which reflects the instance of the component loaded for the route's corresponsind outlet. * If the corresponding outlet wasn't marked with the `publishComponent` directive, the `component` argument will be null. * @param {number} [levels=-1] (Optional) The number of levels (excluding the parent) to dive deeper into the route tree. * A value of 1 for example, will process the route and its first-level children only. By default, scans all levels of the route tree. */ function deepScanRoute(componentBus, route, process, levels = -1) { // Make sure the caller wants scan to proceed, then make sure level limit wasn't reached. const processing = process(route, componentBus === null || componentBus === void 0 ? void 0 : componentBus.instance(route.outlet)); // Negative values will scan all, positives will scan until reaching zero. const shouldScanChildren = !processing.done && levels !== 0; if (shouldScanChildren && route.children) route.children.forEach(childRoute => deepScanRoute(componentBus, childRoute, process, levels - 1)); } function observeRouteDeepScan(route, componentBus, process, levels) { return new Observable(({ next, error, complete }) => { const processAndEmit = (...args) => { const result = process(...args); if (result.emit) next(result.emit); return result; }; try { deepScanRoute(componentBus, route, processAndEmit, levels); } catch (e) { error(e); } finally { complete(); } }); } /** * Creates an observable which, upon navigation end, deep scans the activated route by running the provided * processing function. * * @export * @template TResult The type of the value emitted by the provided processing function. * @param {ObservedRouteProcessFunction<TResult>} process The function to run on the activated route and its children. * @param {number} [levels=-1] (Optional) The number of levels (excluding the parent) to dive deeper into the route tree. * A value of 1 for example, will process the route and its first-level children only. By default, scans all levels of the route tree. * @return {Observable<TResult>} An observable which, upon navigation end, deep scans the activated route by running the provided * processing function. */ function useRouteDeepScan(process, levels = -1) { const route = inject(ActivatedRoute); const componentBus = inject(RouterOutletComponentBus); return useRouterEvent(NavigationEnd).pipe(switchMap(() => observeRouteDeepScan(route.snapshot, componentBus, process, levels))); } /** * Creates an observable which emits only the specified router events. * * @export * @param {readonly [...Events]} eventTypes * @template Events The types of events to observe. * @returns {Observable<TypeInstance<Events[number]>>} An observable which emits only the specified router events. */ function useRouterEvents(...eventTypes) { return inject(Router).events.pipe(filter((event) => eventTypes.some(eventType => event instanceof eventType))); } /** * Creates an observable which emits the latest state of the published router outlets in the app. * The emitted state is a dictionary of outlet names and corresponding component instances. * * @see `PublishComponentDirective` for more details. * * @export * @return {Observable<Map<string, AnyObject | null>>} An observable which emits the latest state of the published router outlets in the app. */ function useRouterOutletStateTracker() { const componentBus = inject(RouterOutletComponentBus); return merge([componentBus.componentPublished, componentBus.componentUnpublished]).pipe(map(() => componentBus.outletsState), shareReplay(1)); } /** * Creates an observable which emits the latest component instance for the currently activated route. * * @see `PublishComponentDirective` for more details. * * @export * @return {Observable<ActivatedRouteWithComponent>} An observable which emits the component instance for the currently activated route. */ function useActivatedRouteComponent() { const componentBus = inject(RouterOutletComponentBus); const route = inject(ActivatedRoute); return useRouterEvent(NavigationEnd).pipe(map(() => ({ component: componentBus.instance(route.outlet), route: route.snapshot })), shareReplay(1)); } // export * from './lib/use-activated-route-component-resolves'; /** * Generated bundle index. Do not edit. */ export { deepScanRoute, useActivatedRouteComponent, useRouteDeepScan, useRouterEvent, useRouterEvents, useRouterOutletStateTracker }; //# sourceMappingURL=bespunky-angular-zen-router-x-utils.mjs.map