@clarify-labs/renderer 0.7.2 → 0.8.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.
Files changed (59) hide show
  1. package/output/{ThemeRoot-QULrwQf6.js → ClarifyShell-BxB_6Uhd.js} +292 -142
  2. package/output/ClarifyShell-BxB_6Uhd.js.map +1 -0
  3. package/output/{ThemeRoot-UWj0iK1X.cjs → ClarifyShell-DNN5erFD.cjs} +320 -146
  4. package/output/ClarifyShell-DNN5erFD.cjs.map +1 -0
  5. package/output/{OpenApiOperation-BcyW_ULy.cjs → OpenApiOperation-9SvCA_B4.cjs} +209 -7
  6. package/output/OpenApiOperation-9SvCA_B4.cjs.map +1 -0
  7. package/output/{OpenApiOperation-tUKf7lZ4.js → OpenApiOperation-J41rHO2l.js} +205 -9
  8. package/output/OpenApiOperation-J41rHO2l.js.map +1 -0
  9. package/output/{PageActions-yoDRjkq8.js → PageActions-DR0asnKH.js} +30 -69
  10. package/output/PageActions-DR0asnKH.js.map +1 -0
  11. package/output/{PageActions-1RDCHcUY.cjs → PageActions-yycPlNyL.cjs} +35 -68
  12. package/output/PageActions-yycPlNyL.cjs.map +1 -0
  13. package/output/app/AppShell.d.ts +2 -3
  14. package/output/app/PageBanner.d.ts +0 -2
  15. package/output/app/PageFooter.d.ts +1 -5
  16. package/output/client.cjs +8 -8
  17. package/output/client.js +3 -3
  18. package/output/components/Code.d.ts +5 -1
  19. package/output/components/Mermaid.d.ts +7 -0
  20. package/output/components/index.d.ts +1 -0
  21. package/output/context.d.ts +1 -1
  22. package/output/core/i18n.d.ts +1 -1
  23. package/output/core/types.d.ts +7 -14
  24. package/output/index.cjs +27 -24
  25. package/output/index.cjs.map +1 -1
  26. package/output/index.d.ts +7 -4
  27. package/output/index.js +14 -14
  28. package/output/index.js.map +1 -1
  29. package/output/mdx/components.d.ts +3 -0
  30. package/output/mdx/primitives.d.ts +1 -0
  31. package/output/preview.cjs +2 -2
  32. package/output/preview.cjs.map +1 -1
  33. package/output/preview.js +2 -2
  34. package/output/preview.js.map +1 -1
  35. package/output/{render-ByWbJbrA.cjs → render-CWvm77UW.cjs} +10 -20
  36. package/output/render-CWvm77UW.cjs.map +1 -0
  37. package/output/{render-psutGbsg.js → render-mGozubG5.js} +10 -20
  38. package/output/render-mGozubG5.js.map +1 -0
  39. package/output/renderer.css +77 -16
  40. package/output/runtime/ClarifyShell.d.ts +22 -0
  41. package/output/server.cjs +10 -19
  42. package/output/server.cjs.map +1 -1
  43. package/output/server.js +10 -19
  44. package/output/server.js.map +1 -1
  45. package/output/shell/search/pagefind.d.ts +0 -1
  46. package/output/slots/RuntimeSlot.d.ts +58 -0
  47. package/output/slots/context.d.ts +20 -0
  48. package/output/slots/index.d.ts +5 -0
  49. package/output/slots/types.d.ts +50 -0
  50. package/output/utils/localized-text.d.ts +7 -0
  51. package/package.json +8 -3
  52. package/output/OpenApiOperation-BcyW_ULy.cjs.map +0 -1
  53. package/output/OpenApiOperation-tUKf7lZ4.js.map +0 -1
  54. package/output/PageActions-1RDCHcUY.cjs.map +0 -1
  55. package/output/PageActions-yoDRjkq8.js.map +0 -1
  56. package/output/ThemeRoot-QULrwQf6.js.map +0 -1
  57. package/output/ThemeRoot-UWj0iK1X.cjs.map +0 -1
  58. package/output/render-ByWbJbrA.cjs.map +0 -1
  59. package/output/render-psutGbsg.js.map +0 -1
@@ -1,9 +1,140 @@
1
- import { C as isExternalHref, D as useBuiltInText, E as copyTextToClipboard, S as themeCookieName, a as safeDecodeURIComponent, b as storeLocalePreference, d as isSameRoutePath, f as normalizeRoutePath, g as getStoredLocalePreference, h as useTheme, i as Navigation, j as useConfig, k as LocaleContext, o as SectionProvider, r as Header, t as PageActionsProvider, w as localizeHref } from "./PageActions-yoDRjkq8.js";
1
+ import { A as LocaleContext, C as themeCookieName, D as copyTextToClipboard, M as useConfig, N as useLocale, O as useBuiltInText, T as localizeHref, _ as getStoredLocalePreference, a as safeDecodeURIComponent, d as isSameRoutePath, f as normalizeRoutePath, g as useTheme, h as ThemeProvider, i as Navigation, j as OpenApisContext, k as ConfigContext, o as SectionProvider, p as resolveLocalizedText, r as Header, t as PageActionsProvider, w as isExternalHref, x as storeLocalePreference } from "./PageActions-DR0asnKH.js";
2
2
  import clsx from "clsx";
