@clarify-labs/renderer 0.7.0 → 0.7.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 (64) hide show
  1. package/output/{OpenApiOperation-ZXToVSFC.cjs → OpenApiOperation-BcyW_ULy.cjs} +186 -140
  2. package/output/OpenApiOperation-BcyW_ULy.cjs.map +1 -0
  3. package/output/{OpenApiOperation-CWSOhUVa.js → OpenApiOperation-tUKf7lZ4.js} +166 -120
  4. package/output/OpenApiOperation-tUKf7lZ4.js.map +1 -0
  5. package/output/{shell-xxhV0p7k.cjs → PageActions-1RDCHcUY.cjs} +280 -308
  6. package/output/PageActions-1RDCHcUY.cjs.map +1 -0
  7. package/output/{shell-CumiARRe.js → PageActions-yoDRjkq8.js} +235 -263
  8. package/output/PageActions-yoDRjkq8.js.map +1 -0
  9. package/output/{ThemeRoot-C_ZdzSMu.js → ThemeRoot-QULrwQf6.js} +407 -53
  10. package/output/ThemeRoot-QULrwQf6.js.map +1 -0
  11. package/output/{ThemeRoot-CEvwrGp5.cjs → ThemeRoot-UWj0iK1X.cjs} +458 -80
  12. package/output/ThemeRoot-UWj0iK1X.cjs.map +1 -0
  13. package/output/app/AppShell.d.ts +3 -2
  14. package/output/app/PageActions.d.ts +12 -0
  15. package/output/app/PageBanner.d.ts +7 -0
  16. package/output/app/SectionProvider.d.ts +1 -0
  17. package/output/client.cjs +14 -7
  18. package/output/client.d.ts +4 -2
  19. package/output/client.js +4 -4
  20. package/output/context.d.ts +1 -1
  21. package/output/core/context.d.ts +5 -5
  22. package/output/core/index.d.ts +1 -1
  23. package/output/core/types.d.ts +70 -61
  24. package/output/index.cjs +56 -28
  25. package/output/index.cjs.map +1 -1
  26. package/output/index.d.ts +7 -5
  27. package/output/index.js +37 -12
  28. package/output/index.js.map +1 -1
  29. package/output/mdx/components.d.ts +2 -0
  30. package/output/mdx/primitives.d.ts +2 -0
  31. package/output/openapi/components/EndpointSections.d.ts +30 -0
  32. package/output/preview.cjs +7 -7
  33. package/output/preview.cjs.map +1 -1
  34. package/output/preview.js +4 -4
  35. package/output/preview.js.map +1 -1
  36. package/output/{render-zHU25Nm9.cjs → render-ByWbJbrA.cjs} +8 -7
  37. package/output/render-ByWbJbrA.cjs.map +1 -0
  38. package/output/{render-CnUd0XwZ.js → render-psutGbsg.js} +6 -5
  39. package/output/render-psutGbsg.js.map +1 -0
  40. package/output/renderer.css +371 -269
  41. package/output/server.cjs +8 -7
  42. package/output/server.cjs.map +1 -1
  43. package/output/server.js +5 -4
  44. package/output/server.js.map +1 -1
  45. package/output/shell/ContentActions.d.ts +0 -1
  46. package/output/shell/Header.d.ts +3 -2
  47. package/output/shell/SiteLogo.d.ts +2 -2
  48. package/output/shell/mobile.d.ts +2 -2
  49. package/output/theme/ThemeEditor.d.ts +53 -17
  50. package/output/theme/ThemeProvider.d.ts +2 -1
  51. package/output/theme/ThemeRoot.d.ts +2 -2
  52. package/output/theme/cookies.d.ts +11 -0
  53. package/output/theme/randomTheme.d.ts +2 -2
  54. package/output/theme/variables.d.ts +58 -20
  55. package/output/utils/href.d.ts +3 -3
  56. package/package.json +1 -1
  57. package/output/OpenApiOperation-CWSOhUVa.js.map +0 -1
  58. package/output/OpenApiOperation-ZXToVSFC.cjs.map +0 -1
  59. package/output/ThemeRoot-CEvwrGp5.cjs.map +0 -1
  60. package/output/ThemeRoot-C_ZdzSMu.js.map +0 -1
  61. package/output/render-CnUd0XwZ.js.map +0 -1
  62. package/output/render-zHU25Nm9.cjs.map +0 -1
  63. package/output/shell-CumiARRe.js.map +0 -1
  64. package/output/shell-xxhV0p7k.cjs.map +0 -1
