@tenphi/starlight 0.1.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
1
  # @tenphi/starlight
2
2
 
3
- The supported Astro/Starlight renderer for Tasty Docs. The default export is a
3
+ The supported Astro/Starlight renderer for Cookbook. The default export is a
4
4
  complete Astro integration; consumers do not compose Starlight themselves.
@@ -1,5 +1,5 @@
1
1
  //#region src/client/appearance.ts
2
- const STORAGE_KEY = "tasty-docs-appearance";
2
+ const STORAGE_KEY = "cookbook-appearance";
3
3
  const themes = /* @__PURE__ */ new Set([
4
4
  "light",
5
5
  "dark",
@@ -1 +1 @@
1
- {"version":3,"file":"appearance.js","names":[],"sources":["../../src/client/appearance.ts"],"sourcesContent":["const STORAGE_KEY = \"tasty-docs-appearance\";\n\ntype Theme = \"light\" | \"dark\" | \"system\";\ntype Contrast = \"normal\" | \"more\" | \"system\";\ntype Appearance = { theme?: Theme; contrast?: Contrast };\n\nconst themes = new Set([\"light\", \"dark\", \"system\"]);\nconst contrasts = new Set([\"normal\", \"more\", \"system\"]);\n\nexport function applyAppearance(value: Appearance): void {\n const root = document.documentElement;\n if (value.theme && value.theme !== \"system\") root.dataset.theme = value.theme;\n else delete root.dataset.theme;\n if (value.contrast && value.contrast !== \"system\")\n root.dataset.contrast = value.contrast;\n else delete root.dataset.contrast;\n}\n\nexport function saveAppearance(value: Appearance): void {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(value));\n applyAppearance(value);\n}\n\ntry {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) applyAppearance(normalizeAppearance(JSON.parse(stored)));\n} catch {\n // Storage may be unavailable; CSS media queries remain the fallback.\n}\n\nconst theme = document.querySelector<HTMLSelectElement>(\"[data-docs-theme]\");\nconst contrast = document.querySelector<HTMLSelectElement>(\n \"[data-docs-contrast]\",\n);\nlet current: Appearance = { theme: \"system\", contrast: \"system\" };\ntry {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) current = normalizeAppearance(JSON.parse(stored));\n} catch {\n // The controls retain system defaults when storage is unavailable.\n}\nif (theme) theme.value = current.theme ?? \"system\";\nif (contrast) contrast.value = current.contrast ?? \"system\";\nconst update = () => {\n current = {\n theme: normalizeTheme(theme?.value),\n contrast: normalizeContrast(contrast?.value),\n };\n saveAppearance(current);\n};\ntheme?.addEventListener(\"change\", update);\ncontrast?.addEventListener(\"change\", update);\n\nfunction normalizeAppearance(value: unknown): Appearance {\n if (!value || typeof value !== \"object\") return {};\n const record = value as Record<string, unknown>;\n return {\n theme: normalizeTheme(record.theme),\n contrast: normalizeContrast(record.contrast),\n };\n}\n\nfunction normalizeTheme(value: unknown): Theme {\n return typeof value === \"string\" && themes.has(value)\n ? (value as Theme)\n : \"system\";\n}\n\nfunction normalizeContrast(value: unknown): Contrast {\n return typeof value === \"string\" && contrasts.has(value)\n ? (value as Contrast)\n : \"system\";\n}\n"],"mappings":";AAAA,MAAM,cAAc;AAMpB,MAAM,yBAAS,IAAI,IAAI;CAAC;CAAS;CAAQ;AAAQ,CAAC;AAClD,MAAM,4BAAY,IAAI,IAAI;CAAC;CAAU;CAAQ;AAAQ,CAAC;AAEtD,SAAgB,gBAAgB,OAAyB;CACvD,MAAM,OAAO,SAAS;CACtB,IAAI,MAAM,SAAS,MAAM,UAAU,UAAU,KAAK,QAAQ,QAAQ,MAAM;MACnE,OAAO,KAAK,QAAQ;CACzB,IAAI,MAAM,YAAY,MAAM,aAAa,UACvC,KAAK,QAAQ,WAAW,MAAM;MAC3B,OAAO,KAAK,QAAQ;AAC3B;AAEA,SAAgB,eAAe,OAAyB;CACtD,aAAa,QAAQ,aAAa,KAAK,UAAU,KAAK,CAAC;CACvD,gBAAgB,KAAK;AACvB;AAEA,IAAI;CACF,MAAM,SAAS,aAAa,QAAQ,WAAW;CAC/C,IAAI,QAAQ,gBAAgB,oBAAoB,KAAK,MAAM,MAAM,CAAC,CAAC;AACrE,QAAQ,CAER;AAEA,MAAM,QAAQ,SAAS,cAAiC,mBAAmB;AAC3E,MAAM,WAAW,SAAS,cACxB,sBACF;AACA,IAAI,UAAsB;CAAE,OAAO;CAAU,UAAU;AAAS;AAChE,IAAI;CACF,MAAM,SAAS,aAAa,QAAQ,WAAW;CAC/C,IAAI,QAAQ,UAAU,oBAAoB,KAAK,MAAM,MAAM,CAAC;AAC9D,QAAQ,CAER;AACA,IAAI,OAAO,MAAM,QAAQ,QAAQ,SAAS;AAC1C,IAAI,UAAU,SAAS,QAAQ,QAAQ,YAAY;AACnD,MAAM,eAAe;CACnB,UAAU;EACR,OAAO,eAAe,OAAO,KAAK;EAClC,UAAU,kBAAkB,UAAU,KAAK;CAC7C;CACA,eAAe,OAAO;AACxB;AACA,OAAO,iBAAiB,UAAU,MAAM;AACxC,UAAU,iBAAiB,UAAU,MAAM;AAE3C,SAAS,oBAAoB,OAA4B;CACvD,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO,CAAC;CACjD,MAAM,SAAS;CACf,OAAO;EACL,OAAO,eAAe,OAAO,KAAK;EAClC,UAAU,kBAAkB,OAAO,QAAQ;CAC7C;AACF;AAEA,SAAS,eAAe,OAAuB;CAC7C,OAAO,OAAO,UAAU,YAAY,OAAO,IAAI,KAAK,IAC/C,QACD;AACN;AAEA,SAAS,kBAAkB,OAA0B;CACnD,OAAO,OAAO,UAAU,YAAY,UAAU,IAAI,KAAK,IAClD,QACD;AACN"}
1
+ {"version":3,"file":"appearance.js","names":[],"sources":["../../src/client/appearance.ts"],"sourcesContent":["const STORAGE_KEY = \"cookbook-appearance\";\n\ntype Theme = \"light\" | \"dark\" | \"system\";\ntype Contrast = \"normal\" | \"more\" | \"system\";\ntype Appearance = { theme?: Theme; contrast?: Contrast };\n\nconst themes = new Set([\"light\", \"dark\", \"system\"]);\nconst contrasts = new Set([\"normal\", \"more\", \"system\"]);\n\nexport function applyAppearance(value: Appearance): void {\n const root = document.documentElement;\n if (value.theme && value.theme !== \"system\") root.dataset.theme = value.theme;\n else delete root.dataset.theme;\n if (value.contrast && value.contrast !== \"system\")\n root.dataset.contrast = value.contrast;\n else delete root.dataset.contrast;\n}\n\nexport function saveAppearance(value: Appearance): void {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(value));\n applyAppearance(value);\n}\n\ntry {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) applyAppearance(normalizeAppearance(JSON.parse(stored)));\n} catch {\n // Storage may be unavailable; CSS media queries remain the fallback.\n}\n\nconst theme = document.querySelector<HTMLSelectElement>(\"[data-docs-theme]\");\nconst contrast = document.querySelector<HTMLSelectElement>(\n \"[data-docs-contrast]\",\n);\nlet current: Appearance = { theme: \"system\", contrast: \"system\" };\ntry {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) current = normalizeAppearance(JSON.parse(stored));\n} catch {\n // The controls retain system defaults when storage is unavailable.\n}\nif (theme) theme.value = current.theme ?? \"system\";\nif (contrast) contrast.value = current.contrast ?? \"system\";\nconst update = () => {\n current = {\n theme: normalizeTheme(theme?.value),\n contrast: normalizeContrast(contrast?.value),\n };\n saveAppearance(current);\n};\ntheme?.addEventListener(\"change\", update);\ncontrast?.addEventListener(\"change\", update);\n\nfunction normalizeAppearance(value: unknown): Appearance {\n if (!value || typeof value !== \"object\") return {};\n const record = value as Record<string, unknown>;\n return {\n theme: normalizeTheme(record.theme),\n contrast: normalizeContrast(record.contrast),\n };\n}\n\nfunction normalizeTheme(value: unknown): Theme {\n return typeof value === \"string\" && themes.has(value)\n ? (value as Theme)\n : \"system\";\n}\n\nfunction normalizeContrast(value: unknown): Contrast {\n return typeof value === \"string\" && contrasts.has(value)\n ? (value as Contrast)\n : \"system\";\n}\n"],"mappings":";AAAA,MAAM,cAAc;AAMpB,MAAM,yBAAS,IAAI,IAAI;CAAC;CAAS;CAAQ;AAAQ,CAAC;AAClD,MAAM,4BAAY,IAAI,IAAI;CAAC;CAAU;CAAQ;AAAQ,CAAC;AAEtD,SAAgB,gBAAgB,OAAyB;CACvD,MAAM,OAAO,SAAS;CACtB,IAAI,MAAM,SAAS,MAAM,UAAU,UAAU,KAAK,QAAQ,QAAQ,MAAM;MACnE,OAAO,KAAK,QAAQ;CACzB,IAAI,MAAM,YAAY,MAAM,aAAa,UACvC,KAAK,QAAQ,WAAW,MAAM;MAC3B,OAAO,KAAK,QAAQ;AAC3B;AAEA,SAAgB,eAAe,OAAyB;CACtD,aAAa,QAAQ,aAAa,KAAK,UAAU,KAAK,CAAC;CACvD,gBAAgB,KAAK;AACvB;AAEA,IAAI;CACF,MAAM,SAAS,aAAa,QAAQ,WAAW;CAC/C,IAAI,QAAQ,gBAAgB,oBAAoB,KAAK,MAAM,MAAM,CAAC,CAAC;AACrE,QAAQ,CAER;AAEA,MAAM,QAAQ,SAAS,cAAiC,mBAAmB;AAC3E,MAAM,WAAW,SAAS,cACxB,sBACF;AACA,IAAI,UAAsB;CAAE,OAAO;CAAU,UAAU;AAAS;AAChE,IAAI;CACF,MAAM,SAAS,aAAa,QAAQ,WAAW;CAC/C,IAAI,QAAQ,UAAU,oBAAoB,KAAK,MAAM,MAAM,CAAC;AAC9D,QAAQ,CAER;AACA,IAAI,OAAO,MAAM,QAAQ,QAAQ,SAAS;AAC1C,IAAI,UAAU,SAAS,QAAQ,QAAQ,YAAY;AACnD,MAAM,eAAe;CACnB,UAAU;EACR,OAAO,eAAe,OAAO,KAAK;EAClC,UAAU,kBAAkB,UAAU,KAAK;CAC7C;CACA,eAAe,OAAO;AACxB;AACA,OAAO,iBAAiB,UAAU,MAAM;AACxC,UAAU,iBAAiB,UAAU,MAAM;AAE3C,SAAS,oBAAoB,OAA4B;CACvD,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO,CAAC;CACjD,MAAM,SAAS;CACf,OAAO;EACL,OAAO,eAAe,OAAO,KAAK;EAClC,UAAU,kBAAkB,OAAO,QAAQ;CAC7C;AACF;AAEA,SAAS,eAAe,OAAuB;CAC7C,OAAO,OAAO,UAAU,YAAY,OAAO,IAAI,KAAK,IAC/C,QACD;AACN;AAEA,SAAS,kBAAkB,OAA0B;CACnD,OAAO,OAAO,UAAU,YAAY,UAAU,IAAI,KAAK,IAClD,QACD;AACN"}
@@ -6,10 +6,23 @@ const status = document.querySelector("[data-docs-search-status]");
6
6
  const results = document.querySelector("[data-docs-search-results]");
7
7
  const base = document.querySelector("[data-docs-base]")?.dataset.docsBase ?? "/";
8
8
  const basePath = base === "/" ? "" : `/${base.replace(/^\/+|\/+$/g, "")}`;
9
- open?.addEventListener("click", () => {
9
+ const openDialog = () => {
10
10
  dialog?.showModal();
11
11
  input?.focus();
12
+ };
13
+ open?.addEventListener("click", openDialog);
14
+ window.addEventListener("keydown", (event) => {
15
+ if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
16
+ if (dialog?.open) dialog.close();
17
+ else openDialog();
18
+ event.preventDefault();
19
+ }
12
20
  });
21
+ const shortcutKey = document.querySelector("[data-docs-search-shortcut]")?.querySelector("kbd");
22
+ if (shortcutKey && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) {
23
+ shortcutKey.textContent = "⌘";
24
+ open?.setAttribute("aria-keyshortcuts", "Meta+K");
25
+ }
13
26
  let pagefind;
14
27
  input?.addEventListener("input", async () => {
15
28
  const query = input.value.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","names":[],"sources":["../../src/client/search.ts"],"sourcesContent":["export {};\n\nconst open = document.querySelector<HTMLButtonElement>(\n \"[data-docs-search-open]\",\n);\nconst dialog = document.querySelector<HTMLDialogElement>(\"[data-docs-search]\");\nconst input = document.querySelector<HTMLInputElement>(\n \"[data-docs-search-input]\",\n);\nconst status = document.querySelector<HTMLElement>(\"[data-docs-search-status]\");\nconst results = document.querySelector<HTMLUListElement>(\n \"[data-docs-search-results]\",\n);\nconst base =\n document.querySelector<HTMLElement>(\"[data-docs-base]\")?.dataset.docsBase ??\n \"/\";\nconst basePath = base === \"/\" ? \"\" : `/${base.replace(/^\\/+|\\/+$/g, \"\")}`;\n\nopen?.addEventListener(\"click\", () => {\n dialog?.showModal();\n input?.focus();\n});\n\ntype Pagefind = {\n search(query: string): Promise<{\n results: Array<{\n data(): Promise<{ url: string; meta: { title?: string } }>;\n }>;\n }>;\n};\nlet pagefind: Promise<Pagefind> | undefined;\ninput?.addEventListener(\"input\", async () => {\n const query = input.value.trim();\n if (!status || !results) return;\n if (!query) {\n status.textContent = \"\";\n results.replaceChildren();\n return;\n }\n status.textContent = \"Searching…\";\n const modulePath = `${basePath}/pagefind/pagefind.js`;\n pagefind ??= import(/* @vite-ignore */ modulePath);\n const response = await (await pagefind).search(query);\n const records = await Promise.all(\n response.results.slice(0, 12).map((result) => result.data()),\n );\n results.replaceChildren(\n ...records.map((record) => {\n const item = document.createElement(\"li\");\n const link = document.createElement(\"a\");\n link.href = `${basePath}${record.url}`;\n link.textContent = record.meta.title ?? record.url;\n item.append(link);\n return item;\n }),\n );\n status.textContent = `${records.length} result${records.length === 1 ? \"\" : \"s\"}`;\n});\n"],"mappings":";AAEA,MAAM,OAAO,SAAS,cACpB,yBACF;AACA,MAAM,SAAS,SAAS,cAAiC,oBAAoB;AAC7E,MAAM,QAAQ,SAAS,cACrB,0BACF;AACA,MAAM,SAAS,SAAS,cAA2B,2BAA2B;AAC9E,MAAM,UAAU,SAAS,cACvB,4BACF;AACA,MAAM,OACJ,SAAS,cAA2B,kBAAkB,CAAC,EAAE,QAAQ,YACjE;AACF,MAAM,WAAW,SAAS,MAAM,KAAK,IAAI,KAAK,QAAQ,cAAc,EAAE;AAEtE,MAAM,iBAAiB,eAAe;CACpC,QAAQ,UAAU;CAClB,OAAO,MAAM;AACf,CAAC;AASD,IAAI;AACJ,OAAO,iBAAiB,SAAS,YAAY;CAC3C,MAAM,QAAQ,MAAM,MAAM,KAAK;CAC/B,IAAI,CAAC,UAAU,CAAC,SAAS;CACzB,IAAI,CAAC,OAAO;EACV,OAAO,cAAc;EACrB,QAAQ,gBAAgB;EACxB;CACF;CACA,OAAO,cAAc;CACrB,MAAM,aAAa,GAAG,SAAS;CAC/B,aAAa;;EAA0B;;CACvC,MAAM,WAAW,OAAO,MAAM,SAAA,CAAU,OAAO,KAAK;CACpD,MAAM,UAAU,MAAM,QAAQ,IAC5B,SAAS,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,WAAW,OAAO,KAAK,CAAC,CAC7D;CACA,QAAQ,gBACN,GAAG,QAAQ,KAAK,WAAW;EACzB,MAAM,OAAO,SAAS,cAAc,IAAI;EACxC,MAAM,OAAO,SAAS,cAAc,GAAG;EACvC,KAAK,OAAO,GAAG,WAAW,OAAO;EACjC,KAAK,cAAc,OAAO,KAAK,SAAS,OAAO;EAC/C,KAAK,OAAO,IAAI;EAChB,OAAO;CACT,CAAC,CACH;CACA,OAAO,cAAc,GAAG,QAAQ,OAAO,SAAS,QAAQ,WAAW,IAAI,KAAK;AAC9E,CAAC"}
1
+ {"version":3,"file":"search.js","names":[],"sources":["../../src/client/search.ts"],"sourcesContent":["export {};\n\nconst open = document.querySelector<HTMLButtonElement>(\n \"[data-docs-search-open]\",\n);\nconst dialog = document.querySelector<HTMLDialogElement>(\"[data-docs-search]\");\nconst input = document.querySelector<HTMLInputElement>(\n \"[data-docs-search-input]\",\n);\nconst status = document.querySelector<HTMLElement>(\"[data-docs-search-status]\");\nconst results = document.querySelector<HTMLUListElement>(\n \"[data-docs-search-results]\",\n);\nconst base =\n document.querySelector<HTMLElement>(\"[data-docs-base]\")?.dataset.docsBase ??\n \"/\";\nconst basePath = base === \"/\" ? \"\" : `/${base.replace(/^\\/+|\\/+$/g, \"\")}`;\n\nconst openDialog = () => {\n dialog?.showModal();\n input?.focus();\n};\n\nopen?.addEventListener(\"click\", openDialog);\n\nwindow.addEventListener(\"keydown\", (event) => {\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"k\") {\n if (dialog?.open) dialog.close();\n else openDialog();\n event.preventDefault();\n }\n});\n\nconst shortcut = document.querySelector<HTMLElement>(\n \"[data-docs-search-shortcut]\",\n);\nconst shortcutKey = shortcut?.querySelector(\"kbd\");\nif (shortcutKey && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) {\n shortcutKey.textContent = \"⌘\";\n open?.setAttribute(\"aria-keyshortcuts\", \"Meta+K\");\n}\n\ntype Pagefind = {\n search(query: string): Promise<{\n results: Array<{\n data(): Promise<{ url: string; meta: { title?: string } }>;\n }>;\n }>;\n};\nlet pagefind: Promise<Pagefind> | undefined;\ninput?.addEventListener(\"input\", async () => {\n const query = input.value.trim();\n if (!status || !results) return;\n if (!query) {\n status.textContent = \"\";\n results.replaceChildren();\n return;\n }\n status.textContent = \"Searching…\";\n const modulePath = `${basePath}/pagefind/pagefind.js`;\n pagefind ??= import(/* @vite-ignore */ modulePath);\n const response = await (await pagefind).search(query);\n const records = await Promise.all(\n response.results.slice(0, 12).map((result) => result.data()),\n );\n results.replaceChildren(\n ...records.map((record) => {\n const item = document.createElement(\"li\");\n const link = document.createElement(\"a\");\n link.href = `${basePath}${record.url}`;\n link.textContent = record.meta.title ?? record.url;\n item.append(link);\n return item;\n }),\n );\n status.textContent = `${records.length} result${records.length === 1 ? \"\" : \"s\"}`;\n});\n"],"mappings":";AAEA,MAAM,OAAO,SAAS,cACpB,yBACF;AACA,MAAM,SAAS,SAAS,cAAiC,oBAAoB;AAC7E,MAAM,QAAQ,SAAS,cACrB,0BACF;AACA,MAAM,SAAS,SAAS,cAA2B,2BAA2B;AAC9E,MAAM,UAAU,SAAS,cACvB,4BACF;AACA,MAAM,OACJ,SAAS,cAA2B,kBAAkB,CAAC,EAAE,QAAQ,YACjE;AACF,MAAM,WAAW,SAAS,MAAM,KAAK,IAAI,KAAK,QAAQ,cAAc,EAAE;AAEtE,MAAM,mBAAmB;CACvB,QAAQ,UAAU;CAClB,OAAO,MAAM;AACf;AAEA,MAAM,iBAAiB,SAAS,UAAU;AAE1C,OAAO,iBAAiB,YAAY,UAAU;CAC5C,KAAK,MAAM,WAAW,MAAM,YAAY,MAAM,IAAI,YAAY,MAAM,KAAK;EACvE,IAAI,QAAQ,MAAM,OAAO,MAAM;OAC1B,WAAW;EAChB,MAAM,eAAe;CACvB;AACF,CAAC;AAKD,MAAM,cAHW,SAAS,cACxB,6BAEyB,CAAC,EAAE,cAAc,KAAK;AACjD,IAAI,eAAe,0BAA0B,KAAK,UAAU,QAAQ,GAAG;CACrE,YAAY,cAAc;CAC1B,MAAM,aAAa,qBAAqB,QAAQ;AAClD;AASA,IAAI;AACJ,OAAO,iBAAiB,SAAS,YAAY;CAC3C,MAAM,QAAQ,MAAM,MAAM,KAAK;CAC/B,IAAI,CAAC,UAAU,CAAC,SAAS;CACzB,IAAI,CAAC,OAAO;EACV,OAAO,cAAc;EACrB,QAAQ,gBAAgB;EACxB;CACF;CACA,OAAO,cAAc;CACrB,MAAM,aAAa,GAAG,SAAS;CAC/B,aAAa;;EAA0B;;CACvC,MAAM,WAAW,OAAO,MAAM,SAAA,CAAU,OAAO,KAAK;CACpD,MAAM,UAAU,MAAM,QAAQ,IAC5B,SAAS,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,WAAW,OAAO,KAAK,CAAC,CAC7D;CACA,QAAQ,gBACN,GAAG,QAAQ,KAAK,WAAW;EACzB,MAAM,OAAO,SAAS,cAAc,IAAI;EACxC,MAAM,OAAO,SAAS,cAAc,GAAG;EACvC,KAAK,OAAO,GAAG,WAAW,OAAO;EACjC,KAAK,cAAc,OAAO,KAAK,SAAS,OAAO;EAC/C,KAAK,OAAO,IAAI;EAChB,OAAO;CACT,CAAC,CACH;CACA,OAAO,cAAc,GAAG,QAAQ,OAAO,SAAS,QAAQ,WAAW,IAAI,KAAK;AAC9E,CAAC"}
@@ -0,0 +1,40 @@
1
+ ---
2
+ import { layout } from "virtual:cookbook/layout";
3
+ import { activeNavigationTab, navigationPath } from "../navigation.js";
4
+
5
+ interface Props {
6
+ base?: string;
7
+ currentPath: string;
8
+ }
9
+
10
+ const { base = "/", currentPath } = Astro.props;
11
+ const basePath = base === "/" ? "" : `/${base.replace(/^\/+|\/+$/g, "")}`;
12
+ const activeTab = activeNavigationTab(
13
+ layout.tabs,
14
+ navigationPath(currentPath, basePath || "/"),
15
+ );
16
+
17
+ function tabHref(link: string): string {
18
+ return link.startsWith("/") ? `${basePath}${link}` || "/" : link;
19
+ }
20
+ ---
21
+
22
+ {
23
+ layout.tabs.length > 0 && (
24
+ <nav class="td-mobile-tabs print:hidden" aria-label="Sections">
25
+ <span class="td-mobile-tabs__label">Sections</span>
26
+ <ul>
27
+ {layout.tabs.map((tab, index) => (
28
+ <li>
29
+ <a
30
+ href={tabHref(tab.link)}
31
+ aria-current={index === activeTab ? "page" : undefined}
32
+ >
33
+ {tab.label}
34
+ </a>
35
+ </li>
36
+ ))}
37
+ </ul>
38
+ </nav>
39
+ )
40
+ }
@@ -0,0 +1,98 @@
1
+ ---
2
+ import type { DocsRoute, NavigationItem } from "@tenphi/docs";
3
+ import { normalizeNavigationPath } from "../navigation.js";
4
+
5
+ interface Props {
6
+ items: NavigationItem[];
7
+ routes: DocsRoute[];
8
+ current: string;
9
+ base: string;
10
+ nested?: boolean;
11
+ }
12
+
13
+ const { items, routes, current, base, nested = false } = Astro.props;
14
+ const routeTitle = new Map(routes.map((route) => [route.route, route.title]));
15
+ const withBase = (route: string) =>
16
+ route.startsWith("/")
17
+ ? `${base === "/" ? "" : `/${base.replace(/^\/+|\/+$/g, "")}`}${route}` ||
18
+ "/"
19
+ : route;
20
+ const labelFor = (route: string) =>
21
+ routeTitle.get(normalizeNavigationPath(route)) ??
22
+ normalizeNavigationPath(route).split("/").filter(Boolean).at(-1) ??
23
+ "Home";
24
+ const isCurrent = (route: string) =>
25
+ route.startsWith("/") && normalizeNavigationPath(route) === current;
26
+ const generatedItems = (directory: string): NavigationItem[] => {
27
+ const root = normalizeNavigationPath(directory);
28
+ return routes
29
+ .filter(
30
+ (route) =>
31
+ root === "/" ||
32
+ route.route === root ||
33
+ route.route.startsWith(`${root}/`),
34
+ )
35
+ .map((route) => route.route);
36
+ };
37
+ ---
38
+
39
+ <ul class:list={{ "td-shell__nav-root": !nested }}>
40
+ {
41
+ items.map((item) => {
42
+ if (typeof item === "string") {
43
+ return (
44
+ <li>
45
+ <a
46
+ href={withBase(item)}
47
+ aria-current={isCurrent(item) ? "page" : undefined}
48
+ >
49
+ {labelFor(item)}
50
+ </a>
51
+ </li>
52
+ );
53
+ }
54
+ if ("items" in item) {
55
+ return (
56
+ <li>
57
+ <details open>
58
+ <summary>{item.label}</summary>
59
+ <Astro.self
60
+ items={item.items}
61
+ routes={routes}
62
+ current={current}
63
+ base={base}
64
+ nested
65
+ />
66
+ </details>
67
+ </li>
68
+ );
69
+ }
70
+ if ("autogenerate" in item) {
71
+ return (
72
+ <li>
73
+ <details open>
74
+ <summary>{item.label}</summary>
75
+ <Astro.self
76
+ items={generatedItems(item.autogenerate.directory)}
77
+ routes={routes}
78
+ current={current}
79
+ base={base}
80
+ nested
81
+ />
82
+ </details>
83
+ </li>
84
+ );
85
+ }
86
+ return (
87
+ <li>
88
+ <a
89
+ href={withBase(item.link)}
90
+ aria-current={isCurrent(item.link) ? "page" : undefined}
91
+ >
92
+ {item.label}
93
+ </a>
94
+ </li>
95
+ );
96
+ })
97
+ }
98
+ </ul>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m5 12 6 6"/><path d="m5 12 6-6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m13 18 6-6"/><path d="m13 6 6 6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 6 6 6-6 6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0-18 0M12 3v18"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 9.667A2.667 2.667 0 0 1 9.667 7h8.666A2.667 2.667 0 0 1 21 9.667v8.666A2.667 2.667 0 0 1 18.333 21H9.667A2.667 2.667 0 0 1 7 18.333z"/><path d="M4.012 16.737A2.005 2.005 0 0 1 3 15V5c0-1.1.9-2 2-2h10c.75 0 1.158.385 1.5 1"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 5a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1zM7 20h10M9 16v4M15 16v4"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6h16M4 12h16M4 18h16"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3h.393a7.5 7.5 0 0 0 7.92 12.446A9 9 0 1 1 12 2.992z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 10a7 7 0 1 0 14 0a7 7 0 1 0-14 0"/><path d="m21 21-6-6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 12a4 4 0 1 0 8 0 4 4 0 1 0-8 0M3 12h1m8-9v1m8 8h1m-9 8v1M5.6 5.6l.7.7m12.1-.7-.7.7m0 11.4.7.7m-12.1-.7-.7.7"/></svg>
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as createStarlightCollection } from "./content-B9C0vXAq.js";
2
- import { DocsConfig, DocsDiagnostic, ThemeConfig } from "@tenphi/docs";
2
+ import { DocsConfig, DocsDiagnostic, ThemeConfig, ThemeTokens, TypographyPreset } from "@tenphi/docs";
3
3
  import { AstroIntegration } from "astro";
4
4
  //#region src/starlight-runtime.d.ts
5
5
  interface StarlightOptions {
@@ -13,11 +13,11 @@ interface StarlightOptions {
13
13
  declare function starlight(options: StarlightOptions): AstroIntegration;
14
14
  //#endregion
15
15
  //#region src/integration.d.ts
16
- interface TastyDocsOptions {
16
+ interface CookbookOptions {
17
17
  config?: DocsConfig;
18
18
  root?: string;
19
19
  }
20
- declare function tastyDocs(options?: TastyDocsOptions): AstroIntegration;
20
+ declare function cookbook(options?: CookbookOptions): AstroIntegration;
21
21
  declare function tastyStarlight(config: Parameters<typeof starlight>[0]): AstroIntegration;
22
22
  //#endregion
23
23
  //#region src/theme/index.d.ts
@@ -25,11 +25,17 @@ interface ResolvedDocsTheme {
25
25
  css: string;
26
26
  colors: {
27
27
  surface: Record<string, string>;
28
+ surface2: Record<string, string>;
29
+ surface3: Record<string, string>;
30
+ text: Record<string, string>;
31
+ textSoft: Record<string, string>;
28
32
  accentText: Record<string, string>;
29
33
  accentSurface: Record<string, string>;
30
34
  accentSurfaceText: Record<string, string>;
31
35
  focus: Record<string, string>;
32
36
  };
37
+ tokens: ThemeTokens;
38
+ presets: Record<string, TypographyPreset>;
33
39
  contrast: {
34
40
  light: number;
35
41
  dark: number;
@@ -40,5 +46,20 @@ interface ResolvedDocsTheme {
40
46
  }
41
47
  declare function resolveDocsTheme(theme?: ThemeConfig): ResolvedDocsTheme;
42
48
  //#endregion
43
- export { type ResolvedDocsTheme, type TastyDocsOptions, createStarlightCollection, tastyDocs as default, resolveDocsTheme, tastyStarlight };
49
+ //#region src/theme/defaults.d.ts
50
+ declare const DEFAULT_THEME_TOKENS: {
51
+ $gap: string;
52
+ $radius: string;
53
+ "$card-radius": string;
54
+ "$border-width": string;
55
+ "$outline-width": string;
56
+ "$outline-offset": string;
57
+ "$layout-width": string;
58
+ "$content-width": string;
59
+ "$sidebar-width": string;
60
+ "$control-height": string;
61
+ };
62
+ declare const DEFAULT_TYPOGRAPHY_PRESETS: Record<string, TypographyPreset>;
63
+ //#endregion
64
+ export { type CookbookOptions, DEFAULT_THEME_TOKENS, DEFAULT_TYPOGRAPHY_PRESETS, type ResolvedDocsTheme, createStarlightCollection, cookbook as default, resolveDocsTheme, tastyStarlight };
44
65
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/starlight-runtime.d.ts","../src/integration.ts","../src/theme/index.ts"],"mappings":";;;;UAEiB;EACf;EACA;EACA;EACA,mBAAmB;EACnB;GACC;;iBAGqB,UAAU,SAAS,mBAAmB;;;UCU7C;EACf,SAAS;EACT;;iBAGsB,UACtB,UAAS,mBACR;iBAkNa,eACd,QAAQ,kBAAkB,gBACzB;;;UCrOc;EACf;EACA;IACE,SAAS;IACT,YAAY;IACZ,eAAe;IACf,mBAAmB;IACnB,OAAO;;EAET;IACE;IACA;IACA;IACA;;EAEF,aAAa;;iBAGC,iBAAiB,QAAO,cAAmB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/starlight-runtime.d.ts","../src/integration.ts","../src/theme/index.ts","../src/theme/defaults.ts"],"mappings":";;;;UAEiB;EACf;EACA;EACA;EACA,mBAAmB;EACnB;GACC;;iBAGqB,UAAU,SAAS,mBAAmB;;;UCqB7C;EACf,SAAS;EACT;;iBAGsB,SACtB,UAAS,kBACR;iBAsZa,eACd,QAAQ,kBAAkB,gBACzB;;;UC7ac;EACf;EACA;IACE,SAAS;IACT,UAAU;IACV,UAAU;IACV,MAAM;IACN,UAAU;IACV,YAAY;IACZ,eAAe;IACf,mBAAmB;IACnB,OAAO;;EAET,QAAQ;EACR,SAAS,eAAe;EACxB;IACE;IACA;IACA;IACA;;EAEF,aAAa;;iBAGC,iBAAiB,QAAO,cAAmB;;;cCpC9C;;;;;;;;;;;;cAkBA,4BAA4B,eAAe"}