@clarify-labs/renderer 0.7.2 → 0.8.2

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-UWj0iK1X.cjs → ClarifyShell-B74Fq4UU.cjs} +389 -161
  2. package/output/ClarifyShell-B74Fq4UU.cjs.map +1 -0
  3. package/output/{ThemeRoot-QULrwQf6.js → ClarifyShell-BPv2bxI4.js} +361 -157
  4. package/output/ClarifyShell-BPv2bxI4.js.map +1 -0
  5. package/output/{OpenApiOperation-BcyW_ULy.cjs → OpenApiOperation-BMXfV15v.cjs} +209 -7
  6. package/output/OpenApiOperation-BMXfV15v.cjs.map +1 -0
  7. package/output/{OpenApiOperation-tUKf7lZ4.js → OpenApiOperation-fJ3QQOJX.js} +205 -9
  8. package/output/OpenApiOperation-fJ3QQOJX.js.map +1 -0
  9. package/output/{PageActions-yoDRjkq8.js → PageActions-BwY7ierv.js} +55 -81
  10. package/output/PageActions-BwY7ierv.js.map +1 -0
  11. package/output/{PageActions-1RDCHcUY.cjs → PageActions-DOKkt2zo.cjs} +59 -79
  12. package/output/PageActions-DOKkt2zo.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 +8 -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 +3 -2
  32. package/output/preview.cjs.map +1 -1
  33. package/output/preview.js +3 -2
  34. package/output/preview.js.map +1 -1
  35. package/output/{render-psutGbsg.js → render-Cghgq1AQ.js} +10 -20
  36. package/output/render-Cghgq1AQ.js.map +1 -0
  37. package/output/{render-ByWbJbrA.cjs → render-ZSckbg74.cjs} +10 -20
  38. package/output/render-ZSckbg74.cjs.map +1 -0
  39. package/output/renderer.css +77 -21
  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-BwY7ierv.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,21 @@ 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
+ const links = footer?.links ?? [];
399
+ const socials = Object.entries(footer?.socials ?? {});
400
+ const copyright = footer?.copyright ? resolveLocalizedText(footer.copyright, locale, config.i18n?.defaultLocale) : void 0;
401
+ if (!Boolean(copyright || links.length > 0 || socials.length > 0)) return /* @__PURE__ */ jsx("footer", {
402
+ "aria-hidden": "true",
403
+ className: "clarify-page-footer mt-16 w-full border-t border-(--clarify-theme-tokens-colors-border) pt-8 lg:mt-24"
404
+ });
405
+ return /* @__PURE__ */ jsx("footer", {
308
406
  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"),
407
+ children: /* @__PURE__ */ jsxs("div", {
408
+ className: clsx("clarify-footer-content flex flex-col items-end gap-3 text-right", "sm:items-start sm:text-left"),
314
409
  children: [copyright ? /* @__PURE__ */ jsx("p", {
315
410
  className: "clarify-footer-copyright m-0",
316
411
  children: copyright
@@ -325,10 +420,7 @@ function PageFooter(props = {}) {
325
420
  href
326
421
  }, name))]
327
422
  }) : null]
328
- }) : null, /* @__PURE__ */ jsx("div", {
329
- className: "clarify-footer-brand flex justify-end self-end",
330
- children: /* @__PURE__ */ jsx(BuiltWithClarify, {})
331
- })]
423
+ })
332
424
  });
333
425
  }
334
426
  //#endregion
@@ -487,6 +579,23 @@ function PageSkeleton() {
487
579
  }
488
580
  //#endregion
489
581
  //#region source/app/AppShell.tsx