@@ -1,7 +1,7 @@
1
- import { C as isExternalHref, D as useBuiltInText, E as copyTextToClipboard, S as ContentActions, _ as resolveThemeColorValue, g as cloneTheme, h as clarifyThemePresets, i as SectionProvider, j as useClarifyConfig, k as ClarifyLocaleContext, l as isSameRoutePath, m as applyThemeCssVariables, n as Navigation, p as useTheme, r as safeDecodeURIComponent, t as Header, u as normalizeRoutePath, v as resolveThemeVariableTargets, w as localizeHref, x as themeToCssVariables } from "./shell-CumiARRe.js";
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";
2
2
  import clsx from "clsx";
3
3
  import { Component, Suspense, lazy, useEffect, useMemo, useState } from "react";
4
- import { Link, Route, Routes, useLocation } from "react-router-dom";
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
7
  //#region source/app/ErrorBoundary.tsx
@@ -147,6 +147,86 @@ var PageErrorBoundary = class extends Component {
147
147
  }
148
148
  };
149
149
  //#endregion
150
+ //#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
+ function bannerStorageKey(config, content) {
156
+ return `clarify:banner:dismissed:${config.title}:${content}`;
157
+ }
158
+ function PageBannerLink(props) {
159
+ const { href, label, external: externalProp, config, locale } = props;
160
+ const external = externalProp ?? isExternalHref(href);
161
+ const resolvedHref = external ? href : localizeHref(href, config, locale);
162
+ const className = "clarify-banner-link shrink-0 rounded-full bg-(--clarify-theme-tokens-colors-primary) px-3 py-1 text-xs/5 font-semibold text-white no-underline transition hover:opacity-90";
163
+ if (external) return /* @__PURE__ */ jsx("a", {
164
+ href: resolvedHref,
165
+ target: "_blank",
166
+ rel: "noreferrer",
167
+ className,
168
+ children: label
169
+ });
170
+ return /* @__PURE__ */ jsx(Link, {
171
+ to: resolvedHref,
172
+ className,
173
+ children: label
174
+ });
175
+ }
176
+ function PageBanner(props) {
177
+ const { component: CustomBanner, currentLocale, onDismiss } = props;
178
+ const config = useConfig();
179
+ 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]);
185
+ const [dismissed, setDismissed] = useState(() => {
186
+ if (!storageKey || !builtInBanner?.dismissible || typeof window === "undefined") return false;
187
+ return window.localStorage.getItem(storageKey) === "1";
188
+ });
189
+ useEffect(() => {
190
+ if (dismissed) onDismiss?.();
191
+ }, [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;
200
+ return /* @__PURE__ */ jsxs("div", {
201
+ 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
+ children: [/* @__PURE__ */ jsxs("div", {
203
+ className: "mx-auto flex w-full max-w-(--clarify-theme-layout-max-width) items-center justify-center gap-3 pr-8 sm:pr-0",
204
+ children: [/* @__PURE__ */ jsx("p", {
205
+ className: "clarify-banner-content m-0 text-center font-medium",
206
+ children: content
207
+ }), link ? /* @__PURE__ */ jsx(PageBannerLink, {
208
+ href: link.href,
209
+ label: linkLabel,
210
+ external: link.external,
211
+ config,
212
+ locale: currentLocale
213
+ }) : null]
214
+ }), builtInBanner.dismissible ? /* @__PURE__ */ jsx("button", {
215
+ type: "button",
216
+ 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
+ "aria-label": "Dismiss announcement",
218
+ onClick: () => {
219
+ if (storageKey) window.localStorage.setItem(storageKey, "1");
220
+ setDismissed(true);
221
+ },
222
+ children: /* @__PURE__ */ jsx(X, {
223
+ className: "size-4",
224
+ "aria-hidden": "true"
225
+ })
226
+ }) : null]
227
+ });
228
+ }
229
+ //#endregion
150
230
  //#region source/assets/clarify.svg?url
151
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";
152
232
  //#endregion
@@ -179,7 +259,7 @@ function resolveLocalizedText(text, locale, fallbackLocale) {
179
259
  if (typeof text === "string") return text;
180
260
  return (locale ? text[locale] : void 0) ?? (fallbackLocale ? text[fallbackLocale] : void 0) ?? Object.values(text)[0] ?? "";
181
261
  }
182
- function localeForPath$1(config, pathname) {
262
+ function localeForPath(config, pathname) {
183
263
  const i18n = config.i18n;
184
264
  if (!i18n) return void 0;
185
265
  const firstSegment = pathname.split("/").filter(Boolean)[0];
@@ -215,8 +295,8 @@ function SocialLink(arg0) {
215
295
  });
216
296
  }
217
297
  function PageFooter(props = {}) {
218
- const config = useClarifyConfig();
219
- const locale = localeForPath$1(config, useLocation().pathname);
298
+ const config = useConfig();
299
+ const locale = localeForPath(config, useLocation().pathname);
220
300
  const footer = config.footer;
221
301
  const builtInFooter = footer && typeof footer === "object" ? footer : void 0;
222
302
  const CustomFooter = props.component;
@@ -225,7 +305,7 @@ function PageFooter(props = {}) {
225
305
  const copyright = builtInFooter?.copyright ? resolveLocalizedText(builtInFooter.copyright, locale, config.i18n?.defaultLocale) : void 0;
226
306
  const hasBuiltInFooter = Boolean(copyright || links.length > 0 || socials.length > 0);
227
307
  return /* @__PURE__ */ jsxs("footer", {
228
- className: "clarify-page-footer mx-auto flex w-full max-w-(--clarify-theme-layout-max-width) flex-col gap-4 border-t border-(--clarify-theme-tokens-colors-border) px-4 py-8 sm:px-6 lg:mt-24 lg:px-5",
308
+ 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",
229
309
  children: [CustomFooter ? /* @__PURE__ */ jsx("div", {
230
310
  className: "clarify-footer-custom w-full",
231
311
  children: /* @__PURE__ */ jsx(CustomFooter, {})
@@ -419,6 +499,7 @@ function sectionsForRoute(route) {
419
499
  return route?.sections?.map((section) => ({
420
500
  id: section.id,
421
501
  title: section.title,
502
+ level: section.level,
422
503
  badge: section.badge,
423
504
  tags: section.tags
424
505
  })) ?? [];
@@ -437,12 +518,20 @@ function scrollToHash(hash) {
437
518
  });
438
519
  });
439
520
  }
440
- function localeForPath(config, pathname, route) {
441
- if (route?.locale) return route.locale;
521
+ function explicitLocaleForPath(config, pathname) {
442
522
  const i18n = config.i18n;
443
523
  if (!i18n) return void 0;
444
524
  const firstSegment = pathname.split("/").filter(Boolean)[0];
445
- return i18n.locales.find((locale) => locale.code === firstSegment)?.code ?? i18n.defaultLocale;
525
+ return i18n.locales.find((locale) => locale.code === firstSegment)?.code;
526
+ }
527
+ function fallbackLocale(config) {
528
+ return config.i18n?.defaultLocale;
529
+ }
530
+ function storedLocaleForConfig(config) {
531
+ return getStoredLocalePreference(config.i18n?.locales.map((locale) => locale.code));
532
+ }
533
+ function isDefaultLocale(config, locale) {
534
+ return Boolean(locale && config.i18n?.defaultLocale === locale);
446
535
  }
447
536
  function isTabbedNavigation(navigation) {
448
537
  return !Array.isArray(navigation) && "tabs" in navigation;
@@ -521,22 +610,46 @@ function NotFoundRouteElement(props) {
521
610
  return /* @__PURE__ */ jsx(RouteComponent, {});
522
611
  }
523
612
  function AppShell(arg0) {
524
- const { config, routes, navigation, footerComponent } = arg0;
613
+ const { config, routes, navigation, bannerComponent, footerComponent } = arg0;
525
614
  const location = useLocation();
615
+ const navigate = useNavigate();
526
616
  const pathname = normalizeRoutePath(location.pathname);
527
617
  const currentRoute = routeForPath(routes, pathname);
528
- const currentLocale = localeForPath(config, pathname, currentRoute);
618
+ const explicitLocale = explicitLocaleForPath(config, pathname);
619
+ const [storedLocale] = useState(() => storedLocaleForConfig(config));
620
+ const currentLocale = explicitLocale ?? storedLocale ?? fallbackLocale(config);
529
621
  const currentLocaleConfig = config.i18n?.locales.find((locale) => locale.code === currentLocale);
530
622
  const notFoundRoute = currentRoute ? void 0 : notFoundRouteForPath(routes, pathname, currentLocale);
531
623
  const text = useBuiltInText(currentLocale);
532
624
  const currentNavigation = navigationForLocale(navigation, currentLocale, pathname);
533
625
  const sections = sectionsForRoute(currentRoute);
626
+ const [dismissedBannerKey, setDismissedBannerKey] = useState();
627
+ const activeBannerKey = config.banner ? JSON.stringify(config.banner) : void 0;
628
+ const hasBanner = Boolean(config.banner) && dismissedBannerKey !== activeBannerKey;
534
629
  const hasTabs = Boolean(currentNavigation.tabs?.length);
535
630
  const renderRoutes = useMemo(() => routes.map((route) => ({
536
631
  ...route,
537
632
  component: resolveRouteComponent(route)
538
633
  })), [routes]);
539
634
  const NotFoundRouteComponent = notFoundRoute ? renderRoutes.find((route) => isSameRoutePath(route.path, notFoundRoute.path))?.component : void 0;
635
+ useEffect(() => {
636
+ if (explicitLocale) storeLocalePreference(explicitLocale);
637
+ }, [explicitLocale]);
638
+ useEffect(() => {
639
+ if (explicitLocale || !storedLocale || isDefaultLocale(config, storedLocale)) return;
640
+ const localizedPath = currentRoute?.alternates?.[storedLocale];
641
+ if (!localizedPath || isSameRoutePath(localizedPath, pathname)) return;
642
+ navigate(`${localizedPath}${location.search}${location.hash}`, { replace: true });
643
+ }, [
644
+ config,
645
+ currentRoute,
646
+ explicitLocale,
647
+ location.hash,
648
+ location.search,
649
+ navigate,
650
+ pathname,
651
+ storedLocale
652
+ ]);
540
653
  useEffect(() => {
541
654
  if (location.hash) {
542
655
  scrollToHash(location.hash);
@@ -563,33 +676,38 @@ function AppShell(arg0) {
563
676
  currentRoute,
564
677
  notFoundRoute
565
678
  ]);
566
- return /* @__PURE__ */ jsx(ClarifyLocaleContext.Provider, {
679
+ return /* @__PURE__ */ jsx(LocaleContext.Provider, {
567
680
  value: currentLocale,
568
681
  children: /* @__PURE__ */ jsxs(SectionProvider, {
569
682
  sections,
570
- children: [
571
- /* @__PURE__ */ jsx(Header, {
572
- config,
573
- navigation: currentNavigation.items,
574
- tabs: currentNavigation.tabs,
575
- routes,
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,
576
692
  currentLocale,
577
- currentRoute
578
- }),
579
- /* @__PURE__ */ jsxs("div", {
580
- className: "clarify-layout pb-12 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)",
581
- children: [/* @__PURE__ */ jsx("aside", {
582
- "data-pagefind-ignore": true,
583
- className: clsx("clarify-sidebar hidden lg:sticky lg:z-30 lg:block lg:h-(--clarify-sidebar-height) lg:self-start lg:overflow-y-auto lg:bg-(--clarify-theme-tokens-colors-background) lg:px-5 lg:pb-8 xl:px-6", hasTabs ? "lg:top-28 lg:h-(--clarify-sidebar-height-with-tabs) lg:pt-6" : "lg:top-14 lg:pt-6"),
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"),
584
703
  children: /* @__PURE__ */ jsx(Navigation, { navigation: currentNavigation.items })
585
- }), /* @__PURE__ */ jsxs("div", {
586
- className: clsx("clarify-content @container relative flex min-h-screen min-w-0 flex-col px-4 sm:px-6 lg:px-8 xl:px-10", hasTabs ? "pt-14 lg:pt-28" : "pt-14"),
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,
587
710
  children: [
588
- /* @__PURE__ */ jsx(ContentActions, {
589
- hasTabs,
590
- route: currentRoute,
591
- routePrefix: config.routePrefix
592
- }),
593
711
  /* @__PURE__ */ jsx("main", {
594
712
  className: "clarify-main min-w-0 flex-auto",
595
713
  "data-pagefind-body": true,
@@ -622,12 +740,12 @@ function AppShell(arg0) {
622
740
  /* @__PURE__ */ jsx(PageNavigation, {
623
741
  navigation: currentNavigation.items,
624
742
  currentRoute
625
- })
743
+ }),
744
+ /* @__PURE__ */ jsx(PageFooter, { component: footerComponent })
626
745
  ]
627
- })]
628
- }),
629
- /* @__PURE__ */ jsx(PageFooter, { component: footerComponent })
630
- ]
746
+ })
747
+ })]
748
+ })]
631
749
  })
632
750
  });
633
751
  }
@@ -1284,6 +1402,183 @@ function createRandomTheme() {
1284
1402
  };
1285
1403
  }
1286
1404
  //#endregion
1405
+ //#region source/theme/variables.ts
1406
+ var themeStorageKey = themeCookieName;
1407
+ var themePresets = {
1408
+ default: {
1409
+ preset: "default",
1410
+ tokens: {
1411
+ colors: {
1412
+ primary: "#047857",
1413
+ accent: "#0D9488",
1414
+ background: {
1415
+ light: "#ffffff",
1416
+ dark: "#09090b"
1417
+ },
1418
+ foreground: {
1419
+ light: "#111827",
1420
+ dark: "#ffffff"
1421
+ },
1422
+ surface: {
1423
+ light: "#ffffff",
1424
+ dark: "#18181b"
1425
+ },
1426
+ muted: {
1427
+ light: "#64748b",
1428
+ dark: "#a1a1aa"
1429
+ },
1430
+ border: {
1431
+ light: "rgb(15 23 42 / 0.12)",
1432
+ dark: "rgb(255 255 255 / 0.1)"
1433
+ },
1434
+ codeBackground: {
1435
+ light: "#f6fbf8",
1436
+ dark: "#18181b"
1437
+ }
1438
+ },
1439
+ radius: {
1440
+ sm: "6px",
1441
+ md: "10px",
1442
+ lg: "14px",
1443
+ xl: "18px"
1444
+ }
1445
+ },
1446
+ layout: { maxWidth: "82rem" },
1447
+ editor: false
1448
+ },
1449
+ base: {
1450
+ preset: "base",
1451
+ tokens: {
1452
+ colors: {
1453
+ primary: "#18181b",
1454
+ accent: "#52525b",
1455
+ background: {
1456
+ light: "#ffffff",
1457
+ dark: "#09090b"
1458
+ },
1459
+ foreground: {
1460
+ light: "#18181b",
1461
+ dark: "#ffffff"
1462
+ },
1463
+ surface: {
1464
+ light: "#ffffff",
1465
+ dark: "#18181b"
1466
+ },
1467
+ muted: {
1468
+ light: "#71717a",
1469
+ dark: "#a1a1aa"
1470
+ },
1471
+ border: {
1472
+ light: "rgb(24 24 27 / 0.12)",
1473
+ dark: "rgb(255 255 255 / 0.1)"
1474
+ },
1475
+ codeBackground: {
1476
+ light: "#f4f4f5",
1477
+ dark: "#18181b"
1478
+ }
1479
+ },
1480
+ radius: {
1481
+ sm: "6px",
1482
+ md: "8px",
1483
+ lg: "12px",
1484
+ xl: "16px"
1485
+ }
1486
+ },
1487
+ layout: { maxWidth: "80rem" },
1488
+ editor: false
1489
+ }
1490
+ };
1491
+ function cloneThemeColorValue(value) {
1492
+ return typeof value === "string" ? value : { ...value };
1493
+ }
1494
+ function cloneTheme(theme) {
1495
+ return {
1496
+ preset: theme.preset,
1497
+ tokens: {
1498
+ colors: {
1499
+ primary: cloneThemeColorValue(theme.tokens.colors.primary),
1500
+ accent: cloneThemeColorValue(theme.tokens.colors.accent),
1501
+ background: cloneThemeColorValue(theme.tokens.colors.background),
1502
+ foreground: cloneThemeColorValue(theme.tokens.colors.foreground),
1503
+ surface: cloneThemeColorValue(theme.tokens.colors.surface),
1504
+ muted: cloneThemeColorValue(theme.tokens.colors.muted),
1505
+ border: cloneThemeColorValue(theme.tokens.colors.border),
1506
+ codeBackground: cloneThemeColorValue(theme.tokens.colors.codeBackground)
1507
+ },
1508
+ radius: { ...theme.tokens.radius }
1509
+ },
1510
+ layout: { ...theme.layout },
1511
+ editor: theme.editor
1512
+ };
1513
+ }
1514
+ function isModeColorValue(value) {
1515
+ return typeof value === "object" && value !== null;
1516
+ }
1517
+ function resolveThemeColorValue(value, resolvedTheme = "light") {
1518
+ if (!isModeColorValue(value)) return value;
1519
+ return value[resolvedTheme] ?? value.light ?? value.dark ?? "";
1520
+ }
1521
+ function resolveThemeColors(colors, resolvedTheme = "light") {
1522
+ return {
1523
+ primary: resolveThemeColorValue(colors.primary, resolvedTheme),
1524
+ accent: resolveThemeColorValue(colors.accent, resolvedTheme),
1525
+ background: resolveThemeColorValue(colors.background, resolvedTheme),
1526
+ foreground: resolveThemeColorValue(colors.foreground, resolvedTheme),
1527
+ surface: resolveThemeColorValue(colors.surface, resolvedTheme),
1528
+ muted: resolveThemeColorValue(colors.muted, resolvedTheme),
1529
+ border: resolveThemeColorValue(colors.border, resolvedTheme),
1530
+ codeBackground: resolveThemeColorValue(colors.codeBackground, resolvedTheme)
1531
+ };
1532
+ }
1533
+ function themeToCssVariables(theme, resolvedTheme) {
1534
+ const colors = resolveThemeColors(theme.tokens.colors, resolvedTheme);
1535
+ const { radius } = theme.tokens;
1536
+ return {
1537
+ "--clarify-theme-tokens-colors-primary": colors.primary,
1538
+ "--clarify-theme-tokens-colors-accent": colors.accent,
1539
+ "--clarify-theme-tokens-colors-background": colors.background,
1540
+ "--clarify-theme-tokens-colors-foreground": colors.foreground,
1541
+ "--clarify-theme-tokens-colors-surface": colors.surface,
1542
+ "--clarify-theme-tokens-colors-muted": colors.muted,
1543
+ "--clarify-theme-tokens-colors-border": colors.border,
1544
+ "--clarify-theme-tokens-colors-code-background": colors.codeBackground,
1545
+ "--clarify-theme-tokens-radius-sm": radius.sm,
1546
+ "--clarify-theme-tokens-radius-md": radius.md,
1547
+ "--clarify-theme-tokens-radius-lg": radius.lg,
1548
+ "--clarify-theme-tokens-radius-xl": radius.xl,
1549
+ "--clarify-theme-layout-max-width": theme.layout.maxWidth
1550
+ };
1551
+ }
1552
+ function themeBootstrapScript(theme = themePresets.default) {
1553
+ const darkVariables = themeToCssVariables(theme, "dark");
1554
+ const lightVariables = themeToCssVariables(theme, "light");
1555
+ return `(function(){try{var c=${JSON.stringify(themeCookieName)};var m=document.cookie?document.cookie.split('; '):[];var e=null;for(var i=0;i<m.length;i++){var p=m[i].indexOf('=');var n=p===-1?m[i]:m[i].slice(0,p);if(decodeURIComponent(n)===c){e=p===-1?'':decodeURIComponent(m[i].slice(p+1));break}}var t=e==='dark'||e==='light'||e==='system'?e:'system';var r=t==='system'?window.matchMedia('(prefers-color-scheme: dark)').matches:t==='dark';var v=r?${JSON.stringify(darkVariables)}:${JSON.stringify(lightVariables)};var s=document.documentElement.style;for(var k in v)s.setProperty(k,v[k]);document.documentElement.classList.toggle('dark',r);document.documentElement.style.colorScheme=r?'dark':'light'}catch(e){}})();`;
1556
+ }
1557
+ function uniqueElements(elements) {
1558
+ return Array.from(new Set(elements));
1559
+ }
1560
+ function resolveThemeVariableTargets(target) {
1561
+ if (typeof document === "undefined") return [];
1562
+ if (target instanceof HTMLElement) return [target];
1563
+ if (typeof target === "string") return Array.from(document.querySelectorAll(target));
1564
+ return uniqueElements([document.documentElement, ...Array.from(document.querySelectorAll(".clarify-app"))]);
1565
+ }
1566
+ function applyThemeCssVariables(variables, targets) {
1567
+ const previousValues = /* @__PURE__ */ new Map();
1568
+ for (const element of targets) {
1569
+ const elementPreviousValues = /* @__PURE__ */ new Map();
1570
+ for (const [property, value] of Object.entries(variables)) {
1571
+ elementPreviousValues.set(property, element.style.getPropertyValue(property));
1572
+ element.style.setProperty(property, value);
1573
+ }
1574
+ previousValues.set(element, elementPreviousValues);
1575
+ }
1576
+ return () => {
1577
+ for (const [element, elementPreviousValues] of previousValues) for (const [property, previousValue] of elementPreviousValues) if (previousValue) element.style.setProperty(property, previousValue);
1578
+ else element.style.removeProperty(property);
1579
+ };
1580
+ }
1581
+ //#endregion
1287
1582
  //#region source/theme/ThemeEditor.tsx
1288
1583
  var colorTokenFields = [
1289
1584
  {
@@ -1341,18 +1636,24 @@ var layoutFields = [{
1341
1636
  key: "maxWidth",
1342
1637
  label: "Max width"
1343
1638
  }];
1344
- var clarifyThemeEditorPresets = clarifyThemePresets;
1345
- function applyClarifyThemeVariables(theme, target) {
1639
+ var themeEditorPresets = themePresets;
1640
+ function applyThemeVariables(theme, target) {
1346
1641
  return applyThemeCssVariables(themeToCssVariables(theme), resolveThemeVariableTargets(target));
1347
1642
  }
1348
1643
  function isHexColor(value) {
1349
1644
  return /^#[0-9a-f]{6}$/i.test(value);
1350
1645
  }
1351
- function updateThemeModeColorValue(value, resolvedTheme, nextValue) {
1352
- if (typeof value === "string") return nextValue;
1646
+ function updateThemeModeColorValue(value, mode, nextValue) {
1647
+ if (typeof value === "string") return mode === "light" ? {
1648
+ light: nextValue,
1649
+ dark: value
1650
+ } : {
1651
+ light: value,
1652
+ dark: nextValue
1653
+ };
1353
1654
  return {
1354
1655
  ...value,
1355
- [resolvedTheme]: nextValue
1656
+ [mode]: nextValue
1356
1657
  };
1357
1658
  }
1358
1659
  function TextField(props) {
@@ -1385,6 +1686,61 @@ function TextField(props) {
1385
1686
  })]
1386
1687
  });
1387
1688
  }
1689
+ function ColorField(props) {
1690
+ const { id, label, value, onChange } = props;
1691
+ const lightValue = resolveThemeColorValue(value, "light");
1692
+ const darkValue = resolveThemeColorValue(value, "dark");
1693
+ return /* @__PURE__ */ jsxs("div", {
1694
+ className: "grid min-w-0 gap-1.5",
1695
+ children: [/* @__PURE__ */ jsx("span", {
1696
+ className: "text-xs/5 font-medium text-(--clarify-ui-text)",
1697
+ children: label
1698
+ }), /* @__PURE__ */ jsxs("div", {
1699
+ className: "grid grid-cols-2 gap-2",
1700
+ children: [/* @__PURE__ */ jsx(ColorModeInput, {
1701
+ id: `${id}-light`,
1702
+ mode: "light",
1703
+ value: lightValue,
1704
+ onChange: (v) => onChange("light", v)
1705
+ }), /* @__PURE__ */ jsx(ColorModeInput, {
1706
+ id: `${id}-dark`,
1707
+ mode: "dark",
1708
+ value: darkValue,
1709
+ onChange: (v) => onChange("dark", v)
1710
+ })]
1711
+ })]
1712
+ });
1713
+ }
1714
+ function ColorModeInput(props) {
1715
+ const { id, mode, value, onChange } = props;
1716
+ const canUseColorInput = isHexColor(value);
1717
+ function handleTextChange(event) {
1718
+ onChange(event.target.value);
1719
+ }
1720
+ return /* @__PURE__ */ jsxs("label", {
1721
+ htmlFor: id,
1722
+ className: "grid min-w-0 gap-1 text-[11px]/4 font-medium text-(--clarify-ui-text-faint)",
1723
+ children: [/* @__PURE__ */ jsxs("span", {
1724
+ className: "flex min-w-0 items-center justify-between gap-2",
1725
+ children: [/* @__PURE__ */ jsx("span", {
1726
+ className: "uppercase tracking-wide",
1727
+ children: mode
1728
+ }), canUseColorInput ? /* @__PURE__ */ jsx("input", {
1729
+ type: "color",
1730
+ value,
1731
+ "aria-label": `${id} color`,
1732
+ className: "h-4 w-6 shrink-0 cursor-pointer rounded border border-(--clarify-theme-tokens-colors-border) bg-transparent p-0",
1733
+ onChange: handleTextChange
1734
+ }) : null]
1735
+ }), /* @__PURE__ */ jsx("input", {
1736
+ id,
1737
+ value,
1738
+ spellCheck: false,
1739
+ className: "h-8 w-full min-w-0 rounded-(--clarify-theme-tokens-radius-sm) border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-background) px-2 font-mono text-xs text-(--clarify-theme-tokens-colors-foreground) shadow-xs outline-none transition focus:border-(--clarify-theme-tokens-colors-primary) focus:ring-2 focus:ring-(--clarify-ui-accent-border)",
1740
+ onChange: handleTextChange
1741
+ })]
1742
+ });
1743
+ }
1388
1744
  function themeToConfigSource(theme) {
1389
1745
  return JSON.stringify({ theme: {
1390
1746
  preset: theme.preset,
@@ -1396,7 +1752,7 @@ function ThemeEditor(props) {
1396
1752
  const { initialTheme, onChange, target, defaultOpen = false, className } = props;
1397
1753
  const { resolvedTheme } = useTheme();
1398
1754
  const [isOpen, setIsOpen] = useState(defaultOpen);
1399
- const [theme, setTheme] = useState(() => cloneTheme(initialTheme ?? clarifyThemeEditorPresets.default));
1755
+ const [theme, setTheme] = useState(() => cloneTheme(initialTheme ?? themeEditorPresets.default));
1400
1756
  const [copyState, setCopyState] = useState("idle");
1401
1757
  const configSource = useMemo(() => themeToConfigSource(theme), [theme]);
1402
1758
  useEffect(() => applyThemeCssVariables(themeToCssVariables(theme, resolvedTheme), resolveThemeVariableTargets(target)), [
@@ -1409,16 +1765,16 @@ function ThemeEditor(props) {
1409
1765
  onChange?.(nextTheme);
1410
1766
  }
1411
1767
  function updatePreset(nextPreset) {
1412
- commit(cloneTheme(clarifyThemeEditorPresets[nextPreset]));
1768
+ commit(cloneTheme(themeEditorPresets[nextPreset]));
1413
1769
  }
1414
- function updateColorToken(key, value) {
1770
+ function updateColorToken(key, mode, value) {
1415
1771
  commit({
1416
1772
  ...theme,
1417
1773
  tokens: {
1418
1774
  ...theme.tokens,
1419
1775
  colors: {
1420
1776
  ...theme.tokens.colors,
1421
- [key]: updateThemeModeColorValue(theme.tokens.colors[key], resolvedTheme, value)
1777
+ [key]: updateThemeModeColorValue(theme.tokens.colors[key], mode, value)
1422
1778
  }
1423
1779
  }
1424
1780
  });
@@ -1508,12 +1864,11 @@ function ThemeEditor(props) {
1508
1864
  children: "Colors"
1509
1865
  }), /* @__PURE__ */ jsx("div", {
1510
1866
  className: "grid grid-cols-1 gap-3",
1511
- children: colorTokenFields.map((field) => /* @__PURE__ */ jsx(TextField, {
1867
+ children: colorTokenFields.map((field) => /* @__PURE__ */ jsx(ColorField, {
1512
1868
  id: `clarify-theme-editor-color-${field.key}`,
1513
1869
  label: field.label,
1514
- value: resolveThemeColorValue(theme.tokens.colors[field.key], resolvedTheme),
1515
- withColorInput: true,
1516
- onChange: (value) => updateColorToken(field.key, value)
1870
+ value: theme.tokens.colors[field.key],
1871
+ onChange: (mode, value) => updateColorToken(field.key, mode, value)
1517
1872
  }, field.key))
1518
1873
  })]
1519
1874
  }),
@@ -1590,11 +1945,10 @@ function ThemeRoot(props) {
1590
1945
  return /* @__PURE__ */ jsxs("div", {
1591
1946
  className: "clarify-app h-full min-h-screen bg-(--clarify-theme-tokens-colors-background) text-(--clarify-theme-tokens-colors-foreground)",
1592
1947
  "data-theme-preset": theme.preset,
1593
- style: themeVariables,
1594
1948
  children: [children, themeEditor ? /* @__PURE__ */ jsx(ThemeEditor, { initialTheme: theme }) : null]
1595
1949
  });
1596
1950
  }
1597
1951
  //#endregion
1598
- export { AppShell as a, clarifyThemeEditorPresets as i, ThemeEditor as n, PageFooter as o, applyClarifyThemeVariables as r, BuiltWithClarify as s, ThemeRoot as t };
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 };
1599
1953
 
1600
- //# sourceMappingURL=ThemeRoot-C_ZdzSMu.js.map
1954
+ //# sourceMappingURL=ThemeRoot-QULrwQf6.js.map