ardo 3.1.0 → 3.2.1

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 (123) hide show
  1. package/README.md +9 -19
  2. package/dist/DocPage-CIBiCAxZ.js +1010 -0
  3. package/dist/DocPage-CIBiCAxZ.js.map +1 -0
  4. package/dist/assets/src/ui/Breadcrumb.css.ts.vanilla-Dpgq-C_p.css +20 -0
  5. package/dist/assets/src/ui/DocPage.css.ts.vanilla-CXKuz4U-.css +34 -0
  6. package/dist/assets/src/ui/Footer.css.ts.vanilla-BSzPIPt4.css +100 -0
  7. package/dist/assets/src/ui/Header.css.ts.vanilla-8QL0Jzgk.css +156 -0
  8. package/dist/assets/src/ui/Layout.css.ts.vanilla-Bpx_-gJt.css +67 -0
  9. package/dist/assets/src/ui/Nav.css.ts.vanilla-CsAQjogy.css +51 -0
  10. package/dist/assets/src/ui/Sidebar.css.ts.vanilla-D70qXTEr.css +115 -0
  11. package/dist/assets/src/ui/Toc.css.ts.vanilla-CYqcWgvD.css +52 -0
  12. package/dist/assets/src/ui/components/ApiItem.css.ts.vanilla-B_DW-1iJ.css +218 -0
  13. package/dist/assets/src/ui/components/CodeBlock.css.ts.vanilla-lNKqskjQ.css +182 -0
  14. package/dist/assets/src/ui/components/Container.css.ts.vanilla-CUhRUA9t.css +80 -0
  15. package/dist/assets/src/ui/components/CopyButton.css.ts.vanilla-DZZ5jgTM.css +24 -0
  16. package/dist/assets/src/ui/components/Features.css.ts.vanilla-D-pNXM9Q.css +129 -0
  17. package/dist/assets/src/ui/components/Hero.css.ts.vanilla-DHJVZ6GX.css +134 -0
  18. package/dist/assets/src/ui/components/Search.css.ts.vanilla-BYpWHzky.css +135 -0
  19. package/dist/assets/src/ui/components/Steps.css.ts.vanilla-CisaxeNj.css +59 -0
  20. package/dist/assets/src/ui/components/Tabs.css.ts.vanilla-C4-vJSnf.css +30 -0
  21. package/dist/assets/src/ui/components/ThemeToggle.css.ts.vanilla---sSUELC.css +22 -0
  22. package/dist/assets/src/ui/content.css.ts.vanilla-O_RaSPXm.css +106 -0
  23. package/dist/assets/src/ui/theme/animations.css.ts.vanilla-D6ImVUKy.css +10 -0
  24. package/dist/assets/src/ui/theme/dark.css.ts.vanilla-2iJgcpbU.css +87 -0
  25. package/dist/assets/src/ui/theme/light.css.ts.vanilla-CwinfWSf.css +87 -0
  26. package/dist/assets/src/ui/theme/reset.css.ts.vanilla-0Q3pLjfC.css +34 -0
  27. package/dist/brand-icons-DLJKqTun.js +59 -0
  28. package/dist/brand-icons-DLJKqTun.js.map +1 -0
  29. package/dist/config/index.d.ts +5 -5
  30. package/dist/config/index.d.ts.map +1 -0
  31. package/dist/config/index.js +54 -11
  32. package/dist/config/index.js.map +1 -1
  33. package/dist/contract.css-DYvFVCFE.d.ts +105 -0
  34. package/dist/contract.css-DYvFVCFE.d.ts.map +1 -0
  35. package/dist/generator-DPtRXxM_.js +1194 -0
  36. package/dist/generator-DPtRXxM_.js.map +1 -0
  37. package/dist/icons/index.d.ts +22 -1
  38. package/dist/icons/index.d.ts.map +1 -0
  39. package/dist/icons/index.js +2 -2
  40. package/dist/index-BTeHvysI.d.ts +807 -0
  41. package/dist/index-BTeHvysI.d.ts.map +1 -0
  42. package/dist/index-DySzkJlC.d.ts +78 -0
  43. package/dist/index-DySzkJlC.d.ts.map +1 -0
  44. package/dist/index.d.ts +5 -8
  45. package/dist/index.js +6 -100
  46. package/dist/mdx/provider.d.ts +61 -4
  47. package/dist/mdx/provider.d.ts.map +1 -0
  48. package/dist/mdx/provider.js +89 -117
  49. package/dist/mdx/provider.js.map +1 -1
  50. package/dist/runtime/index.d.ts +2 -41
  51. package/dist/runtime/index.js +2 -28
  52. package/dist/sidebar-utils-1Skqle1Q.js +109 -0
  53. package/dist/sidebar-utils-1Skqle1Q.js.map +1 -0
  54. package/dist/theme/index.d.ts +201 -182
  55. package/dist/theme/index.d.ts.map +1 -0
  56. package/dist/theme/index.js +288 -128
  57. package/dist/theme/index.js.map +1 -1
  58. package/dist/typedoc/components/index.d.ts +55 -0
  59. package/dist/typedoc/components/index.d.ts.map +1 -0
  60. package/dist/typedoc/components/index.js +339 -0
  61. package/dist/typedoc/components/index.js.map +1 -0
  62. package/dist/typedoc/index.d.ts +36 -305
  63. package/dist/typedoc/index.d.ts.map +1 -0
  64. package/dist/typedoc/index.js +97 -268
  65. package/dist/typedoc/index.js.map +1 -1
  66. package/dist/types-BCuJBsJu.d.ts +182 -0
  67. package/dist/types-BCuJBsJu.d.ts.map +1 -0
  68. package/dist/types-CTd_mkrv.d.ts +175 -0
  69. package/dist/types-CTd_mkrv.d.ts.map +1 -0
  70. package/dist/ui/index.d.ts +2 -178
  71. package/dist/ui/index.js +3 -95
  72. package/dist/ui/styles.css +1401 -1335
  73. package/dist/ui/styles.d.ts +1 -2
  74. package/dist/ui/styles.js +23 -4
  75. package/dist/ui-3grzJSsq.js +1314 -0
  76. package/dist/ui-3grzJSsq.js.map +1 -0
  77. package/dist/vite/index.d.ts +78 -86
  78. package/dist/vite/index.d.ts.map +1 -0
  79. package/dist/vite/index.js +2931 -1282
  80. package/dist/vite/index.js.map +1 -1
  81. package/package.json +30 -19
  82. package/dist/Features-D_Pt7zpA.d.ts +0 -615
  83. package/dist/Search-DOJMNI2T.css +0 -193
  84. package/dist/Search-DOJMNI2T.css.map +0 -1
  85. package/dist/Search-VYYG3D43.js +0 -10
  86. package/dist/Search-VYYG3D43.js.map +0 -1
  87. package/dist/chunk-4YQE3TNM.js +0 -1
  88. package/dist/chunk-4YQE3TNM.js.map +0 -1
  89. package/dist/chunk-AXLJDGQL.js +0 -1
  90. package/dist/chunk-AXLJDGQL.js.map +0 -1
  91. package/dist/chunk-CZM5NX27.js +0 -909
  92. package/dist/chunk-CZM5NX27.js.map +0 -1
  93. package/dist/chunk-FZP2AVJL.js +0 -43
  94. package/dist/chunk-FZP2AVJL.js.map +0 -1
  95. package/dist/chunk-IEPSORG5.js +0 -444
  96. package/dist/chunk-IEPSORG5.js.map +0 -1
  97. package/dist/chunk-KUWEUO37.js +0 -1
  98. package/dist/chunk-KUWEUO37.js.map +0 -1
  99. package/dist/chunk-NBRHGTR2.js +0 -79
  100. package/dist/chunk-NBRHGTR2.js.map +0 -1
  101. package/dist/chunk-PGHUPTGL.js +0 -1035
  102. package/dist/chunk-PGHUPTGL.js.map +0 -1
  103. package/dist/chunk-PMS3P4MA.js +0 -43
  104. package/dist/chunk-PMS3P4MA.js.map +0 -1
  105. package/dist/chunk-QELSOHIY.js +0 -46
  106. package/dist/chunk-QELSOHIY.js.map +0 -1
  107. package/dist/chunk-R2QKY6G3.js +0 -1
  108. package/dist/chunk-R2QKY6G3.js.map +0 -1
  109. package/dist/chunk-ZPYQQZ7J.js +0 -210
  110. package/dist/chunk-ZPYQQZ7J.js.map +0 -1
  111. package/dist/icons/index.js.map +0 -1
  112. package/dist/index.css +0 -1290
  113. package/dist/index.css.map +0 -1
  114. package/dist/index.js.map +0 -1
  115. package/dist/mdx/provider.css +0 -403
  116. package/dist/mdx/provider.css.map +0 -1
  117. package/dist/runtime/index.js.map +0 -1
  118. package/dist/types-CLkHwCch.d.ts +0 -248
  119. package/dist/ui/index.css +0 -1290
  120. package/dist/ui/index.css.map +0 -1
  121. package/dist/ui/index.js.map +0 -1
  122. package/dist/ui/styles.css.map +0 -1
  123. package/dist/ui/styles.js.map +0 -1
