@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,11 +1,142 @@
1
1
  const require_chunk = require("./chunk-DakpK96I.cjs");
2
- const require_PageActions = require("./PageActions-1RDCHcUY.cjs");
2
+ const require_PageActions = require("./PageActions-yycPlNyL.cjs");
3
3
  let clsx = require("clsx");
4
4
  clsx = require_chunk.__toESM(clsx, 1);
5
5
  let react = require("react");
6
6
  let react_router_dom = require("react-router-dom");
7
7
  let lucide_react = require("lucide-react");
8
8
  let react_jsx_runtime = require("react/jsx-runtime");
9
+ //#region source/slots/context.tsx
10
+ var SlotContextValue = (0, react.createContext)(null);
11
+ /**
12
+ * Provides an isolated {@link SlotContext} for a single slot component.
13
+ * `RuntimeSlot` wraps every rendered slot component with this provider.
14
+ */
15
+ function SlotProvider(arg0) {
16
+ const { value, children } = arg0;
17
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SlotContextValue.Provider, {
18
+ value,
19
+ children
20
+ });
21
+ }
22
+ /**
23
+ * Reads the current slot context.
24
+ *
25
+ * Must be called inside a slot component (or a descendant). Calling it outside a
26
+ * slot provider throws, which helps plugin authors notice that the component was
27
+ * not mounted through a Clarify slot.
28
+ */
29
+ function useSlot() {
30
+ const context = (0, react.useContext)(SlotContextValue);
31
+ if (!context) throw new Error("[clarify] useSlot must be called inside a slot component");
32
+ return context;
33
+ }
34
+ //#endregion
35
+ //#region source/slots/RuntimeSlot.tsx
36
+ var RuntimeSlotsContext = (0, react.createContext)({ slots: {} });
37
+ /**
38
+ * Makes the compiled slot registry and the current route available to every
39
+ * {@link RuntimeSlot} in the tree. Mounted once near the top of `AppShell`.
40
+ */
41
+ function RuntimeSlotsProvider(arg0) {
42
+ const { slots, route, children } = arg0;
43
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeSlotsContext.Provider, {
44
+ value: {
45
+ slots: slots ?? {},
46
+ route
47
+ },
48
+ children
49
+ });
50
+ }
51
+ /**
52
+ * Renders plugin components registered for a slot, in registration order.
53
+ *
54
+ * For extension slots (*.before/*.after), renders all plugin components.
55
+ * For replacement slots (*.replace), renders only the last registered plugin
56
+ * component (if any), and passes the default component through context.
57
+ *
58
+ * Each component is loaded via the import factory. If `_resolved` is set
59
+ * (SSR pre-resolution), the component is rendered synchronously for
60
+ * compatibility with `renderToString`. Otherwise, `React.lazy` + `Suspense`
61
+ * is used for client-side code-splitting.
62
+ */
63
+ function RuntimeSlot(arg0) {
64
+ const { name, default: DefaultComponent } = arg0;
65
+ const { slots, route } = (0, react.useContext)(RuntimeSlotsContext);
66
+ const locale = require_PageActions.useLocale();
67
+ const entries = slots[name];
68
+ if (!entries || entries.length === 0) return DefaultComponent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultComponent, {}) : null;
69
+ if (name.endsWith(".replace")) {
70
+ const lastEntry = entries[entries.length - 1];
71
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SlotProvider, {
72
+ value: {
73
+ name,
74
+ plugin: lastEntry.plugin,
75
+ route,
76
+ locale,
77
+ DefaultComponent
78
+ },
79
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SlotEntryRenderer, { entry: lastEntry })
80
+ });
81
+ }
82
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: entries.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SlotProvider, {
83
+ value: {
84
+ name,
85
+ plugin: entry.plugin,
86
+ route,
87
+ locale
88
+ },
89
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SlotEntryRenderer, { entry })
90
+ }, `${name}:${entry.plugin}`)) });
91
+ }
92
+ function SlotEntryRenderer(props) {
93
+ const { entry } = props;
94
+ if (entry._resolved) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(entry._resolved, {});
95
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LazySlotComponent, { loader: entry.component });
96
+ }
97
+ function LazySlotComponent(props) {
98
+ const { loader } = props;
99
+ const [Component, setComponent] = (0, react.useState)(null);
100
+ (0, react.useEffect)(() => {
101
+ let cancelled = false;
102
+ loader().then((mod) => {
103
+ if (!cancelled) setComponent(() => mod.default);
104
+ });
105
+ return () => {
106
+ cancelled = true;
107
+ };
108
+ }, [loader]);
109
+ if (!Component) return null;
110
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {});
111
+ }
112
+ //#endregion
113
+ //#region source/assets/clarify.svg?url
114
+ 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";
115
+ //#endregion
116
+ //#region source/app/BuiltWithClarify.tsx
117
+ function BuiltWithClarify() {
118
+ const t = require_PageActions.useBuiltInText();
119
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
120
+ href: "https://clarify.pub",
121
+ target: "_blank",
122
+ rel: "noreferrer",
123
+ "aria-label": t("builtWith.label"),
124
+ className: "clarify-built-with inline-flex items-center gap-1.5 rounded-full px-2 py-1 font-medium no-underline transition",
125
+ children: [
126
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("builtWith.prefix") }),
127
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
128
+ src: clarify_default,
129
+ alt: "",
130
+ className: "clarify-built-with-logo h-3.5 w-auto flex-none object-contain"
131
+ }),
132
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
133
+ className: "clarify-built-with-brand font-semibold",
134
+ children: "Clarify"
135
+ })
136
+ ]
137
+ });
138
+ }
139
+ //#endregion
9
140
  //#region source/app/ErrorBoundary.tsx
