# presentation/widgets/home.widget.ts

> 76 lines of code and 21 definitions.

Tree: Site tree
Language: typescript
Layer: product
Canonical: https://banes-lab.com/anatomy/tree#file-presentation-widgets-home-widget-ts
Source text: https://banes-lab.com/assets/sources/source.64bc0f63090a86fe00a86875fd53cc99a9df96c2ca9081f15e6b0fefbad60649.generated.txt

## Definitions

- `dispose` (lexical_declaration, line 73, exported)
- `routeMap` (lexical_declaration, line 38)
- `unsubscribe` (lexical_declaration, line 74, exported)
- `wire` (lexical_declaration, line 55)
- `onClick` (lexical_declaration, line 39)
- `mountHome` (lexical_declaration, line 72, exported)
- `VECTOR_SELECTOR` (lexical_declaration, line 15)
- `TRACE_SELECTOR` (lexical_declaration, line 16)
- `placedOf` (lexical_declaration, line 18)
- `node` (lexical_declaration, line 19)
- `viewOf` (lexical_declaration, line 23)
- `vector` (lexical_declaration, line 24)
- `trace` (lexical_declaration, line 25)
- `stops` (lexical_declaration, line 29)
- `placed` (lexical_declaration, line 31)
- `{ target }` (lexical_declaration, line 40)
- `jump` (lexical_declaration, line 41)
- `href` (lexical_declaration, line 42)
- `shell` (lexical_declaration, line 56)
- `view` (lexical_declaration, line 57)
- `disposers` (lexical_declaration, line 58)

## Uses

- [core/assets/link.assets.ts](https://banes-lab.com/source/tree/core/assets/link.assets.ts.md)
- [core/buses/base.bus.ts](https://banes-lab.com/source/tree/core/buses/base.bus.ts.md)
- [presentation/components/learning.component.ts](https://banes-lab.com/source/tree/presentation/components/learning.component.ts.md)
- [presentation/components/learning.fragment.component.ts](https://banes-lab.com/source/tree/presentation/components/learning.fragment.component.ts.md)

## Used by

- [presentation/components/home.component.ts](https://banes-lab.com/source/tree/presentation/components/home.component.ts.md)
- [presentation/widgets/overlay.widget.ts](https://banes-lab.com/source/tree/presentation/widgets/overlay.widget.ts.md)
- [runtime/entrypoints/site.entrypoint.ts](https://banes-lab.com/source/tree/runtime/entrypoints/site.entrypoint.ts.md)

## Source

```typescript
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 "#assets/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 "#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 routeMap = function routeMap(shell: Element): 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 });
    };
    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: Disposer = () => {};
    const unsubscribe = subscribeEvent(ROUTE_CHANGED, (event) => {
        dispose();
        dispose = event.page === HOME_PAGE ? wire(main) : () => {};
    });
    return () => {
        dispose();
        unsubscribe();
    };
};
```