3
- import { Component, Suspense, lazy, useEffect, useMemo, useState } from "react";
3
+ import { Component, Suspense, createContext, lazy, useContext, useEffect, useMemo, useState } from "react";
4
4
  import { Link, Route, Routes, useLocation, useNavigate } from "react-router-dom";
5
5
  import { ChevronDown, ChevronLeft, ChevronRight, Settings, WandSparkles, X } from "lucide-react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
+ //#region source/slots/context.tsx
8
+ var SlotContextValue = createContext(null);
9
+ /**
10
+ * Provides an isolated {@link SlotContext} for a single slot component.
11
+ * `RuntimeSlot` wraps every rendered slot component with this provider.
12
+ */
13
+ function SlotProvider(arg0) {
14
+ const { value, children } = arg0;
15
+ return /* @__PURE__ */ jsx(SlotContextValue.Provider, {
16
+ value,
17
+ children
18
+ });
19
+ }
20
+ /**
21
+ * Reads the current slot context.
22
+ *
23
+ * Must be called inside a slot component (or a descendant). Calling it outside a
24
+ * slot provider throws, which helps plugin authors notice that the component was
25
+ * not mounted through a Clarify slot.
26
+ */
27
+ function useSlot() {
28
+ const context = useContext(SlotContextValue);
29
+ if (!context) throw new Error("[clarify] useSlot must be called inside a slot component");
30
+ return context;
31
+ }
32
+ //#endregion
33
+ //#region source/slots/RuntimeSlot.tsx
34
+ var RuntimeSlotsContext = createContext({ slots: {} });
35
+ /**
36
+ * Makes the compiled slot registry and the current route available to every
37
+ * {@link RuntimeSlot} in the tree. Mounted once near the top of `AppShell`.
38
+ */
39
+ function RuntimeSlotsProvider(arg0) {
40
+ const { slots, route, children } = arg0;
41
+ return /* @__PURE__ */ jsx(RuntimeSlotsContext.Provider, {
42
+ value: {
43
+ slots: slots ?? {},
44
+ route
45
+ },
46
+ children
47
+ });
48
+ }
49
+ /**
50
+ * Renders plugin components registered for a slot, in registration order.
51
+ *
52
+ * For extension slots (*.before/*.after), renders all plugin components.
53
+ * For replacement slots (*.replace), renders only the last registered plugin
54
+ * component (if any), and passes the default component through context.
55
+ *
56
+ * Each component is loaded via the import factory. If `_resolved` is set
57
+ * (SSR pre-resolution), the component is rendered synchronously for
58
+ * compatibility with `renderToString`. Otherwise, `React.lazy` + `Suspense`
59
+ * is used for client-side code-splitting.
60
+ */
61
+ function RuntimeSlot(arg0) {
62
+ const { name, default: DefaultComponent } = arg0;
63
+ const { slots, route } = useContext(RuntimeSlotsContext);
64
+ const locale = useLocale();
65
+ const entries = slots[name];
66
+ if (!entries || entries.length === 0) return DefaultComponent ? /* @__PURE__ */ jsx(DefaultComponent, {}) : null;
67
+ if (name.endsWith(".replace")) {
68
+ const lastEntry = entries[entries.length - 1];
69
+ return /* @__PURE__ */ jsx(SlotProvider, {
70
+ value: {
71
+ name,
72
+ plugin: lastEntry.plugin,
73
+ route,
74
+ locale,
75
+ DefaultComponent
76
+ },
77
+ children: /* @__PURE__ */ jsx(SlotEntryRenderer, { entry: lastEntry })
78
+ });
79
+ }
80
+ return /* @__PURE__ */ jsx(Fragment$1, { children: entries.map((entry) => /* @__PURE__ */ jsx(SlotProvider, {
81
+ value: {
82
+ name,
83
+ plugin: entry.plugin,
84
+ route,
85
+ locale
86
+ },
87
+ children: /* @__PURE__ */ jsx(SlotEntryRenderer, { entry })
88
+ }, `${name}:${entry.plugin}`)) });
89
+ }
90
+ function SlotEntryRenderer(props) {
91
+ const { entry } = props;
92
+ if (entry._resolved) return /* @__PURE__ */ jsx(entry._resolved, {});
93
+ return /* @__PURE__ */ jsx(LazySlotComponent, { loader: entry.component });
94
+ }
95
+ function LazySlotComponent(props) {
96
+ const { loader } = props;
97
+ const [Component, setComponent] = useState(null);
98
+ useEffect(() => {
99
+ let cancelled = false;
100
+ loader().then((mod) => {
101
+ if (!cancelled) setComponent(() => mod.default);
102
+ });
103
+ return () => {
104
+ cancelled = true;
105
+ };
106
+ }, [loader]);
107
+ if (!Component) return null;
108
+ return /* @__PURE__ */ jsx(Component, {});
109
+ }
110
+ //#endregion
111
+ //#region source/assets/clarify.svg?url
112
+ var clarify_default = "data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'?%3e%3csvg%20width='279px'%20height='200px'%20viewBox='0%200%20279%20200'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3ctitle%3eclarify%3c/title%3e%3cg%20id='页面-1'%20stroke='none'%20stroke-width='1'%20fill='none'%20fill-rule='evenodd'%3e%3cg%20id='clarify'%20transform='translate(-0,%200.0054)'%3e%3cpath%20d='M44.867217,0.0054376148%20C130.715579,1.00591567%20200,70.9091172%20200,156.994562%20L199.986321,155.127494%20C199.384888,180.009127%20179.026368,199.994562%20154,199.994562%20L46,199.994562%20C20.5949015,199.994562%200,179.399661%200,153.994562%20L0,45.9945624%20C0,21.0975659%2019.7793434,0.820282524%2044.4815926,0.0191499894%20Z'%20fill='%2300D492'%3e%3c/path%3e%3cpath%20d='M123.867217,0.0054376148%20C209.715579,1.00591567%20279,70.9091172%20279,156.994562%20L278.986321,155.127494%20C278.384888,180.009127%20258.026368,199.994562%20233,199.994562%20L125,199.994562%20C99.5949015,199.994562%2079,179.399661%2079,153.994562%20L79,45.9945624%20C79,21.0975659%2098.7793434,0.820282524%20123.481593,0.0191499894%20Z'%20id='clarify-right'%20fill-opacity='0.6'%20fill='%2300F6C9'%20transform='translate(179,%20100)%20rotate(-90)%20translate(-179,%20-100)'%3e%3c/path%3e%3cpath%20d='M199.979267,154.416906%20L199.984438,155.157125%20L199.962366,155.872459%20C198.977251,180.406837%20178.776104,199.994562%20154,199.994562%20L124.372438,199.994125%20L124.249053,199.994081%20C99.6939678,199.603921%2079.8122712,179.973634%2079.01915,155.518407%20L79.0054376,155.132783%20C79.5830823,105.566626%20103.129768,61.5221348%20139.498462,33.1463428%20C175.69419,61.3871018%20199.186123,105.143863%20199.979267,154.416906%20Z'%20id='形状结合'%20fill='%2300F692'%3e%3c/path%3e%3c/g%3e%3c/g%3e%3c/svg%3e";
113
+ //#endregion
114
+ //#region source/app/BuiltWithClarify.tsx
115
+ function BuiltWithClarify() {
116
+ const t = useBuiltInText();
117
+ return /* @__PURE__ */ jsxs("a", {
118
+ href: "https://clarify.pub",
119
+ target: "_blank",
120
+ rel: "noreferrer",
121
+ "aria-label": t("builtWith.label"),
122
+ className: "clarify-built-with inline-flex items-center gap-1.5 rounded-full px-2 py-1 font-medium no-underline transition",
123
+ children: [
124
+ /* @__PURE__ */ jsx("span", { children: t("builtWith.prefix") }),
125
+ /* @__PURE__ */ jsx("img", {
126
+ src: clarify_default,
127
+ alt: "",
128
+ className: "clarify-built-with-logo h-3.5 w-auto flex-none object-contain"
129
+ }),
130
+ /* @__PURE__ */ jsx("span", {
131
+ className: "clarify-built-with-brand font-semibold",
132
+ children: "Clarify"
133
+ })
134
+ ]
135
+ });
136
+ }
137
+ //#endregion
7
138
  //#region source/app/ErrorBoundary.tsx