10
141
  function PageErrorPanel(props) {
11
142
  const { title, description, reloadLabel, detailsLabel, pathLabel, typeLabel, messageLabel, stackLabel, componentStackLabel, timestampLabel, copyLabel, copiedLabel, path, error, errorInfo, occurredAt } = props;
@@ -88,7 +219,7 @@ function PageErrorPanel(props) {
88
219
  children: messageLabel
89
220
  }),
90
221
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
91
- className: "mt-2 break-words font-mono text-sm/6 font-semibold text-(--clarify-theme-tokens-colors-foreground)",
222
+ className: "mt-2 wrap-break-word font-mono text-sm/6 font-semibold text-(--clarify-theme-tokens-colors-foreground)",
92
223
  children: error.message
93
224
  }),
94
225
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
@@ -96,14 +227,14 @@ function PageErrorPanel(props) {
96
227
  children: stackLabel
97
228
  }),
98
229
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
99
- className: "mt-2 max-h-(--clarify-error-details-max-height) overflow-auto whitespace-pre-wrap break-words font-mono",
230
+ className: "mt-2 max-h-(--clarify-error-details-max-height) overflow-auto whitespace-pre-wrap wrap-break-word font-mono",
100
231
  children: stack
101
232
  }),
102
233
  componentStack ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
103
234
  className: "mt-6 font-semibold uppercase tracking-wide text-(--clarify-ui-text-faint)",
104
235
  children: componentStackLabel
105
236
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
106
- className: "mt-2 max-h-(--clarify-error-component-stack-max-height) overflow-auto whitespace-pre-wrap break-words font-mono",
237
+ className: "mt-2 max-h-(--clarify-error-component-stack-max-height) overflow-auto whitespace-pre-wrap wrap-break-word font-mono",
107
238
  children: componentStack
108
239
  })] }) : null
109
240
  ]
@@ -150,10 +281,6 @@ var PageErrorBoundary = class extends react.Component {
150
281
  };
151
282
  //#endregion
152
283
  //#region source/app/PageBanner.tsx
153
- function resolveLocalizedText$1(text, locale, fallbackLocale) {
154
- if (typeof text === "string") return text;
155
- return (locale ? text[locale] : void 0) ?? (fallbackLocale ? text[fallbackLocale] : void 0) ?? Object.values(text)[0] ?? "";
156
- }
157
284
  function bannerStorageKey(config, content) {
158
285
  return `clarify:banner:dismissed:${config.title}:${content}`;
159
286
  }
@@ -176,29 +303,30 @@ function PageBannerLink(props) {
176
303
  });
177
304
  }