@@ -0,0 +1,1314 @@
1
+ import { a as ArdoProvider, l as useArdoPageData, o as ArdoSiteConfigProvider, s as useArdoConfig, u as useArdoSidebar } from "./sidebar-utils-1Skqle1Q.js";
2
+ import { c as TwitterIcon, i as LinkedinIcon, n as GithubIcon, o as NpmIcon, u as YoutubeIcon } from "./brand-icons-DLJKqTun.js";
3
+ import { A as home, F as footerContainer, G as SearchIcon, H as MessageCircleIcon, K as SunIcon, L as footerLink, M as layout, O as ArdoLayout, U as MonitorIcon, V as ChevronDownIcon, W as MoonIcon, j as homeMain, q as XIcon, z as footerPrimary } from "./DocPage-CIBiCAxZ.js";
4
+ import React, { Children, cloneElement, createContext, isValidElement, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+ import { Link, NavLink, Outlet, useLocation, useNavigate } from "react-router";
7
+ import MiniSearch from "minisearch";
8
+ import searchDocs from "virtual:ardo/search-index";
9
+ import "./assets/src/ui/components/Search.css.ts.vanilla-BYpWHzky.css";
10
+ import { createPortal } from "react-dom";
11
+ import "./assets/src/ui/components/ThemeToggle.css.ts.vanilla---sSUELC.css";
12
+ import "./assets/src/ui/Header.css.ts.vanilla-8QL0Jzgk.css";
13
+ import "./assets/src/ui/Nav.css.ts.vanilla-CsAQjogy.css";
14
+ import "./assets/src/ui/Sidebar.css.ts.vanilla-D70qXTEr.css";
15
+ import "./assets/src/ui/theme/animations.css.ts.vanilla-D6ImVUKy.css";
16
+ import "./assets/src/ui/components/Features.css.ts.vanilla-D-pNXM9Q.css";
17
+ import "./assets/src/ui/components/Hero.css.ts.vanilla-DHJVZ6GX.css";
18
+ //#region src/ui/components/Search.css.ts
19
+ var search = "wxcdiv0";
20
+ var searchField = "wxcdiv1";
21
+ var searchFooter = "wxcdiv9";
22
+ var searchInput = "wxcdiv2";
23
+ var searchKbd = "wxcdivb";
24
+ var searchNoResults = "wxcdiv8";
25
+ var searchPopover = "wxcdiv3";
26
+ var searchResult = "wxcdiv5";
27
+ var searchResultTitle = "wxcdiv6";
28
+ var searchResults = "wxcdiv4";
29
+ //#endregion
30
+ //#region src/ui/components/SearchPopover.tsx
31
+ /**
32
+ * Renders the search popover as a portal attached to document.body.
33
+ * Uses getBoundingClientRect to position it below the anchor element.
34
+ */
35
+ function SearchPopover({ anchorRef, children }) {
36
+ const [pos, setPos] = useState({
37
+ top: 0,
38
+ left: 0,
39
+ width: 0
40
+ });
41
+ useLayoutEffect(() => {
42
+ const el = anchorRef.current;
43
+ if (!el) return;
44
+ const rect = el.getBoundingClientRect();
45
+ setPos({
46
+ top: rect.bottom + 8,
47
+ left: rect.left,
48
+ width: Math.max(rect.width, 400)
49
+ });
50
+ }, [anchorRef]);
51
+ if (typeof document === "undefined") return null;
52
+ return createPortal(/* @__PURE__ */ jsx("div", {
53
+ className: searchPopover,
54
+ style: {
55
+ top: pos.top,
56
+ left: pos.left,
57
+ width: Math.min(pos.width, globalThis.innerWidth - 32)
58
+ },
59
+ children
60
+ }), document.body);
61
+ }
62
+ //#endregion
63
+ //#region src/ui/components/Search.tsx
64
+ function useGlobalSearchShortcut(inputRef, setIsOpen) {
65
+ useEffect(() => {
66
+ const handleGlobalKeyDown = (e) => {
67
+ if ((e.metaKey || e.ctrlKey) && e.key === "k") {
68
+ e.preventDefault();
69
+ inputRef.current?.focus();
70
+ setIsOpen(true);
71
+ }
72
+ if (e.key === "Escape") setIsOpen(false);
73
+ };
74
+ document.addEventListener("keydown", handleGlobalKeyDown);
75
+ return () => {
76
+ document.removeEventListener("keydown", handleGlobalKeyDown);
77
+ };
78
+ }, [inputRef, setIsOpen]);
79
+ }
80
+ function useOutsideClick({ containerRef, popoverClass, isOpen, setIsOpen }) {
81
+ useEffect(() => {
82
+ if (!isOpen) return;
83
+ const handleOutsideClick = (e) => {
84
+ if (!(e.target instanceof Element)) return;
85
+ const target = e.target;
86
+ const inContainer = containerRef.current?.contains(target) === true;
87
+ const inPopover = target.closest(`.${popoverClass}`) != null;
88
+ if (!inContainer && !inPopover) setIsOpen(false);
89
+ };
90
+ document.addEventListener("mousedown", handleOutsideClick);
91
+ document.addEventListener("touchstart", handleOutsideClick);
92
+ return () => {
93
+ document.removeEventListener("mousedown", handleOutsideClick);
94
+ document.removeEventListener("touchstart", handleOutsideClick);
95
+ };
96
+ }, [
97
+ containerRef,
98
+ popoverClass,
99
+ isOpen,
100
+ setIsOpen
101
+ ]);
102
+ }
103
+ function useSearchIndex() {
104
+ return useMemo(() => {
105
+ const index = new MiniSearch({
106
+ fields: [
107
+ "title",
108
+ "content",
109
+ "section"
110
+ ],
111
+ storeFields: [
112
+ "title",
113
+ "path",
114
+ "section"
115
+ ],
116
+ searchOptions: {
117
+ boost: { title: 2 },
118
+ fuzzy: .2,
119
+ prefix: true
120
+ }
121
+ });
122
+ index.addAll(searchDocs);
123
+ return index;
124
+ }, []);
125
+ }
126
+ function normalizeResults(rawResults) {
127
+ return rawResults.flatMap((result) => {
128
+ const resultPath = typeof result.path === "string" ? result.path : void 0;
129
+ const title = typeof result.title === "string" ? result.title : void 0;
130
+ if (resultPath === void 0 || title === void 0) return [];
131
+ return [{
132
+ id: String(result.id),
133
+ title,
134
+ path: resultPath,
135
+ section: typeof result.section === "string" ? result.section : void 0
136
+ }];
137
+ });
138
+ }
139
+ function SearchResults({ results, selectedIndex, query, onClose }) {
140
+ return /* @__PURE__ */ jsxs(Fragment, { children: [results.length > 0 ? /* @__PURE__ */ jsx("ul", {
141
+ className: searchResults,
142
+ children: results.map((result, index) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(Link, {
143
+ to: result.path,
144
+ className: [searchResult, index === selectedIndex && "selected"].filter(Boolean).join(" "),
145
+ onClick: onClose,
146
+ children: [/* @__PURE__ */ jsx("span", {
147
+ className: searchResultTitle,
148
+ children: result.title
149
+ }), result.section !== void 0 && /* @__PURE__ */ jsx("span", {
150
+ className: "wxcdiv7",
151
+ children: result.section
152
+ })]
153
+ }) }, result.id))
154
+ }) : /* @__PURE__ */ jsxs("div", {
155
+ className: searchNoResults,
156
+ children: [
157
+ "No results found for \"",
158
+ query,
159
+ "\""
160
+ ]
161
+ }), /* @__PURE__ */ jsxs("div", {
162
+ className: searchFooter,
163
+ children: [
164
+ /* @__PURE__ */ jsxs("span", { children: [
165
+ /* @__PURE__ */ jsx("kbd", { children: "↑" }),
166
+ " ",
167
+ /* @__PURE__ */ jsx("kbd", { children: "↓" }),
168
+ " to navigate"
169
+ ] }),
170
+ /* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("kbd", { children: "↵" }), " to select"] }),
171
+ /* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("kbd", { children: "esc" }), " to close"] })
172
+ ]
173
+ })] });
174
+ }
175
+ function useSearch(searchIndex) {
176
+ const [isOpen, setIsOpen] = useState(false);
177
+ const [query, setQuery] = useState("");
178
+ const [results, setResults] = useState([]);
179
+ const [selectedIndex, setSelectedIndex] = useState(0);
180
+ const search = (searchQuery) => {
181
+ setQuery(searchQuery);
182
+ if (!searchQuery.trim()) {
183
+ setResults([]);
184
+ setIsOpen(false);
185
+ setSelectedIndex(0);
186
+ return;
187
+ }
188
+ setResults(normalizeResults(searchIndex.search(searchQuery).slice(0, 10)));
189
+ setSelectedIndex(0);
190
+ setIsOpen(true);
191
+ };
192
+ return {
193
+ isOpen,
194
+ setIsOpen,
195
+ query,
196
+ results,
197
+ selectedIndex,
198
+ setSelectedIndex,
199
+ search
200
+ };
201
+ }
202
+ function SearchInput({ inputRef, placeholder, query, hasQuery, onSearch, onKeyDown, onFocus }) {
203
+ return /* @__PURE__ */ jsxs("div", {
204
+ className: searchField,
205
+ children: [
206
+ /* @__PURE__ */ jsx(SearchIcon, { size: 18 }),
207
+ /* @__PURE__ */ jsx("input", {
208
+ ref: inputRef,
209
+ type: "text",
210
+ className: searchInput,
211
+ placeholder,
212
+ value: query,
213
+ onChange: (e) => {
214
+ onSearch(e.target.value);
215
+ },
216
+ onKeyDown,
217
+ onFocus,
218
+ "aria-label": "Search"
219
+ }),
220
+ hasQuery && /* @__PURE__ */ jsx("button", {
221
+ type: "button",
222
+ className: "wxcdiva",
223
+ onClick: (e) => {
224
+ e.stopPropagation();
225
+ onSearch("");
226
+ inputRef.current?.focus();
227
+ },
228
+ "aria-label": "Clear search",
229
+ children: "×"
230
+ }),
231
+ /* @__PURE__ */ jsxs("span", {
232
+ className: searchKbd,
233
+ children: [/* @__PURE__ */ jsx("kbd", { children: "⌘" }), /* @__PURE__ */ jsx("kbd", { children: "K" })]
234
+ })
235
+ ]
236
+ });
237
+ }
238
+ function ArdoSearch({ placeholder = "Search..." }) {
239
+ const navigate = useNavigate();
240
+ const containerRef = useRef(null);
241
+ const inputRef = useRef(null);
242
+ const state = useSearch(useSearchIndex());
243
+ const hasQuery = state.query.trim().length > 0;
244
+ useGlobalSearchShortcut(inputRef, state.setIsOpen);
245
+ useOutsideClick({
246
+ containerRef,
247
+ popoverClass: searchPopover,
248
+ isOpen: state.isOpen,
249
+ setIsOpen: state.setIsOpen
250
+ });
251
+ const handleKeyDown = (e) => {
252
+ switch (e.key) {
253
+ case "ArrowDown":
254
+ if (state.results.length > 0) {
255
+ e.preventDefault();
256
+ state.setSelectedIndex((p) => Math.min(p + 1, state.results.length - 1));
257
+ }
258
+ break;
259
+ case "ArrowUp":
260
+ if (state.results.length > 0) {
261
+ e.preventDefault();
262
+ state.setSelectedIndex((p) => Math.max(p - 1, 0));
263
+ }
264
+ break;
265
+ case "Enter": {
266
+ const p = state.results[state.selectedIndex]?.path;
267
+ if (typeof p === "string") {
268
+ e.preventDefault();
269
+ navigate(p);
270
+ state.setIsOpen(false);
271
+ }
272
+ break;
273
+ }
274
+ case "Escape":
275
+ state.setIsOpen(false);
276
+ inputRef.current?.blur();
277
+ break;
278
+ default: break;
279
+ }
280
+ };
281
+ return /* @__PURE__ */ jsxs("div", {
282
+ className: search,
283
+ ref: containerRef,
284
+ "data-expanded": state.isOpen || hasQuery ? "true" : "false",
285
+ onMouseDown: () => inputRef.current?.focus(),
286
+ children: [/* @__PURE__ */ jsx(SearchInput, {
287
+ inputRef,
288
+ placeholder,
289
+ query: state.query,
290
+ hasQuery,
291
+ onSearch: state.search,
292
+ onKeyDown: handleKeyDown,
293
+ onFocus: () => {
294
+ if (hasQuery) state.setIsOpen(true);
295
+ }
296
+ }), state.isOpen && hasQuery && /* @__PURE__ */ jsx(SearchPopover, {
297
+ anchorRef: containerRef,
298
+ children: /* @__PURE__ */ jsx(SearchResults, {
299
+ results: state.results,
300
+ selectedIndex: state.selectedIndex,
301
+ query: state.query,
302
+ onClose: () => {
303
+ state.setIsOpen(false);
304
+ }
305
+ })
306
+ })]
307
+ });
308
+ }
309
+ //#endregion
310
+ //#region src/ui/Footer.tsx
311
+ function formatBuildTime(iso) {
312
+ try {
313
+ return new Date(iso).toLocaleDateString("en-US", {
314
+ month: "long",
315
+ day: "numeric",
316
+ year: "numeric"
317
+ });
318
+ } catch {
319
+ return iso;
320
+ }
321
+ }
322
+ /**
323
+ * Footer component with structured layout for project info, sponsor, and build metadata.
324
+ *
325
+ * Automatically pulls data from Ardo context (`config.project`, `config.buildTime`,
326
+ * `config.buildHash`). Props serve as overrides.
327
+ *
328
+ * When `children` is provided, all automatic rendering is skipped.
329
+ *
330
+ * @example Automatic (zero-config)
331
+ * ```tsx
332
+ * <Footer />
333
+ * ```
334
+ *
335
+ * @example With overrides
336
+ * ```tsx
337
+ * <Footer
338
+ * sponsor={{ text: "Sebastian Software", link: "https://sebastian-software.com/oss" }}
339
+ * message="Released under the MIT License."
340
+ * copyright="Copyright 2026 Sebastian Software GmbH"
341
+ * />
342
+ * ```
343
+ *
344
+ * @example Custom content
345
+ * ```tsx
346
+ * <Footer>
347
+ * <CustomFooterContent />
348
+ * </Footer>
349
+ * ```
350
+ */
351
+ function FooterProjectLink({ project, config }) {
352
+ const resolved = project ?? config.project;
353
+ const name = resolved?.name ?? "";
354
+ const version = resolved?.version ?? "";
355
+ const homepage = resolved?.homepage ?? "";
356
+ if (name === "") return null;
357
+ const label = version !== "" ? `${name} v${version}` : name;
358
+ return homepage !== "" ? /* @__PURE__ */ jsx("a", {
359
+ href: homepage,
360
+ className: footerLink,
361
+ children: label
362
+ }) : /* @__PURE__ */ jsx("span", { children: label });
363
+ }
364
+ function FooterSponsorLink({ sponsor }) {
365
+ const text = sponsor?.text ?? "";
366
+ const link = sponsor?.link ?? "";
367
+ if (text === "" || link === "") return null;
368
+ return /* @__PURE__ */ jsxs("a", {
369
+ href: link,
370
+ className: footerLink,
371
+ children: ["Sponsored by ", text]
372
+ });
373
+ }
374
+ function FooterPrimaryLine({ project, sponsor, ardoLink, config }) {
375
+ const items = [];
376
+ const projectNode = /* @__PURE__ */ jsx(FooterProjectLink, {
377
+ project,
378
+ config
379
+ });
380
+ const sponsorNode = /* @__PURE__ */ jsx(FooterSponsorLink, { sponsor });
381
+ const hasProject = (project ?? config.project)?.name !== void 0 && (project ?? config.project)?.name !== "";
382
+ const hasSponsor = (sponsor?.text ?? "") !== "" && (sponsor?.link ?? "") !== "";
383
+ if (hasProject) items.push(projectNode);
384
+ if (ardoLink) items.push(/* @__PURE__ */ jsx("a", {
385
+ href: "https://ardo-docs.dev",
386
+ className: footerLink,
387
+ children: "Built with Ardo"
388
+ }));
389
+ if (hasSponsor) items.push(sponsorNode);
390
+ if (items.length === 0) return null;
391
+ return /* @__PURE__ */ jsx("p", {
392
+ className: footerPrimary,
393
+ children: items.map((item, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [i > 0 && /* @__PURE__ */ jsx("span", {
394
+ className: "_169q00b3",
395
+ "aria-hidden": "true"
396
+ }), item] }, i))
397
+ });
398
+ }
399
+ function ArdoFooter({ children, className, ardoLink = true, message, copyright, project, sponsor, buildTime, buildHash }) {
400
+ const config = useArdoConfig();
401
+ const resolvedBuildTime = buildTime ?? config.buildTime;
402
+ const resolvedBuildHash = buildHash ?? config.buildHash;
403
+ if (children != null) return /* @__PURE__ */ jsx("footer", {
404
+ className: className ?? "_169q00b0",
405
+ children: /* @__PURE__ */ jsx("div", {
406
+ className: footerContainer,
407
+ children
408
+ })
409
+ });
410
+ return /* @__PURE__ */ jsx("footer", {
411
+ className: className ?? "_169q00b0",
412
+ children: /* @__PURE__ */ jsxs("div", {
413
+ className: footerContainer,
414
+ children: [
415
+ /* @__PURE__ */ jsx(FooterPrimaryLine, {
416
+ project,
417
+ sponsor,
418
+ ardoLink,
419
+ config
420
+ }),
421
+ (message ?? "") !== "" && /* @__PURE__ */ jsx("p", {
422
+ className: "_169q00b5",
423
+ dangerouslySetInnerHTML: { __html: message ?? "" }
424
+ }),
425
+ (copyright ?? "") !== "" && /* @__PURE__ */ jsx("p", {
426
+ className: "_169q00b6",
427
+ dangerouslySetInnerHTML: { __html: copyright ?? "" }
428
+ }),
429
+ (resolvedBuildTime ?? "") !== "" && /* @__PURE__ */ jsxs("p", {
430
+ className: "_169q00b7",
431
+ children: [
432
+ "Built on ",
433
+ formatBuildTime(resolvedBuildTime ?? ""),
434
+ (resolvedBuildHash ?? "") !== "" && /* @__PURE__ */ jsxs(Fragment, { children: [
435
+ " (",
436
+ resolvedBuildHash,
437
+ ")"
438
+ ] })
439
+ ]
440
+ })
441
+ ]
442
+ })
443
+ });
444
+ }
445
+ //#endregion
446
+ //#region src/ui/components/ThemeToggle.css.ts
447
+ var themeIcon = "_18g5iyz0";
448
+ var themeToggle = "_18g5iyz1";
449
+ //#endregion
450
+ //#region src/ui/components/ThemeToggle.tsx
451
+ const isBrowser = typeof document !== "undefined";
452
+ function getInitialTheme() {
453
+ if (!isBrowser) return "system";
454
+ const stored = localStorage.getItem("ardo-theme");
455
+ return isTheme(stored) ? stored : "system";
456
+ }
457
+ function ArdoThemeToggle() {
458
+ const [theme, setTheme] = useState(getInitialTheme);
459
+ const [mounted] = useState(isBrowser);
460
+ useEffect(() => {
461
+ applyTheme(theme);
462
+ }, [theme]);
463
+ const toggleTheme = () => {
464
+ const nextTheme = theme === "light" ? "dark" : theme === "dark" ? "system" : "light";
465
+ setTheme(nextTheme);
466
+ localStorage.setItem("ardo-theme", nextTheme);
467
+ applyTheme(nextTheme);
468
+ };
469
+ if (!mounted) return /* @__PURE__ */ jsx("button", {
470
+ type: "button",
471
+ className: themeToggle,
472
+ "aria-label": "Toggle theme",
473
+ children: /* @__PURE__ */ jsx("span", {
474
+ className: themeIcon,
475
+ children: /* @__PURE__ */ jsx(SunIcon, { size: 20 })
476
+ })
477
+ });
478
+ return /* @__PURE__ */ jsx("button", {
479
+ type: "button",
480
+ className: themeToggle,
481
+ onClick: toggleTheme,
482
+ "aria-label": `Switch to ${theme === "light" ? "dark" : theme === "dark" ? "system" : "light"} theme`,
483
+ children: /* @__PURE__ */ jsxs("span", {
484
+ className: themeIcon,
485
+ children: [
486
+ theme === "light" && /* @__PURE__ */ jsx(SunIcon, { size: 20 }),
487
+ theme === "dark" && /* @__PURE__ */ jsx(MoonIcon, { size: 20 }),
488
+ theme === "system" && /* @__PURE__ */ jsx(MonitorIcon, { size: 20 })
489
+ ]
490
+ })
491
+ });
492
+ }
493
+ function applyTheme(theme) {
494
+ const root = document.documentElement;
495
+ if (theme === "system") {
496
+ const isDark = globalThis.matchMedia("(prefers-color-scheme: dark)").matches;
497
+ root.classList.toggle("dark", isDark);
498
+ root.classList.toggle("light", !isDark);
499
+ } else {
500
+ root.classList.toggle("dark", theme === "dark");
501
+ root.classList.toggle("light", theme === "light");
502
+ }
503
+ }
504
+ function isTheme(value) {
505
+ return value === "dark" || value === "light" || value === "system";
506
+ }
507
+ var headerContainer = "qjc2r51";
508
+ var headerLeft = "qjc2r52";
509
+ var headerRight = "qjc2r53";
510
+ var logoLink = "qjc2r54";
511
+ var mobileBackdrop = "qjc2r5a";
512
+ var mobilePanel = "qjc2r5b";
513
+ var mobilePanelClose = "qjc2r5d";
514
+ var mobilePanelHeader = "qjc2r5c";
515
+ var mobilePanelSidebar = "qjc2r5f";
516
+ //#endregion
517
+ //#region src/ui/Header.tsx
518
+ function ArdoHeader({ logo: logo$1, title, nav, actions, search = false, searchPlaceholder, themeToggle = true, mobileMenuContent, className }) {
519
+ const location = useLocation();
520
+ const config = useArdoConfig();
521
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
522
+ const resolvedLogo = logo$1;
523
+ const resolvedTitle = title ?? config.title;
524
+ const hasLogo = resolvedLogo !== void 0;
525
+ const hasTitle = resolvedTitle !== "";
526
+ const hasMobileMenu = mobileMenuContent != null;
527
+ useEffect(() => {
528
+ setMobileMenuOpen(false);
529
+ }, [location.pathname]);
530
+ useEffect(() => {
531
+ if (mobileMenuOpen) document.body.style.overflow = "hidden";
532
+ else document.body.style.overflow = "";
533
+ return () => {
534
+ document.body.style.overflow = "";
535
+ };
536
+ }, [mobileMenuOpen]);
537
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("header", {
538
+ className: className ?? "qjc2r50",
539
+ children: /* @__PURE__ */ jsxs("div", {
540
+ className: headerContainer,
541
+ children: [
542
+ /* @__PURE__ */ jsxs("div", {
543
+ className: headerLeft,
544
+ children: [hasMobileMenu && /* @__PURE__ */ jsx("button", {
545
+ type: "button",
546
+ className: "qjc2r57",
547
+ onClick: () => {
548
+ setMobileMenuOpen(!mobileMenuOpen);
549
+ },
550
+ "aria-label": "Toggle menu",
551
+ "aria-expanded": mobileMenuOpen,
552
+ children: /* @__PURE__ */ jsxs("span", {
553
+ className: "qjc2r58",
554
+ children: [
555
+ /* @__PURE__ */ jsx("span", {}),
556
+ /* @__PURE__ */ jsx("span", {}),
557
+ /* @__PURE__ */ jsx("span", {})
558
+ ]
559
+ })
560
+ }), /* @__PURE__ */ jsxs(Link, {
561
+ to: "/",
562
+ className: logoLink,
563
+ children: [hasLogo && /* @__PURE__ */ jsx("img", {
564
+ src: typeof resolvedLogo === "string" ? resolvedLogo : resolvedLogo.light,
565
+ alt: resolvedTitle,
566
+ className: "qjc2r55"
567
+ }), hasTitle && /* @__PURE__ */ jsx("span", {
568
+ className: "qjc2r56",
569
+ children: resolvedTitle
570
+ })]
571
+ })]
572
+ }),
573
+ nav != null && /* @__PURE__ */ jsx("div", {
574
+ className: "qjc2r59",
575
+ children: nav
576
+ }),
577
+ /* @__PURE__ */ jsxs("div", {
578
+ className: headerRight,
579
+ children: [
580
+ search && /* @__PURE__ */ jsx(ArdoSearch, { placeholder: searchPlaceholder }),
581
+ themeToggle && /* @__PURE__ */ jsx(ArdoThemeToggle, {}),
582
+ actions
583
+ ]
584
+ })
585
+ ]
586
+ })
587
+ }), hasMobileMenu && /* @__PURE__ */ jsx(MobileSlidePanel, {
588
+ isOpen: mobileMenuOpen,
589
+ logo: resolvedLogo,
590
+ title: resolvedTitle,
591
+ nav,
592
+ themeToggle,
593
+ onClose: () => {
594
+ setMobileMenuOpen(false);
595
+ },
596
+ children: mobileMenuContent
597
+ })] });
598
+ }
599
+ function MobileSlidePanel({ isOpen, logo: logo$2, title, nav, themeToggle, children, onClose }) {
600
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
601
+ className: mobileBackdrop,
602
+ "data-open": isOpen,
603
+ onClick: onClose
604
+ }), /* @__PURE__ */ jsxs("div", {
605
+ className: mobilePanel,
606
+ "data-open": isOpen,
607
+ "aria-hidden": !isOpen,
608
+ children: [
609
+ /* @__PURE__ */ jsxs("div", {
610
+ className: mobilePanelHeader,
611
+ children: [/* @__PURE__ */ jsx(Link, {
612
+ to: "/",
613
+ className: logoLink,
614
+ onClick: onClose,
615
+ children: logo$2 != null && /* @__PURE__ */ jsx("img", {
616
+ src: typeof logo$2 === "string" ? logo$2 : logo$2.light,
617
+ alt: title,
618
+ className: "qjc2r55"
619
+ })
620
+ }), /* @__PURE__ */ jsxs("div", {
621
+ style: {
622
+ display: "flex",
623
+ alignItems: "center",
624
+ gap: "0.5rem"
625
+ },
626
+ children: [themeToggle && /* @__PURE__ */ jsx(ArdoThemeToggle, {}), /* @__PURE__ */ jsx("button", {
627
+ type: "button",
628
+ className: mobilePanelClose,
629
+ onClick: onClose,
630
+ "aria-label": "Close menu",
631
+ children: /* @__PURE__ */ jsx(XIcon, { size: 20 })
632
+ })]
633
+ })]
634
+ }),
635
+ nav != null && /* @__PURE__ */ jsx("div", {
636
+ className: "qjc2r5e",
637
+ onClickCapture: handleLinkClick(onClose),
638
+ children: nav
639
+ }),
640
+ /* @__PURE__ */ jsx("div", {
641
+ className: mobilePanelSidebar,
642
+ onClickCapture: handleLinkClick(onClose),
643
+ children
644
+ })
645
+ ]
646
+ })] });
647
+ }
648
+ function handleLinkClick(onClose) {
649
+ return (event) => {
650
+ if (event.target instanceof HTMLElement && event.target.closest("a") !== null) onClose();
651
+ };
652
+ }
653
+ function ArdoSocialLink({ href, icon, ariaLabel, className }) {
654
+ return /* @__PURE__ */ jsx("a", {
655
+ href,
656
+ target: "_blank",
657
+ rel: "noopener noreferrer",
658
+ className: className ?? "_85hnke2",
659
+ "aria-label": ariaLabel ?? icon,
660
+ children: /* @__PURE__ */ jsx(SocialIcon, { icon })
661
+ });
662
+ }
663
+ const socialIcons = {
664
+ github: GithubIcon,
665
+ twitter: TwitterIcon,
666
+ discord: MessageCircleIcon,
667
+ linkedin: LinkedinIcon,
668
+ youtube: YoutubeIcon,
669
+ npm: NpmIcon
670
+ };
671
+ function SocialIcon({ icon }) {
672
+ const IconComponent = socialIcons[icon];
673
+ return /* @__PURE__ */ jsx(IconComponent, { size: 20 });
674
+ }
675
+ var sidebarItem = "_1057ydn6";
676
+ var sidebarItemHeader = "_1057ydn7";
677
+ var sidebarLink = "_1057ydn8";
678
+ var sidebarList = "_1057ydn3";
679
+ var sidebarList0 = "_1057ydn4";
680
+ var sidebarList1 = "_1057ydn5";
681
+ var sidebarNav = "_1057ydn2";
682
+ var sidebarText = "_1057ydn9";
683
+ var sidebarTextButton = "_1057ydna";
684
+ //#endregion
685
+ //#region src/ui/Sidebar.tsx
686
+ const SidebarContext = createContext({ currentPath: "" });
687
+ function useSidebarContext() {
688
+ return use(SidebarContext);
689
+ }
690
+ /**
691
+ * Sidebar component supporting data-driven, JSX composition, and zero-config patterns.
692
+ *
693
+ * When neither `items` nor `children` are provided, automatically renders from
694
+ * the Ardo sidebar context (`virtual:ardo/sidebar`).
695
+ *
696
+ * @example Zero-config (from context)
697
+ * ```tsx
698
+ * <Sidebar />
699
+ * ```
700
+ *
701
+ * @example Data-driven (items prop)
702
+ * ```tsx
703
+ * <Sidebar items={[
704
+ * { text: 'Introduction', link: '/intro' },
705
+ * { text: 'Guide', items: [
706
+ * { text: 'Getting Started', link: '/guide/getting-started' }
707
+ * ]}
708
+ * ]} />
709
+ * ```
710
+ *
711
+ * @example JSX composition
712
+ * ```tsx
713
+ * <Sidebar>
714
+ * <SidebarLink to="/intro">Introduction</SidebarLink>
715
+ * <SidebarGroup title="Guide">
716
+ * <SidebarLink to="/guide/getting-started">Getting Started</SidebarLink>
717
+ * </SidebarGroup>
718
+ * </Sidebar>
719
+ * ```
720
+ */
721
+ function ArdoSidebar({ items, children, header, className }) {
722
+ const { pathname } = useLocation();
723
+ const contextSidebar = useArdoSidebar();
724
+ const hasCustomChildren = children != null;
725
+ const resolvedItems = items ?? (hasCustomChildren ? void 0 : contextSidebar);
726
+ const hasResolvedItems = (resolvedItems?.length ?? 0) > 0;
727
+ return /* @__PURE__ */ jsx(SidebarContext, {
728
+ value: useMemo(() => ({ currentPath: pathname }), [pathname]),
729
+ children: /* @__PURE__ */ jsxs("aside", {
730
+ className: className ?? "_1057ydn0",
731
+ children: [header != null && /* @__PURE__ */ jsx("div", {
732
+ className: "_1057ydn1",
733
+ children: header
734
+ }), /* @__PURE__ */ jsx("nav", {
735
+ "aria-label": "Main navigation",
736
+ className: sidebarNav,
737
+ children: hasCustomChildren ? /* @__PURE__ */ jsx("ul", {
738
+ className: `${sidebarList} ${sidebarList0}`,
739
+ children
740
+ }) : hasResolvedItems ? /* @__PURE__ */ jsx(SidebarItems, {
741
+ items: resolvedItems ?? [],
742
+ depth: 0
743
+ }) : null
744
+ })]
745
+ })
746
+ });
747
+ }
748
+ /**
749
+ * Group component for organizing sidebar links.
750
+ *
751
+ * @example
752
+ * ```tsx
753
+ * <SidebarGroup title="Guide">
754
+ * <SidebarLink to="/guide/intro">Introduction</SidebarLink>
755
+ * <SidebarLink to="/guide/setup">Setup</SidebarLink>
756
+ * </SidebarGroup>
757
+ * ```
758
+ *
759
+ * @example With collapsible state
760
+ * ```tsx
761
+ * <SidebarGroup title="Advanced" collapsed>
762
+ * <SidebarLink to="/advanced/config">Configuration</SidebarLink>
763
+ * </SidebarGroup>
764
+ * ```
765
+ */
766
+ function ArdoSidebarGroup({ title, to, collapsed: initialCollapsed = false, collapsible = true, children, className }) {
767
+ const [collapsed, setCollapsed] = useState(initialCollapsed);
768
+ const { currentPath } = useSidebarContext();
769
+ const textClassName = [sidebarText, checkChildrenActive(children, currentPath) && "child-active"].filter(Boolean).join(" ");
770
+ const textButtonClassName = [textClassName, sidebarTextButton].join(" ");
771
+ const hasChildren = Children.count(children) > 0;
772
+ const hasTo = (to ?? "") !== "";
773
+ const canToggle = collapsible && hasChildren;
774
+ return /* @__PURE__ */ jsxs("li", {
775
+ className: className ?? "_1057ydn6",
776
+ children: [/* @__PURE__ */ jsxs("div", {
777
+ className: sidebarItemHeader,
778
+ children: [hasTo ? /* @__PURE__ */ jsx(NavLink, {
779
+ to: to ?? "/",
780
+ end: true,
781
+ className: ({ isActive }) => [textClassName, isActive && "active"].filter(Boolean).join(" "),
782
+ children: title
783
+ }) : /* @__PURE__ */ jsx("button", {
784
+ type: "button",
785
+ className: textButtonClassName,
786
+ onClick: () => {
787
+ if (canToggle) setCollapsed(!collapsed);
788
+ },
789
+ children: title
790
+ }), canToggle && /* @__PURE__ */ jsx("button", {
791
+ type: "button",
792
+ className: ["_1057ydnb", collapsed && "collapsed"].filter(Boolean).join(" "),
793
+ onClick: () => {
794
+ setCollapsed(!collapsed);
795
+ },
796
+ "aria-label": collapsed ? "Expand" : "Collapse",
797
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { size: 16 })
798
+ })]
799
+ }), hasChildren && /* @__PURE__ */ jsx("div", {
800
+ className: "_1057ydnc",
801
+ "data-collapsed": collapsed,
802
+ children: /* @__PURE__ */ jsx("div", {
803
+ className: "_1057ydnd",
804
+ children: /* @__PURE__ */ jsx("ul", {
805
+ className: `_1057ydn3 _1057ydn5`,
806
+ children
807
+ })
808
+ })
809
+ })]
810
+ });
811
+ }
812
+ /**
813
+ * Sidebar navigation link.
814
+ *
815
+ * @example
816
+ * ```tsx
817
+ * <SidebarLink to="/guide/getting-started">Getting Started</SidebarLink>
818
+ * ```
819
+ */
820
+ function ArdoSidebarLink({ to, children, className }) {
821
+ const baseClassName = className ?? "_1057ydn8";
822
+ return /* @__PURE__ */ jsx("li", {
823
+ className: sidebarItem,
824
+ children: /* @__PURE__ */ jsx(NavLink, {
825
+ to,
826
+ className: ({ isActive }) => [baseClassName, isActive && "active"].filter(Boolean).join(" "),
827
+ children
828
+ })
829
+ });
830
+ }
831
+ function SidebarItems({ items, depth }) {
832
+ return /* @__PURE__ */ jsx("ul", {
833
+ className: `${sidebarList} ${depth === 0 ? sidebarList0 : sidebarList1}`,
834
+ children: items.map((item) => /* @__PURE__ */ jsx(SidebarItemComponent, {
835
+ item,
836
+ depth
837
+ }, item.link ?? `${item.text}-${String(depth)}`))
838
+ });
839
+ }
840
+ function SidebarItemComponent({ item, depth }) {
841
+ const { currentPath } = useSidebarContext();
842
+ const [collapsed, setCollapsed] = useState(item.collapsed ?? false);
843
+ const childItems = item.items ?? [];
844
+ const hasChildren = childItems.length > 0;
845
+ const hasActiveChild = hasChildren && childItems.some((child) => child.link === currentPath || child.items?.some((grandchild) => grandchild.link === currentPath));
846
+ const hasItemLink = (item.link ?? "") !== "";
847
+ const linkClassName = [sidebarLink, hasActiveChild && "child-active"].filter(Boolean).join(" ");
848
+ const textButtonClassName = [[sidebarText, hasActiveChild && "child-active"].filter(Boolean).join(" "), sidebarTextButton].join(" ");
849
+ return /* @__PURE__ */ jsxs("li", {
850
+ className: sidebarItem,
851
+ children: [/* @__PURE__ */ jsxs("div", {
852
+ className: sidebarItemHeader,
853
+ children: [hasItemLink ? /* @__PURE__ */ jsx(NavLink, {
854
+ to: item.link ?? "/",
855
+ className: ({ isActive }) => [linkClassName, isActive && "active"].filter(Boolean).join(" "),
856
+ children: item.text
857
+ }) : /* @__PURE__ */ jsx("button", {
858
+ type: "button",
859
+ className: textButtonClassName,
860
+ onClick: () => {
861
+ if (hasChildren) setCollapsed(!collapsed);
862
+ },
863
+ children: item.text
864
+ }), hasChildren && /* @__PURE__ */ jsx("button", {
865
+ type: "button",
866
+ className: ["_1057ydnb", collapsed && "collapsed"].filter(Boolean).join(" "),
867
+ onClick: () => {
868
+ setCollapsed(!collapsed);
869
+ },
870
+ "aria-label": collapsed ? "Expand" : "Collapse",
871
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { size: 16 })
872
+ })]
873
+ }), hasChildren && /* @__PURE__ */ jsx("div", {
874
+ className: "_1057ydnc",
875
+ "data-collapsed": collapsed,
876
+ children: /* @__PURE__ */ jsx("div", {
877
+ className: "_1057ydnd",
878
+ children: /* @__PURE__ */ jsx(SidebarItems, {
879
+ items: childItems,
880
+ depth: depth + 1
881
+ })
882
+ })
883
+ })]
884
+ });
885
+ }
886
+ function isSidebarChildActive(child, currentPath) {
887
+ if (isSidebarLinkElement(child)) return child.props.to === currentPath;
888
+ if (isSidebarGroupElement(child)) {
889
+ const groupProps = child.props;
890
+ return groupProps.to === currentPath || groupProps.children != null && checkChildrenActive(groupProps.children, currentPath);
891
+ }
892
+ return false;
893
+ }
894
+ function checkChildrenActive(children, currentPath) {
895
+ return Children.toArray(children).some((child) => isValidElement(child) && isSidebarChildActive(child, currentPath));
896
+ }
897
+ function isSidebarLinkElement(child) {
898
+ return child.type === ArdoSidebarLink;
899
+ }
900
+ function isSidebarGroupElement(child) {
901
+ return child.type === ArdoSidebarGroup;
902
+ }
903
+ //#endregion
904
+ //#region src/ui/ArdoRoot.tsx
905
+ /**
906
+ * All-in-one root component that combines ArdoProvider, Layout, Header,
907
+ * Sidebar, Footer, and homepage detection into a single component.
908
+ *
909
+ * @example Minimal usage
910
+ * ```tsx
911
+ * import config from "virtual:ardo/config"
912
+ * import sidebar from "virtual:ardo/sidebar"
913
+ *
914
+ * export default function Root() {
915
+ * return <ArdoRoot config={config} sidebar={sidebar} />
916
+ * }
917
+ * ```
918
+ *
919
+ * @example With custom nav and footer overrides
920
+ * ```tsx
921
+ * export default function Root() {
922
+ * return (
923
+ * <ArdoRoot
924
+ * config={config}
925
+ * sidebar={sidebar}
926
+ * headerProps={{
927
+ * nav: (
928
+ * <Nav>
929
+ * <NavLink to="/guide">Guide</NavLink>
930
+ * <NavLink to="/api">API</NavLink>
931
+ * </Nav>
932
+ * ),
933
+ * }}
934
+ * footerProps={{
935
+ * message: "Released under the MIT License.",
936
+ * }}
937
+ * editLink={{
938
+ * pattern: "https://github.com/user/repo/edit/main/docs/:path",
939
+ * text: "Edit this page on GitHub",
940
+ * }}
941
+ * lastUpdated={{ enabled: true }}
942
+ * />
943
+ * )
944
+ * }
945
+ * ```
946
+ */
947
+ function resolveRootHeader(header, headerProps, mobileMenuContent) {
948
+ if (header != null) return enhanceHeaderWithMobileMenuContent(header, mobileMenuContent);
949
+ return /* @__PURE__ */ jsx(ArdoHeader, {
950
+ ...headerProps,
951
+ mobileMenuContent: headerProps?.mobileMenuContent ?? mobileMenuContent
952
+ });
953
+ }
954
+ function resolveLayoutClassName(className, isHomePage) {
955
+ if (className != null) return className;
956
+ return isHomePage ? `${layout} ${home}` : layout;
957
+ }
958
+ function ArdoRoot({ config, sidebar, header, sidebarContent, footer, headerProps, sidebarProps, footerProps, editLink, lastUpdated, tocLabel, className, children }) {
959
+ const location = useLocation();
960
+ const isHomePage = location.pathname === "/" || location.pathname === "";
961
+ const searchPlaceholder = headerProps?.searchPlaceholder;
962
+ const showSearch = headerProps?.search !== false;
963
+ const resolvedSidebar = isHomePage ? void 0 : wrapSidebarWithSearch(sidebarContent, sidebarProps, !isHomePage && showSearch ? /* @__PURE__ */ jsx(ArdoSearch, { placeholder: searchPlaceholder }) : void 0);
964
+ const resolvedHeader = resolveRootHeader(header, {
965
+ ...headerProps,
966
+ search: false
967
+ }, isHomePage ? void 0 : resolvedSidebar);
968
+ const siteConfig = useMemo(() => ({
969
+ editLink,
970
+ lastUpdated,
971
+ tocLabel
972
+ }), [
973
+ editLink,
974
+ lastUpdated,
975
+ tocLabel
976
+ ]);
977
+ const content = /* @__PURE__ */ jsx(ArdoProvider, {
978
+ config,
979
+ sidebar,
980
+ children: /* @__PURE__ */ jsx(ArdoLayout, {
981
+ className: resolveLayoutClassName(className, isHomePage),
982
+ header: resolvedHeader,
983
+ sidebar: resolvedSidebar,
984
+ footer: footer ?? /* @__PURE__ */ jsx(ArdoFooter, { ...footerProps }),
985
+ children: children ?? /* @__PURE__ */ jsx(Outlet, {})
986
+ })
987
+ });
988
+ return editLink !== void 0 || lastUpdated !== void 0 || (tocLabel ?? "") !== "" ? /* @__PURE__ */ jsx(ArdoSiteConfigProvider, {
989
+ value: siteConfig,
990
+ children: content
991
+ }) : content;
992
+ }
993
+ /**
994
+ * Wraps sidebar content with a search field header.
995
+ * If the user provides custom sidebarContent (which is typically an <ArdoSidebar>),
996
+ * we clone it and inject the search as its `header` prop.
997
+ * Otherwise we create a default <ArdoSidebar> with search.
998
+ */
999
+ function wrapSidebarWithSearch(sidebarContent, sidebarProps, search) {
1000
+ if (sidebarContent == null) return /* @__PURE__ */ jsx(ArdoSidebar, {
1001
+ ...sidebarProps,
1002
+ header: search
1003
+ });
1004
+ if (isValidElement(sidebarContent) && sidebarContent.type === ArdoSidebar) return cloneElement(sidebarContent, { header: sidebarContent.props.header ?? search });
1005
+ return /* @__PURE__ */ jsx(ArdoSidebar, {
1006
+ header: search,
1007
+ children: sidebarContent
1008
+ });
1009
+ }
1010
+ function enhanceHeaderWithMobileMenuContent(header, mobileMenuContent) {
1011
+ if (!isValidElement(header) || header.type !== ArdoHeader) return header;
1012
+ if (header.props.mobileMenuContent !== void 0) return header;
1013
+ return cloneElement(header, { mobileMenuContent });
1014
+ }
1015
+ var featureDetails = "_15qe9bp8";
1016
+ var featureTitle = "_15qe9bp7";
1017
+ var featuresContainer = "_15qe9bp4";
1018
+ //#endregion
1019
+ //#region src/ui/components/Features.tsx
1020
+ /**
1021
+ * Individual feature card component.
1022
+ *
1023
+ * @example
1024
+ * ```tsx
1025
+ * import { Zap } from "lucide-react"
1026
+ *
1027
+ * <ArdoFeatureCard title="Fast" icon={<Zap size={28} />}>
1028
+ * Lightning fast builds with Vite
1029
+ * </ArdoFeatureCard>
1030
+ * ```
1031
+ */
1032
+ function ArdoFeatureCard({ title, icon, children, link, linkText, className }) {
1033
+ return /* @__PURE__ */ jsxs("div", {
1034
+ className: className ?? "_15qe9bp5",
1035
+ children: [
1036
+ icon != null && /* @__PURE__ */ jsx("div", {
1037
+ className: "_15qe9bp6",
1038
+ children: icon
1039
+ }),
1040
+ /* @__PURE__ */ jsx("h3", {
1041
+ className: featureTitle,
1042
+ children: title
1043
+ }),
1044
+ /* @__PURE__ */ jsx("p", {
1045
+ className: featureDetails,
1046
+ children
1047
+ }),
1048
+ (link ?? "") !== "" && /* @__PURE__ */ jsx(Link, {
1049
+ to: link ?? "",
1050
+ className: "_15qe9bp9",
1051
+ children: linkText ?? "Learn more"
1052
+ })
1053
+ ]
1054
+ });
1055
+ }
1056
+ /**
1057
+ * Features grid component for displaying multiple feature cards.
1058
+ *
1059
+ * @example
1060
+ * ```tsx
1061
+ * <ArdoFeatures title="Key Features" subtitle="Everything you need">
1062
+ * <ArdoFeatureCard title="React-First" icon="⚛️">Built on React.</ArdoFeatureCard>
1063
+ * <ArdoFeatureCard title="Fast" icon="⚡">Powered by Vite.</ArdoFeatureCard>
1064
+ * </ArdoFeatures>
1065
+ * ```
1066
+ */
1067
+ function ArdoFeatures({ children, title, subtitle, className }) {
1068
+ const hasTitle = (title ?? "") !== "";
1069
+ const hasSubtitle = (subtitle ?? "") !== "";
1070
+ return /* @__PURE__ */ jsxs("section", {
1071
+ className: className ?? "_15qe9bp0",
1072
+ children: [(hasTitle || hasSubtitle) && /* @__PURE__ */ jsxs("div", {
1073
+ className: "_15qe9bp1",
1074
+ children: [hasTitle && /* @__PURE__ */ jsx("h2", {
1075
+ className: "_15qe9bp2",
1076
+ children: title
1077
+ }), hasSubtitle && /* @__PURE__ */ jsx("p", {
1078
+ className: "_15qe9bp3",
1079
+ children: subtitle
1080
+ })]
1081
+ }), /* @__PURE__ */ jsx("div", {
1082
+ className: featuresContainer,
1083
+ children
1084
+ })]
1085
+ });
1086
+ }
1087
+ //#endregion
1088
+ //#region src/ui/components/Hero.css.ts
1089
+ var hero = "j780910";
1090
+ var heroAction = "j780918";
1091
+ var heroActionAlt = "j78091a";
1092
+ var heroActionBrand = "j780919";
1093
+ var heroAnimate = "j780912";
1094
+ var heroContainer = "j780911";
1095
+ //#endregion
1096
+ //#region src/ui/components/Hero.tsx
1097
+ /**
1098
+ * Hero section component for landing pages.
1099
+ *
1100
+ * @example
1101
+ * ```tsx
1102
+ * import { ArrowRight, Github } from "lucide-react"
1103
+ *
1104
+ * <Hero
1105
+ * name="Ardo"
1106
+ * text="React-first Documentation"
1107
+ * tagline="Build beautiful documentation sites with React."
1108
+ * image="/logo.svg"
1109
+ * actions={[
1110
+ * { text: "Get Started", link: "/guide/getting-started", theme: "brand", icon: <ArrowRight size={16} /> },
1111
+ * { text: "GitHub", link: "https://github.com/...", theme: "alt", icon: <Github size={16} /> }
1112
+ * ]}
1113
+ * />
1114
+ * ```
1115
+ */
1116
+ function HeroActionButton({ action }) {
1117
+ const link = action.link;
1118
+ const isExternal = typeof link === "string" && (link.startsWith("http://") || link.startsWith("https://"));
1119
+ const cls = `${heroAction} ${action.theme === "alt" ? heroActionAlt : heroActionBrand}`;
1120
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [action.icon, action.text] });
1121
+ if (isExternal) return /* @__PURE__ */ jsx("a", {
1122
+ href: link,
1123
+ className: cls,
1124
+ target: "_blank",
1125
+ rel: "noopener noreferrer",
1126
+ children: content
1127
+ });
1128
+ return /* @__PURE__ */ jsx(Link, {
1129
+ to: link,
1130
+ className: cls,
1131
+ children: content
1132
+ });
1133
+ }
1134
+ function resolveHeroImage(image, name) {
1135
+ return {
1136
+ url: typeof image === "string" ? image : image?.light ?? "",
1137
+ alt: typeof image === "string" ? name ?? "" : image?.alt ?? name ?? ""
1138
+ };
1139
+ }
1140
+ function ArdoHero({ name, text, tagline, image, actions, className, version }) {
1141
+ const img = resolveHeroImage(image, name);
1142
+ return /* @__PURE__ */ jsx("section", {
1143
+ className: className ?? "j780910",
1144
+ children: /* @__PURE__ */ jsxs("div", {
1145
+ className: `${heroContainer} ${heroAnimate}`,
1146
+ children: [img.url !== "" && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("img", {
1147
+ src: img.url,
1148
+ alt: img.alt
1149
+ }) }), /* @__PURE__ */ jsxs("div", { children: [
1150
+ (version ?? "") !== "" && /* @__PURE__ */ jsxs("span", {
1151
+ className: "j780913",
1152
+ children: ["v", version]
1153
+ }),
1154
+ (name ?? "") !== "" && /* @__PURE__ */ jsx("h1", {
1155
+ className: "j780914",
1156
+ children: name
1157
+ }),
1158
+ (text ?? "") !== "" && /* @__PURE__ */ jsx("p", {
1159
+ className: "j780915",
1160
+ children: text
1161
+ }),
1162
+ (tagline ?? "") !== "" && /* @__PURE__ */ jsx("p", {
1163
+ className: "j780916",
1164
+ children: tagline
1165
+ }),
1166
+ (actions?.length ?? 0) > 0 && /* @__PURE__ */ jsx("div", {
1167
+ className: "j780917",
1168
+ children: actions?.map((action) => {
1169
+ const key = typeof action.link === "string" ? `${action.link}-${action.text}` : action.text;
1170
+ return /* @__PURE__ */ jsx(HeroActionButton, { action }, key);
1171
+ })
1172
+ })
1173
+ ] })]
1174
+ })
1175
+ });
1176
+ }
1177
+ //#endregion
1178
+ //#region src/ui/HomePage.tsx
1179
+ function HomeHeroSection({ hero: hero$1, fallbackTitle }) {
1180
+ if (hero$1 === void 0) return null;
1181
+ const heroImage = hero$1.image;
1182
+ const heroActions$1 = hero$1.actions ?? [];
1183
+ const heroName$1 = hero$1.name ?? "";
1184
+ return /* @__PURE__ */ jsx("section", {
1185
+ className: hero,
1186
+ children: /* @__PURE__ */ jsxs("div", {
1187
+ className: heroContainer,
1188
+ children: [heroImage !== void 0 && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("img", {
1189
+ src: typeof heroImage === "string" ? heroImage : heroImage.light,
1190
+ alt: heroName$1 !== "" ? heroName$1 : fallbackTitle
1191
+ }) }), /* @__PURE__ */ jsxs("div", { children: [
1192
+ heroName$1 !== "" && /* @__PURE__ */ jsx("h1", {
1193
+ className: "j780914",
1194
+ children: heroName$1
1195
+ }),
1196
+ (hero$1.text ?? "") !== "" && /* @__PURE__ */ jsx("p", {
1197
+ className: "j780915",
1198
+ children: hero$1.text
1199
+ }),
1200
+ (hero$1.tagline ?? "") !== "" && /* @__PURE__ */ jsx("p", {
1201
+ className: "j780916",
1202
+ children: hero$1.tagline
1203
+ }),
1204
+ heroActions$1.length > 0 && /* @__PURE__ */ jsx("div", {
1205
+ className: "j780917",
1206
+ children: heroActions$1.map((action) => /* @__PURE__ */ jsx(Link, {
1207
+ to: action.link,
1208
+ className: `j780918 ${action.theme === "alt" ? "j78091a" : "j780919"}`,
1209
+ children: action.text
1210
+ }, `${action.link}-${action.text}`))
1211
+ })
1212
+ ] })]
1213
+ })
1214
+ });
1215
+ }
1216
+ function HomeFeaturesSection({ features }) {
1217
+ const safeFeatures = features ?? [];
1218
+ if (safeFeatures.length === 0) return null;
1219
+ return /* @__PURE__ */ jsx(ArdoFeatures, { children: safeFeatures.map((feature) => /* @__PURE__ */ jsx(ArdoFeatureCard, {
1220
+ title: feature.title,
1221
+ icon: feature.icon,
1222
+ link: feature.link,
1223
+ linkText: feature.linkText,
1224
+ children: feature.details
1225
+ }, feature.link ?? feature.title)) });
1226
+ }
1227
+ function ArdoHomePage({ headerProps, footerProps, header, footer } = {}) {
1228
+ const pageData = useArdoPageData();
1229
+ const config = useArdoConfig();
1230
+ return /* @__PURE__ */ jsxs("div", {
1231
+ className: home,
1232
+ children: [
1233
+ header ?? /* @__PURE__ */ jsx(ArdoHeader, {
1234
+ title: config.title,
1235
+ ...headerProps
1236
+ }),
1237
+ /* @__PURE__ */ jsxs("main", {
1238
+ className: homeMain,
1239
+ children: [/* @__PURE__ */ jsx(HomeHeroSection, {
1240
+ hero: pageData?.frontmatter.hero,
1241
+ fallbackTitle: config.title
1242
+ }), /* @__PURE__ */ jsx(HomeFeaturesSection, { features: pageData?.frontmatter.features })]
1243
+ }),
1244
+ footer ?? /* @__PURE__ */ jsx(ArdoFooter, { ...footerProps })
1245
+ ]
1246
+ });
1247
+ }
1248
+ //#endregion
1249
+ //#region src/ui/Nav.tsx
1250
+ const NavContext = createContext(null);
1251
+ function useNavContext() {
1252
+ return use(NavContext);
1253
+ }
1254
+ /**
1255
+ * Navigation container component for composing navigation links.
1256
+ *
1257
+ * @example
1258
+ * ```tsx
1259
+ * <Nav>
1260
+ * <NavLink to="/guide">Guide</NavLink>
1261
+ * <NavLink to="/api">API</NavLink>
1262
+ * <NavLink href="https://github.com/...">GitHub</NavLink>
1263
+ * </Nav>
1264
+ * ```
1265
+ */
1266
+ function ArdoNav({ children, className }) {
1267
+ return /* @__PURE__ */ jsx("nav", {
1268
+ className: className ?? "_85hnke0",
1269
+ children
1270
+ });
1271
+ }
1272
+ /**
1273
+ * Navigation link component supporting both internal routes and external URLs.
1274
+ *
1275
+ * @example
1276
+ * ```tsx
1277
+ * // Internal link
1278
+ * <NavLink to="/guide">Guide</NavLink>
1279
+ *
1280
+ * // External link
1281
+ * <NavLink href="https://github.com/...">GitHub</NavLink>
1282
+ * ```
1283
+ */
1284
+ function ArdoNavLink({ to, href, children, className, activeMatch: _activeMatch }) {
1285
+ const navContext = useNavContext();
1286
+ const baseClassName = className ?? "_85hnke1";
1287
+ const hasHref = (href ?? "") !== "";
1288
+ const hasTo = to !== void 0;
1289
+ const handleClick = () => {
1290
+ navContext?.setMobileMenuOpen(false);
1291
+ };
1292
+ if (hasHref) return /* @__PURE__ */ jsx("a", {
1293
+ href: href ?? "",
1294
+ className: baseClassName,
1295
+ target: "_blank",
1296
+ rel: "noopener noreferrer",
1297
+ onClick: handleClick,
1298
+ children
1299
+ });
1300
+ if (hasTo) return /* @__PURE__ */ jsx(NavLink, {
1301
+ to,
1302
+ className: ({ isActive }) => [baseClassName, isActive && "active"].filter(Boolean).join(" "),
1303
+ onClick: handleClick,
1304
+ children
1305
+ });
1306
+ return /* @__PURE__ */ jsx("span", {
1307
+ className: baseClassName,
1308
+ children
1309
+ });
1310
+ }
1311
+ //#endregion
1312
+ export { ArdoFeatureCard as a, ArdoSidebar as c, ArdoHeader as d, ArdoSocialLink as f, ArdoSearch as h, ArdoHero as i, ArdoSidebarGroup as l, ArdoFooter as m, ArdoNavLink as n, ArdoFeatures as o, ArdoThemeToggle as p, ArdoHomePage as r, ArdoRoot as s, ArdoNav as t, ArdoSidebarLink as u };
1313
+
1314
+ //# sourceMappingURL=ui-3grzJSsq.js.map