(function (global) {
"use strict";
var SUPPORTED_LOCALES = ["en", "ru", "zh", "hi"];
var LABELS = {
en: {
language: "Language",
theme: "Theme",
themeAuto: "Auto",
themeLight: "Light",
themeDark: "Dark",
footerVersion: "Version",
footerSource: "Source on GitHub",
sourceEyebrow: "Open source",
},
ru: {
language: "Язык",
theme: "Тема",
themeAuto: "Авто",
themeLight: "Светлая",
themeDark: "Тёмная",
footerVersion: "Версия",
footerSource: "Исходный код на GitHub",
sourceEyebrow: "Открытый код",
},
zh: {
language: "语言",
theme: "主题",
themeAuto: "自动",
themeLight: "浅色",
themeDark: "深色",
footerVersion: "版本",
footerSource: "GitHub 源代码",
sourceEyebrow: "开源",
},
hi: {
language: "भाषा",
theme: "थीम",
themeAuto: "ऑटो",
themeLight: "लाइट",
themeDark: "डार्क",
footerVersion: "संस्करण",
footerSource: "GitHub पर सोर्स कोड",
sourceEyebrow: "ओपन सोर्स",
},
};
function normalizeLocale(tag) {
var lower = String(tag || "").toLowerCase();
for (var i = 0; i < SUPPORTED_LOCALES.length; i += 1) {
if (lower === SUPPORTED_LOCALES[i] || lower.indexOf(SUPPORTED_LOCALES[i] + "-") === 0) {
return SUPPORTED_LOCALES[i];
}
}
if (lower.indexOf("zh") === 0) return "zh";
return undefined;
}
function detectLocaleFromBrowser() {
var nav = typeof navigator !== "undefined" ? navigator : {};
var languages = nav.languages || (nav.language ? [nav.language] : ["en"]);
for (var i = 0; i < languages.length; i += 1) {
var match = normalizeLocale(languages[i]);
if (match) return match;
}
return "en";
}
function resolveLocale(localePreference) {
var normalized = normalizeLocale(localePreference);
if (normalized) return normalized;
return detectLocaleFromBrowser();
}
function resolveTheme(themePreference) {
if (themePreference === "dark") return "dark";
if (themePreference === "light") return "light";
if (
typeof global.matchMedia === "function" &&
global.matchMedia("(prefers-color-scheme: dark)").matches
) {
return "dark";
}
return "light";
}
function readPreferences() {
if (global.FormalAiPreferences && typeof global.FormalAiPreferences.load === "function") {
return global.FormalAiPreferences.load({});
}
return {};
}
function writePreference(key, value) {
if (!global.FormalAiPreferences || typeof global.FormalAiPreferences.save !== "function") {
return;
}
var current = global.FormalAiPreferences.load({});
current[key] = value;
global.FormalAiPreferences.save(current);
}
function readVersion() {
if (typeof document === "undefined") return "";
var meta = document.querySelector('meta[name="formal-ai-version"]');
var content = meta && meta.getAttribute("content");
if (!content || content.indexOf("__") === 0 || !/^v?\d/.test(content)) return "";
return content.charAt(0).toLowerCase() === "v" ? content.slice(1) : content;
}
function h(tag, props) {
var el = document.createElement(tag);
if (props) {
Object.keys(props).forEach(function (key) {
var value = props[key];
if (value == null || value === false) return;
if (key === "class") {
el.className = value;
} else if (key === "text") {
el.textContent = value;
} else if (key.indexOf("on") === 0 && typeof value === "function") {
el.addEventListener(key.slice(2).toLowerCase(), value);
} else if (value === true) {
el.setAttribute(key, "");
} else {
el.setAttribute(key, String(value));
}
});
}
for (var i = 2; i < arguments.length; i += 1) {
appendChild(el, arguments[i]);
}
return el;
}
function appendChild(parent, child) {
if (child == null || child === false) return;
if (Array.isArray(child)) {
child.forEach(function (item) {
appendChild(parent, item);
});
return;
}
if (typeof child === "string" || typeof child === "number") {
parent.appendChild(document.createTextNode(String(child)));
return;
}
parent.appendChild(child);
}
function segmentedControl(options, activeValue, onSelect, ariaLabel, className) {
return h(
"div",
{ class: className, role: "group", "aria-label": ariaLabel },
options.map(function (option) {
return h("button", {
type: "button",
class: activeValue === option.value ? "active" : "",
"aria-pressed": activeValue === option.value ? "true" : "false",
"data-value": option.value,
text: option.label,
onClick: function () {
onSelect(option.value);
},
});
}),
);
}
function createChooser(config) {
var state = { locale: "en", themePreference: "auto" };
function text(locale, key) {
var c = config.copy || {};
return (
(c[locale] && c[locale][key]) ||
(c.en && c.en[key]) ||
(LABELS[locale] && LABELS[locale][key]) ||
LABELS.en[key] ||
key
);
}
function applyDocumentChrome() {
if (typeof document === "undefined") return;
document.documentElement.setAttribute("data-theme", resolveTheme(state.themePreference));
document.documentElement.lang = state.locale;
}
function navCard(locale, destination) {
var props = {
class: "nav-card",
href: destination.href,
"data-testid": "nav-" + destination.id,
};
if (destination.external) {
props.target = "_blank";
props.rel = "noopener noreferrer";
}
return h(
"a",
props,
h("span", { class: "nav-card-icon", "aria-hidden": "true", text: destination.icon }),
h("span", { class: "nav-card-title", text: text(locale, destination.titleKey) }),
h("span", { class: "nav-card-desc", text: text(locale, destination.descKey) }),
h("span", { class: "nav-card-action", text: text(locale, destination.actionKey) }),
);
}
function render() {
var root = document.getElementById(config.rootId);
if (!root) return;
var locale = state.locale;
root.textContent = "";
var topbar = h(
"header",
{ class: config.topbarClass || "landing-topbar" },
h(
"a",
{ class: "brand", href: config.brandHref || "./", "data-testid": "brand-home" },
h("span", { class: "brand-mark", "aria-hidden": "true", text: "◆" }),
h("span", { text: "formal-ai" }),
),
h(
"div",
{ class: "topbar-controls" },
segmentedControl(
SUPPORTED_LOCALES.map(function (value) {
return { value: value, label: value.toUpperCase() };
}),
locale,
function (value) {
state.locale = value;
writePreference("uiLanguage", value);
applyDocumentChrome();
render();
},
text(locale, "language"),
"locale-switch",
),
segmentedControl(
[
{ value: "auto", label: text(locale, "themeAuto") },
{ value: "light", label: text(locale, "themeLight") },
{ value: "dark", label: text(locale, "themeDark") },
],
state.themePreference,
function (value) {
state.themePreference = value;
writePreference("theme", value);
applyDocumentChrome();
render();
},
text(locale, "theme"),
"theme-switch",
),
),
);
var sourceCta = config.repoUrl
? h(
"a",
{
class: "source-cta",
href: config.repoUrl,
target: "_blank",
rel: "noopener noreferrer",
"data-testid": "source-cta",
},
h("span", { class: "source-cta-icon", "aria-hidden": "true", text: "</>" }),
h(
"span",
{ class: "source-cta-text" },
h("span", { class: "source-cta-eyebrow", text: text(locale, "sourceEyebrow") }),
h("strong", { class: "source-cta-label", text: text(locale, "footerSource") }),
),
)
: null;
var hero = h(
"section",
{ class: "hero" },
h("p", { class: "eyebrow", text: text(locale, "eyebrow") }),
h("h1", { text: text(locale, "heading") }),
h("p", {
class: "summary",
"data-testid": config.rootId + "-summary",
text: text(locale, "summary"),
}),
sourceCta,
);
var cards = h(
"section",
{ class: "nav-cards", "data-testid": "nav-cards" },
(config.destinations || []).map(function (destination) {
return navCard(locale, destination);
}),
);
var version = readVersion();
var footer = h(
"footer",
{ class: "landing-footer" },
version
? h("span", {
class: "landing-version",
"data-testid": "landing-version",
text: text(locale, "footerVersion") + " " + version,
})
: null,
);
root.appendChild(topbar);
root.appendChild(hero);
root.appendChild(cards);
root.appendChild(footer);
}
function init() {
var prefs = readPreferences();
state.themePreference =
prefs.theme === "dark" || prefs.theme === "light" ? prefs.theme : "auto";
state.locale = resolveLocale(prefs.uiLanguage);
applyDocumentChrome();
render();
if (typeof global.matchMedia === "function") {
var media = global.matchMedia("(prefers-color-scheme: dark)");
var onChange = function () {
if (state.themePreference === "auto") {
applyDocumentChrome();
render();
}
};
if (typeof media.addEventListener === "function") {
media.addEventListener("change", onChange);
} else if (typeof media.addListener === "function") {
media.addListener(onChange);
}
}
}
var api = {
config: config,
state: state,
text: text,
render: render,
init: init,
applyDocumentChrome: applyDocumentChrome,
resolveLocale: resolveLocale,
resolveTheme: resolveTheme,
SUPPORTED_LOCALES: SUPPORTED_LOCALES,
};
if (config.exposeAs) {
global[config.exposeAs] = api;
}
if (typeof document !== "undefined") {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
}
return api;
}
global.FormalAiSiteChrome = {
SUPPORTED_LOCALES: SUPPORTED_LOCALES,
LABELS: LABELS,
normalizeLocale: normalizeLocale,
detectLocaleFromBrowser: detectLocaleFromBrowser,
resolveLocale: resolveLocale,
resolveTheme: resolveTheme,
readPreferences: readPreferences,
writePreference: writePreference,
readVersion: readVersion,
h: h,
appendChild: appendChild,
segmentedControl: segmentedControl,
createChooser: createChooser,
};
})(typeof window !== "undefined" ? window : globalThis);