presentation/widgets/home.widget.ts
presentation/widgets/home.widget.ts is a file in Bane's Lab Site. 77 lines of code and 22 definitions.
import { JUMP_SELECTOR, MAP_SELECTOR } from "#core/ids/home.ids";
import type { LaidStop, LearningView, PlacedStop } from "#types/learning.types";
import { ROUTE_CHANGED, ROUTE_REQUESTED } from "#core/ids/route.ids";
import { emitEvent, subscribeEvent } from "#core/buses/base.bus";
import type { Disposer } from "#types/base.types";
import { HOME_PAGE } from "#core/ids/page.ids";
import { HREF_ATTRIBUTE } from "#configuration/constants/element.constants";
import { LEARNING } from "#core/generated/learning.generated";
import { attachHome } from "#presentation/components/home.component";
import { attachLearningMap } from "#presentation/components/learning.component";
import { attachPrerequisites } from "#presentation/components/learning.fragment.component";
import { layoutLearning } from "#domain/converters/learning.converter";
import { pageFromPath } from "#core/assets/link.assets";
const VECTOR_SELECTOR = "svg";
const TRACE_SELECTOR = ".learning-trace";
const placedOf = function placedOf(shell: Element, stop: LaidStop, block: PlacedStop["block"]): PlacedStop | null {
const node = shell.querySelector(`#${stop.id}`);
return node === null ? null : { ...stop, block, node };
};
const viewOf = function viewOf(shell: Element): LearningView | null {
const vector = shell.querySelector(VECTOR_SELECTOR);
const trace = shell.querySelector(TRACE_SELECTOR);
if (vector === null || trace === null) {
return null;
}
const stops = layoutLearning(LEARNING).blocks.flatMap((block) =>
block.stops.flatMap((stop) => {
const placed = placedOf(shell, stop, block);
return placed === null ? [] : [placed];
}),
);
return { stops, trace, vector };
};
const idle: Disposer = () => {};
const onClick = function onClick(event: Event): void {
const { target } = event;
const jump = target instanceof Element ? target.closest(JUMP_SELECTOR) : null;
const href = jump?.getAttribute(HREF_ATTRIBUTE) ?? "";
if (href.length === 0) {
return;
}
event.preventDefault();
emitEvent({ name: ROUTE_REQUESTED, page: pageFromPath(href, HOME_PAGE), path: href });
};
const routeMap = function routeMap(shell: Element): Disposer {
shell.addEventListener("click", onClick);
return () => {
shell.removeEventListener("click", onClick);
};
};
const wire = function wire(main: Element): Disposer {
const shell = main.querySelector(MAP_SELECTOR);
const view = shell === null ? null : viewOf(shell);
const disposers = [attachHome(main)];
if (shell !== null) {
disposers.push(routeMap(shell));
}
if (shell !== null && view !== null) {
disposers.push(attachLearningMap(shell, view), attachPrerequisites(view));
}
return () => {
for (const dispose of disposers) {
dispose();
}
};
};
export const mountHome = function mountHome(main: Element): Disposer {
let dispose = idle;
const unsubscribe = subscribeEvent(ROUTE_CHANGED, (event) => {
dispose();
dispose = event.page === HOME_PAGE ? wire(main) : idle;
});
return () => {
dispose();
unsubscribe();
};
};