582
+ function BannerSlot(props) {
583
+ const { activeBannerKey, dismissedBannerKey, onDismiss, config, locale } = props;
584
+ function DefaultBannerComponent() {
585
+ if (!(Boolean(config.banner) && dismissedBannerKey !== activeBannerKey)) return null;
586
+ return /* @__PURE__ */ jsx(PageBanner, {
587
+ currentLocale: locale,
588
+ onDismiss
589
+ });
590
+ }
591
+ return /* @__PURE__ */ jsx(RuntimeSlot, {
592
+ name: "page.banner.replace",
593
+ default: DefaultBannerComponent
594
+ });
595
+ }
596
+ function DefaultFooterComponent() {
597
+ return /* @__PURE__ */ jsx(PageFooter, {});
598
+ }
490
599
  function routeForPath(routes, pathname) {
491
600
  return routes.find((route) => isSameRoutePath(route.path, pathname));
492
601
  }
@@ -610,13 +719,13 @@ function NotFoundRouteElement(props) {
610
719
  return /* @__PURE__ */ jsx(RouteComponent, {});
611
720
  }
612
721
  function AppShell(arg0) {
613
- const { config, routes, navigation, bannerComponent, footerComponent } = arg0;
722
+ const { config, routes, navigation, runtimeSlots } = arg0;
614
723
  const location = useLocation();
615
724
  const navigate = useNavigate();
616
725
  const pathname = normalizeRoutePath(location.pathname);
617
726
  const currentRoute = routeForPath(routes, pathname);
618
727
  const explicitLocale = explicitLocaleForPath(config, pathname);
619
- const [storedLocale] = useState(() => storedLocaleForConfig(config));
728
+ const storedLocale = storedLocaleForConfig(config);
620
729
  const currentLocale = explicitLocale ?? storedLocale ?? fallbackLocale(config);
621
730
  const currentLocaleConfig = config.i18n?.locales.find((locale) => locale.code === currentLocale);
622
731
  const notFoundRoute = currentRoute ? void 0 : notFoundRouteForPath(routes, pathname, currentLocale);
@@ -678,74 +787,88 @@ function AppShell(arg0) {
678
787
  ]);
679
788
  return /* @__PURE__ */ jsx(LocaleContext.Provider, {
680
789
  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,
790
+ children: /* @__PURE__ */ jsx(RuntimeSlotsProvider, {
791
+ slots: runtimeSlots,
792
+ route: currentRoute,
793
+ children: /* @__PURE__ */ jsxs(SectionProvider, {
794
+ sections,
795
+ children: [/* @__PURE__ */ jsx(Header, {
796
+ config,
797
+ navigation: currentNavigation.items,
798
+ tabs: currentNavigation.tabs,
799
+ routes,
692
800
  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
- ]
801
+ currentRoute,
802
+ banner: /* @__PURE__ */ jsx(BannerSlot, {
803
+ activeBannerKey,
804
+ dismissedBannerKey,
805
+ onDismiss: () => setDismissedBannerKey(activeBannerKey),
806
+ config,
807
+ locale: currentLocale
746
808
  })
809
+ }), /* @__PURE__ */ jsxs("div", {
810
+ 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)",
811
+ style: { "--clarify-header-offset": hasTabs && hasBanner ? "10rem" : hasTabs && !hasBanner ? "7rem" : !hasTabs && hasBanner ? "6.5rem" : "3.5rem" },
812
+ children: [/* @__PURE__ */ jsx("aside", {
813
+ "data-pagefind-ignore": true,
814
+ className: "clarify-sidebar hidden lg:block lg:self-stretch lg:bg-(--clarify-theme-tokens-colors-background) lg:px-5 xl:px-6",
815
+ children: /* @__PURE__ */ jsx("div", {
816
+ 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"),
817
+ children: /* @__PURE__ */ jsx(Navigation, { navigation: currentNavigation.items })
818
+ })
819
+ }), /* @__PURE__ */ jsx("div", {
820
+ 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"),
821
+ children: /* @__PURE__ */ jsxs(PageActionsProvider, {
822
+ route: currentRoute,
823
+ routePrefix: config.routePrefix,
824
+ children: [
825
+ /* @__PURE__ */ jsx("main", {
826
+ className: "clarify-main min-w-0 flex-auto",
827
+ "data-pagefind-body": true,
828
+ children: /* @__PURE__ */ jsx(PageErrorBoundary, {
829
+ title: text("renderError.title"),
830
+ description: text("renderError.description"),
831
+ reloadLabel: text("renderError.reload"),
832
+ detailsLabel: text("renderError.details"),
833
+ pathLabel: text("renderError.path"),
834
+ typeLabel: text("renderError.type"),
835
+ messageLabel: text("renderError.message"),
836
+ stackLabel: text("renderError.stack"),
837
+ componentStackLabel: text("renderError.componentStack"),
838
+ timestampLabel: text("renderError.timestamp"),
839
+ copyLabel: text("actions.copy"),
840
+ copiedLabel: text("actions.copied"),
841
+ path: pathname,
842
+ children: /* @__PURE__ */ jsx(Suspense, {
843
+ fallback: /* @__PURE__ */ jsx(PageSkeleton, {}),
844
+ children: /* @__PURE__ */ jsxs(Routes, { children: [renderRoutes.map((route) => /* @__PURE__ */ jsx(Route, {
845
+ path: route.path,
846
+ element: /* @__PURE__ */ jsx(route.component, {})
847
+ }, route.path)), /* @__PURE__ */ jsx(Route, {
848
+ path: "*",
849
+ element: /* @__PURE__ */ jsx(NotFoundRouteElement, { component: NotFoundRouteComponent })
850
+ })] })
851
+ })
852
+ }, pathname)
853
+ }),
854
+ /* @__PURE__ */ jsx(PageNavigation, {
855
+ navigation: currentNavigation.items,
856
+ currentRoute
857
+ }),
858
+ /* @__PURE__ */ jsx(RuntimeSlot, { name: "page.footer.before" }),
859
+ /* @__PURE__ */ jsx(RuntimeSlot, {
860
+ name: "page.footer.replace",
861
+ default: DefaultFooterComponent
862
+ }),
863
+ /* @__PURE__ */ jsx("div", {
864
+ className: "flex justify-end",
865
+ children: /* @__PURE__ */ jsx(BuiltWithClarify, {})
866
+ })
867
+ ]
868
+ })
869
+ })]
747
870
  })]
748
- })]
871
+ })
749
872
  })
