import { ANATOMY_CARD, ARCHITECTURE_CARD, AUTHOR_NAME, DEVELOPED_BY, GRAMMAR_CARD, HOME_HEADING, INFORMATION_LINK, LIST_FINAL_SEPARATOR, LIST_SEPARATOR, METHODOLOGY_CARD, ONTOLOGY_CARD, PLATFORM_LINKS_LEAD, PRIVACY_LINK, SENTENCE_END, TERMS_LINK, VIEW_PREFIX, } from "#configuration/strings/home.strings"; import { ANATOMY_CARD_LINK, ARCHITECTURE_CARD_LINK, GRAMMAR_CARD_LINK, METHODOLOGY_CARD_LINK, ONTOLOGY_CARD_LINK, } from "#configuration/icons/home.icons"; import { BOUNCE_IN, FADE_IN, FADE_IN_UP, FADE_IN_UP_LARGE, HIGH_PRIORITY, PRIORITY_ATTRIBUTE, SCALE_IN, } from "#configuration/constants/element.constants"; import { CHEVRON_ICON, ICON_BASE_CLASS } from "#configuration/icons/element.icons"; import { HOME_DESCRIPTION, HOME_TITLE } from "#configuration/strings/page.strings"; import { HOME_PAGE, INFORMATION_PAGE, PRIVACY_PAGE, TERMS_PAGE } from "#core/ids/page.ids"; import type { HomeCardCopy, HomeCardLink } from "#types/home.types"; import { createExternalLink, createPageLink } from "#presentation/components/link.component"; import { AUTHOR_PROFILE } from "#assets/link.assets"; import { BADGE_LOGO } from "#assets/image.assets"; import type { PageDefinition } from "#types/page.types"; import { animated } from "#presentation/renderers/element.renderer"; import { createElement } from "#core/factories/element.factory"; const CARD_BASE_DELAY = 100; const CARD_STEP_DELAY = 150; const DELAY_ICON = 50; const DELAY_TITLE = 90; const DELAY_SUBTITLE = 125; const DELAY_DESCRIPTION = 160; const DELAY_EXAMPLES = 200; const DELAY_EXAMPLE_STEP = 30; const DELAY_AUDIENCE = 310; const DELAY_BUTTON = 350; const DELAY_HEADING = 150; const DELAY_LEAD = 200; const DELAY_FOOTER = 550; const DELAY_CREATOR = 650; const DELAY_LINKS = 700; const cardHeader = function cardHeader(copy: HomeCardCopy, link: HomeCardLink, base: number): HTMLElement { const icon = animated("div", { className: "card-icon-wrapper" }, SCALE_IN, base + DELAY_ICON); icon.append(createElement("i", { className: `${link.icon} card-icon` })); const titles = createElement("div", { children: [ animated("h2", { className: "card-title", text: copy.title }, FADE_IN_UP, base + DELAY_TITLE), animated("p", { className: "card-subtitle", text: copy.subtitle }, FADE_IN, base + DELAY_SUBTITLE), ], className: "card-title-group", }); return createElement("div", { children: [icon, titles], className: "card-header" }); }; const cardExamples = function cardExamples(copy: HomeCardCopy, base: number): HTMLElement { const lines = copy.examples.map((example, index) => animated( "div", { className: "example-line", text: example }, FADE_IN_UP, base + DELAY_EXAMPLES + index * DELAY_EXAMPLE_STEP, ), ); return createElement("div", { children: lines, className: "card-examples" }); }; const cardFooter = function cardFooter(copy: HomeCardCopy, link: HomeCardLink, base: number): HTMLElement { const button = createPageLink(link.page, "card-button", [ createElement("span", { text: VIEW_PREFIX + copy.title }), createElement("i", { className: `${ICON_BASE_CLASS} ${CHEVRON_ICON}` }), ]); const wrapped = animated("div", { children: [button] }, FADE_IN_UP, base + DELAY_BUTTON); return createElement("div", { children: [ animated("p", { className: "card-audience", text: copy.audience }, FADE_IN, base + DELAY_AUDIENCE), wrapped, ], className: "card-footer", }); }; const card = function card(copy: HomeCardCopy, link: HomeCardLink, base: number): HTMLElement { const content = createElement("div", { children: [ cardHeader(copy, link, base), animated( "p", { className: "card-description", text: copy.description }, FADE_IN_UP, base + DELAY_DESCRIPTION, ), cardExamples(copy, base), cardFooter(copy, link, base), ], className: "card-content", }); const overlay = createElement("div", { className: "card-gradient-overlay" }); return animated( "div", { children: [overlay, content], className: `home-card ${link.accent}` }, FADE_IN_UP_LARGE, base, ); }; const footer = function footer(): HTMLElement { const creator = animated("p", { className: "footer-creator" }, FADE_IN, DELAY_CREATOR); creator.append(DEVELOPED_BY, createExternalLink(AUTHOR_PROFILE, "footer-link", [AUTHOR_NAME])); const links = animated("p", { className: "footer-links-text" }, FADE_IN, DELAY_LINKS); links.append( PLATFORM_LINKS_LEAD, createPageLink(TERMS_PAGE, "footer-link", [TERMS_LINK]), LIST_SEPARATOR, createPageLink(PRIVACY_PAGE, "footer-link", [PRIVACY_LINK]), LIST_FINAL_SEPARATOR, createPageLink(INFORMATION_PAGE, "footer-link", [INFORMATION_LINK]), SENTENCE_END, ); return animated("div", { children: [creator, links], className: "home-footer" }, FADE_IN_UP, DELAY_FOOTER); }; const renderHome = function renderHome(): Element { const logo = animated( "img", { attributes: { alt: HOME_HEADING, [PRIORITY_ATTRIBUTE]: HIGH_PRIORITY, src: BADGE_LOGO }, className: "home-logo", }, BOUNCE_IN, ); const heading = animated("h1", { className: "home-title", text: HOME_HEADING }, FADE_IN_UP, DELAY_HEADING); const lead = animated("p", { className: "home-lead", text: HOME_DESCRIPTION }, FADE_IN, DELAY_LEAD); const header = createElement("header", { children: [logo, heading, lead], className: "home-header" }); const cardSet: readonly [HomeCardCopy, HomeCardLink][] = [ [GRAMMAR_CARD, GRAMMAR_CARD_LINK], [METHODOLOGY_CARD, METHODOLOGY_CARD_LINK], [ARCHITECTURE_CARD, ARCHITECTURE_CARD_LINK], [ONTOLOGY_CARD, ONTOLOGY_CARD_LINK], [ANATOMY_CARD, ANATOMY_CARD_LINK], ]; const cards = createElement("div", { children: cardSet.map(([copy, link], index) => card(copy, link, CARD_BASE_DELAY + CARD_STEP_DELAY * index)), className: "home-cards-grid", }); const main = createElement("div", { children: [cards, footer()], className: "home-main" }); return createElement("div", { children: [header, main], className: "home-content" }); }; export const PAGE: PageDefinition = { content: { cards: [GRAMMAR_CARD, METHODOLOGY_CARD, ARCHITECTURE_CARD, ONTOLOGY_CARD, ANATOMY_CARD], heading: HOME_HEADING, kind: "home", lead: HOME_DESCRIPTION, }, description: HOME_DESCRIPTION, id: HOME_PAGE, render: renderHome, title: HOME_TITLE, };