178
305
  function PageBanner(props) {
179
- const { component: CustomBanner, currentLocale, onDismiss } = props;
306
+ const { currentLocale, onDismiss } = props;
180
307
  const config = require_PageActions.useConfig();
181
308
  const banner = config.banner;
182
- const builtInBanner = banner && typeof banner === "object" ? banner : void 0;
183
- const content = builtInBanner ? resolveLocalizedText$1(builtInBanner.content, currentLocale, config.i18n?.defaultLocale) : "";
184
- const link = builtInBanner?.link;
185
- const linkLabel = link ? resolveLocalizedText$1(link.label, currentLocale, config.i18n?.defaultLocale) : "";
186
- const storageKey = (0, react.useMemo)(() => content ? bannerStorageKey(config, content) : "", [config, content]);
309
+ const content = banner ? require_PageActions.resolveLocalizedText(banner.content, currentLocale, config.i18n?.defaultLocale) : "";
310
+ const storageKey = (0, react.useMemo)(() => {
311
+ if (!banner || !content) return "";
312
+ return bannerStorageKey(config, content);
313
+ }, [
314
+ config,
315
+ content,
316
+ banner
317
+ ]);
187
318
  const [dismissed, setDismissed] = (0, react.useState)(() => {
188
- if (!storageKey || !builtInBanner?.dismissible || typeof window === "undefined") return false;
319
+ if (!banner?.dismissible || typeof window === "undefined") return false;
189
320
  return window.localStorage.getItem(storageKey) === "1";
190
321
  });
191
322
  (0, react.useEffect)(() => {
192
323
  if (dismissed) onDismiss?.();
193
324
  }, [dismissed, onDismiss]);
194
- if (CustomBanner) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
195
- 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",
196
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
197
- className: "mx-auto w-full max-w-(--clarify-theme-layout-max-width)",
198
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomBanner, {})
199
- })
200
- });
201
- if (!builtInBanner || !content || dismissed) return null;
325
+ if (!banner) return null;
326
+ if (!content) return null;
327
+ if (dismissed) return null;
328
+ const link = banner.link;
329
+ const linkLabel = link ? require_PageActions.resolveLocalizedText(link.label, currentLocale, config.i18n?.defaultLocale) : "";
202
330
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
203
331
  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",
204
332
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -213,7 +341,7 @@ function PageBanner(props) {
213
341
  config,
214
342
  locale: currentLocale
215
343
  }) : null]
216
- }), builtInBanner.dismissible ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
344
+ }), banner.dismissible ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
217
345
  type: "button",
218
346
  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)",
219
347
  "aria-label": "Dismiss announcement",
@@ -229,38 +357,7 @@ function PageBanner(props) {
229
357
  });
230
358
  }
231
359
  //#endregion
232
- //#region source/assets/clarify.svg?url
233
- 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";
234
- //#endregion
235
- //#region source/app/BuiltWithClarify.tsx
236
- function BuiltWithClarify() {
237
- const t = require_PageActions.useBuiltInText();
238
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
239
- href: "https://clarify.pub",
240
- target: "_blank",
241
- rel: "noreferrer",
242
- "aria-label": t("builtWith.label"),
243
- className: "clarify-built-with inline-flex items-center gap-1.5 rounded-full px-2 py-1 font-medium no-underline transition",
244
- children: [
245
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("builtWith.prefix") }),
246
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
247
- src: clarify_default,
248
- alt: "",
249
- className: "clarify-built-with-logo h-3.5 w-auto flex-none object-contain"
250
- }),
251
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
252
- className: "clarify-built-with-brand font-semibold",
253
- children: "Clarify"
254
- })
255
- ]
256
- });
257
- }
258
- //#endregion
259
360
  //#region source/app/PageFooter.tsx
260
- function resolveLocalizedText(text, locale, fallbackLocale) {
261
- if (typeof text === "string") return text;
262
- return (locale ? text[locale] : void 0) ?? (fallbackLocale ? text[fallbackLocale] : void 0) ?? Object.values(text)[0] ?? "";
263
- }
264
361
  function localeForPath(config, pathname) {
265
362
  const i18n = config.i18n;
266
363
  if (!i18n) return void 0;
@@ -272,7 +369,7 @@ function FooterLink(arg0) {
272
369
  const external = link.external ?? require_PageActions.isExternalHref(link.href);
273
370
  const href = external ? link.href : require_PageActions.localizeHref(link.href, config, locale);
274
371
  const className = "clarify-footer-link no-underline transition";
275
- const label = resolveLocalizedText(link.label, locale, config.i18n?.defaultLocale);
372
+ const label = require_PageActions.resolveLocalizedText(link.label, locale, config.i18n?.defaultLocale);
276
373
  if (external) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
277
374
  href,
278
375
  target: "_blank",
@@ -296,23 +393,19 @@ function SocialLink(arg0) {
296
393
  children: name
297
394
  });
298
395
  }