8
139
  function PageErrorPanel(props) {
9
140
  const { title, description, reloadLabel, detailsLabel, pathLabel, typeLabel, messageLabel, stackLabel, componentStackLabel, timestampLabel, copyLabel, copiedLabel, path, error, errorInfo, occurredAt } = props;
@@ -86,7 +217,7 @@ function PageErrorPanel(props) {
86
217
  children: messageLabel
87
218
  }),
88
219
  /* @__PURE__ */ jsx("p", {
89
- className: "mt-2 break-words font-mono text-sm/6 font-semibold text-(--clarify-theme-tokens-colors-foreground)",
220
+ className: "mt-2 wrap-break-word font-mono text-sm/6 font-semibold text-(--clarify-theme-tokens-colors-foreground)",
90
221
  children: error.message
91
222
  }),
92
223
  /* @__PURE__ */ jsx("p", {
@@ -94,14 +225,14 @@ function PageErrorPanel(props) {
94
225
  children: stackLabel
95
226
  }),
96
227
  /* @__PURE__ */ jsx("pre", {
97
- className: "mt-2 max-h-(--clarify-error-details-max-height) overflow-auto whitespace-pre-wrap break-words font-mono",
228
+ className: "mt-2 max-h-(--clarify-error-details-max-height) overflow-auto whitespace-pre-wrap wrap-break-word font-mono",
98
229
  children: stack
99
230
  }),
100
231
  componentStack ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("p", {
101
232
  className: "mt-6 font-semibold uppercase tracking-wide text-(--clarify-ui-text-faint)",
102
233
  children: componentStackLabel
103
234
  }), /* @__PURE__ */ jsx("pre", {
104
- className: "mt-2 max-h-(--clarify-error-component-stack-max-height) overflow-auto whitespace-pre-wrap break-words font-mono",
235
+ className: "mt-2 max-h-(--clarify-error-component-stack-max-height) overflow-auto whitespace-pre-wrap wrap-break-word font-mono",
105
236
  children: componentStack
106
237
  })] }) : null
