@tenphi/renderer 0.20.4 → 0.21.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 +2 -2
- package/dist/client/navigation.js +2 -6
- package/dist/client/navigation.js.map +1 -1
- package/dist/client/popover-motion.d.ts +6 -0
- package/dist/client/popover-motion.d.ts.map +1 -0
- package/dist/client/popover-motion.js +14 -0
- package/dist/client/popover-motion.js.map +1 -0
- package/dist/client/search.js +55 -14
- package/dist/client/search.js.map +1 -1
- package/dist/components/GlobalStyles.js +97 -48
- package/dist/components/HeaderLinks.astro +14 -3
- package/dist/components/Icon.astro +1 -1
- package/dist/components/LayoutComponents.js +31 -40
- package/dist/components/Preview.astro +1 -1
- package/dist/components/SelectPopover.astro +64 -0
- package/dist/components/TastyComponents.js +16 -2
- package/dist/components/VersionSwitcher.astro +11 -18
- package/dist/components/component-styles.test.ts +4 -20
- package/dist/components/component-styles.ts +2 -22
- package/dist/components/select-popover-styles.js +107 -0
- package/dist/eslint-plugin.js +2 -2
- package/dist/eslint-plugin.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -10
- package/dist/index.js.map +1 -1
- package/dist/localization.d.ts.map +1 -1
- package/dist/localization.js +19 -5
- package/dist/localization.js.map +1 -1
- package/dist/overrides/Head.astro +3 -0
- package/dist/overrides/Header.astro +8 -0
- package/dist/overrides/LanguageSelect.astro +29 -35
- package/dist/overrides/MobileMenuFooter.astro +1 -1
- package/dist/overrides/Search.astro +25 -1
- package/dist/overrides/ThemeSelect.astro +2 -0
- package/dist/routes/Page.astro +1 -0
- package/dist/styling.d.ts.map +1 -1
- package/dist/styling.js +1 -1
- package/dist/{tasty-states-BDKIbfw2.js → tasty-states-rTLFy26t.js} +5 -13
- package/dist/tasty-states-rTLFy26t.js.map +1 -0
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +2 -0
- package/dist/ui.js.map +1 -1
- package/package.json +2 -2
- package/dist/tasty-states-BDKIbfw2.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ collections remain independent.
|
|
|
10
10
|
|
|
11
11
|
`@tenphi/renderer/styling` exports `tasty`, `useGlobalStyles`, `mergeStyles`,
|
|
12
12
|
the `Styles` type, and the `defineComponent` and `resolveComponentStyles`
|
|
13
|
-
helpers for merging `theme.
|
|
13
|
+
helpers for merging `theme.customStyles` into custom components. The facade exposes
|
|
14
14
|
the same API through `@tenphi/cookbook/styling`.
|
|
15
15
|
|
|
16
16
|
`@tenphi/renderer/eslint-plugin` exports the default Tasty ESLint plugin,
|
|
@@ -19,5 +19,5 @@ the same API through `@tenphi/cookbook/styling`.
|
|
|
19
19
|
Use `extends: "@tenphi/renderer"` in `tasty.config.ts` to inherit this preset
|
|
20
20
|
and list only your additional tokens, states, or presets.
|
|
21
21
|
It matches `@tenphi/cookbook/eslint-plugin`; see
|
|
22
|
-
[Linting custom styles](https://cookbook.tenphi.me/
|
|
22
|
+
[Linting custom styles](https://cookbook.tenphi.me/custom-components/#linting-custom-styles)
|
|
23
23
|
for ESLint and oxlint setup.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { initializePopoverMotion } from "./popover-motion.js";
|
|
1
2
|
//#region src/client/navigation.ts
|
|
2
3
|
var CookbookSidebarPane = class extends HTMLElement {
|
|
3
4
|
#listeners;
|
|
@@ -93,12 +94,7 @@ var CookbookHeaderLinks = class extends HTMLElement {
|
|
|
93
94
|
const close = () => {
|
|
94
95
|
if (panel?.matches(":popover-open")) panel.hidePopover();
|
|
95
96
|
};
|
|
96
|
-
panel
|
|
97
|
-
if (panel.matches(":popover-open")) {
|
|
98
|
-
panel.getBoundingClientRect();
|
|
99
|
-
panel.setAttribute("data-open", "");
|
|
100
|
-
} else panel.removeAttribute("data-open");
|
|
101
|
-
}, { signal });
|
|
97
|
+
if (panel) initializePopoverMotion(panel, signal);
|
|
102
98
|
desktop.addEventListener("change", () => {
|
|
103
99
|
if (desktop.matches) close();
|
|
104
100
|
}, { signal });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.js","names":[],"sources":["../../src/client/navigation.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"navigation.js","names":[],"sources":["../../src/client/navigation.ts"],"sourcesContent":["import { initializePopoverMotion } from \"./popover-motion.js\";\n\nclass CookbookSidebarPane extends HTMLElement {\n #listeners?: AbortController;\n #inert = new Map<HTMLElement, boolean>();\n #trigger: HTMLButtonElement | undefined;\n\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n const { signal } = this.#listeners;\n this.#trigger =\n document.querySelector<HTMLButtonElement>(\n '.td-menu-button[popovertarget=\"cookbook__sidebar\"]',\n ) ?? undefined;\n const desktop = matchMedia(\"(min-width: 50rem)\");\n const syncViewport = () => {\n if (desktop.matches) {\n if (this.matches(\":popover-open\")) this.hidePopover();\n this.#release();\n this.popover = null;\n this.removeAttribute(\"role\");\n this.removeAttribute(\"aria-modal\");\n } else {\n this.popover = \"auto\";\n this.setAttribute(\"role\", \"dialog\");\n this.setAttribute(\"aria-modal\", \"true\");\n }\n };\n syncViewport();\n desktop.addEventListener(\"change\", syncViewport, { signal });\n this.addEventListener(\n \"toggle\",\n () => {\n const open = !desktop.matches && this.matches(\":popover-open\");\n this.#trigger?.setAttribute(\"aria-expanded\", String(open));\n if (open) {\n // Establish the closed position after the popover enters the top\n // layer so its attribute change transitions from an actual layout.\n // Tasty's global SSR renderer does not preserve @starting-style.\n this.getBoundingClientRect();\n this.setAttribute(\"data-open\", \"\");\n for (const element of document.querySelectorAll<HTMLElement>(\n \".header, .main-frame, .cookbook-skip-link\",\n )) {\n this.#inert.set(element, element.inert);\n element.inert = true;\n }\n this.querySelector<HTMLElement>(\"[autofocus]\")?.focus({\n preventScroll: true,\n });\n } else {\n const restoreFocus =\n this.contains(document.activeElement) ||\n document.activeElement === document.body;\n this.#release();\n if (restoreFocus && !desktop.matches) this.#trigger?.focus();\n }\n },\n { signal },\n );\n this.addEventListener(\n \"keydown\",\n (event) => {\n if (desktop.matches || !this.matches(\":popover-open\")) return;\n const sections = this.querySelector<HTMLDetailsElement>(\n \".td-mobile-tabs details[open]\",\n );\n if (event.key === \"Escape\" && sections) {\n event.preventDefault();\n sections.open = false;\n sections.querySelector(\"summary\")?.focus();\n return;\n }\n if (event.key !== \"Tab\") return;\n const focusable = Array.from(\n this.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), select:not([disabled]), input:not([disabled]), summary, [tabindex=\"0\"]',\n ),\n ).filter(\n (element) =>\n element.tabIndex >= 0 && element.getClientRects().length > 0,\n );\n const first = focusable[0];\n const last = focusable.at(-1);\n if (!first || !last) {\n event.preventDefault();\n this.focus();\n return;\n }\n if (\n event.shiftKey &&\n (document.activeElement === first || document.activeElement === this)\n ) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n },\n { signal },\n );\n this.addEventListener(\n \"click\",\n (event) => {\n if (\n !event.defaultPrevented &&\n event.target instanceof Element &&\n event.target.closest(\"a[href]\") &&\n this.matches(\":popover-open\")\n )\n this.hidePopover();\n },\n { signal },\n );\n }\n\n #release() {\n this.removeAttribute(\"data-open\");\n for (const [element, inert] of this.#inert) element.inert = inert;\n this.#inert.clear();\n this.#trigger?.setAttribute(\"aria-expanded\", \"false\");\n }\n\n disconnectedCallback() {\n this.#listeners?.abort();\n this.#release();\n }\n}\n\nclass CookbookHeaderLinks extends HTMLElement {\n #listeners?: AbortController;\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n const { signal } = this.#listeners;\n const panel = this.querySelector<HTMLElement>(\"[popover]\");\n const desktop = matchMedia(\"(min-width: 50rem)\");\n const close = () => {\n if (panel?.matches(\":popover-open\")) panel.hidePopover();\n };\n if (panel) initializePopoverMotion(panel, signal);\n desktop.addEventListener(\n \"change\",\n () => {\n if (desktop.matches) close();\n },\n { signal },\n );\n panel?.addEventListener(\n \"click\",\n (event) => {\n if (event.target instanceof Element && event.target.closest(\"a[href]\"))\n close();\n },\n { signal },\n );\n }\n disconnectedCallback() {\n this.#listeners?.abort();\n }\n}\n\nif (!customElements.get(\"cookbook-sidebar-pane\"))\n customElements.define(\"cookbook-sidebar-pane\", CookbookSidebarPane);\nif (!customElements.get(\"cookbook-header-links\"))\n customElements.define(\"cookbook-header-links\", CookbookHeaderLinks);\n"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/client/popover-motion.d.ts
|
|
2
|
+
/** Animate popovers after they have entered the top layer. */
|
|
3
|
+
declare function initializePopoverMotion(panel: HTMLElement, signal?: AbortSignal): void;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { initializePopoverMotion };
|
|
6
|
+
//# sourceMappingURL=popover-motion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover-motion.d.ts","names":[],"sources":["../../src/client/popover-motion.ts"],"mappings":";;iBACgB,wBACd,OAAO,aACP,SAAS"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/client/popover-motion.ts
|
|
2
|
+
/** Animate popovers after they have entered the top layer. */
|
|
3
|
+
function initializePopoverMotion(panel, signal) {
|
|
4
|
+
panel.addEventListener("toggle", () => {
|
|
5
|
+
if (panel.matches(":popover-open")) {
|
|
6
|
+
panel.getBoundingClientRect();
|
|
7
|
+
panel.setAttribute("data-open", "");
|
|
8
|
+
} else panel.removeAttribute("data-open");
|
|
9
|
+
}, signal ? { signal } : void 0);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { initializePopoverMotion };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=popover-motion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover-motion.js","names":[],"sources":["../../src/client/popover-motion.ts"],"sourcesContent":["/** Animate popovers after they have entered the top layer. */\nexport function initializePopoverMotion(\n panel: HTMLElement,\n signal?: AbortSignal,\n): void {\n panel.addEventListener(\n \"toggle\",\n () => {\n if (panel.matches(\":popover-open\")) {\n panel.getBoundingClientRect();\n panel.setAttribute(\"data-open\", \"\");\n } else {\n panel.removeAttribute(\"data-open\");\n }\n },\n signal ? { signal } : undefined,\n );\n}\n"],"mappings":";;AACA,SAAgB,wBACd,OACA,QACM;CACN,MAAM,iBACJ,gBACM;EACJ,IAAI,MAAM,QAAQ,eAAe,GAAG;GAClC,MAAM,sBAAsB;GAC5B,MAAM,aAAa,aAAa,EAAE;EACpC,OACE,MAAM,gBAAgB,WAAW;CAErC,GACA,SAAS,EAAE,OAAO,IAAI,KAAA,CACxB;AACF"}
|
package/dist/client/search.js
CHANGED
|
@@ -8,6 +8,8 @@ function initializeSearch(element, options, development, base) {
|
|
|
8
8
|
const dialog = element.querySelector("dialog");
|
|
9
9
|
const frame = element.querySelector(".dialog-frame");
|
|
10
10
|
const status = element.querySelector("[data-search-status]");
|
|
11
|
+
const input = element.querySelector("[data-search-input]");
|
|
12
|
+
const clear = element.querySelector("[data-clear-search]");
|
|
11
13
|
const shortcut = open.querySelector("kbd");
|
|
12
14
|
if (/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) {
|
|
13
15
|
shortcut.querySelector("kbd").textContent = "⌘";
|
|
@@ -15,7 +17,24 @@ function initializeSearch(element, options, development, base) {
|
|
|
15
17
|
}
|
|
16
18
|
delete shortcut.dataset.pending;
|
|
17
19
|
let initialized;
|
|
20
|
+
let engineInput = null;
|
|
18
21
|
let returnFocus = null;
|
|
22
|
+
let closing = false;
|
|
23
|
+
let generation = 0;
|
|
24
|
+
const updateSearch = () => {
|
|
25
|
+
if (clear) clear.hidden = !input?.value;
|
|
26
|
+
if (engineInput) {
|
|
27
|
+
engineInput.value = input?.value ?? "";
|
|
28
|
+
engineInput.dispatchEvent(new Event("input", { bubbles: true }));
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
input?.addEventListener("input", updateSearch);
|
|
32
|
+
clear?.addEventListener("click", () => {
|
|
33
|
+
if (!input) return;
|
|
34
|
+
input.value = "";
|
|
35
|
+
updateSearch();
|
|
36
|
+
input.focus();
|
|
37
|
+
});
|
|
19
38
|
const initialize = () => {
|
|
20
39
|
if (development) return Promise.resolve();
|
|
21
40
|
return initialized ??= (async () => {
|
|
@@ -24,7 +43,7 @@ function initializeSearch(element, options, development, base) {
|
|
|
24
43
|
const format = (url) => element.hasAttribute("data-strip-trailing-slash") ? url.replace(/(.)\/(#.*)?$/, "$1$2") : url;
|
|
25
44
|
new PagefindUI({
|
|
26
45
|
...options,
|
|
27
|
-
element: "
|
|
46
|
+
element: element.querySelector("[data-search-results]"),
|
|
28
47
|
baseUrl: base,
|
|
29
48
|
bundlePath: `${base.replace(/\/$/, "")}/pagefind/`,
|
|
30
49
|
showImages: false,
|
|
@@ -39,6 +58,13 @@ function initializeSearch(element, options, development, base) {
|
|
|
39
58
|
return result;
|
|
40
59
|
}
|
|
41
60
|
});
|
|
61
|
+
engineInput = element.querySelector(".pagefind-ui__search-input");
|
|
62
|
+
element.querySelector(".pagefind-ui__form")?.removeAttribute("role");
|
|
63
|
+
element.querySelectorAll(".pagefind-ui__search-input, .pagefind-ui__search-clear").forEach((control) => {
|
|
64
|
+
control.hidden = true;
|
|
65
|
+
control.tabIndex = -1;
|
|
66
|
+
});
|
|
67
|
+
updateSearch();
|
|
42
68
|
})().catch((error) => {
|
|
43
69
|
initialized = void 0;
|
|
44
70
|
if (status) {
|
|
@@ -49,38 +75,53 @@ function initializeSearch(element, options, development, base) {
|
|
|
49
75
|
throw error;
|
|
50
76
|
});
|
|
51
77
|
};
|
|
52
|
-
const show =
|
|
53
|
-
if (dialog.open) return;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
dialog.
|
|
78
|
+
const show = (trigger) => {
|
|
79
|
+
if (dialog.open && !closing) return;
|
|
80
|
+
generation += 1;
|
|
81
|
+
closing = false;
|
|
82
|
+
if (!dialog.open) {
|
|
83
|
+
returnFocus = trigger ?? (document.activeElement instanceof HTMLElement && document.activeElement !== document.body ? document.activeElement : open);
|
|
84
|
+
dialog.removeAttribute("data-open");
|
|
85
|
+
dialog.showModal();
|
|
86
|
+
}
|
|
87
|
+
input?.focus({ preventScroll: true });
|
|
57
88
|
dialog.getBoundingClientRect();
|
|
58
89
|
dialog.setAttribute("data-open", "");
|
|
59
90
|
document.body.setAttribute("data-search-modal-open", "");
|
|
60
91
|
if (!development && status) status.hidden = true;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
92
|
+
initialize().catch(() => {});
|
|
93
|
+
};
|
|
94
|
+
const hide = async () => {
|
|
95
|
+
if (!dialog.open || closing) return;
|
|
96
|
+
closing = true;
|
|
97
|
+
const current = ++generation;
|
|
98
|
+
dialog.removeAttribute("data-open");
|
|
99
|
+
await Promise.allSettled(dialog.getAnimations().filter((animation) => Number.isFinite(animation.effect?.getComputedTiming().endTime)).map((animation) => animation.finished));
|
|
100
|
+
if (current === generation && dialog.open) dialog.close();
|
|
65
101
|
};
|
|
66
102
|
open.addEventListener("click", () => {
|
|
67
|
-
show();
|
|
103
|
+
show(open);
|
|
68
104
|
});
|
|
69
105
|
open.disabled = false;
|
|
70
|
-
close.addEventListener("click", () =>
|
|
106
|
+
close.addEventListener("click", () => void hide());
|
|
107
|
+
dialog.addEventListener("cancel", (event) => {
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
hide();
|
|
110
|
+
});
|
|
71
111
|
dialog.addEventListener("click", (event) => {
|
|
72
112
|
if (!(event.target instanceof Element)) return;
|
|
73
|
-
if (event.target.closest("a[href]") || !frame.contains(event.target))
|
|
113
|
+
if (event.target.closest("a[href]") || !frame.contains(event.target)) hide();
|
|
74
114
|
});
|
|
75
115
|
dialog.addEventListener("close", () => {
|
|
76
116
|
dialog.removeAttribute("data-open");
|
|
117
|
+
closing = false;
|
|
77
118
|
document.body.removeAttribute("data-search-modal-open");
|
|
78
119
|
returnFocus?.focus();
|
|
79
120
|
});
|
|
80
121
|
window.addEventListener("keydown", (event) => {
|
|
81
122
|
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
|
|
82
123
|
event.preventDefault();
|
|
83
|
-
if (dialog.open)
|
|
124
|
+
if (dialog.open && !closing) hide();
|
|
84
125
|
else show();
|
|
85
126
|
}
|
|
86
127
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","names":[],"sources":["../../src/client/search.ts"],"sourcesContent":["type SearchResult = { url: string; sub_results?: SearchResult[] };\ntype PagefindOptions = Record<string, unknown> & {\n processResult?: (result: SearchResult) => SearchResult | void;\n};\n\n/** Own the dialog lifecycle; Pagefind owns indexing, filtering and result rendering. */\nexport function initializeSearch(\n element: HTMLElement,\n options: PagefindOptions,\n development: boolean,\n base: string,\n): void {\n if (element.dataset.initialized) return;\n element.dataset.initialized = \"true\";\n const open = element.querySelector<HTMLButtonElement>(\"[data-open-modal]\")!;\n const close = element.querySelector<HTMLButtonElement>(\"[data-close-modal]\")!;\n const dialog = element.querySelector(\"dialog\")!;\n const frame = element.querySelector(\".dialog-frame\")!;\n const status = element.querySelector<HTMLElement>(\"[data-search-status]\");\n const shortcut = open.querySelector(\"kbd\")!;\n if (/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) {\n shortcut.querySelector(\"kbd\")!.textContent = \"⌘\";\n open.setAttribute(\"aria-keyshortcuts\", \"Meta+K\");\n }\n delete shortcut.dataset.pending;\n let initialized: Promise<void> | undefined;\n let returnFocus: HTMLElement | null = null;\n const initialize = () => {\n if (development) return Promise.resolve();\n return (initialized ??= (async () => {\n // @ts-expect-error Pagefind publishes no declarations for its default UI.\n const { PagefindUI } = await import(\"@pagefind/default-ui\");\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n const format = (url: string) =>\n element.hasAttribute(\"data-strip-trailing-slash\")\n ? url.replace(/(.)\\/(#.*)?$/, \"$1$2\")\n : url;\n new PagefindUI({\n ...options,\n element: \"
|
|
1
|
+
{"version":3,"file":"search.js","names":[],"sources":["../../src/client/search.ts"],"sourcesContent":["type SearchResult = { url: string; sub_results?: SearchResult[] };\ntype PagefindOptions = Record<string, unknown> & {\n processResult?: (result: SearchResult) => SearchResult | void;\n};\n\n/** Own the dialog lifecycle; Pagefind owns indexing, filtering and result rendering. */\nexport function initializeSearch(\n element: HTMLElement,\n options: PagefindOptions,\n development: boolean,\n base: string,\n): void {\n if (element.dataset.initialized) return;\n element.dataset.initialized = \"true\";\n const open = element.querySelector<HTMLButtonElement>(\"[data-open-modal]\")!;\n const close = element.querySelector<HTMLButtonElement>(\"[data-close-modal]\")!;\n const dialog = element.querySelector(\"dialog\")!;\n const frame = element.querySelector(\".dialog-frame\")!;\n const status = element.querySelector<HTMLElement>(\"[data-search-status]\");\n const input = element.querySelector<HTMLInputElement>(\"[data-search-input]\");\n const clear = element.querySelector<HTMLButtonElement>(\"[data-clear-search]\");\n const shortcut = open.querySelector(\"kbd\")!;\n if (/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) {\n shortcut.querySelector(\"kbd\")!.textContent = \"⌘\";\n open.setAttribute(\"aria-keyshortcuts\", \"Meta+K\");\n }\n delete shortcut.dataset.pending;\n let initialized: Promise<void> | undefined;\n let engineInput: HTMLInputElement | null = null;\n let returnFocus: HTMLElement | null = null;\n let closing = false;\n let generation = 0;\n const updateSearch = () => {\n if (clear) clear.hidden = !input?.value;\n if (engineInput) {\n engineInput.value = input?.value ?? \"\";\n engineInput.dispatchEvent(new Event(\"input\", { bubbles: true }));\n }\n };\n input?.addEventListener(\"input\", updateSearch);\n clear?.addEventListener(\"click\", () => {\n if (!input) return;\n input.value = \"\";\n updateSearch();\n input.focus();\n });\n const initialize = () => {\n if (development) return Promise.resolve();\n return (initialized ??= (async () => {\n // @ts-expect-error Pagefind publishes no declarations for its default UI.\n const { PagefindUI } = await import(\"@pagefind/default-ui\");\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n const format = (url: string) =>\n element.hasAttribute(\"data-strip-trailing-slash\")\n ? url.replace(/(.)\\/(#.*)?$/, \"$1$2\")\n : url;\n new PagefindUI({\n ...options,\n element: element.querySelector(\"[data-search-results]\"),\n baseUrl: base,\n bundlePath: `${base.replace(/\\/$/, \"\")}/pagefind/`,\n showImages: false,\n showSubResults: true,\n translations,\n processResult(result: SearchResult) {\n result = options.processResult?.(result) ?? result;\n result.url = format(result.url);\n result.sub_results?.forEach((child) => {\n child.url = format(child.url);\n });\n return result;\n },\n });\n engineInput = element.querySelector(\".pagefind-ui__search-input\");\n element.querySelector(\".pagefind-ui__form\")?.removeAttribute(\"role\");\n // Cookbook owns the field so focus stays within the opening tap on mobile.\n // Pagefind still owns query processing and its lazily rendered results.\n element\n .querySelectorAll<HTMLElement>(\n \".pagefind-ui__search-input, .pagefind-ui__search-clear\",\n )\n .forEach((control) => {\n control.hidden = true;\n control.tabIndex = -1;\n });\n updateSearch();\n })().catch((error: unknown) => {\n initialized = undefined;\n if (status) {\n status.hidden = false;\n // Reuse the localized Pagefind error, with a plain fallback.\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n status.textContent =\n translations.error ?? \"Search could not load. Close and try again.\";\n }\n throw error;\n }));\n };\n const show = (trigger?: HTMLElement) => {\n if (dialog.open && !closing) return;\n generation += 1;\n closing = false;\n if (!dialog.open) {\n returnFocus =\n trigger ??\n (document.activeElement instanceof HTMLElement &&\n document.activeElement !== document.body\n ? document.activeElement\n : open);\n dialog.removeAttribute(\"data-open\");\n dialog.showModal();\n }\n // Do this synchronously, before the lazy import releases user activation.\n input?.focus({ preventScroll: true });\n // Establish the initial state after entering the top layer. The global\n // style renderer does not preserve @starting-style in server output.\n dialog.getBoundingClientRect();\n dialog.setAttribute(\"data-open\", \"\");\n document.body.setAttribute(\"data-search-modal-open\", \"\");\n if (!development && status) status.hidden = true;\n void initialize().catch(() => {\n /* Keep the close control usable when the search bundle fails. */\n });\n };\n const hide = async () => {\n if (!dialog.open || closing) return;\n closing = true;\n const current = ++generation;\n dialog.removeAttribute(\"data-open\");\n // Keep the modal in the top layer until its exit transition has finished.\n // This also works in browsers without discrete display/overlay transitions.\n await Promise.allSettled(\n dialog\n .getAnimations()\n .filter((animation) =>\n Number.isFinite(animation.effect?.getComputedTiming().endTime),\n )\n .map((animation) => animation.finished),\n );\n if (current === generation && dialog.open) dialog.close();\n };\n open.addEventListener(\"click\", () => {\n show(open);\n });\n open.disabled = false;\n close.addEventListener(\"click\", () => void hide());\n dialog.addEventListener(\"cancel\", (event) => {\n event.preventDefault();\n void hide();\n });\n dialog.addEventListener(\"click\", (event) => {\n if (!(event.target instanceof Element)) return;\n if (event.target.closest(\"a[href]\") || !frame.contains(event.target))\n void hide();\n });\n dialog.addEventListener(\"close\", () => {\n dialog.removeAttribute(\"data-open\");\n closing = false;\n document.body.removeAttribute(\"data-search-modal-open\");\n returnFocus?.focus();\n });\n window.addEventListener(\"keydown\", (event) => {\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"k\") {\n event.preventDefault();\n if (dialog.open && !closing) void hide();\n else void show();\n }\n });\n}\n"],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ import closeIcon from "../icons/close.svg?raw";
|
|
|
9
9
|
import copyIcon from "../icons/copy.svg?raw";
|
|
10
10
|
import searchIcon from "../icons/search.svg?raw";
|
|
11
11
|
import { resolveComponentStyles } from "./component-styles.js";
|
|
12
|
+
import { selectPopoverStyles } from "./select-popover-styles.js";
|
|
12
13
|
import { svgIconUrl } from "./svg-icon.js";
|
|
13
14
|
import { configureCookbookStates } from "./tasty-states.js";
|
|
14
15
|
import { getDefaultFontUsage, getFontFaces } from "../theme/fonts.js";
|
|
@@ -362,18 +363,18 @@ export default function GlobalStyles() {
|
|
|
362
363
|
},
|
|
363
364
|
Backdrop: {
|
|
364
365
|
$: "dialog::backdrop",
|
|
365
|
-
fill: "#overlay",
|
|
366
|
-
backdropFilter: "blur(0.25rem)",
|
|
366
|
+
fill: { "": "#overlay", "@mobile": "#clear" },
|
|
367
|
+
backdropFilter: { "": "blur(0.25rem)", "@mobile": "none" },
|
|
367
368
|
opacity: "0",
|
|
368
369
|
transition: {
|
|
369
370
|
"": "none",
|
|
370
|
-
"!@reduced-motion":
|
|
371
|
+
"!@reduced-motion & !@mobile":
|
|
371
372
|
"opacity $dialog-transition ease-out, display $dialog-transition allow-discrete, overlay $dialog-transition allow-discrete",
|
|
372
373
|
},
|
|
373
374
|
},
|
|
374
375
|
EnteredBackdrop: {
|
|
375
376
|
$: "dialog[open][data-open]::backdrop",
|
|
376
|
-
opacity: "1",
|
|
377
|
+
opacity: { "": "1", "@mobile": "0" },
|
|
377
378
|
},
|
|
378
379
|
Frame: {
|
|
379
380
|
$: ".dialog-frame",
|
|
@@ -935,8 +936,9 @@ export default function GlobalStyles() {
|
|
|
935
936
|
marginBlockStart: "0",
|
|
936
937
|
marginBlockEnd: "0",
|
|
937
938
|
},
|
|
939
|
+
// Linked Cards are block content even though their root is an anchor.
|
|
938
940
|
BlockSpacing: {
|
|
939
|
-
$: ":not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br) + :not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br):not(li):not(dt):not(dd):not(.not-content *)",
|
|
941
|
+
$: ":not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br) + :not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br):not(li):not(dt):not(dd):not(.not-content *), :not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br) + a.td-card, a.td-card + :not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br):not(li):not(dt):not(dd):not(.not-content *), a.td-card + a.td-card",
|
|
940
942
|
marginBlockStart: "($gap * 3)",
|
|
941
943
|
},
|
|
942
944
|
HeadingSpacing: {
|
|
@@ -1173,21 +1175,21 @@ export default function GlobalStyles() {
|
|
|
1173
1175
|
lineHeight: "0",
|
|
1174
1176
|
},
|
|
1175
1177
|
DiffLine: {
|
|
1176
|
-
$: "pre.td-diff .line",
|
|
1178
|
+
$: "pre.td-diff > code > .line",
|
|
1177
1179
|
display: "block",
|
|
1178
1180
|
inlinePadding: "1rem",
|
|
1179
1181
|
preset: "code",
|
|
1180
1182
|
},
|
|
1181
1183
|
EmptyDiffLine: {
|
|
1182
|
-
$: "pre.td-diff .line:empty::before",
|
|
1184
|
+
$: "pre.td-diff > code > .line:empty::before",
|
|
1183
1185
|
content: '"\\200b"',
|
|
1184
1186
|
},
|
|
1185
1187
|
InsertedLine: {
|
|
1186
|
-
$: "pre.td-diff .td-diff-line--inserted",
|
|
1188
|
+
$: "pre.td-diff > code > .td-diff-line--inserted",
|
|
1187
1189
|
fill: "#green-surface",
|
|
1188
1190
|
},
|
|
1189
1191
|
DeletedLine: {
|
|
1190
|
-
$: "pre.td-diff .td-diff-line--deleted",
|
|
1192
|
+
$: "pre.td-diff > code > .td-diff-line--deleted",
|
|
1191
1193
|
fill: "#red-surface",
|
|
1192
1194
|
},
|
|
1193
1195
|
}),
|
|
@@ -1431,47 +1433,85 @@ export default function GlobalStyles() {
|
|
|
1431
1433
|
}),
|
|
1432
1434
|
);
|
|
1433
1435
|
|
|
1436
|
+
const languageSelectStyles = selectPopoverStyles();
|
|
1434
1437
|
useGlobalStyles(
|
|
1435
1438
|
"cookbook-language-select",
|
|
1436
1439
|
resolveComponentStyles("LanguageSelect", {
|
|
1437
|
-
display: "
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
alignItems: "center",
|
|
1443
|
-
color: "#text-soft",
|
|
1444
|
-
},
|
|
1445
|
-
HoverLabel: { $: "label:hover", color: "#text" },
|
|
1446
|
-
LabelIcon: {
|
|
1447
|
-
$: ".label-icon",
|
|
1448
|
-
position: "absolute",
|
|
1449
|
-
zIndex: "1",
|
|
1450
|
-
insetInlineStart: "$gap",
|
|
1451
|
-
pointerEvents: "none",
|
|
1440
|
+
display: "flex",
|
|
1441
|
+
flexShrink: "0",
|
|
1442
|
+
"$popover-transition": languageSelectStyles["$popover-transition"],
|
|
1443
|
+
Compact: {
|
|
1444
|
+
$: "&[data-compact]",
|
|
1452
1445
|
},
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
appearance: "none",
|
|
1446
|
+
Trigger: {
|
|
1447
|
+
...languageSelectStyles.Trigger,
|
|
1456
1448
|
inlineSize: "8rem",
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
paddingInlineEnd: "($gap * 3.5)",
|
|
1460
|
-
color: "#text-soft",
|
|
1461
|
-
border: "0",
|
|
1462
|
-
radius: "$header-control-radius",
|
|
1449
|
+
blockSize: "$control-height",
|
|
1450
|
+
padding: "0 $gap",
|
|
1463
1451
|
fill: "#clear",
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
textOverflow: "ellipsis",
|
|
1452
|
+
border: "0",
|
|
1453
|
+
transition: "color $transition, fill $transition",
|
|
1467
1454
|
},
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1455
|
+
HoverTrigger: languageSelectStyles.HoverTrigger,
|
|
1456
|
+
ActiveTrigger: {
|
|
1457
|
+
$: "> button:active",
|
|
1458
|
+
color: "#text",
|
|
1459
|
+
fill: "#surface-2-pressed",
|
|
1460
|
+
},
|
|
1461
|
+
LabelIcon: {
|
|
1462
|
+
$: "> button > .label-icon",
|
|
1463
|
+
display: "block",
|
|
1464
|
+
flexShrink: "0",
|
|
1465
|
+
inlineSize: { "": "1.25rem", "@mobile": "1.125rem" },
|
|
1466
|
+
blockSize: { "": "1.25rem", "@mobile": "1.125rem" },
|
|
1473
1467
|
},
|
|
1474
|
-
|
|
1468
|
+
TriggerLabel: languageSelectStyles.TriggerLabel,
|
|
1469
|
+
Caret: languageSelectStyles.Caret,
|
|
1470
|
+
CompactTrigger: {
|
|
1471
|
+
$: "&[data-compact] > button",
|
|
1472
|
+
inlineSize: "$docs-menu-button-size",
|
|
1473
|
+
blockSize: "$docs-menu-button-size",
|
|
1474
|
+
padding: "0",
|
|
1475
|
+
},
|
|
1476
|
+
CompactLabel: {
|
|
1477
|
+
$: "&[data-compact] > button > .trigger-label",
|
|
1478
|
+
hide: true,
|
|
1479
|
+
},
|
|
1480
|
+
CompactCaret: { $: "&[data-compact] > button > .caret", hide: true },
|
|
1481
|
+
Label: { $: "> button" },
|
|
1482
|
+
HoverLabel: { $: "> button:hover" },
|
|
1483
|
+
Select: { $: "> button" },
|
|
1484
|
+
CompactSelect: { $: "&[data-compact] > button" },
|
|
1485
|
+
CompactLabelIcon: { $: "&[data-compact] > button > .label-icon" },
|
|
1486
|
+
SidebarTrigger: {
|
|
1487
|
+
$: "&[data-sidebar] > button",
|
|
1488
|
+
anchorName: "--language-trigger",
|
|
1489
|
+
},
|
|
1490
|
+
Panel: {
|
|
1491
|
+
...languageSelectStyles.Panel,
|
|
1492
|
+
blockInset: { "": "4rem start", "@mobile": "3.5rem start" },
|
|
1493
|
+
inlineInset:
|
|
1494
|
+
"max($docs-nav-pad-x, ((100vw - $layout-width) / 2 + $docs-sidebar-pad-x)) end",
|
|
1495
|
+
},
|
|
1496
|
+
SidebarPanel: {
|
|
1497
|
+
$: "&[data-sidebar] > [popover]",
|
|
1498
|
+
positionAnchor: "--language-trigger",
|
|
1499
|
+
blockInset: "auto start, anchor(top) end",
|
|
1500
|
+
blockMargin: "$gap end",
|
|
1501
|
+
inlineInset: "$gap start, auto end",
|
|
1502
|
+
inlineSize: "min(20rem, calc(100vw - 4rem))",
|
|
1503
|
+
blockSize: "max (100dvh - 8rem)",
|
|
1504
|
+
transformOrigin: "bottom",
|
|
1505
|
+
},
|
|
1506
|
+
OpenPanel: languageSelectStyles.OpenPanel,
|
|
1507
|
+
PanelTitle: languageSelectStyles.PanelTitle,
|
|
1508
|
+
Options: languageSelectStyles.Options,
|
|
1509
|
+
Option: languageSelectStyles.Option,
|
|
1510
|
+
HoverOption: languageSelectStyles.HoverOption,
|
|
1511
|
+
CurrentOption: languageSelectStyles.CurrentOption,
|
|
1512
|
+
Fallback: { $: ".fallback-label", color: "#text-muted" },
|
|
1513
|
+
Checkmark: languageSelectStyles.Checkmark,
|
|
1514
|
+
SelectedCheckmark: languageSelectStyles.SelectedCheckmark,
|
|
1475
1515
|
}),
|
|
1476
1516
|
);
|
|
1477
1517
|
|
|
@@ -1490,7 +1530,7 @@ export default function GlobalStyles() {
|
|
|
1490
1530
|
"$pagefind-ui-tag": "#surface-3",
|
|
1491
1531
|
preset: "body",
|
|
1492
1532
|
UI: {
|
|
1493
|
-
$: ".pagefind-ui",
|
|
1533
|
+
$: ".pagefind-ui, [data-search-results]",
|
|
1494
1534
|
display: "flex",
|
|
1495
1535
|
flow: "column",
|
|
1496
1536
|
flexGrow: "1",
|
|
@@ -1504,6 +1544,15 @@ export default function GlobalStyles() {
|
|
|
1504
1544
|
flexGrow: "1",
|
|
1505
1545
|
minBlockSize: "0",
|
|
1506
1546
|
},
|
|
1547
|
+
Field: {
|
|
1548
|
+
$: ".cookbook-search-field",
|
|
1549
|
+
position: "relative",
|
|
1550
|
+
flexShrink: "0",
|
|
1551
|
+
},
|
|
1552
|
+
EngineControls: {
|
|
1553
|
+
$: ".pagefind-ui__search-input, .pagefind-ui__search-clear",
|
|
1554
|
+
display: "none",
|
|
1555
|
+
},
|
|
1507
1556
|
Drawer: {
|
|
1508
1557
|
$: ".pagefind-ui__drawer",
|
|
1509
1558
|
display: "flex",
|
|
@@ -1512,7 +1561,7 @@ export default function GlobalStyles() {
|
|
|
1512
1561
|
minBlockSize: "0",
|
|
1513
1562
|
},
|
|
1514
1563
|
Input: {
|
|
1515
|
-
$: ".
|
|
1564
|
+
$: ".cookbook-search-input",
|
|
1516
1565
|
flexShrink: "0",
|
|
1517
1566
|
inlineSize: "100%",
|
|
1518
1567
|
minBlockSize: "3rem",
|
|
@@ -1526,7 +1575,7 @@ export default function GlobalStyles() {
|
|
|
1526
1575
|
boxShadow: "none",
|
|
1527
1576
|
},
|
|
1528
1577
|
Clear: {
|
|
1529
|
-
$: ".
|
|
1578
|
+
$: ".cookbook-search-clear",
|
|
1530
1579
|
position: "absolute",
|
|
1531
1580
|
insetBlockStart: "0",
|
|
1532
1581
|
insetInlineEnd: "0",
|
|
@@ -1614,7 +1663,7 @@ export default function GlobalStyles() {
|
|
|
1614
1663
|
},
|
|
1615
1664
|
HoverMore: { $: ".pagefind-ui__button:hover", fill: "#surface-2-hover" },
|
|
1616
1665
|
SearchIcon: {
|
|
1617
|
-
$: ".
|
|
1666
|
+
$: ".cookbook-search-field::before",
|
|
1618
1667
|
content: '""',
|
|
1619
1668
|
position: "absolute",
|
|
1620
1669
|
zIndex: "1",
|
|
@@ -1628,7 +1677,7 @@ export default function GlobalStyles() {
|
|
|
1628
1677
|
pointerEvents: "none",
|
|
1629
1678
|
},
|
|
1630
1679
|
ClearIcon: {
|
|
1631
|
-
$: ".
|
|
1680
|
+
$: ".cookbook-search-clear::before",
|
|
1632
1681
|
content: '""',
|
|
1633
1682
|
display: "block",
|
|
1634
1683
|
inlineSize: "1rem",
|
|
@@ -1637,7 +1686,7 @@ export default function GlobalStyles() {
|
|
|
1637
1686
|
mask: `url("${svgIconUrl(closeIcon)}") center / 1rem no-repeat`,
|
|
1638
1687
|
},
|
|
1639
1688
|
SuppressedClear: {
|
|
1640
|
-
$: ".
|
|
1689
|
+
$: ".cookbook-search-clear[hidden]",
|
|
1641
1690
|
display: "none",
|
|
1642
1691
|
},
|
|
1643
1692
|
}),
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { messages } from "../localization.js";
|
|
3
|
+
import { localeHref, routeLocale } from "../localization.js";
|
|
4
|
+
import { navigationPath } from "../navigation.js";
|
|
3
5
|
import { content } from "virtual:cookbook/config";
|
|
4
6
|
import { HeaderLinksRoot } from "./LayoutComponents.js";
|
|
5
7
|
|
|
6
8
|
const links = content.site.headerLinks ?? [];
|
|
7
9
|
const base = import.meta.env.BASE_URL.replace(/\/$/, "");
|
|
8
|
-
const
|
|
10
|
+
const currentPath = navigationPath(Astro.url.pathname, base || "/");
|
|
11
|
+
const href = (link: string) =>
|
|
12
|
+
localeHref(link, currentPath, content.routes, content, base || "/");
|
|
13
|
+
const locale = routeLocale(currentPath, content);
|
|
14
|
+
const language =
|
|
15
|
+
content.locales?.[locale]?.lang ?? (locale === "root" ? "en" : locale);
|
|
16
|
+
const label = (value: string) =>
|
|
17
|
+
content.translations?.[language]?.[`navigation.${value}`] ??
|
|
18
|
+
content.translations?.[language.split("-")[0]!]?.[`navigation.${value}`] ??
|
|
19
|
+
value;
|
|
9
20
|
const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
|
|
10
21
|
---
|
|
11
22
|
|
|
@@ -20,7 +31,7 @@ const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
|
|
|
20
31
|
target={link.newTab ? "_blank" : undefined}
|
|
21
32
|
rel={link.newTab ? "noopener noreferrer" : undefined}
|
|
22
33
|
>
|
|
23
|
-
{link.label}
|
|
34
|
+
{label(link.label)}
|
|
24
35
|
</a>
|
|
25
36
|
))}
|
|
26
37
|
</nav>
|
|
@@ -74,7 +85,7 @@ const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
|
|
|
74
85
|
target={link.newTab ? "_blank" : undefined}
|
|
75
86
|
rel={link.newTab ? "noopener noreferrer" : undefined}
|
|
76
87
|
>
|
|
77
|
-
{link.label}
|
|
88
|
+
{label(link.label)}
|
|
78
89
|
</a>
|
|
79
90
|
))}
|
|
80
91
|
</nav>
|
|
@@ -23,7 +23,7 @@ const originals: Record<string, string> = {
|
|
|
23
23
|
laptop: desktop,
|
|
24
24
|
"approve-check": check,
|
|
25
25
|
translate:
|
|
26
|
-
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
26
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="9"/><ellipse cx="12" cy="12" rx="4" ry="9"/><path d="M3 12h18"/></svg>',
|
|
27
27
|
github:
|
|
28
28
|
'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2a10 10 0 0 0-3.16 19.49c.5.09.68-.22.68-.48v-1.7c-2.77.6-3.36-1.18-3.36-1.18-.45-1.14-1.1-1.44-1.1-1.44-.9-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.89 1.52 2.33 1.08 2.9.83.09-.65.35-1.08.63-1.33-2.21-.25-4.53-1.1-4.53-4.94 0-1.09.39-1.98 1.03-2.68-.1-.25-.45-1.27.1-2.65 0 0 .84-.27 2.75 1.02A9.6 9.6 0 0 1 12 6.66c.85 0 1.7.11 2.5.34 1.9-1.29 2.74-1.02 2.74-1.02.55 1.38.2 2.4.1 2.65.64.7 1.03 1.59 1.03 2.68 0 3.85-2.33 4.68-4.55 4.93.36.31.68.92.68 1.86v2.91c0 .27.18.58.69.48A10 10 0 0 0 12 2Z"/></svg>',
|
|
29
29
|
gitlab:
|