presentation/renderers/home.renderer.ts

presentation/renderers/home.renderer.ts is a file in Bane's Lab Site. 77 lines of code and 13 definitions.

import type { HomeRowCopy, HomeRowLink, HomeStat, HomeTag } from "#types/home.types";
import { createLink, createPageLink } from "#presentation/components/link.component";
import { FADE_IN_UP } from "#configuration/constants/element.constants";
import { RAIL_ID } from "#core/ids/home.ids";
import { SETTLED_TEXT_ATTRIBUTE } from "#configuration/constants/document.constants";
import { STAT_START } from "#configuration/strings/home.strings";
import { animated } from "#presentation/renderers/element.renderer";
import { createElement } from "#core/factories/element.factory";
import { tagsFor } from "#domain/converters/home.converter";

const ROW_STEP = 60;
const STAT_STEP = 60;

const chip = function chip(tag: HomeTag): HTMLElement {
    return createElement("li", {
        children: [createLink(tag.path, "chip chip-link", [tag.label])],
        className: "chip-row",
    });
};

const audienceChip = function audienceChip(label: string): HTMLElement {
    return createElement("li", {
        children: [createElement("span", { className: "chip muted", text: label })],
        className: "audience",
    });
};

const renderRow = function renderRow(copy: HomeRowCopy, link: HomeRowLink, delay: number): HTMLElement {
    const icon = createPageLink(link.page, `page-icon ${link.accent}`, [createElement("i", { className: link.icon })]);
    icon.setAttribute("aria-label", copy.title);
    const heading = createElement("h2", {
        children: [
            createPageLink(link.page, "row-title", [copy.title]),
            createElement("small", { text: copy.subtitle }),
        ],
    });
    const chips = createElement("ul", {
        children: [
            ...tagsFor(link.page).map(chip),
            ...(copy.audience === undefined ? [] : [audienceChip(copy.audience)]),
        ],
        className: "chips",
    });
    const go = createPageLink(link.page, "go", [copy.go]);
    return animated(
        "article",
        { children: [icon, heading, createElement("p", { text: copy.description }), chips, go], className: "home-row" },
        FADE_IN_UP,
        delay,
    );
};

export const renderRows = function renderRows(
    rows: readonly (readonly [HomeRowCopy, HomeRowLink])[],
    base: number,
): HTMLElement {
    const rail = createElement("div", { attributes: { id: RAIL_ID }, className: "home-rail" });
    return createElement("div", {
        children: [rail, ...rows.map(([copy, link], index) => renderRow(copy, link, base + index * ROW_STEP))],
        className: "home-rows",
    });
};

const renderStat = function renderStat(stat: HomeStat, delay: number): HTMLElement {
    return animated(
        "div",
        {
            children: [
                createElement("b", { attributes: { [SETTLED_TEXT_ATTRIBUTE]: String(stat.value) }, text: STAT_START }),
                createElement("span", { text: stat.label }),
            ],
            className: "home-stat",
        },
        FADE_IN_UP,
        delay,
    );
};

export const renderStats = function renderStats(stats: readonly HomeStat[], base: number): HTMLElement {
    return createElement("div", {
        children: stats.map((stat, index) => renderStat(stat, base + index * STAT_STEP)),
        className: "home-stats",
    });
};