750
873
  });
751
874
  }
@@ -1366,6 +1489,48 @@ var randomLayoutWidths = [
1366
1489
  "128rem",
1367
1490
  "144rem"
1368
1491
  ];
1492
+ var randomDarkAccentPairs = [
1493
+ {
1494
+ primary: "#34d399",
1495
+ accent: "#2dd4bf"
1496
+ },
1497
+ {
1498
+ primary: "#60a5fa",
1499
+ accent: "#38bdf8"
1500
+ },
1501
+ {
1502
+ primary: "#a78bfa",
1503
+ accent: "#c084fc"
1504
+ },
1505
+ {
1506
+ primary: "#f472b6",
1507
+ accent: "#fb7185"
1508
+ },
1509
+ {
1510
+ primary: "#fb923c",
1511
+ accent: "#facc15"
1512
+ },
1513
+ {
1514
+ primary: "#a3e635",
1515
+ accent: "#22c55e"
1516
+ },
1517
+ {
1518
+ primary: "#22d3ee",
1519
+ accent: "#818cf8"
1520
+ },
1521
+ {
1522
+ primary: "#f87171",
1523
+ accent: "#fb923c"
1524
+ },
1525
+ {
1526
+ primary: "#e879f9",
1527
+ accent: "#f472b6"
1528
+ },
1529
+ {
1530
+ primary: "#5eead4",
1531
+ accent: "#60a5fa"
1532
+ }
1533
+ ];
1369
1534
  function randomItem(items) {
1370
1535
  return items[Math.floor(Math.random() * items.length)];
1371
1536
  }
@@ -1378,26 +1543,36 @@ function modeColor(light, dark) {
1378
1543
  dark
1379
1544
  };
1380
1545
  }
