@krak-stack/registry 0.1.24 → 0.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,7 +20,8 @@ import {
20
20
  } from "@krak-stack/registry/httpapi-toolkit";
21
21
  import { ApiClient } from "@krak-stack/registry/httpapi/client";
22
22
  import { HttpApiSpec } from "@krak-stack/registry/httpapi/helpers";
23
- import { createMdxDocsSource, makeDocs } from "@krak-stack/registry/docs";
23
+ import { createDocsSource, makeDocs } from "@krak-stack/registry/docs";
24
+ import { loadMdxDocsDirectory } from "@krak-stack/registry/docs/server";
24
25
  import {
25
26
  DocumentationToolkit,
26
27
  DocumentationToolkitLayer,
@@ -68,8 +69,18 @@ HTTP API client, schema, AI tool, CLI, and MCP utilities are available under
68
69
  the `@krak-stack/registry/httpapi/*` subpaths. Keep application-specific API
69
70
  layers, handlers, authentication, and client bindings in the application.
70
71
 
71
- Documentation consumers create their content source in the application so Vite
72
- can resolve the local `import.meta.glob`, then pass it to `makeDocs`.
72
+ Documentation consumers load and compile their application-owned MDX on the
73
+ server, then pass the validated page records to `createDocsSource` and
74
+ `makeDocs`:
75
+
76
+ ```ts
77
+ const pages = await loadMdxDocsDirectory("src/content/docs");
78
+ const source = createDocsSource({ pages, locales: ["en", "fr"] });
79
+ ```
80
+
81
+ The `@krak-stack/registry/docs/server` export requires the Bun runtime. Keep it
82
+ behind a server-only module or server function so it is not included in browser
83
+ bundles.
73
84
 
74
85
  Add the package's Tailwind source to the application stylesheet:
75
86
 
@@ -2,7 +2,7 @@ import type { LucideIcon } from "lucide-react";
2
2
  type NavItem = {
3
3
  label: () => string;
4
4
  href: string;
5
- icon: LucideIcon;
5
+ icon?: LucideIcon;
6
6
  badge?: () => string;
7
7
  external?: boolean;
8
8
  };
@@ -10,6 +10,7 @@ type NavGroup = {
10
10
  label: () => string;
11
11
  items: NavItem[];
12
12
  };
13
+ export type SidebarCollapsible = "icon" | "offcanvas" | "none";
13
14
  export type { NavItem, NavGroup };
14
15
  export declare const useSidebarLayout: () => {
15
16
  isMobile: boolean;
@@ -24,7 +25,7 @@ type SidebarPageHeaderProps = {
24
25
  actions?: React.ReactNode;
25
26
  };
26
27
  export declare function SidebarPageHeader({ title, description, badge, actions, }: SidebarPageHeaderProps): import("react").JSX.Element;
27
- export declare function SidebarLayout({ groups, children, sidebarFooter, sidebarHeader, headerActions, contentClassName, fullPage, }: {
28
+ export declare function SidebarLayout({ groups, children, sidebarFooter, sidebarHeader, headerActions, contentClassName, fullPage, sidebarCollapsible, defaultOpen, }: {
28
29
  groups: NavGroup[];
29
30
  children?: React.ReactNode;
30
31
  sidebarFooter?: React.ReactNode;
@@ -32,4 +33,6 @@ export declare function SidebarLayout({ groups, children, sidebarFooter, sidebar
32
33
  headerActions?: React.ReactNode;
33
34
  contentClassName?: string;
34
35
  fullPage?: boolean;
36
+ sidebarCollapsible?: SidebarCollapsible;
37
+ defaultOpen?: boolean;
35
38
  }): import("react").JSX.Element;
@@ -1,9 +1,8 @@
1
1
  // ../../src/components/ui/sidebar-layout.tsx
2
- import { useAtom } from "@effect/atom-react";
3
- import { BrowserKeyValueStore } from "@effect/platform-browser";
4
2
  import { Link, Outlet, useRouterState } from "@tanstack/react-router";
5
- import { Schema as Schema2 } from "effect";
6
- import { Atom } from "effect/unstable/reactivity";
3
+ import { Option, Schema as Schema2 } from "effect";
4
+ import { Cookies } from "effect/unstable/http";
5
+ import { useState as useState3 } from "react";
7
6
 
8
7
  // ../../src/components/ui/badge.tsx
9
8
  import { mergeProps } from "@base-ui/react/merge-props";
@@ -599,18 +598,18 @@ function SidebarMenuButton({
599
598
 
600
599
  // ../../src/components/ui/sidebar-layout.tsx
601
600
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
602
- var sidebarStorageRuntime = Atom.runtime(BrowserKeyValueStore.layerLocalStorage);
603
- var sidebarOpenAtom = Atom.kvs({
604
- runtime: sidebarStorageRuntime,
605
- key: "sidebar:open",
606
- schema: Schema2.Boolean,
607
- defaultValue: () => true
601
+ var SIDEBAR_COOKIE_NAME2 = "sidebar_state";
602
+ var SidebarOpenCookie = Schema2.Literals(["true", "false"]).annotate({
603
+ identifier: "SidebarOpenCookie"
608
604
  });
605
+ var getSidebarDefaultOpen = (defaultOpen) => {
606
+ return Schema2.decodeUnknownOption(SidebarOpenCookie)(Cookies.parseHeader(globalThis.document?.cookie ?? "")[SIDEBAR_COOKIE_NAME2]).pipe(Option.map((value) => value === "true"), Option.getOrElse(() => defaultOpen));
607
+ };
609
608
  var useSidebarLayout = () => {
610
609
  const { isMobile } = useSidebar();
611
610
  return { isMobile };
612
611
  };
613
- function AppSidebar({ footer, groups, header }) {
612
+ function AppSidebar({ collapsible, footer, groups, header }) {
614
613
  const { isMobile, setOpenMobile } = useSidebar();
615
614
  const pathname = useRouterState({
616
615
  select: (state) => state.location.pathname
@@ -620,12 +619,13 @@ function AppSidebar({ footer, groups, header }) {
620
619
  setOpenMobile(false);
621
620
  };
622
621
  return /* @__PURE__ */ jsxs4(Sidebar, {
623
- collapsible: "icon",
622
+ collapsible,
624
623
  children: [
625
624
  header && /* @__PURE__ */ jsx5(SidebarHeader, {
626
625
  children: header
627
626
  }),
628
627
  /* @__PURE__ */ jsx5(SidebarContent, {
628
+ className: "group-data-[collapsible=icon]:overflow-x-hidden group-data-[collapsible=icon]:overflow-y-auto",
629
629
  children: groups.map((group) => /* @__PURE__ */ jsxs4(SidebarGroup, {
630
630
  children: [
631
631
  /* @__PURE__ */ jsx5(SidebarGroupLabel, {
@@ -648,7 +648,7 @@ function AppSidebar({ footer, groups, header }) {
648
648
  render,
649
649
  tooltip: item.label(),
650
650
  children: [
651
- /* @__PURE__ */ jsx5(item.icon, {}),
651
+ item.icon ? /* @__PURE__ */ jsx5(item.icon, {}) : null,
652
652
  /* @__PURE__ */ jsx5("span", {
653
653
  children: item.label()
654
654
  }),
@@ -719,15 +719,18 @@ function SidebarLayout({
719
719
  sidebarHeader,
720
720
  headerActions,
721
721
  contentClassName,
722
- fullPage = false
722
+ fullPage = false,
723
+ sidebarCollapsible = "icon",
724
+ defaultOpen = true
723
725
  }) {
724
- const [sidebarOpen, setSidebarOpen] = useAtom(sidebarOpenAtom);
726
+ const [sidebarOpen, setSidebarOpen] = useState3(() => getSidebarDefaultOpen(defaultOpen));
725
727
  return /* @__PURE__ */ jsxs4(SidebarProvider, {
726
728
  open: sidebarOpen,
727
729
  onOpenChange: setSidebarOpen,
728
730
  className: cn(fullPage && "xl:h-svh xl:min-h-0 xl:overflow-hidden"),
729
731
  children: [
730
732
  /* @__PURE__ */ jsx5(AppSidebar, {
733
+ collapsible: sidebarCollapsible,
731
734
  footer: sidebarFooter,
732
735
  groups,
733
736
  header: sidebarHeader
@@ -1,5 +1,6 @@
1
1
  import { Schema } from "effect";
2
2
  import { type ComponentPropsWithoutRef, type ForwardRefExoticComponent, type RefAttributes, type ReactNode } from "react";
3
+ import { type SidebarCollapsible } from "../components/ui/sidebar-layout.js";
3
4
  type DocsIconProps = ComponentPropsWithoutRef<"svg"> & {
4
5
  absoluteStrokeWidth?: boolean;
5
6
  size?: string | number;
@@ -710,8 +711,9 @@ export type DocsLayoutProps = {
710
711
  docs: DocsCatalog;
711
712
  headerActions?: ReactNode;
712
713
  locale: DocsLocale;
714
+ sidebarCollapsible?: SidebarCollapsible;
713
715
  };
714
- export declare const DocsLayout: ({ children, docs, headerActions, locale, }: DocsLayoutProps) => import("react").JSX.Element;
716
+ export declare const DocsLayout: ({ children, docs, headerActions, locale, sidebarCollapsible, }: DocsLayoutProps) => import("react").JSX.Element;
715
717
  export type DocsPageProps = {
716
718
  children?: ReactNode;
717
719
  docs: DocsCatalog;
package/dist/lib/docs.js CHANGED
@@ -1,10 +1,13 @@
1
1
  // ../../src/lib/docs.tsx
2
- import { Schema as Schema3 } from "effect";
2
+ import { createIsomorphicFn } from "@tanstack/react-start";
3
+ import { getCookie } from "@tanstack/react-start/server";
4
+ import { Option as Option2, Schema as Schema3 } from "effect";
5
+ import { Cookies as Cookies2 } from "effect/unstable/http";
3
6
  import {
4
7
  forwardRef,
5
8
  useDeferredValue,
6
9
  useEffect as useEffect5,
7
- useState as useState5
10
+ useState as useState6
8
11
  } from "react";
9
12
 
10
13
  // ../../src/components/ui/app-brand.tsx
@@ -385,7 +388,7 @@ var MarkdownContent = ({
385
388
  dangerouslySetInnerHTML: { __html: remainingHtml }
386
389
  }, "html-final"));
387
390
  return /* @__PURE__ */ jsx5("div", {
388
- className: cn("[&_a:hover]:text-primary [&_a]:decoration-border [&_blockquote]:border-primary/40 [&_blockquote]:bg-muted/40 [&_h2_a]:text-muted-foreground [&_h3_a]:text-muted-foreground [&_[data-inline-code]]:bg-muted text-[0.98rem] leading-7 [&_[data-markdown-table]]:overflow-x-auto [&_[data-inline-code]]:rounded [&_[data-inline-code]]:px-1.5 [&_[data-inline-code]]:py-0.5 [&_[data-inline-code]]:font-mono [&_[data-inline-code]]:text-[0.875em] [&_a]:font-medium [&_a]:underline [&_a]:decoration-1 [&_a]:underline-offset-4 [&_a]:transition-colors [&_blockquote]:rounded-r-lg [&_blockquote]:border-l-4 [&_blockquote]:px-5 [&_blockquote]:py-1 [&_h2]:mt-12 [&_h2]:scroll-mt-20 [&_h2]:border-t [&_h2]:pt-8 [&_h2]:text-2xl [&_h2]:font-bold [&_h2]:tracking-tight [&_h2_a]:ml-2 [&_h2_a]:no-underline [&_h2:first-of-type]:mt-0 [&_h2:first-of-type]:border-t-0 [&_h2:first-of-type]:pt-0 [&_h3]:mt-8 [&_h3]:scroll-mt-20 [&_h3]:text-xl [&_h3]:font-semibold [&_h3]:tracking-tight [&_h3_a]:ml-2 [&_h3_a]:no-underline [&_ol]:my-5 [&_p]:my-5 [&_table]:w-full [&_table]:text-sm [&_td]:border-b [&_td]:p-2 [&_th]:border-b [&_th]:p-2 [&_th]:text-left [&_ul]:my-5", className),
391
+ className: cn("[&_a:hover]:text-primary [&_a]:decoration-border [&_blockquote]:border-primary/40 [&_blockquote]:bg-muted/40 [&_h2_a]:text-muted-foreground [&_h3_a]:text-muted-foreground [&_[data-inline-code]]:bg-muted text-[0.98rem] leading-7 [&_[data-markdown-table]]:overflow-x-auto [&_[data-inline-code]]:rounded [&_[data-inline-code]]:px-1.5 [&_[data-inline-code]]:py-0.5 [&_[data-inline-code]]:font-mono [&_[data-inline-code]]:text-[0.875em] [&_a]:font-medium [&_a]:underline [&_a]:decoration-1 [&_a]:underline-offset-4 [&_a]:transition-colors [&_blockquote]:my-5 [&_blockquote]:rounded-r-lg [&_blockquote]:border-l-4 [&_blockquote]:px-5 [&_blockquote]:py-1 [&_h2]:mt-12 [&_h2]:scroll-mt-20 [&_h2]:border-t [&_h2]:pt-8 [&_h2]:text-2xl [&_h2]:font-bold [&_h2]:tracking-tight [&_h2_a]:ml-2 [&_h2_a]:no-underline [&_h2:first-of-type]:mt-0 [&_h2:first-of-type]:border-t-0 [&_h2:first-of-type]:pt-0 [&_h3]:mt-8 [&_h3]:scroll-mt-20 [&_h3]:text-xl [&_h3]:font-semibold [&_h3]:tracking-tight [&_h3_a]:ml-2 [&_h3_a]:no-underline [&_ol]:my-5 [&_p]:my-5 [&_table]:w-full [&_table]:text-sm [&_td]:border-b [&_td]:p-2 [&_th]:border-b [&_th]:p-2 [&_th]:text-left [&_ul]:my-5", className),
389
392
  children: content
390
393
  });
391
394
  };
@@ -1206,11 +1209,10 @@ function SearchMenu({
1206
1209
  }
1207
1210
 
1208
1211
  // ../../src/components/ui/sidebar-layout.tsx
1209
- import { useAtom } from "@effect/atom-react";
1210
- import { BrowserKeyValueStore } from "@effect/platform-browser";
1211
1212
  import { Link as Link2, Outlet, useRouterState } from "@tanstack/react-router";
1212
- import { Schema as Schema2 } from "effect";
1213
- import { Atom } from "effect/unstable/reactivity";
1213
+ import { Option, Schema as Schema2 } from "effect";
1214
+ import { Cookies } from "effect/unstable/http";
1215
+ import { useState as useState5 } from "react";
1214
1216
 
1215
1217
  // ../../src/components/ui/sidebar.tsx
1216
1218
  import * as React2 from "react";
@@ -1716,14 +1718,14 @@ function SidebarMenuButton({
1716
1718
 
1717
1719
  // ../../src/components/ui/sidebar-layout.tsx
1718
1720
  import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1719
- var sidebarStorageRuntime = Atom.runtime(BrowserKeyValueStore.layerLocalStorage);
1720
- var sidebarOpenAtom = Atom.kvs({
1721
- runtime: sidebarStorageRuntime,
1722
- key: "sidebar:open",
1723
- schema: Schema2.Boolean,
1724
- defaultValue: () => true
1721
+ var SIDEBAR_COOKIE_NAME2 = "sidebar_state";
1722
+ var SidebarOpenCookie = Schema2.Literals(["true", "false"]).annotate({
1723
+ identifier: "SidebarOpenCookie"
1725
1724
  });
1726
- function AppSidebar({ footer, groups, header }) {
1725
+ var getSidebarDefaultOpen = (defaultOpen) => {
1726
+ return Schema2.decodeUnknownOption(SidebarOpenCookie)(Cookies.parseHeader(globalThis.document?.cookie ?? "")[SIDEBAR_COOKIE_NAME2]).pipe(Option.map((value) => value === "true"), Option.getOrElse(() => defaultOpen));
1727
+ };
1728
+ function AppSidebar({ collapsible, footer, groups, header }) {
1727
1729
  const { isMobile, setOpenMobile } = useSidebar();
1728
1730
  const pathname = useRouterState({
1729
1731
  select: (state) => state.location.pathname
@@ -1733,12 +1735,13 @@ function AppSidebar({ footer, groups, header }) {
1733
1735
  setOpenMobile(false);
1734
1736
  };
1735
1737
  return /* @__PURE__ */ jsxs10(Sidebar, {
1736
- collapsible: "icon",
1738
+ collapsible,
1737
1739
  children: [
1738
1740
  header && /* @__PURE__ */ jsx13(SidebarHeader, {
1739
1741
  children: header
1740
1742
  }),
1741
1743
  /* @__PURE__ */ jsx13(SidebarContent, {
1744
+ className: "group-data-[collapsible=icon]:overflow-x-hidden group-data-[collapsible=icon]:overflow-y-auto",
1742
1745
  children: groups.map((group) => /* @__PURE__ */ jsxs10(SidebarGroup, {
1743
1746
  children: [
1744
1747
  /* @__PURE__ */ jsx13(SidebarGroupLabel, {
@@ -1761,7 +1764,7 @@ function AppSidebar({ footer, groups, header }) {
1761
1764
  render,
1762
1765
  tooltip: item.label(),
1763
1766
  children: [
1764
- /* @__PURE__ */ jsx13(item.icon, {}),
1767
+ item.icon ? /* @__PURE__ */ jsx13(item.icon, {}) : null,
1765
1768
  /* @__PURE__ */ jsx13("span", {
1766
1769
  children: item.label()
1767
1770
  }),
@@ -1793,15 +1796,18 @@ function SidebarLayout({
1793
1796
  sidebarHeader,
1794
1797
  headerActions,
1795
1798
  contentClassName,
1796
- fullPage = false
1799
+ fullPage = false,
1800
+ sidebarCollapsible = "icon",
1801
+ defaultOpen = true
1797
1802
  }) {
1798
- const [sidebarOpen, setSidebarOpen] = useAtom(sidebarOpenAtom);
1803
+ const [sidebarOpen, setSidebarOpen] = useState5(() => getSidebarDefaultOpen(defaultOpen));
1799
1804
  return /* @__PURE__ */ jsxs10(SidebarProvider, {
1800
1805
  open: sidebarOpen,
1801
1806
  onOpenChange: setSidebarOpen,
1802
1807
  className: cn(fullPage && "xl:h-svh xl:min-h-0 xl:overflow-hidden"),
1803
1808
  children: [
1804
1809
  /* @__PURE__ */ jsx13(AppSidebar, {
1810
+ collapsible: sidebarCollapsible,
1805
1811
  footer: sidebarFooter,
1806
1812
  groups,
1807
1813
  header: sidebarHeader
@@ -1944,6 +1950,12 @@ var createSeo = (defaults) => (options) => seo({
1944
1950
 
1945
1951
  // ../../src/lib/docs.tsx
1946
1952
  import { jsx as jsx14, jsxs as jsxs11, Fragment as Fragment3 } from "react/jsx-runtime";
1953
+ var SIDEBAR_COOKIE_NAME3 = "sidebar_state";
1954
+ var SidebarOpenCookie2 = Schema3.Literals(["true", "false"]).annotate({
1955
+ identifier: "SidebarOpenCookie"
1956
+ });
1957
+ var getSidebarOpenCookie = createIsomorphicFn().server(() => getCookie(SIDEBAR_COOKIE_NAME3)).client(() => Cookies2.parseHeader(globalThis.document?.cookie ?? "")[SIDEBAR_COOKIE_NAME3]);
1958
+ var getSidebarDefaultOpen2 = () => Schema3.decodeUnknownOption(SidebarOpenCookie2)(getSidebarOpenCookie()).pipe(Option2.map((value) => value === "true"), Option2.getOrElse(() => true));
1947
1959
  var makeIcon = (name, paths) => {
1948
1960
  const Icon = forwardRef(({ absoluteStrokeWidth: _absoluteStrokeWidth, size = 24, ...props }, ref) => /* @__PURE__ */ jsx14("svg", {
1949
1961
  "aria-hidden": "true",
@@ -2425,8 +2437,7 @@ var getDocsMessages = (locale, overrides) => ({
2425
2437
  ...locale.startsWith("fr") ? messages2.fr : messages2.en,
2426
2438
  ...overrides
2427
2439
  });
2428
- var EmptyIcon = forwardRef(() => null);
2429
- var iconFor = (icons, name) => name ? icons[name] ?? EmptyIcon : EmptyIcon;
2440
+ var iconFor = (icons, name) => name ? icons[name] : undefined;
2430
2441
  var DocsArticle = ({
2431
2442
  messages: messages3,
2432
2443
  page
@@ -2438,7 +2449,7 @@ var DocsArticle = ({
2438
2449
  });
2439
2450
  };
2440
2451
  var useActiveDocsHeading = (headings) => {
2441
- const [activeHeadingId, setActiveHeadingId] = useState5(headings[0]?.id);
2452
+ const [activeHeadingId, setActiveHeadingId] = useState6(headings[0]?.id);
2442
2453
  useEffect5(() => {
2443
2454
  const elements = headings.flatMap((heading) => {
2444
2455
  const element = document.getElementById(heading.id);
@@ -2550,7 +2561,7 @@ var DocsSearch = ({
2550
2561
  locale,
2551
2562
  messages: messages3
2552
2563
  }) => {
2553
- const [query, setQuery] = useState5("");
2564
+ const [query, setQuery] = useState6("");
2554
2565
  const deferredQuery = useDeferredValue(query);
2555
2566
  const results = docs.search(deferredQuery, locale);
2556
2567
  const isSearching = deferredQuery.trim().length > 0;
@@ -2588,9 +2599,10 @@ var DocsSearch = ({
2588
2599
  };
2589
2600
  if (page.icon) {
2590
2601
  const PageIcon = iconFor(docs.icons, page.icon);
2591
- item.icon = /* @__PURE__ */ jsx14(PageIcon, {
2592
- className: "size-4"
2593
- });
2602
+ if (PageIcon)
2603
+ item.icon = /* @__PURE__ */ jsx14(PageIcon, {
2604
+ className: "size-4"
2605
+ });
2594
2606
  }
2595
2607
  return item;
2596
2608
  })())
@@ -2614,7 +2626,8 @@ var DocsLayout = ({
2614
2626
  children,
2615
2627
  docs,
2616
2628
  headerActions,
2617
- locale
2629
+ locale,
2630
+ sidebarCollapsible = "icon"
2618
2631
  }) => {
2619
2632
  const { brand, resources, sidebarGroups } = docs;
2620
2633
  const resolvedMessages = docs.getMessages(locale);
@@ -2623,9 +2636,11 @@ var DocsLayout = ({
2623
2636
  items: section.pages.map((item) => {
2624
2637
  const navItem = {
2625
2638
  label: () => item.title,
2626
- href: item.path,
2627
- icon: iconFor(docs.icons, item.icon)
2639
+ href: item.path
2628
2640
  };
2641
+ const ItemIcon = iconFor(docs.icons, item.icon);
2642
+ if (ItemIcon)
2643
+ navItem.icon = ItemIcon;
2629
2644
  if (isDocsPageNew(item.createdAt)) {
2630
2645
  navItem.badge = () => resolvedMessages.newLabel;
2631
2646
  }
@@ -2639,7 +2654,6 @@ var DocsLayout = ({
2639
2654
  badge: item.badge,
2640
2655
  label: item.label,
2641
2656
  href: item.href,
2642
- icon: EmptyIcon,
2643
2657
  external: item.external
2644
2658
  }))
2645
2659
  })));
@@ -2652,14 +2666,12 @@ var DocsLayout = ({
2652
2666
  badge: item.badge,
2653
2667
  label: item.label,
2654
2668
  href: item.href,
2655
- icon: EmptyIcon,
2656
2669
  external: item.external
2657
2670
  })),
2658
2671
  ...docs.githubUrl ? [
2659
2672
  {
2660
2673
  label: () => docs.githubLabel,
2661
2674
  href: docs.githubUrl,
2662
- icon: EmptyIcon,
2663
2675
  external: true
2664
2676
  }
2665
2677
  ] : []
@@ -2667,7 +2679,9 @@ var DocsLayout = ({
2667
2679
  });
2668
2680
  }
2669
2681
  return /* @__PURE__ */ jsx14(SidebarLayout, {
2682
+ defaultOpen: getSidebarDefaultOpen2(),
2670
2683
  groups,
2684
+ sidebarCollapsible,
2671
2685
  sidebarHeader: /* @__PURE__ */ jsx14(AppBrand, {
2672
2686
  label: brand.label,
2673
2687
  subtitle: brand.subtitle(),
@@ -0,0 +1,41 @@
1
+ import { type DocsPage } from "./docs.js";
2
+ export declare const compileDocsMarkdown: (source: string) => {
3
+ codeBlocks: import("./markdown/server.js").MarkdownCodeBlock[];
4
+ html: string;
5
+ source: string;
6
+ headings: {
7
+ readonly depth: 2 | 3;
8
+ readonly id: string;
9
+ readonly title: string;
10
+ }[];
11
+ searchText: string;
12
+ };
13
+ export declare const compileMdxDocsPage: (sourceFile: string, source: string) => DocsPage;
14
+ export declare const loadMdxDocsDirectory: (root: string) => Promise<{
15
+ readonly slug: string;
16
+ readonly path: string;
17
+ readonly title: string;
18
+ readonly description: string;
19
+ readonly icon?: string | undefined;
20
+ readonly order: number;
21
+ readonly locale: string;
22
+ readonly section: string;
23
+ readonly type: "concept" | "how-to" | "reference" | "runbook" | "tutorial";
24
+ readonly createdAt?: string | undefined;
25
+ readonly updatedAt?: string | undefined;
26
+ readonly legacySlugs?: readonly string[] | undefined;
27
+ readonly tags?: readonly string[] | undefined;
28
+ readonly codeBlocks: readonly {
29
+ readonly code: string;
30
+ readonly language: string;
31
+ }[];
32
+ readonly headings: readonly {
33
+ readonly depth: 2 | 3;
34
+ readonly id: string;
35
+ readonly title: string;
36
+ }[];
37
+ readonly html: string;
38
+ readonly searchText: string;
39
+ readonly sourceFile: string;
40
+ readonly source: string;
41
+ }[]>;
@@ -0,0 +1,475 @@
1
+ // @bun
2
+ // ../../src/lib/docs.server.ts
3
+ import { Schema as Schema4 } from "effect";
4
+
5
+ // ../../src/lib/docs.tsx
6
+ import { createIsomorphicFn } from "@tanstack/react-start";
7
+ import { getCookie } from "@tanstack/react-start/server";
8
+ import { Option as Option2, Schema as Schema3 } from "effect";
9
+ import { Cookies as Cookies2 } from "effect/unstable/http";
10
+ import {
11
+ forwardRef,
12
+ useDeferredValue,
13
+ useEffect as useEffect5,
14
+ useState as useState6
15
+ } from "react";
16
+
17
+ // ../../src/components/ui/app-brand.tsx
18
+ import { Link } from "@tanstack/react-router";
19
+
20
+ // ../../src/components/ui/badge.tsx
21
+ import { mergeProps } from "@base-ui/react/merge-props";
22
+ import { useRender } from "@base-ui/react/use-render";
23
+ import { cva } from "class-variance-authority";
24
+
25
+ // ../../src/lib/utils.ts
26
+ import { clsx } from "clsx";
27
+ import { twMerge } from "tailwind-merge";
28
+
29
+ // ../../src/components/ui/badge.tsx
30
+ var badgeVariants = cva("group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!", {
31
+ variants: {
32
+ variant: {
33
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
34
+ secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
35
+ destructive: "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
36
+ outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
37
+ ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
38
+ link: "text-primary underline-offset-4 hover:underline"
39
+ }
40
+ },
41
+ defaultVariants: {
42
+ variant: "default"
43
+ }
44
+ });
45
+
46
+ // ../../src/components/ui/button.tsx
47
+ import { Button as ButtonPrimitive } from "@base-ui/react/button";
48
+ import { cva as cva2 } from "class-variance-authority";
49
+ var buttonVariants = cva2("group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
50
+ variants: {
51
+ variant: {
52
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
53
+ outline: "border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
54
+ secondary: "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
55
+ ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
56
+ destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
57
+ link: "text-primary underline-offset-4 hover:underline"
58
+ },
59
+ size: {
60
+ default: "h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
61
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
62
+ sm: "h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5",
63
+ lg: "h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
64
+ icon: "size-9",
65
+ "icon-xs": "size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3",
66
+ "icon-sm": "size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md",
67
+ "icon-lg": "size-10"
68
+ }
69
+ },
70
+ defaultVariants: {
71
+ variant: "default",
72
+ size: "default"
73
+ }
74
+ });
75
+
76
+ // ../../src/components/ui/copy-button.tsx
77
+ import { Check, Copy, TriangleAlert } from "lucide-react";
78
+ import { useEffect, useRef, useState } from "react";
79
+
80
+ // ../../src/components/ui/code-block.tsx
81
+ import { highlight } from "@tanstack/highlight";
82
+ import { createThemeCss } from "@tanstack/highlight/theme";
83
+ import { githubDarkTheme } from "@tanstack/highlight/themes/github-dark";
84
+ import { githubLightTheme } from "@tanstack/highlight/themes/github-light";
85
+ var themeCss = `${createThemeCss({
86
+ light: githubLightTheme,
87
+ dark: githubDarkTheme,
88
+ lightSelector: "[data-code-theme]",
89
+ darkSelector: ".dark [data-code-theme]",
90
+ codeBlockSelector: "[data-code-theme] pre.th-code",
91
+ lineNumbersSelector: "[data-code-theme] .th-code--line-numbers"
92
+ })}
93
+ [data-code-theme] pre.th-code {
94
+ margin: 0;
95
+ overflow: visible;
96
+ background: transparent;
97
+ font: inherit;
98
+ color: inherit;
99
+ }
100
+ [data-code-theme] pre.th-code code { font: inherit; }`;
101
+
102
+ // ../../src/components/ui/collapsible.tsx
103
+ import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible";
104
+
105
+ // ../../src/components/ui/search-menu.tsx
106
+ import { SearchIcon as SearchIcon2 } from "lucide-react";
107
+ import { useCallback, useEffect as useEffect2, useState as useState2 } from "react";
108
+
109
+ // ../../src/components/ui/command.tsx
110
+ import { Command as CommandPrimitive } from "cmdk";
111
+ import { SearchIcon } from "lucide-react";
112
+
113
+ // ../../src/components/ui/dialog.tsx
114
+ import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
115
+ import { XIcon } from "lucide-react";
116
+
117
+ // ../../src/paraglide/runtime.js
118
+ import"@inlang/paraglide-js/urlpattern-polyfill";
119
+ var isServer = import.meta.env?.SSR ?? typeof window === "undefined";
120
+ globalThis.__paraglide = globalThis.__paraglide ?? {};
121
+ globalThis.__paraglide.ssr = globalThis.__paraglide.ssr ?? {};
122
+ var rtlLanguages = new Set([
123
+ "ar",
124
+ "dv",
125
+ "fa",
126
+ "he",
127
+ "ks",
128
+ "ku",
129
+ "ps",
130
+ "sd",
131
+ "ug",
132
+ "ur",
133
+ "yi"
134
+ ]);
135
+ var customServerStrategies = new Map;
136
+ var customClientStrategies = new Map;
137
+
138
+ // ../../src/components/ui/sidebar-layout.tsx
139
+ import { Link as Link2, Outlet, useRouterState } from "@tanstack/react-router";
140
+ import { Option, Schema as Schema2 } from "effect";
141
+ import { Cookies } from "effect/unstable/http";
142
+ import { useState as useState5 } from "react";
143
+
144
+ // ../../src/components/ui/sidebar.tsx
145
+ import * as React2 from "react";
146
+ import { mergeProps as mergeProps2 } from "@base-ui/react/merge-props";
147
+ import { useRender as useRender2 } from "@base-ui/react/use-render";
148
+ import { cva as cva3 } from "class-variance-authority";
149
+
150
+ // ../../src/hooks/use-mobile.ts
151
+ import * as React from "react";
152
+
153
+ // ../../src/components/ui/input.tsx
154
+ import { Input as InputPrimitive } from "@base-ui/react/input";
155
+
156
+ // ../../src/components/ui/separator.tsx
157
+ import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
158
+
159
+ // ../../src/components/ui/sheet.tsx
160
+ import { Dialog as SheetPrimitive } from "@base-ui/react/dialog";
161
+ import { XIcon as XIcon2 } from "lucide-react";
162
+ "use client";
163
+
164
+ // ../../src/components/ui/tooltip.tsx
165
+ import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
166
+ "use client";
167
+
168
+ // ../../src/components/ui/sidebar.tsx
169
+ import { PanelLeftIcon } from "lucide-react";
170
+ import { Schema } from "effect";
171
+ var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
172
+ var SidebarContext = React2.createContext(null);
173
+ var sidebarMenuButtonVariants = cva3("peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate", {
174
+ variants: {
175
+ variant: {
176
+ default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
177
+ outline: "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]"
178
+ },
179
+ size: {
180
+ default: "h-8 text-sm",
181
+ sm: "h-7 text-xs",
182
+ lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!"
183
+ }
184
+ },
185
+ defaultVariants: {
186
+ variant: "default",
187
+ size: "default"
188
+ }
189
+ });
190
+
191
+ // ../../src/components/ui/sidebar-layout.tsx
192
+ var SidebarOpenCookie = Schema2.Literals(["true", "false"]).annotate({
193
+ identifier: "SidebarOpenCookie"
194
+ });
195
+
196
+ // ../../src/lib/docs.tsx
197
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
198
+ var SIDEBAR_COOKIE_NAME = "sidebar_state";
199
+ var SidebarOpenCookie2 = Schema3.Literals(["true", "false"]).annotate({
200
+ identifier: "SidebarOpenCookie"
201
+ });
202
+ var getSidebarOpenCookie = createIsomorphicFn().server(() => getCookie(SIDEBAR_COOKIE_NAME)).client(() => Cookies2.parseHeader(globalThis.document?.cookie ?? "")[SIDEBAR_COOKIE_NAME]);
203
+ var makeIcon = (name, paths) => {
204
+ const Icon = forwardRef(({ absoluteStrokeWidth: _absoluteStrokeWidth, size = 24, ...props }, ref) => /* @__PURE__ */ jsx("svg", {
205
+ "aria-hidden": "true",
206
+ fill: "none",
207
+ height: size,
208
+ ref,
209
+ stroke: "currentColor",
210
+ strokeLinecap: "round",
211
+ strokeLinejoin: "round",
212
+ strokeWidth: "2",
213
+ viewBox: "0 0 24 24",
214
+ width: size,
215
+ ...props,
216
+ children: paths
217
+ }));
218
+ Icon.displayName = name;
219
+ return Icon;
220
+ };
221
+ var ArrowLeft = makeIcon("ArrowLeft", /* @__PURE__ */ jsxs(Fragment, {
222
+ children: [
223
+ /* @__PURE__ */ jsx("path", {
224
+ d: "m12 19-7-7 7-7"
225
+ }),
226
+ /* @__PURE__ */ jsx("path", {
227
+ d: "M19 12H5"
228
+ })
229
+ ]
230
+ }));
231
+ var ArrowRight = makeIcon("ArrowRight", /* @__PURE__ */ jsxs(Fragment, {
232
+ children: [
233
+ /* @__PURE__ */ jsx("path", {
234
+ d: "M5 12h14"
235
+ }),
236
+ /* @__PURE__ */ jsx("path", {
237
+ d: "m12 5 7 7-7 7"
238
+ })
239
+ ]
240
+ }));
241
+ var BookOpen = makeIcon("BookOpen", /* @__PURE__ */ jsxs(Fragment, {
242
+ children: [
243
+ /* @__PURE__ */ jsx("path", {
244
+ d: "M12 7v14"
245
+ }),
246
+ /* @__PURE__ */ jsx("path", {
247
+ d: "M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-5a4 4 0 0 0-4 4 4 4 0 0 0-4-4Z"
248
+ })
249
+ ]
250
+ }));
251
+ var ChevronDown = makeIcon("ChevronDown", /* @__PURE__ */ jsx("path", {
252
+ d: "m6 9 6 6 6-6"
253
+ }));
254
+ var ExternalLink = makeIcon("ExternalLink", /* @__PURE__ */ jsxs(Fragment, {
255
+ children: [
256
+ /* @__PURE__ */ jsx("path", {
257
+ d: "M15 3h6v6"
258
+ }),
259
+ /* @__PURE__ */ jsx("path", {
260
+ d: "M10 14 21 3"
261
+ }),
262
+ /* @__PURE__ */ jsx("path", {
263
+ d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"
264
+ })
265
+ ]
266
+ }));
267
+ var Hash = makeIcon("Hash", /* @__PURE__ */ jsxs(Fragment, {
268
+ children: [
269
+ /* @__PURE__ */ jsx("line", {
270
+ x1: "4",
271
+ x2: "20",
272
+ y1: "9",
273
+ y2: "9"
274
+ }),
275
+ /* @__PURE__ */ jsx("line", {
276
+ x1: "4",
277
+ x2: "20",
278
+ y1: "15",
279
+ y2: "15"
280
+ }),
281
+ /* @__PURE__ */ jsx("line", {
282
+ x1: "10",
283
+ x2: "8",
284
+ y1: "3",
285
+ y2: "21"
286
+ }),
287
+ /* @__PURE__ */ jsx("line", {
288
+ x1: "16",
289
+ x2: "14",
290
+ y1: "3",
291
+ y2: "21"
292
+ })
293
+ ]
294
+ }));
295
+ var DocsSection = Schema3.String.annotate({
296
+ identifier: "DocsSection"
297
+ });
298
+ var DocsPageType = Schema3.Literals([
299
+ "concept",
300
+ "tutorial",
301
+ "how-to",
302
+ "reference",
303
+ "runbook"
304
+ ]).annotate({ identifier: "DocsPageType" });
305
+ var DocsDate = Schema3.String.pipe(Schema3.check(Schema3.makeFilter((date) => Number.isNaN(new Date(date).getTime()) ? "Expected a valid date" : undefined)));
306
+ var DocsFrontmatter = Schema3.Struct({
307
+ slug: Schema3.String,
308
+ path: Schema3.String,
309
+ title: Schema3.String,
310
+ description: Schema3.String,
311
+ icon: Schema3.optional(Schema3.String),
312
+ order: Schema3.Number,
313
+ locale: Schema3.String,
314
+ section: DocsSection,
315
+ type: DocsPageType,
316
+ createdAt: Schema3.optional(DocsDate),
317
+ updatedAt: Schema3.optional(DocsDate),
318
+ legacySlugs: Schema3.optional(Schema3.Array(Schema3.String)),
319
+ tags: Schema3.optional(Schema3.Array(Schema3.NonEmptyString))
320
+ }).annotate({ identifier: "DocsFrontmatter" });
321
+ var DocsHeadingSchema = Schema3.Struct({
322
+ depth: Schema3.Literals([2, 3]),
323
+ id: Schema3.String,
324
+ title: Schema3.String
325
+ }).annotate({ identifier: "DocsHeading" });
326
+ var DocsCodeBlockSchema = Schema3.Struct({
327
+ code: Schema3.String,
328
+ language: Schema3.String
329
+ }).annotate({ identifier: "DocsCodeBlock" });
330
+ var DocsPageSchema = Schema3.Struct({
331
+ ...DocsFrontmatter.fields,
332
+ codeBlocks: Schema3.Array(DocsCodeBlockSchema),
333
+ headings: Schema3.Array(DocsHeadingSchema),
334
+ html: Schema3.String,
335
+ searchText: Schema3.String,
336
+ sourceFile: Schema3.String,
337
+ source: Schema3.String
338
+ }).annotate({ identifier: "DocsPage" });
339
+
340
+ // ../../src/lib/markdown/server.ts
341
+ var escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
342
+ var decodeMarkdownCode = (value) => value.replaceAll("&quot;", '"').replaceAll("&#39;", "'").replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&amp;", "&");
343
+ var safeUrl = (value, image = false) => {
344
+ if (value.startsWith("/") || value.startsWith("#") || value.startsWith("https://") || value.startsWith("http://") || !image && value.startsWith("mailto:")) {
345
+ return value;
346
+ }
347
+ return image ? "" : "#";
348
+ };
349
+ var markdownOptions = {
350
+ autolinks: true,
351
+ headings: { ids: true },
352
+ noHtmlBlocks: true,
353
+ noHtmlSpans: true,
354
+ tagFilter: true
355
+ };
356
+ var markdownPlainText = (source, includeCode = false) => Bun.markdown.render(source, {
357
+ blockquote: (children) => `${children} `,
358
+ code: (children) => includeCode ? `${children} ` : " ",
359
+ codespan: (children) => `${children} `,
360
+ heading: (children) => `${children} `,
361
+ html: () => " ",
362
+ image: (children) => `${children} `,
363
+ list: (children) => `${children} `,
364
+ listItem: (children) => `${children} `,
365
+ paragraph: (children) => `${children} `,
366
+ table: (children) => `${children} `,
367
+ td: (children) => `${children} `,
368
+ th: (children) => `${children} `,
369
+ tr: (children) => `${children} `
370
+ }, markdownOptions).replace(/\s+/g, " ").trim();
371
+ var compileMarkdown = (source) => {
372
+ const codeBlocks = [];
373
+ const html = Bun.markdown.render(source, {
374
+ blockquote: (children) => `<blockquote>${children}</blockquote>`,
375
+ code: (children, meta) => {
376
+ const index = codeBlocks.length;
377
+ const code = decodeMarkdownCode(children.replace(/\n$/, ""));
378
+ const language = meta?.language ?? "text";
379
+ codeBlocks.push({ code, language });
380
+ return `<markdown-code-block data-index="${index}"></markdown-code-block>`;
381
+ },
382
+ codespan: (children) => `<code data-inline-code>${escapeHtml(children)}</code>`,
383
+ emphasis: (children) => `<em>${children}</em>`,
384
+ heading: (children, { id, level }) => {
385
+ const headingId = escapeHtml(id ?? "");
386
+ const anchor = level === 2 || level === 3 ? `<a href="#${headingId}" aria-hidden="true">#</a>` : "";
387
+ return `<h${level} id="${headingId}">${children}${anchor}</h${level}>`;
388
+ },
389
+ hr: () => "<hr>",
390
+ html: (children) => escapeHtml(children),
391
+ image: (children, { src, title }) => {
392
+ const resolvedSrc = safeUrl(src, true);
393
+ if (!resolvedSrc)
394
+ return children;
395
+ const titleAttribute = title ? ` title="${escapeHtml(title)}"` : "";
396
+ return `<img src="${escapeHtml(resolvedSrc)}" alt="${escapeHtml(children)}"${titleAttribute}>`;
397
+ },
398
+ link: (children, { href, title }) => {
399
+ const resolvedHref = safeUrl(href);
400
+ const external = /^https?:\/\//.test(resolvedHref);
401
+ const titleAttribute = title ? ` title="${escapeHtml(title)}"` : "";
402
+ const externalAttributes = external ? ' target="_blank" rel="noreferrer"' : "";
403
+ return `<a href="${escapeHtml(resolvedHref)}"${titleAttribute}${externalAttributes}>${children}</a>`;
404
+ },
405
+ list: (children, { ordered, start }) => ordered ? `<ol${start && start !== 1 ? ` start="${start}"` : ""}>${children}</ol>` : `<ul>${children}</ul>`,
406
+ listItem: (children, { checked }) => {
407
+ const checkbox = checked === undefined ? "" : `<input type="checkbox" disabled${checked ? " checked" : ""}>`;
408
+ return `<li>${checkbox}${children}</li>`;
409
+ },
410
+ paragraph: (children) => `<p>${children}</p>`,
411
+ strikethrough: (children) => `<del>${children}</del>`,
412
+ strong: (children) => `<strong>${children}</strong>`,
413
+ table: (children) => `<div data-markdown-table><table>${children}</table></div>`,
414
+ tbody: (children) => `<tbody>${children}</tbody>`,
415
+ td: (children, meta) => `<td${meta?.align ? ` align="${meta.align}"` : ""}>${children}</td>`,
416
+ text: escapeHtml,
417
+ th: (children, meta) => `<th${meta?.align ? ` align="${meta.align}"` : ""}>${children}</th>`,
418
+ thead: (children) => `<thead>${children}</thead>`,
419
+ tr: (children) => `<tr>${children}</tr>`
420
+ }, markdownOptions);
421
+ return { codeBlocks, html, source };
422
+ };
423
+
424
+ // ../../src/lib/docs.server.ts
425
+ var compileDocsMarkdown = (source) => {
426
+ const headings = [];
427
+ const seen = new Set;
428
+ Bun.markdown.render(source, {
429
+ heading: (children, { id, level }) => {
430
+ if ((level === 2 || level === 3) && id) {
431
+ if (seen.has(id))
432
+ throw new Error(`Duplicate heading ${id}`);
433
+ seen.add(id);
434
+ headings.push({ depth: level, id, title: children });
435
+ }
436
+ return "";
437
+ }
438
+ }, markdownOptions);
439
+ const compiled = compileMarkdown(source);
440
+ return {
441
+ ...compiled,
442
+ headings,
443
+ searchText: markdownPlainText(source)
444
+ };
445
+ };
446
+ var compileMdxDocsPage = (sourceFile, source) => {
447
+ const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/.exec(source);
448
+ if (!match)
449
+ throw new Error(`Missing frontmatter in ${sourceFile}`);
450
+ const frontmatter = Schema4.decodeUnknownSync(DocsFrontmatter)(Bun.YAML.parse(match[1] ?? ""));
451
+ const bodySource = match[2] ?? "";
452
+ const title = /^#\s+(.+?)\s*$/m.exec(bodySource)?.[1];
453
+ if (!title || markdownPlainText(title, true) !== markdownPlainText(frontmatter.title, true)) {
454
+ throw new Error(`Body title does not match frontmatter in ${sourceFile}`);
455
+ }
456
+ const body = bodySource.replace(/^\s*#\s+.+?\r?\n+/, "");
457
+ return Schema4.decodeUnknownSync(DocsPageSchema)({
458
+ ...frontmatter,
459
+ ...compileDocsMarkdown(body),
460
+ sourceFile
461
+ });
462
+ };
463
+ var loadMdxDocsDirectory = async (root) => {
464
+ const glob = new Bun.Glob("**/*.mdx");
465
+ const pages = [];
466
+ for await (const file of glob.scan({ cwd: root, onlyFiles: true })) {
467
+ pages.push(compileMdxDocsPage(`${root}/${file}`, await Bun.file(`${root}/${file}`).text()));
468
+ }
469
+ return pages;
470
+ };
471
+ export {
472
+ compileDocsMarkdown,
473
+ compileMdxDocsPage,
474
+ loadMdxDocsDirectory
475
+ };
@@ -3,12 +3,15 @@ import { Effect, Schema as Schema4 } from "effect";
3
3
  import { Tool, Toolkit } from "effect/unstable/ai";
4
4
 
5
5
  // ../../src/lib/docs.tsx
6
- import { Schema as Schema3 } from "effect";
6
+ import { createIsomorphicFn } from "@tanstack/react-start";
7
+ import { getCookie } from "@tanstack/react-start/server";
8
+ import { Option as Option2, Schema as Schema3 } from "effect";
9
+ import { Cookies as Cookies2 } from "effect/unstable/http";
7
10
  import {
8
11
  forwardRef,
9
12
  useDeferredValue,
10
13
  useEffect as useEffect5,
11
- useState as useState5
14
+ useState as useState6
12
15
  } from "react";
13
16
 
14
17
  // ../../src/components/ui/app-brand.tsx
@@ -133,11 +136,10 @@ var customServerStrategies = new Map;
133
136
  var customClientStrategies = new Map;
134
137
 
135
138
  // ../../src/components/ui/sidebar-layout.tsx
136
- import { useAtom } from "@effect/atom-react";
137
- import { BrowserKeyValueStore } from "@effect/platform-browser";
138
139
  import { Link as Link2, Outlet, useRouterState } from "@tanstack/react-router";
139
- import { Schema as Schema2 } from "effect";
140
- import { Atom } from "effect/unstable/reactivity";
140
+ import { Option, Schema as Schema2 } from "effect";
141
+ import { Cookies } from "effect/unstable/http";
142
+ import { useState as useState5 } from "react";
141
143
 
142
144
  // ../../src/components/ui/sidebar.tsx
143
145
  import * as React2 from "react";
@@ -187,16 +189,17 @@ var sidebarMenuButtonVariants = cva3("peer/menu-button group/menu-button flex w-
187
189
  });
188
190
 
189
191
  // ../../src/components/ui/sidebar-layout.tsx
190
- var sidebarStorageRuntime = Atom.runtime(BrowserKeyValueStore.layerLocalStorage);
191
- var sidebarOpenAtom = Atom.kvs({
192
- runtime: sidebarStorageRuntime,
193
- key: "sidebar:open",
194
- schema: Schema2.Boolean,
195
- defaultValue: () => true
192
+ var SidebarOpenCookie = Schema2.Literals(["true", "false"]).annotate({
193
+ identifier: "SidebarOpenCookie"
196
194
  });
197
195
 
198
196
  // ../../src/lib/docs.tsx
199
197
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
198
+ var SIDEBAR_COOKIE_NAME = "sidebar_state";
199
+ var SidebarOpenCookie2 = Schema3.Literals(["true", "false"]).annotate({
200
+ identifier: "SidebarOpenCookie"
201
+ });
202
+ var getSidebarOpenCookie = createIsomorphicFn().server(() => getCookie(SIDEBAR_COOKIE_NAME)).client(() => Cookies2.parseHeader(globalThis.document?.cookie ?? "")[SIDEBAR_COOKIE_NAME]);
200
203
  var makeIcon = (name, paths) => {
201
204
  const Icon = forwardRef(({ absoluteStrokeWidth: _absoluteStrokeWidth, size = 24, ...props }, ref) => /* @__PURE__ */ jsx("svg", {
202
205
  "aria-hidden": "true",
@@ -333,7 +336,6 @@ var DocsPageSchema = Schema3.Struct({
333
336
  sourceFile: Schema3.String,
334
337
  source: Schema3.String
335
338
  }).annotate({ identifier: "DocsPage" });
336
- var EmptyIcon = forwardRef(() => null);
337
339
 
338
340
  // ../../src/lib/documentation-toolkit.ts
339
341
  var SearchDocumentation = Tool.make("searchDocumentation", {
@@ -390,7 +390,7 @@ var MarkdownContent = ({
390
390
  dangerouslySetInnerHTML: { __html: remainingHtml }
391
391
  }, "html-final"));
392
392
  return /* @__PURE__ */ jsx4("div", {
393
- className: cn("[&_a:hover]:text-primary [&_a]:decoration-border [&_blockquote]:border-primary/40 [&_blockquote]:bg-muted/40 [&_h2_a]:text-muted-foreground [&_h3_a]:text-muted-foreground [&_[data-inline-code]]:bg-muted text-[0.98rem] leading-7 [&_[data-markdown-table]]:overflow-x-auto [&_[data-inline-code]]:rounded [&_[data-inline-code]]:px-1.5 [&_[data-inline-code]]:py-0.5 [&_[data-inline-code]]:font-mono [&_[data-inline-code]]:text-[0.875em] [&_a]:font-medium [&_a]:underline [&_a]:decoration-1 [&_a]:underline-offset-4 [&_a]:transition-colors [&_blockquote]:rounded-r-lg [&_blockquote]:border-l-4 [&_blockquote]:px-5 [&_blockquote]:py-1 [&_h2]:mt-12 [&_h2]:scroll-mt-20 [&_h2]:border-t [&_h2]:pt-8 [&_h2]:text-2xl [&_h2]:font-bold [&_h2]:tracking-tight [&_h2_a]:ml-2 [&_h2_a]:no-underline [&_h2:first-of-type]:mt-0 [&_h2:first-of-type]:border-t-0 [&_h2:first-of-type]:pt-0 [&_h3]:mt-8 [&_h3]:scroll-mt-20 [&_h3]:text-xl [&_h3]:font-semibold [&_h3]:tracking-tight [&_h3_a]:ml-2 [&_h3_a]:no-underline [&_ol]:my-5 [&_p]:my-5 [&_table]:w-full [&_table]:text-sm [&_td]:border-b [&_td]:p-2 [&_th]:border-b [&_th]:p-2 [&_th]:text-left [&_ul]:my-5", className),
393
+ className: cn("[&_a:hover]:text-primary [&_a]:decoration-border [&_blockquote]:border-primary/40 [&_blockquote]:bg-muted/40 [&_h2_a]:text-muted-foreground [&_h3_a]:text-muted-foreground [&_[data-inline-code]]:bg-muted text-[0.98rem] leading-7 [&_[data-markdown-table]]:overflow-x-auto [&_[data-inline-code]]:rounded [&_[data-inline-code]]:px-1.5 [&_[data-inline-code]]:py-0.5 [&_[data-inline-code]]:font-mono [&_[data-inline-code]]:text-[0.875em] [&_a]:font-medium [&_a]:underline [&_a]:decoration-1 [&_a]:underline-offset-4 [&_a]:transition-colors [&_blockquote]:my-5 [&_blockquote]:rounded-r-lg [&_blockquote]:border-l-4 [&_blockquote]:px-5 [&_blockquote]:py-1 [&_h2]:mt-12 [&_h2]:scroll-mt-20 [&_h2]:border-t [&_h2]:pt-8 [&_h2]:text-2xl [&_h2]:font-bold [&_h2]:tracking-tight [&_h2_a]:ml-2 [&_h2_a]:no-underline [&_h2:first-of-type]:mt-0 [&_h2:first-of-type]:border-t-0 [&_h2:first-of-type]:pt-0 [&_h3]:mt-8 [&_h3]:scroll-mt-20 [&_h3]:text-xl [&_h3]:font-semibold [&_h3]:tracking-tight [&_h3_a]:ml-2 [&_h3_a]:no-underline [&_ol]:my-5 [&_p]:my-5 [&_table]:w-full [&_table]:text-sm [&_td]:border-b [&_td]:p-2 [&_th]:border-b [&_th]:p-2 [&_th]:text-left [&_ul]:my-5", className),
394
394
  children: content
395
395
  });
396
396
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krak-stack/registry",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "description": "Tree-shakable KrakStack components and Effect services.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -52,6 +52,10 @@
52
52
  "types": "./dist/lib/docs.d.ts",
53
53
  "import": "./dist/lib/docs.js"
54
54
  },
55
+ "./docs/server": {
56
+ "types": "./dist/lib/docs.server.d.ts",
57
+ "import": "./dist/lib/docs.server.js"
58
+ },
55
59
  "./documentation-toolkit": {
56
60
  "types": "./dist/lib/documentation-toolkit.d.ts",
57
61
  "import": "./dist/lib/documentation-toolkit.js"