299
- function PageFooter(props = {}) {
396
+ function PageFooter() {
300
397
  const config = require_PageActions.useConfig();
301
398
  const locale = localeForPath(config, (0, react_router_dom.useLocation)().pathname);
302
399
  const footer = config.footer;
303
- const builtInFooter = footer && typeof footer === "object" ? footer : void 0;
304
- const CustomFooter = props.component;
305
- const links = builtInFooter?.links ?? [];
306
- const socials = Object.entries(builtInFooter?.socials ?? {});
307
- const copyright = builtInFooter?.copyright ? resolveLocalizedText(builtInFooter.copyright, locale, config.i18n?.defaultLocale) : void 0;
308
- const hasBuiltInFooter = Boolean(copyright || links.length > 0 || socials.length > 0);
309
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", {
400
+ if (!footer) return null;
401
+ const links = footer.links ?? [];
402
+ const socials = Object.entries(footer.socials ?? {});
403
+ const copyright = footer.copyright ? require_PageActions.resolveLocalizedText(footer.copyright, locale, config.i18n?.defaultLocale) : void 0;
404
+ if (!Boolean(copyright || links.length > 0 || socials.length > 0)) return null;
405
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", {
310
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",
311
- children: [CustomFooter ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
312
- className: "clarify-footer-custom w-full",
313
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomFooter, {})
314
- }) : hasBuiltInFooter ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
315
- className: (0, clsx.default)("clarify-footer-content flex flex-col items-end gap-3 text-right", hasBuiltInFooter && "sm:items-start sm:text-left"),
407
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
408
+ className: (0, clsx.default)("clarify-footer-content flex flex-col items-end gap-3 text-right", "sm:items-start sm:text-left"),
316
409
  children: [copyright ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
317
410
  className: "clarify-footer-copyright m-0",
318
411
  children: copyright
@@ -322,15 +415,12 @@ function PageFooter(props = {}) {
322
415
  link,
323
416
  locale,
324
417
  config
325
- }, `${link.href}-${resolveLocalizedText(link.label, locale, config.i18n?.defaultLocale)}`)), socials.map(([name, href]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SocialLink, {
418
+ }, `${link.href}-${require_PageActions.resolveLocalizedText(link.label, locale, config.i18n?.defaultLocale)}`)), socials.map(([name, href]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SocialLink, {
326
419
  name,
327
420
  href
328
421
  }, name))]
329
422
  }) : null]
330
- }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
331
- className: "clarify-footer-brand flex justify-end self-end",
332
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BuiltWithClarify, {})
333
- })]
423
+ })
334
424
  });
335
425
  }
336
426
  //#endregion
@@ -489,6 +579,23 @@ function PageSkeleton() {
489
579
  }
490
580
  //#endregion
491
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__ */ (0, react_jsx_runtime.jsx)(PageBanner, {
587
+ currentLocale: locale,
588
+ onDismiss
589
+ });
590
+ }
591
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeSlot, {
592
+ name: "page.banner.replace",
593
+ default: DefaultBannerComponent
594
+ });
595
+ }
596
+ function DefaultFooterComponent() {
597
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageFooter, {});
598
+ }
492
599
  function routeForPath(routes, pathname) {
493
600
  return routes.find((route) => require_PageActions.isSameRoutePath(route.path, pathname));
494
601
  }
@@ -612,13 +719,13 @@ function NotFoundRouteElement(props) {
612
719
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RouteComponent, {});
613
720
  }
614
721
  function AppShell(arg0) {
615
- const { config, routes, navigation, bannerComponent, footerComponent } = arg0;
722
+ const { config, routes, navigation, runtimeSlots } = arg0;
616
723
  const location = (0, react_router_dom.useLocation)();
617
724
  const navigate = (0, react_router_dom.useNavigate)();
618
725
  const pathname = require_PageActions.normalizeRoutePath(location.pathname);
619
726
  const currentRoute = routeForPath(routes, pathname);
620
727
  const explicitLocale = explicitLocaleForPath(config, pathname);
621
- const [storedLocale] = (0, react.useState)(() => storedLocaleForConfig(config));
728
+ const storedLocale = storedLocaleForConfig(config);
622
729
  const currentLocale = explicitLocale ?? storedLocale ?? fallbackLocale(config);
623
730
  const currentLocaleConfig = config.i18n?.locales.find((locale) => locale.code === currentLocale);
624
731
  const notFoundRoute = currentRoute ? void 0 : notFoundRouteForPath(routes, pathname, currentLocale);
@@ -680,74 +787,88 @@ function AppShell(arg0) {
680
787
  ]);