1546
+ function createRandomThemeSelection() {
1547
+ return {
1548
+ palette: randomItem(randomThemePalettes),
1549
+ darkAccents: randomItem(randomDarkAccentPairs),
1550
+ radius: randomItem(randomRadiusSets),
1551
+ maxWidth: randomItem(randomLayoutWidths)
1552
+ };
1553
+ }
1554
+ function createRandomThemeColors(selection) {
1555
+ const { palette, darkAccents } = selection;
1556
+ return {
1557
+ primary: modeColor(palette.primary, darkAccents.primary),
1558
+ accent: modeColor(palette.accent, darkAccents.accent),
1559
+ background: modeColor(palette.background, "#09090b"),
1560
+ foreground: modeColor(palette.foreground, "#f8fafc"),
1561
+ surface: modeColor(palette.surface, "#18181b"),
1562
+ muted: modeColor(palette.muted, "#a1a1aa"),
1563
+ border: modeColor(randomRgbMix(palette.foreground, palette.borderMix), "rgb(255 255 255 / 0.1)"),
1564
+ codeBackground: modeColor(randomRgbMix(palette.primary, palette.codeMix), "#18181b")
1565
+ };
1566
+ }
1381
1567
  function createRandomTheme() {
1382
- const palette = randomItem(randomThemePalettes);
1383
- const radius = randomItem(randomRadiusSets);
1384
- const maxWidth = randomItem(randomLayoutWidths);
1568
+ const selection = createRandomThemeSelection();
1385
1569
  return {
1386
1570
  preset: "default",
1387
1571
  tokens: {
1388
- colors: {
1389
- primary: modeColor(palette.primary, palette.accent),
1390
- accent: modeColor(palette.accent, palette.primary),
1391
- background: modeColor(palette.background, "#09090b"),
1392
- foreground: modeColor(palette.foreground, "#f8fafc"),
1393
- surface: modeColor(palette.surface, "#18181b"),
1394
- muted: modeColor(palette.muted, "#a1a1aa"),
1395
- border: modeColor(randomRgbMix(palette.foreground, palette.borderMix), "rgb(255 255 255 / 0.1)"),
1396
- codeBackground: modeColor(randomRgbMix(palette.primary, palette.codeMix), "#18181b")
1397
- },
1398
- radius: { ...radius }
1572
+ colors: createRandomThemeColors(selection),
1573
+ radius: { ...selection.radius }
1399
1574
  },
1400
- layout: { maxWidth },
1575
+ layout: { maxWidth: selection.maxWidth },
1401
1576
  editor: false
1402
1577
  };
1403
1578
  }
@@ -1949,6 +2124,35 @@ function ThemeRoot(props) {
1949
2124
  });
1950
2125
  }
1951
2126
  //#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 };
2127
+ //#region source/runtime/ClarifyShell.tsx
2128
+ /**
2129
+ * Shared provider chain used by both client-side render and server-side
2130
+ * renderToHTML. Wraps AppShell with ConfigContext → OpenApisContext →
2131
+ * ThemeProvider → ThemeRoot.
2132
+ *
2133
+ * The outer Router (BrowserRouter / StaticRouter) is left to the caller
2134
+ * so each entry point can supply the correct router variant.
2135
+ */
2136
+ function ClarifyShell(props) {
2137
+ const { config, routes, navigation, openApis, runtimeSlots, themeEditor = false } = props;
2138
+ return /* @__PURE__ */ jsx(ConfigContext.Provider, {
2139
+ value: config,
2140
+ children: /* @__PURE__ */ jsx(OpenApisContext.Provider, {
2141
+ value: openApis,
2142
+ children: /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(ThemeRoot, {
2143
+ theme: config.theme,
2144
+ themeEditor,
2145
+ children: /* @__PURE__ */ jsx(AppShell, {
2146
+ config,
2147
+ routes,
2148
+ navigation: navigation ?? [],
2149
+ runtimeSlots
2150
+ })
2151
+ }) })
2152
+ })
2153
+ });
2154
+ }
2155
+ //#endregion
2156
+ 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
2157
 
1954
- //# sourceMappingURL=ThemeRoot-QULrwQf6.js.map
2158
+ //# sourceMappingURL=ClarifyShell-BPv2bxI4.js.map