107
238
  ]
@@ -148,10 +279,6 @@ var PageErrorBoundary = class extends Component {
148
279
  };
149
280
  //#endregion
150
281
  //#region source/app/PageBanner.tsx
151
- function resolveLocalizedText$1(text, locale, fallbackLocale) {
152
- if (typeof text === "string") return text;
153
- return (locale ? text[locale] : void 0) ?? (fallbackLocale ? text[fallbackLocale] : void 0) ?? Object.values(text)[0] ?? "";
154
- }
155
282
  function bannerStorageKey(config, content) {
156
283
  return `clarify:banner:dismissed:${config.title}:${content}`;
157
284
  }
@@ -174,29 +301,30 @@ function PageBannerLink(props) {
174
301
  });
175
302
  }
176
303
  function PageBanner(props) {
177
- const { component: CustomBanner, currentLocale, onDismiss } = props;
304
+ const { currentLocale, onDismiss } = props;
178
305
  const config = useConfig();
179
306
  const banner = config.banner;
180
- const builtInBanner = banner && typeof banner === "object" ? banner : void 0;
181
- const content = builtInBanner ? resolveLocalizedText$1(builtInBanner.content, currentLocale, config.i18n?.defaultLocale) : "";
182
- const link = builtInBanner?.link;
183
- const linkLabel = link ? resolveLocalizedText$1(link.label, currentLocale, config.i18n?.defaultLocale) : "";
184
- const storageKey = useMemo(() => content ? bannerStorageKey(config, content) : "", [config, content]);
307
+ const content = banner ? resolveLocalizedText(banner.content, currentLocale, config.i18n?.defaultLocale) : "";
308
+ const storageKey = useMemo(() => {
309
+ if (!banner || !content) return "";
310
+ return bannerStorageKey(config, content);
311
+ }, [
312
+ config,
313
+ content,
314
+ banner
315
+ ]);
185
316
  const [dismissed, setDismissed] = useState(() => {
186
- if (!storageKey || !builtInBanner?.dismissible || typeof window === "undefined") return false;
317
+ if (!banner?.dismissible || typeof window === "undefined") return false;
187
318
  return window.localStorage.getItem(storageKey) === "1";
188
319
  });
189
320
  useEffect(() => {
190
321
  if (dismissed) onDismiss?.();
191
322
  }, [dismissed, onDismiss]);
192
- if (CustomBanner) return /* @__PURE__ */ jsx("div", {
193
- className: "clarify-banner clarify-banner-custom flex min-h-12 items-center border-b border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-background) px-4 text-sm text-(--clarify-theme-tokens-colors-foreground) dark:border-white/10 dark:bg-zinc-950",
194
- children: /* @__PURE__ */ jsx("div", {
195
- className: "mx-auto w-full max-w-(--clarify-theme-layout-max-width)",
196
- children: /* @__PURE__ */ jsx(CustomBanner, {})
197
- })
198
- });
199
- if (!builtInBanner || !content || dismissed) return null;
323
+ if (!banner) return null;
324
+ if (!content) return null;
325
+ if (dismissed) return null;
326
+ const link = banner.link;
327
+ const linkLabel = link ? resolveLocalizedText(link.label, currentLocale, config.i18n?.defaultLocale) : "";
200
328
  return /* @__PURE__ */ jsxs("div", {
201
329
  className: "clarify-banner relative flex min-h-12 items-center border-b border-(--clarify-ui-accent-border) bg-(--clarify-ui-accent-background) px-4 text-sm text-(--clarify-ui-text) dark:border-white/10",
202
330
  children: [/* @__PURE__ */ jsxs("div", {
@@ -211,7 +339,7 @@ function PageBanner(props) {
211
339
  config,
212
340
  locale: currentLocale
213
341
  }) : null]
214
- }), builtInBanner.dismissible ? /* @__PURE__ */ jsx("button", {
342
+ }), banner.dismissible ? /* @__PURE__ */ jsx("button", {
215
343
  type: "button",
216
344
  className: "clarify-banner-dismiss absolute right-3 inline-flex size-8 items-center justify-center rounded-full text-(--clarify-ui-text-soft) transition hover:bg-(--clarify-ui-hover-background) hover:text-(--clarify-ui-text-strong)",
217
345
  "aria-label": "Dismiss announcement",
@@ -227,38 +355,7 @@ function PageBanner(props) {
227
355
  });
228
356
  }
229
357
  //#endregion
230
- //#region source/assets/clarify.svg?url
231
- var clarify_default = "data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'?%3e%3csvg%20width='279px'%20height='200px'%20viewBox='0%200%20279%20200'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3ctitle%3eclarify%3c/title%3e%3cg%20id='页面-1'%20stroke='none'%20stroke-width='1'%20fill='none'%20fill-rule='evenodd'%3e%3cg%20id='clarify'%20transform='translate(-0,%200.0054)'%3e%3cpath%20d='M44.867217,0.0054376148%20C130.715579,1.00591567%20200,70.9091172%20200,156.994562%20L199.986321,155.127494%20C199.384888,180.009127%20179.026368,199.994562%20154,199.994562%20L46,199.994562%20C20.5949015,199.994562%200,179.399661%200,153.994562%20L0,45.9945624%20C0,21.0975659%2019.7793434,0.820282524%2044.4815926,0.0191499894%20Z'%20fill='%2300D492'%3e%3c/path%3e%3cpath%20d='M123.867217,0.0054376148%20C209.715579,1.00591567%20279,70.9091172%20279,156.994562%20L278.986321,155.127494%20C278.384888,180.009127%20258.026368,199.994562%20233,199.994562%20L125,199.994562%20C99.5949015,199.994562%2079,179.399661%2079,153.994562%20L79,45.9945624%20C79,21.0975659%2098.7793434,0.820282524%20123.481593,0.0191499894%20Z'%20id='clarify-right'%20fill-opacity='0.6'%20fill='%2300F6C9'%20transform='translate(179,%20100)%20rotate(-90)%20translate(-179,%20-100)'%3e%3c/path%3e%3cpath%20d='M199.979267,154.416906%20L199.984438,155.157125%20L199.962366,155.872459%20C198.977251,180.406837%20178.776104,199.994562%20154,199.994562%20L124.372438,199.994125%20L124.249053,199.994081%20C99.6939678,199.603921%2079.8122712,179.973634%2079.01915,155.518407%20L79.0054376,155.132783%20C79.5830823,105.566626%20103.129768,61.5221348%20139.498462,33.1463428%20C175.69419,61.3871018%20199.186123,105.143863%20199.979267,154.416906%20Z'%20id='形状结合'%20fill='%2300F692'%3e%3c/path%3e%3c/g%3e%3c/g%3e%3c/svg%3e";
232
- //#endregion
233
- //#region source/app/BuiltWithClarify.tsx
234
- function BuiltWithClarify() {
235
- const t = useBuiltInText();
236
- return /* @__PURE__ */ jsxs("a", {
237
- href: "https://clarify.pub",
238
- target: "_blank",
239
- rel: "noreferrer",
240
- "aria-label": t("builtWith.label"),
241
- className: "clarify-built-with inline-flex items-center gap-1.5 rounded-full px-2 py-1 font-medium no-underline transition",
242
- children: [
243
- /* @__PURE__ */ jsx("span", { children: t("builtWith.prefix") }),
244
- /* @__PURE__ */ jsx("img", {
245
- src: clarify_default,
246
- alt: "",
247
- className: "clarify-built-with-logo h-3.5 w-auto flex-none object-contain"
248
- }),
249
- /* @__PURE__ */ jsx("span", {
250
- className: "clarify-built-with-brand font-semibold",
251
- children: "Clarify"
252
- })
253
- ]
254
- });
255
- }
256
- //#endregion
257
358
  //#region source/app/PageFooter.tsx
258
- function resolveLocalizedText(text, locale, fallbackLocale) {
259
- if (typeof text === "string") return text;
260
- return (locale ? text[locale] : void 0) ?? (fallbackLocale ? text[fallbackLocale] : void 0) ?? Object.values(text)[0] ?? "";
261
- }
262
359
  function localeForPath(config, pathname) {
263
360
  const i18n = config.i18n;
264
361
  if (!i18n) return void 0;
@@ -294,23 +391,19 @@ function SocialLink(arg0) {
294
391
  children: name
295
392
  });
296
393
  }
297
- function PageFooter(props = {}) {
394
+ function PageFooter() {
298
395
  const config = useConfig();
299
396
  const locale = localeForPath(config, useLocation().pathname);
300
397
  const footer = config.footer;
301
- const builtInFooter = footer && typeof footer === "object" ? footer : void 0;
302
- const CustomFooter = props.component;
303
- const links = builtInFooter?.links ?? [];
304
- const socials = Object.entries(builtInFooter?.socials ?? {});
305
- const copyright = builtInFooter?.copyright ? resolveLocalizedText(builtInFooter.copyright, locale, config.i18n?.defaultLocale) : void 0;
306
- const hasBuiltInFooter = Boolean(copyright || links.length > 0 || socials.length > 0);
307
- return /* @__PURE__ */ jsxs("footer", {
398
+ if (!footer) return null;
399
+ const links = footer.links ?? [];
400
+ const socials = Object.entries(footer.socials ?? {});
401
+ const copyright = footer.copyright ? resolveLocalizedText(footer.copyright, locale, config.i18n?.defaultLocale) : void 0;
402
+ if (!Boolean(copyright || links.length > 0 || socials.length > 0)) return null;
403
+ return /* @__PURE__ */ jsx("footer", {
308
404
  className: "clarify-page-footer mt-16 flex w-full flex-col gap-4 border-t border-(--clarify-theme-tokens-colors-border) py-8 lg:mt-24",
309
- children: [CustomFooter ? /* @__PURE__ */ jsx("div", {
310
- className: "clarify-footer-custom w-full",
311
- children: /* @__PURE__ */ jsx(CustomFooter, {})
312
- }) : hasBuiltInFooter ? /* @__PURE__ */ jsxs("div", {
313
- className: clsx("clarify-footer-content flex flex-col items-end gap-3 text-right", hasBuiltInFooter && "sm:items-start sm:text-left"),
405
+ children: /* @__PURE__ */ jsxs("div", {
406
+ className: clsx("clarify-footer-content flex flex-col items-end gap-3 text-right", "sm:items-start sm:text-left"),
314
407
  children: [copyright ? /* @__PURE__ */ jsx("p", {
315
408
  className: "clarify-footer-copyright m-0",
316
409
  children: copyright
@@ -325,10 +418,7 @@ function PageFooter(props = {}) {
325
418
  href
326
419
  }, name))]
327
420
  }) : null]
328
- }) : null, /* @__PURE__ */ jsx("div", {
329
- className: "clarify-footer-brand flex justify-end self-end",
330
- children: /* @__PURE__ */ jsx(BuiltWithClarify, {})
331
- })]
421
+ })
332
422
  });
333
423
  }
334
424
  //#endregion
@@ -487,6 +577,23 @@ function PageSkeleton() {
487
577
  }
488
578
  //#endregion
489
579
  //#region source/app/AppShell.tsx
580
+ function BannerSlot(props) {
581
+ const { activeBannerKey, dismissedBannerKey, onDismiss, config, locale } = props;
582
+ function DefaultBannerComponent() {
583
+ if (!(Boolean(config.banner) && dismissedBannerKey !== activeBannerKey)) return null;
584
+ return /* @__PURE__ */ jsx(PageBanner, {
585
+ currentLocale: locale,
586
+ onDismiss
587
+ });
588
+ }
589
+ return /* @__PURE__ */ jsx(RuntimeSlot, {
590
+ name: "page.banner.replace",
591
+ default: DefaultBannerComponent
592
+ });
593
+ }
594
+ function DefaultFooterComponent() {
595
+ return /* @__PURE__ */ jsx(PageFooter, {});
596
+ }
490
597
  function routeForPath(routes, pathname) {
491
598
  return routes.find((route) => isSameRoutePath(route.path, pathname));
492
599
  }
@@ -610,13 +717,13 @@ function NotFoundRouteElement(props) {
610
717
  return /* @__PURE__ */ jsx(RouteComponent, {});
611
718
  }
612
719
  function AppShell(arg0) {
613
- const { config, routes, navigation, bannerComponent, footerComponent } = arg0;
720
+ const { config, routes, navigation, runtimeSlots } = arg0;
614
721
  const location = useLocation();
615
722
  const navigate = useNavigate();
616
723
  const pathname = normalizeRoutePath(location.pathname);
617
724
  const currentRoute = routeForPath(routes, pathname);
618
725
  const explicitLocale = explicitLocaleForPath(config, pathname);
619
- const [storedLocale] = useState(() => storedLocaleForConfig(config));
726
+ const storedLocale = storedLocaleForConfig(config);
620
727
  const currentLocale = explicitLocale ?? storedLocale ?? fallbackLocale(config);
621
728
  const currentLocaleConfig = config.i18n?.locales.find((locale) => locale.code === currentLocale);
622
729
  const notFoundRoute = currentRoute ? void 0 : notFoundRouteForPath(routes, pathname, currentLocale);
@@ -678,74 +785,88 @@ function AppShell(arg0) {
678
785
  ]);
679
786
  return /* @__PURE__ */ jsx(LocaleContext.Provider, {
680
787
  value: currentLocale,
681
- children: /* @__PURE__ */ jsxs(SectionProvider, {
682
- sections,
683
- children: [/* @__PURE__ */ jsx(Header, {
684
- config,
685
- navigation: currentNavigation.items,
686
- tabs: currentNavigation.tabs,
687
- routes,
688
- currentLocale,
689
- currentRoute,
690
- banner: hasBanner ? /* @__PURE__ */ jsx(PageBanner, {
691
- component: bannerComponent,
788
+ children: /* @__PURE__ */ jsx(RuntimeSlotsProvider, {
789
+ slots: runtimeSlots,
790
+ route: currentRoute,
791
+ children: /* @__PURE__ */ jsxs(SectionProvider, {
792
+ sections,
793
+ children: [/* @__PURE__ */ jsx(Header, {
794
+ config,
795
+ navigation: currentNavigation.items,
796
+ tabs: currentNavigation.tabs,
797
+ routes,
692
798
  currentLocale,
693
- onDismiss: () => setDismissedBannerKey(activeBannerKey)
694
- }) : void 0
695
- }), /* @__PURE__ */ jsxs("div", {
696
- className: "clarify-layout mx-auto grid w-full max-w-(--clarify-theme-layout-max-width) grid-cols-1 lg:grid-cols-(--clarify-layout-sidebar-grid) xl:grid-cols-(--clarify-layout-sidebar-grid-wide)",
697
- style: { "--clarify-header-offset": hasTabs && hasBanner ? "10rem" : hasTabs && !hasBanner ? "7rem" : !hasTabs && hasBanner ? "6.5rem" : "3.5rem" },
698
- children: [/* @__PURE__ */ jsx("aside", {
699
- "data-pagefind-ignore": true,
700
- className: "clarify-sidebar hidden lg:block lg:self-stretch lg:bg-(--clarify-theme-tokens-colors-background) lg:px-5 xl:px-6",
701
- children: /* @__PURE__ */ jsx("div", {
702
- className: clsx("clarify-sidebar-scroll lg:sticky lg:z-30 lg:overflow-y-auto lg:pb-8", hasTabs && hasBanner && "lg:top-40 lg:h-(--clarify-sidebar-height-with-tabs-and-banner) lg:pt-10", hasTabs && !hasBanner && "lg:top-28 lg:h-(--clarify-sidebar-height-with-tabs) lg:pt-10", !hasTabs && hasBanner && "lg:top-[6.5rem] lg:h-(--clarify-sidebar-height-with-banner) lg:pt-10", !hasTabs && !hasBanner && "lg:top-14 lg:h-(--clarify-sidebar-height) lg:pt-10"),
703
- children: /* @__PURE__ */ jsx(Navigation, { navigation: currentNavigation.items })
704
- })
705
- }), /* @__PURE__ */ jsx("div", {
706
- className: clsx("clarify-content @container relative flex min-h-screen min-w-0 flex-col px-4 pb-12 sm:px-6 lg:px-8 xl:px-10", hasTabs && hasBanner && "pt-[6.5rem] lg:pt-40", hasTabs && !hasBanner && "pt-14 lg:pt-28", !hasTabs && hasBanner && "pt-[6.5rem]", !hasTabs && !hasBanner && "pt-14"),
707
- children: /* @__PURE__ */ jsxs(PageActionsProvider, {
708
- route: currentRoute,
709
- routePrefix: config.routePrefix,
710
- children: [
711
- /* @__PURE__ */ jsx("main", {
712
- className: "clarify-main min-w-0 flex-auto",
713
- "data-pagefind-body": true,
714
- children: /* @__PURE__ */ jsx(PageErrorBoundary, {
715
- title: text("renderError.title"),
716
- description: text("renderError.description"),
717
- reloadLabel: text("renderError.reload"),
718
- detailsLabel: text("renderError.details"),
719
- pathLabel: text("renderError.path"),
720
- typeLabel: text("renderError.type"),
721
- messageLabel: text("renderError.message"),
722
- stackLabel: text("renderError.stack"),
723
- componentStackLabel: text("renderError.componentStack"),
724
- timestampLabel: text("renderError.timestamp"),
725
- copyLabel: text("actions.copy"),
726
- copiedLabel: text("actions.copied"),
727
- path: pathname,
728
- children: /* @__PURE__ */ jsx(Suspense, {
729
- fallback: /* @__PURE__ */ jsx(PageSkeleton, {}),
730
- children: /* @__PURE__ */ jsxs(Routes, { children: [renderRoutes.map((route) => /* @__PURE__ */ jsx(Route, {
731
- path: route.path,
732
- element: /* @__PURE__ */ jsx(route.component, {})
733
- }, route.path)), /* @__PURE__ */ jsx(Route, {
734
- path: "*",
735
- element: /* @__PURE__ */ jsx(NotFoundRouteElement, { component: NotFoundRouteComponent })
736
- })] })
737
- })
738
- }, pathname)
739
- }),
740
- /* @__PURE__ */ jsx(PageNavigation, {
741
- navigation: currentNavigation.items,
742
- currentRoute
743
- }),
744
- /* @__PURE__ */ jsx(PageFooter, { component: footerComponent })
745
- ]
799
+ currentRoute,
800
+ banner: /* @__PURE__ */ jsx(BannerSlot, {
801
+ activeBannerKey,
802
+ dismissedBannerKey,
803
+ onDismiss: () => setDismissedBannerKey(activeBannerKey),
804
+ config,
805
+ locale: currentLocale
746
806
  })
807
+ }), /* @__PURE__ */ jsxs("div", {
808
+ className: "clarify-layout mx-auto grid w-full max-w-(--clarify-theme-layout-max-width) grid-cols-1 lg:grid-cols-(--clarify-layout-sidebar-grid) xl:grid-cols-(--clarify-layout-sidebar-grid-wide)",
809
+ style: { "--clarify-header-offset": hasTabs && hasBanner ? "10rem" : hasTabs && !hasBanner ? "7rem" : !hasTabs && hasBanner ? "6.5rem" : "3.5rem" },
810
+ children: [/* @__PURE__ */ jsx("aside", {
811
+ "data-pagefind-ignore": true,
812
+ className: "clarify-sidebar hidden lg:block lg:self-stretch lg:bg-(--clarify-theme-tokens-colors-background) lg:px-5 xl:px-6",
813
+ children: /* @__PURE__ */ jsx("div", {
814
+ className: clsx("clarify-sidebar-scroll lg:sticky lg:z-30 lg:overflow-y-auto lg:pb-8", hasTabs && hasBanner && "lg:top-40 lg:h-(--clarify-sidebar-height-with-tabs-and-banner) lg:pt-10", hasTabs && !hasBanner && "lg:top-28 lg:h-(--clarify-sidebar-height-with-tabs) lg:pt-10", !hasTabs && hasBanner && "lg:top-26 lg:h-(--clarify-sidebar-height-with-banner) lg:pt-10", !hasTabs && !hasBanner && "lg:top-14 lg:h-(--clarify-sidebar-height) lg:pt-10"),
815
+ children: /* @__PURE__ */ jsx(Navigation, { navigation: currentNavigation.items })
816
+ })
817
+ }), /* @__PURE__ */ jsx("div", {
818
+ className: clsx("clarify-content @container relative flex min-h-screen min-w-0 flex-col px-4 pb-12 sm:px-6 lg:px-8 xl:px-10", hasTabs && hasBanner && "pt-26 lg:pt-40", hasTabs && !hasBanner && "pt-14 lg:pt-28", !hasTabs && hasBanner && "pt-26", !hasTabs && !hasBanner && "pt-14"),
819
+ children: /* @__PURE__ */ jsxs(PageActionsProvider, {
820
+ route: currentRoute,
821
+ routePrefix: config.routePrefix,
822
+ children: [
823
+ /* @__PURE__ */ jsx("main", {
824
+ className: "clarify-main min-w-0 flex-auto",
825
+ "data-pagefind-body": true,
826
+ children: /* @__PURE__ */ jsx(PageErrorBoundary, {
827
+ title: text("renderError.title"),
828
+ description: text("renderError.description"),
829
+ reloadLabel: text("renderError.reload"),
830
+ detailsLabel: text("renderError.details"),
831
+ pathLabel: text("renderError.path"),
832
+ typeLabel: text("renderError.type"),
833
+ messageLabel: text("renderError.message"),
834
+ stackLabel: text("renderError.stack"),
835
+ componentStackLabel: text("renderError.componentStack"),
836
+ timestampLabel: text("renderError.timestamp"),
837
+ copyLabel: text("actions.copy"),
838
+ copiedLabel: text("actions.copied"),
839
+ path: pathname,
840
+ children: /* @__PURE__ */ jsx(Suspense, {
841
+ fallback: /* @__PURE__ */ jsx(PageSkeleton, {}),
842
+ children: /* @__PURE__ */ jsxs(Routes, { children: [renderRoutes.map((route) => /* @__PURE__ */ jsx(Route, {
843
+ path: route.path,
844
+ element: /* @__PURE__ */ jsx(route.component, {})
845
+ }, route.path)), /* @__PURE__ */ jsx(Route, {
846
+ path: "*",
847
+ element: /* @__PURE__ */ jsx(NotFoundRouteElement, { component: NotFoundRouteComponent })
848
+ })] })
849
+ })
850
+ }, pathname)
851
+ }),
852
+ /* @__PURE__ */ jsx(PageNavigation, {
853
+ navigation: currentNavigation.items,
854
+ currentRoute
855
+ }),
856
+ /* @__PURE__ */ jsx(RuntimeSlot, { name: "page.footer.before" }),
857
+ /* @__PURE__ */ jsx(RuntimeSlot, {
858
+ name: "page.footer.replace",
859
+ default: DefaultFooterComponent
860
+ }),
861
+ /* @__PURE__ */ jsx("div", {
862
+ className: "flex justify-end",
863
+ children: /* @__PURE__ */ jsx(BuiltWithClarify, {})
864
+ })
865
+ ]
866
+ })
867
+ })]
747
868
  })]
748
- })]
869
+ })
749
870
  })
750
871
  });
751
872
  }
@@ -1949,6 +2070,35 @@ function ThemeRoot(props) {
1949
2070
  });
1950
2071
  }
1951
2072
  //#endregion
1952
- export { themeBootstrapScript as a, AppShell as c, PageBanner as d, themeEditorPresets as i, PageFooter as l, ThemeEditor as n, themePresets as o, applyThemeVariables as r, themeStorageKey as s, ThemeRoot as t, BuiltWithClarify as u };
2073
+ //#region source/runtime/ClarifyShell.tsx
2074
+ /**
2075
+ * Shared provider chain used by both client-side render and server-side
2076
+ * renderToHTML. Wraps AppShell with ConfigContext → OpenApisContext →
2077
+ * ThemeProvider → ThemeRoot.
2078
+ *
2079
+ * The outer Router (BrowserRouter / StaticRouter) is left to the caller
2080
+ * so each entry point can supply the correct router variant.
2081
+ */
2082
+ function ClarifyShell(props) {
2083
+ const { config, routes, navigation, openApis, runtimeSlots, themeEditor = false } = props;
2084
+ return /* @__PURE__ */ jsx(ConfigContext.Provider, {
2085
+ value: config,
2086
+ children: /* @__PURE__ */ jsx(OpenApisContext.Provider, {
2087
+ value: openApis,
2088
+ children: /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(ThemeRoot, {
2089
+ theme: config.theme,
2090
+ themeEditor,
2091
+ children: /* @__PURE__ */ jsx(AppShell, {
2092
+ config,
2093
+ routes,
2094
+ navigation: navigation ?? [],
2095
+ runtimeSlots
2096
+ })
2097
+ }) })
2098
+ })
2099
+ });
2100
+ }
2101
+ //#endregion
2102
+ export { themeBootstrapScript as a, AppShell as c, BuiltWithClarify as d, RuntimeSlot as f, useSlot as h, themeEditorPresets as i, PageFooter as l, SlotProvider as m, ThemeEditor as n, themePresets as o, RuntimeSlotsProvider as p, applyThemeVariables as r, themeStorageKey as s, ClarifyShell as t, PageBanner as u };
1953
2103
 
1954
- //# sourceMappingURL=ThemeRoot-QULrwQf6.js.map
2104
+ //# sourceMappingURL=ClarifyShell-BxB_6Uhd.js.map