681
788
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PageActions.LocaleContext.Provider, {
682
789
  value: currentLocale,
683
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_PageActions.SectionProvider, {
684
- sections,
685
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PageActions.Header, {
686
- config,
687
- navigation: currentNavigation.items,
688
- tabs: currentNavigation.tabs,
689
- routes,
690
- currentLocale,
691
- currentRoute,
692
- banner: hasBanner ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageBanner, {
693
- component: bannerComponent,
790
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeSlotsProvider, {
791
+ slots: runtimeSlots,
792
+ route: currentRoute,
793
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_PageActions.SectionProvider, {
794
+ sections,
795
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PageActions.Header, {
796
+ config,
797
+ navigation: currentNavigation.items,
798
+ tabs: currentNavigation.tabs,
799
+ routes,
694
800
  currentLocale,
695
- onDismiss: () => setDismissedBannerKey(activeBannerKey)
696
- }) : void 0
697
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
698
- 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)",
699
- style: { "--clarify-header-offset": hasTabs && hasBanner ? "10rem" : hasTabs && !hasBanner ? "7rem" : !hasTabs && hasBanner ? "6.5rem" : "3.5rem" },
700
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", {
701
- "data-pagefind-ignore": true,
702
- className: "clarify-sidebar hidden lg:block lg:self-stretch lg:bg-(--clarify-theme-tokens-colors-background) lg:px-5 xl:px-6",
703
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
704
- className: (0, clsx.default)("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"),
705
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PageActions.Navigation, { navigation: currentNavigation.items })
706
- })
707
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
708
- className: (0, clsx.default)("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"),
709
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_PageActions.PageActionsProvider, {
710
- route: currentRoute,
711
- routePrefix: config.routePrefix,
712
- children: [
713
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("main", {
714
- className: "clarify-main min-w-0 flex-auto",
715
- "data-pagefind-body": true,
716
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageErrorBoundary, {
717
- title: text("renderError.title"),
718
- description: text("renderError.description"),
719
- reloadLabel: text("renderError.reload"),
720
- detailsLabel: text("renderError.details"),
721
- pathLabel: text("renderError.path"),
722
- typeLabel: text("renderError.type"),
723
- messageLabel: text("renderError.message"),
724
- stackLabel: text("renderError.stack"),
725
- componentStackLabel: text("renderError.componentStack"),
726
- timestampLabel: text("renderError.timestamp"),
727
- copyLabel: text("actions.copy"),
728
- copiedLabel: text("actions.copied"),
729
- path: pathname,
730
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
731
- fallback: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageSkeleton, {}),
732
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.Routes, { children: [renderRoutes.map((route) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Route, {
733
- path: route.path,
734
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(route.component, {})
735
- }, route.path)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Route, {
736
- path: "*",
737
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NotFoundRouteElement, { component: NotFoundRouteComponent })
738
- })] })
739
- })
740
- }, pathname)
741
- }),
742
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNavigation, {
743
- navigation: currentNavigation.items,
744
- currentRoute
745
- }),
746
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageFooter, { component: footerComponent })
747
- ]
801
+ currentRoute,
802
+ banner: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerSlot, {
803
+ activeBannerKey,
804
+ dismissedBannerKey,
805
+ onDismiss: () => setDismissedBannerKey(activeBannerKey),
806
+ config,
807
+ locale: currentLocale
748
808
  })
809
+ }), /* @__PURE__ */ (0, react_jsx_runtime.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__ */ (0, react_jsx_runtime.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__ */ (0, react_jsx_runtime.jsx)("div", {
816
+ className: (0, clsx.default)("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__ */ (0, react_jsx_runtime.jsx)(require_PageActions.Navigation, { navigation: currentNavigation.items })
818
+ })
819
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
820
+ className: (0, clsx.default)("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__ */ (0, react_jsx_runtime.jsxs)(require_PageActions.PageActionsProvider, {
822
+ route: currentRoute,
823
+ routePrefix: config.routePrefix,
824
+ children: [
825
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("main", {
826
+ className: "clarify-main min-w-0 flex-auto",
827
+ "data-pagefind-body": true,
828
+ children: /* @__PURE__ */ (0, react_jsx_runtime.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__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
843
+ fallback: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageSkeleton, {}),
844
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.Routes, { children: [renderRoutes.map((route) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Route, {
845
+ path: route.path,
846
+ element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(route.component, {})
847
+ }, route.path)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Route, {
848
+ path: "*",
849
+ element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NotFoundRouteElement, { component: NotFoundRouteComponent })
850
+ })] })
851
+ })
852
+ }, pathname)
853
+ }),
854
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNavigation, {
855
+ navigation: currentNavigation.items,
856
+ currentRoute
857
+ }),
858
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeSlot, { name: "page.footer.before" }),
859
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeSlot, {
860
+ name: "page.footer.replace",
861
+ default: DefaultFooterComponent
862
+ }),
863
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
864
+ className: "flex justify-end",
865
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BuiltWithClarify, {})
866
+ })
867
+ ]
868
+ })
869
+ })]
749
870
  })]
750
- })]
871
+ })
751
872
  })
752
873
  });
753
874
  }
@@ -1951,6 +2072,35 @@ function ThemeRoot(props) {
1951
2072
  });
1952
2073
  }
1953
2074
  //#endregion
2075
+ //#region source/runtime/ClarifyShell.tsx
2076
+ /**
2077
+ * Shared provider chain used by both client-side render and server-side
2078
+ * renderToHTML. Wraps AppShell with ConfigContext → OpenApisContext →
2079
+ * ThemeProvider → ThemeRoot.
2080
+ *
2081
+ * The outer Router (BrowserRouter / StaticRouter) is left to the caller
2082
+ * so each entry point can supply the correct router variant.
2083
+ */
2084
+ function ClarifyShell(props) {
2085
+ const { config, routes, navigation, openApis, runtimeSlots, themeEditor = false } = props;
2086
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PageActions.ConfigContext.Provider, {
2087
+ value: config,
2088
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PageActions.OpenApisContext.Provider, {
2089
+ value: openApis,
2090
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PageActions.ThemeProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeRoot, {
2091
+ theme: config.theme,
2092
+ themeEditor,
2093
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AppShell, {
2094
+ config,
2095
+ routes,
2096
+ navigation: navigation ?? [],
2097
+ runtimeSlots
2098
+ })
2099
+ }) })
2100
+ })
2101
+ });
2102
+ }
2103
+ //#endregion
1954
2104
  Object.defineProperty(exports, "AppShell", {
1955
2105
  enumerable: true,
1956
2106
  get: function() {
@@ -1963,6 +2113,12 @@ Object.defineProperty(exports, "BuiltWithClarify", {
1963
2113
  return BuiltWithClarify;
1964
2114
  }
1965
2115
  });
2116
+ Object.defineProperty(exports, "ClarifyShell", {
2117
+ enumerable: true,
2118
+ get: function() {
2119
+ return ClarifyShell;
2120
+ }
2121
+ });
1966
2122
  Object.defineProperty(exports, "PageBanner", {
1967
2123
  enumerable: true,
1968
2124
  get: function() {
@@ -1975,16 +2131,28 @@ Object.defineProperty(exports, "PageFooter", {
1975
2131
  return PageFooter;
1976
2132
  }
1977
2133
  });
1978
- Object.defineProperty(exports, "ThemeEditor", {
2134
+ Object.defineProperty(exports, "RuntimeSlot", {
1979
2135
  enumerable: true,
1980
2136
  get: function() {
1981
- return ThemeEditor;
2137
+ return RuntimeSlot;
2138
+ }
2139
+ });
2140
+ Object.defineProperty(exports, "RuntimeSlotsProvider", {
2141
+ enumerable: true,
2142
+ get: function() {
2143
+ return RuntimeSlotsProvider;
1982
2144
  }
1983
2145
  });
1984
- Object.defineProperty(exports, "ThemeRoot", {
2146
+ Object.defineProperty(exports, "SlotProvider", {
1985
2147
  enumerable: true,
1986
2148
  get: function() {
1987
- return ThemeRoot;
2149
+ return SlotProvider;
2150
+ }
2151
+ });
2152
+ Object.defineProperty(exports, "ThemeEditor", {
2153
+ enumerable: true,
2154
+ get: function() {
2155
+ return ThemeEditor;
1988
2156
  }
1989
2157
  });
1990
2158
  Object.defineProperty(exports, "applyThemeVariables", {
@@ -2017,5 +2185,11 @@ Object.defineProperty(exports, "themeStorageKey", {
2017
2185
  return themeStorageKey;
2018
2186
  }
2019
2187
  });
2188
+ Object.defineProperty(exports, "useSlot", {
2189
+ enumerable: true,
2190
+ get: function() {
2191
+ return useSlot;
2192
+ }
2193
+ });
2020
2194
 
2021
- //# sourceMappingURL=ThemeRoot-UWj0iK1X.cjs.map
2195
+ //# sourceMappingURL=ClarifyShell-DNN5erFD.cjs.map