boltdocs 1.10.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/dist/cache-7G6D532T.mjs +1 -0
  4. package/dist/chunk-A4HQPEPU.mjs +1 -0
  5. package/dist/chunk-BA5NH5HU.mjs +1 -0
  6. package/dist/chunk-BQCD3DWG.mjs +1 -0
  7. package/dist/chunk-H63UMKYF.mjs +1 -0
  8. package/dist/chunk-IWHRQHS7.mjs +1 -0
  9. package/dist/chunk-JZXLCA2E.mjs +1 -0
  10. package/dist/chunk-MFU7Q6WF.mjs +1 -0
  11. package/dist/chunk-QYPNX5UN.mjs +1 -0
  12. package/dist/chunk-XEAPSFMB.mjs +1 -0
  13. package/dist/client/components/mdx/index.d.mts +209 -0
  14. package/dist/client/components/mdx/index.d.ts +209 -0
  15. package/dist/client/components/mdx/index.js +1 -0
  16. package/dist/client/components/mdx/index.mjs +1 -0
  17. package/dist/client/hooks/index.d.mts +133 -0
  18. package/dist/client/hooks/index.d.ts +133 -0
  19. package/dist/client/hooks/index.js +1 -0
  20. package/dist/client/hooks/index.mjs +1 -0
  21. package/dist/client/index.d.mts +138 -298
  22. package/dist/client/index.d.ts +138 -298
  23. package/dist/client/index.js +1 -3630
  24. package/dist/client/index.mjs +1 -697
  25. package/dist/client/ssr.d.mts +7 -3
  26. package/dist/client/ssr.d.ts +7 -3
  27. package/dist/client/ssr.js +1 -2928
  28. package/dist/client/ssr.mjs +1 -33
  29. package/dist/{config-BsFQ-ErD.d.ts → config-CX4l-ZNp.d.mts} +42 -35
  30. package/dist/{config-BsFQ-ErD.d.mts → config-CX4l-ZNp.d.ts} +42 -35
  31. package/dist/node/index.d.mts +2 -4
  32. package/dist/node/index.d.ts +2 -4
  33. package/dist/node/index.js +31 -1161
  34. package/dist/node/index.mjs +31 -736
  35. package/dist/search-dialog-EB3N4TYM.mjs +1 -0
  36. package/dist/types-BuZWFT7r.d.ts +159 -0
  37. package/dist/types-CvT-SGbK.d.mts +159 -0
  38. package/dist/use-routes-5bAtAAYX.d.mts +30 -0
  39. package/dist/use-routes-BefRXY3v.d.ts +30 -0
  40. package/package.json +34 -12
  41. package/src/client/app/config-context.tsx +18 -0
  42. package/src/client/app/docs-layout.tsx +14 -0
  43. package/src/client/app/index.tsx +137 -262
  44. package/src/client/app/mdx-component.tsx +52 -0
  45. package/src/client/app/mdx-components-context.tsx +23 -0
  46. package/src/client/app/mdx-page.tsx +20 -0
  47. package/src/client/app/preload.tsx +38 -30
  48. package/src/client/app/router.tsx +30 -0
  49. package/src/client/app/scroll-handler.tsx +40 -0
  50. package/src/client/app/theme-context.tsx +75 -0
  51. package/src/client/components/default-layout.tsx +80 -0
  52. package/src/client/components/docs-layout.tsx +105 -0
  53. package/src/client/components/icons-dev.tsx +74 -0
  54. package/src/client/components/mdx/admonition.tsx +107 -0
  55. package/src/client/components/mdx/badge.tsx +41 -0
  56. package/src/client/components/mdx/button.tsx +35 -0
  57. package/src/client/components/mdx/card.tsx +124 -0
  58. package/src/client/components/mdx/code-block.tsx +119 -0
  59. package/src/client/components/mdx/component-preview.tsx +47 -0
  60. package/src/client/components/mdx/component-props.tsx +83 -0
  61. package/src/client/components/mdx/field.tsx +66 -0
  62. package/src/client/components/mdx/file-tree.tsx +287 -0
  63. package/src/client/components/mdx/hooks/use-code-block.ts +56 -0
  64. package/src/client/components/mdx/hooks/use-component-preview.ts +16 -0
  65. package/src/client/components/mdx/hooks/useTable.ts +74 -0
  66. package/src/client/components/mdx/hooks/useTabs.ts +68 -0
  67. package/src/client/components/mdx/image.tsx +23 -0
  68. package/src/client/components/mdx/index.ts +53 -0
  69. package/src/client/components/mdx/link.tsx +38 -0
  70. package/src/client/components/mdx/list.tsx +192 -0
  71. package/src/client/components/mdx/table.tsx +156 -0
  72. package/src/client/components/mdx/tabs.tsx +135 -0
  73. package/src/client/components/mdx/video.tsx +68 -0
  74. package/src/client/components/primitives/breadcrumbs.tsx +79 -0
  75. package/src/client/components/primitives/button-group.tsx +54 -0
  76. package/src/client/components/primitives/button.tsx +145 -0
  77. package/src/client/components/primitives/helpers/observer.ts +120 -0
  78. package/src/client/components/primitives/index.ts +17 -0
  79. package/src/client/components/primitives/link.tsx +122 -0
  80. package/src/client/components/primitives/menu.tsx +159 -0
  81. package/src/client/components/primitives/navbar.tsx +359 -0
  82. package/src/client/components/primitives/navigation-menu.tsx +116 -0
  83. package/src/client/components/primitives/on-this-page.tsx +461 -0
  84. package/src/client/components/primitives/page-nav.tsx +87 -0
  85. package/src/client/components/primitives/popover.tsx +47 -0
  86. package/src/client/components/primitives/search-dialog.tsx +183 -0
  87. package/src/client/components/primitives/sidebar.tsx +154 -0
  88. package/src/client/components/primitives/tabs.tsx +90 -0
  89. package/src/client/components/primitives/tooltip.tsx +83 -0
  90. package/src/client/components/primitives/types.ts +11 -0
  91. package/src/client/components/ui-base/breadcrumbs.tsx +42 -0
  92. package/src/client/components/ui-base/copy-markdown.tsx +112 -0
  93. package/src/client/components/ui-base/error-boundary.tsx +52 -0
  94. package/src/client/components/ui-base/github-stars.tsx +27 -0
  95. package/src/client/components/ui-base/head.tsx +69 -0
  96. package/src/client/components/ui-base/loading.tsx +87 -0
  97. package/src/client/components/ui-base/navbar.tsx +138 -0
  98. package/src/client/components/ui-base/not-found.tsx +24 -0
  99. package/src/client/components/ui-base/on-this-page.tsx +152 -0
  100. package/src/client/components/ui-base/page-nav.tsx +39 -0
  101. package/src/client/components/ui-base/powered-by.tsx +19 -0
  102. package/src/client/components/ui-base/progress-bar.tsx +67 -0
  103. package/src/client/components/ui-base/search-dialog.tsx +82 -0
  104. package/src/client/components/ui-base/sidebar.tsx +104 -0
  105. package/src/client/components/ui-base/tabs.tsx +65 -0
  106. package/src/client/components/ui-base/theme-toggle.tsx +32 -0
  107. package/src/client/hooks/index.ts +12 -0
  108. package/src/client/hooks/use-breadcrumbs.ts +22 -0
  109. package/src/client/hooks/use-i18n.ts +84 -0
  110. package/src/client/hooks/use-localized-to.ts +95 -0
  111. package/src/client/hooks/use-location.ts +5 -0
  112. package/src/client/hooks/use-navbar.ts +60 -0
  113. package/src/client/hooks/use-onthispage.ts +23 -0
  114. package/src/client/hooks/use-page-nav.ts +22 -0
  115. package/src/client/hooks/use-routes.ts +72 -0
  116. package/src/client/hooks/use-search.ts +71 -0
  117. package/src/client/hooks/use-sidebar.ts +49 -0
  118. package/src/client/hooks/use-tabs.ts +43 -0
  119. package/src/client/hooks/use-version.ts +78 -0
  120. package/src/client/index.ts +55 -17
  121. package/src/client/integrations/codesandbox.ts +179 -0
  122. package/src/client/ssr.tsx +27 -16
  123. package/src/client/theme/neutral.css +360 -0
  124. package/src/client/types.ts +131 -27
  125. package/src/client/utils/cn.ts +6 -0
  126. package/src/client/utils/copy-clipboard.ts +22 -0
  127. package/src/client/utils/get-base-file-path.ts +21 -0
  128. package/src/client/utils/github.ts +121 -0
  129. package/src/client/utils/use-on-change.ts +15 -0
  130. package/src/client/virtual.d.ts +24 -0
  131. package/src/node/cache.ts +156 -156
  132. package/src/node/config.ts +159 -103
  133. package/src/node/index.ts +13 -13
  134. package/src/node/mdx.ts +213 -61
  135. package/src/node/plugin/entry.ts +29 -18
  136. package/src/node/plugin/html.ts +11 -11
  137. package/src/node/plugin/index.ts +161 -84
  138. package/src/node/plugin/types.ts +2 -4
  139. package/src/node/routes/cache.ts +6 -6
  140. package/src/node/routes/index.ts +206 -113
  141. package/src/node/routes/parser.ts +102 -82
  142. package/src/node/routes/sorter.ts +15 -15
  143. package/src/node/routes/types.ts +24 -24
  144. package/src/node/ssg/index.ts +73 -47
  145. package/src/node/ssg/meta.ts +4 -4
  146. package/src/node/ssg/options.ts +5 -5
  147. package/src/node/ssg/sitemap.ts +14 -14
  148. package/src/node/utils.ts +54 -31
  149. package/tsconfig.json +25 -20
  150. package/tsup.config.ts +23 -14
  151. package/dist/PackageManagerTabs-NVT7G625.mjs +0 -99
  152. package/dist/SearchDialog-AGVF6JBO.mjs +0 -194
  153. package/dist/SearchDialog-YPDOM7Q6.css +0 -2847
  154. package/dist/Video-KNTY5BNO.mjs +0 -6
  155. package/dist/cache-KNL5B4EE.mjs +0 -12
  156. package/dist/chunk-7SFUJWTB.mjs +0 -211
  157. package/dist/chunk-FFBNU6IJ.mjs +0 -386
  158. package/dist/chunk-FMTOYQLO.mjs +0 -37
  159. package/dist/chunk-TKLQWU7H.mjs +0 -1920
  160. package/dist/chunk-Z7JHYNAS.mjs +0 -57
  161. package/dist/client/index.css +0 -2847
  162. package/dist/client/ssr.css +0 -2847
  163. package/dist/types-Dj-bfnC3.d.mts +0 -74
  164. package/dist/types-Dj-bfnC3.d.ts +0 -74
  165. package/src/client/theme/components/CodeBlock/CodeBlock.tsx +0 -61
  166. package/src/client/theme/components/CodeBlock/index.ts +0 -1
  167. package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +0 -131
  168. package/src/client/theme/components/PackageManagerTabs/index.ts +0 -1
  169. package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +0 -64
  170. package/src/client/theme/components/Playground/Playground.tsx +0 -180
  171. package/src/client/theme/components/Playground/index.ts +0 -1
  172. package/src/client/theme/components/Playground/playground.css +0 -238
  173. package/src/client/theme/components/Video/Video.tsx +0 -84
  174. package/src/client/theme/components/Video/index.ts +0 -1
  175. package/src/client/theme/components/Video/video.css +0 -41
  176. package/src/client/theme/components/mdx/Admonition.tsx +0 -80
  177. package/src/client/theme/components/mdx/Badge.tsx +0 -31
  178. package/src/client/theme/components/mdx/Button.tsx +0 -50
  179. package/src/client/theme/components/mdx/Card.tsx +0 -80
  180. package/src/client/theme/components/mdx/Field.tsx +0 -60
  181. package/src/client/theme/components/mdx/FileTree.tsx +0 -229
  182. package/src/client/theme/components/mdx/List.tsx +0 -57
  183. package/src/client/theme/components/mdx/Table.tsx +0 -151
  184. package/src/client/theme/components/mdx/Tabs.tsx +0 -123
  185. package/src/client/theme/components/mdx/index.ts +0 -27
  186. package/src/client/theme/components/mdx/mdx-components.css +0 -764
  187. package/src/client/theme/icons/bun.tsx +0 -62
  188. package/src/client/theme/icons/deno.tsx +0 -20
  189. package/src/client/theme/icons/discord.tsx +0 -12
  190. package/src/client/theme/icons/github.tsx +0 -15
  191. package/src/client/theme/icons/npm.tsx +0 -13
  192. package/src/client/theme/icons/pnpm.tsx +0 -72
  193. package/src/client/theme/icons/twitter.tsx +0 -12
  194. package/src/client/theme/styles/markdown.css +0 -394
  195. package/src/client/theme/styles/variables.css +0 -175
  196. package/src/client/theme/styles.css +0 -39
  197. package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +0 -68
  198. package/src/client/theme/ui/Breadcrumbs/index.ts +0 -1
  199. package/src/client/theme/ui/CopyMarkdown/CopyMarkdown.tsx +0 -82
  200. package/src/client/theme/ui/CopyMarkdown/copy-markdown.css +0 -112
  201. package/src/client/theme/ui/CopyMarkdown/index.ts +0 -1
  202. package/src/client/theme/ui/ErrorBoundary/ErrorBoundary.tsx +0 -50
  203. package/src/client/theme/ui/ErrorBoundary/error-boundary.css +0 -55
  204. package/src/client/theme/ui/ErrorBoundary/index.ts +0 -1
  205. package/src/client/theme/ui/Footer/footer.css +0 -32
  206. package/src/client/theme/ui/Head/Head.tsx +0 -69
  207. package/src/client/theme/ui/Head/index.ts +0 -1
  208. package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +0 -125
  209. package/src/client/theme/ui/LanguageSwitcher/index.ts +0 -1
  210. package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +0 -98
  211. package/src/client/theme/ui/Layout/Layout.tsx +0 -203
  212. package/src/client/theme/ui/Layout/base.css +0 -106
  213. package/src/client/theme/ui/Layout/index.ts +0 -2
  214. package/src/client/theme/ui/Layout/pagination.css +0 -72
  215. package/src/client/theme/ui/Layout/responsive.css +0 -47
  216. package/src/client/theme/ui/Link/Link.tsx +0 -392
  217. package/src/client/theme/ui/Link/LinkPreview.tsx +0 -59
  218. package/src/client/theme/ui/Link/index.ts +0 -2
  219. package/src/client/theme/ui/Link/link-preview.css +0 -48
  220. package/src/client/theme/ui/Loading/Loading.tsx +0 -10
  221. package/src/client/theme/ui/Loading/index.ts +0 -1
  222. package/src/client/theme/ui/Loading/loading.css +0 -30
  223. package/src/client/theme/ui/Navbar/GithubStars.tsx +0 -27
  224. package/src/client/theme/ui/Navbar/Navbar.tsx +0 -193
  225. package/src/client/theme/ui/Navbar/Tabs.tsx +0 -99
  226. package/src/client/theme/ui/Navbar/index.ts +0 -2
  227. package/src/client/theme/ui/Navbar/navbar.css +0 -347
  228. package/src/client/theme/ui/NotFound/NotFound.tsx +0 -19
  229. package/src/client/theme/ui/NotFound/index.ts +0 -1
  230. package/src/client/theme/ui/NotFound/not-found.css +0 -64
  231. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +0 -244
  232. package/src/client/theme/ui/OnThisPage/index.ts +0 -1
  233. package/src/client/theme/ui/OnThisPage/toc.css +0 -152
  234. package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +0 -18
  235. package/src/client/theme/ui/PoweredBy/index.ts +0 -1
  236. package/src/client/theme/ui/PoweredBy/powered-by.css +0 -76
  237. package/src/client/theme/ui/ProgressBar/ProgressBar.css +0 -17
  238. package/src/client/theme/ui/ProgressBar/ProgressBar.tsx +0 -51
  239. package/src/client/theme/ui/ProgressBar/index.ts +0 -1
  240. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +0 -209
  241. package/src/client/theme/ui/SearchDialog/index.ts +0 -1
  242. package/src/client/theme/ui/SearchDialog/search.css +0 -152
  243. package/src/client/theme/ui/Sidebar/Sidebar.tsx +0 -244
  244. package/src/client/theme/ui/Sidebar/index.ts +0 -1
  245. package/src/client/theme/ui/Sidebar/sidebar.css +0 -230
  246. package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +0 -69
  247. package/src/client/theme/ui/ThemeToggle/index.ts +0 -1
  248. package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +0 -136
  249. package/src/client/theme/ui/VersionSwitcher/index.ts +0 -1
  250. package/src/client/utils.ts +0 -49
@@ -1,229 +0,0 @@
1
- import React, { Children, isValidElement, useState } from "react";
2
- import {
3
- Folder,
4
- FileText,
5
- File,
6
- FileCode,
7
- FileImage,
8
- ChevronRight,
9
- } from "lucide-react";
10
-
11
- export interface FileTreeProps {
12
- children: React.ReactNode;
13
- }
14
-
15
- function getTextContent(node: React.ReactNode): string {
16
- if (typeof node === "string") return node;
17
- if (typeof node === "number") return node.toString();
18
- if (Array.isArray(node)) return node.map(getTextContent).join("");
19
- if (isValidElement(node)) {
20
- return getTextContent((node.props as any).children);
21
- }
22
- return "";
23
- }
24
-
25
- function getFileIcon(filename: string) {
26
- const name = filename.toLowerCase();
27
-
28
- if (
29
- name.endsWith(".ts") ||
30
- name.endsWith(".tsx") ||
31
- name.endsWith(".js") ||
32
- name.endsWith(".jsx") ||
33
- name.endsWith(".json") ||
34
- name.endsWith(".mjs") ||
35
- name.endsWith(".cjs") ||
36
- name.endsWith(".astro") ||
37
- name.endsWith(".vue") ||
38
- name.endsWith(".svelte")
39
- ) {
40
- return (
41
- <FileCode size={16} strokeWidth={2} className="ld-file-tree__icon-file" />
42
- );
43
- }
44
-
45
- if (name.endsWith(".md") || name.endsWith(".mdx") || name.endsWith(".txt")) {
46
- return (
47
- <FileText size={16} strokeWidth={2} className="ld-file-tree__icon-file" />
48
- );
49
- }
50
-
51
- if (
52
- name.endsWith(".png") ||
53
- name.endsWith(".jpg") ||
54
- name.endsWith(".jpeg") ||
55
- name.endsWith(".svg") ||
56
- name.endsWith(".gif")
57
- ) {
58
- return (
59
- <FileImage
60
- size={16}
61
- strokeWidth={2}
62
- className="ld-file-tree__icon-file"
63
- />
64
- );
65
- }
66
-
67
- return <File size={16} strokeWidth={2} className="ld-file-tree__icon-file" />;
68
- }
69
-
70
- // Helper to reliably check for ul and li elements, including MDX wrappers
71
- function isListElement(node: any, tag: "ul" | "li"): boolean {
72
- if (typeof node.type === "string") {
73
- return node.type === tag;
74
- }
75
- if (typeof node.type === "function") {
76
- return node.type.name === tag || node.type.name?.toLowerCase() === tag;
77
- }
78
- // MDX specific wrapper detection
79
- if (node.props && node.props.originalType === tag) {
80
- return true;
81
- }
82
- if (node.props && node.props.mdxType === tag) {
83
- return true;
84
- }
85
- return false;
86
- }
87
-
88
- function FolderNode({
89
- labelText,
90
- nestedNodes,
91
- depth,
92
- }: {
93
- labelText: string;
94
- nestedNodes: React.ReactNode[];
95
- depth: number;
96
- }) {
97
- const [isOpen, setIsOpen] = useState(true);
98
-
99
- return (
100
- <li className="ld-file-tree__item">
101
- <div
102
- className="ld-file-tree__label ld-file-tree__label--folder"
103
- onClick={() => setIsOpen(!isOpen)}
104
- style={{ cursor: "pointer" }}
105
- >
106
- <span className="ld-file-tree__icon ld-file-tree__icon--chevron">
107
- <ChevronRight
108
- size={14}
109
- className={`ld-file-tree__chevron ${isOpen ? "ld-file-tree__chevron--open" : ""}`}
110
- strokeWidth={3}
111
- />
112
- </span>
113
- <span className="ld-file-tree__icon">
114
- <Folder
115
- size={16}
116
- strokeWidth={2}
117
- className="ld-file-tree__icon-folder"
118
- fill="currentColor"
119
- fillOpacity={0.15}
120
- />
121
- </span>
122
- <span className="ld-file-tree__name">{labelText}</span>
123
- </div>
124
- {isOpen && nestedNodes.length > 0 && (
125
- <div className="ld-file-tree__nested">
126
- {nestedNodes.map((child, index) => (
127
- <React.Fragment key={index}>
128
- {parseNode(child, depth)}
129
- </React.Fragment>
130
- ))}
131
- </div>
132
- )}
133
- </li>
134
- );
135
- }
136
-
137
- function parseNode(node: React.ReactNode, depth: number = 0): React.ReactNode {
138
- if (!isValidElement(node)) {
139
- return node;
140
- }
141
-
142
- if (isListElement(node, "ul")) {
143
- return (
144
- <ul
145
- className={`ld-file-tree__list ${depth === 0 ? "ld-file-tree__list--root" : ""}`}
146
- >
147
- {Children.map((node.props as any).children, (child, index) => (
148
- <React.Fragment key={index}>
149
- {parseNode(child, depth + 1)}
150
- </React.Fragment>
151
- ))}
152
- </ul>
153
- );
154
- }
155
-
156
- if (isListElement(node, "li")) {
157
- const children = Children.toArray((node.props as any).children);
158
-
159
- // Find nested list indicating a directory
160
- const nestedListIndex = children.findIndex(
161
- (child) => isValidElement(child) && isListElement(child, "ul"),
162
- );
163
- const hasNested = nestedListIndex !== -1;
164
-
165
- // Separate text label from nested items
166
- const labelNodes = hasNested
167
- ? children.slice(0, nestedListIndex)
168
- : children;
169
- const nestedNodes = hasNested ? children.slice(nestedListIndex) : [];
170
-
171
- const rawLabelContent = getTextContent(labelNodes).trim();
172
- const isExplicitDir = rawLabelContent.endsWith("/");
173
- const labelText = isExplicitDir
174
- ? rawLabelContent.slice(0, -1)
175
- : rawLabelContent;
176
-
177
- const isFolder = hasNested || isExplicitDir;
178
-
179
- if (isFolder) {
180
- return (
181
- <FolderNode
182
- labelText={labelText}
183
- nestedNodes={nestedNodes}
184
- depth={depth}
185
- />
186
- );
187
- }
188
-
189
- return (
190
- <li className="ld-file-tree__item">
191
- <div className="ld-file-tree__label ld-file-tree__label--file">
192
- <span className="ld-file-tree__icon ld-file-tree__icon--spacer"></span>
193
- <span className="ld-file-tree__icon">{getFileIcon(labelText)}</span>
194
- <span className="ld-file-tree__name">{labelText}</span>
195
- </div>
196
- </li>
197
- );
198
- }
199
-
200
- // If node is e.g. a paragraph injected by MDX wrapping the list
201
- if ((node.props as any).children) {
202
- return Children.map((node.props as any).children, (child, index) => (
203
- <React.Fragment key={index}>{parseNode(child, depth)}</React.Fragment>
204
- ));
205
- }
206
-
207
- return node;
208
- }
209
-
210
- /**
211
- * FileTree component displays a customized, styled tree structure for markdown lists.
212
- *
213
- * ```mdx
214
- * <FileTree>
215
- * - src/
216
- * - index.ts
217
- * - components/
218
- * - Button.tsx
219
- * - package.json
220
- * </FileTree>
221
- * ```
222
- */
223
- export function FileTree({ children }: FileTreeProps) {
224
- return (
225
- <div className="ld-file-tree" dir="ltr">
226
- {Children.map(children, (child) => parseNode(child, 0))}
227
- </div>
228
- );
229
- }
@@ -1,57 +0,0 @@
1
- import React, { Children } from "react";
2
- import { Check, ChevronRight } from "lucide-react";
3
-
4
- export interface ListProps extends React.HTMLAttributes<HTMLUListElement> {
5
- /** Visual variant */
6
- variant?: "checked" | "arrow" | "default";
7
- children: React.ReactNode;
8
- }
9
-
10
- const ICON_MAP: Record<string, React.ReactNode> = {
11
- checked: <Check size={14} className="ld-list__icon" />,
12
- arrow: <ChevronRight size={14} className="ld-list__icon" />,
13
- };
14
-
15
- /**
16
- * Enhanced list component with icon variants.
17
- *
18
- * ```mdx
19
- * <List variant="checked">
20
- * <li>File-system routing</li>
21
- * <li>MDX support</li>
22
- * <li>Syntax highlighting</li>
23
- * </List>
24
- * ```
25
- */
26
- export function List({
27
- variant = "default",
28
- children,
29
- className = "",
30
- ...rest
31
- }: ListProps) {
32
- if (variant === "default") {
33
- return (
34
- <ul className={`ld-list ${className}`.trim()} {...rest}>
35
- {children}
36
- </ul>
37
- );
38
- }
39
-
40
- const icon = ICON_MAP[variant];
41
-
42
- return (
43
- <ul className={`ld-list ld-list--${variant} ${className}`.trim()} {...rest}>
44
- {Children.map(children, (child) => {
45
- if (!React.isValidElement(child)) return child;
46
- return (
47
- <li className="ld-list__item">
48
- {icon}
49
- <span className="ld-list__text">
50
- {(child as React.ReactElement<any>).props.children}
51
- </span>
52
- </li>
53
- );
54
- })}
55
- </ul>
56
- );
57
- }
@@ -1,151 +0,0 @@
1
- import React, { useState, useMemo } from "react";
2
- import { ChevronUp, ChevronDown, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react";
3
-
4
- export interface TableProps {
5
- headers?: string[];
6
- data?: (string | React.ReactNode)[][];
7
- children?: React.ReactNode;
8
- className?: string;
9
- sortable?: boolean;
10
- paginated?: boolean;
11
- pageSize?: number;
12
- }
13
-
14
- export function Table({
15
- headers,
16
- data,
17
- children,
18
- className = "",
19
- sortable = false,
20
- paginated = false,
21
- pageSize = 10,
22
- }: TableProps) {
23
- const [sortConfig, setSortConfig] = useState<{ key: number; direction: 'asc' | 'desc' } | null>(null);
24
- const [currentPage, setCurrentPage] = useState(1);
25
-
26
- const processedData = useMemo(() => {
27
- if (!data) return [];
28
- let items = [...data];
29
-
30
- if (sortable && sortConfig !== null) {
31
- items.sort((a, b) => {
32
- const aVal = a[sortConfig.key];
33
- const bVal = b[sortConfig.key];
34
-
35
- // Simple string comparison for sorting
36
- const aStr = typeof aVal === 'string' ? aVal : '';
37
- const bStr = typeof bVal === 'string' ? bVal : '';
38
-
39
- if (aStr < bStr) return sortConfig.direction === 'asc' ? -1 : 1;
40
- if (aStr > bStr) return sortConfig.direction === 'asc' ? 1 : -1;
41
- return 0;
42
- });
43
- }
44
-
45
- return items;
46
- }, [data, sortConfig, sortable]);
47
-
48
- const totalPages = Math.ceil(processedData.length / pageSize);
49
- const paginatedData = useMemo(() => {
50
- if (!paginated) return processedData;
51
- const start = (currentPage - 1) * pageSize;
52
- return processedData.slice(start, start + pageSize);
53
- }, [processedData, paginated, currentPage, pageSize]);
54
-
55
- const requestSort = (index: number) => {
56
- if (!sortable) return;
57
- let direction: 'asc' | 'desc' = 'asc';
58
- if (sortConfig && sortConfig.key === index && sortConfig.direction === 'asc') {
59
- direction = 'desc';
60
- }
61
- setSortConfig({ key: index, direction });
62
- };
63
-
64
- const renderSortIcon = (index: number) => {
65
- if (!sortable) return null;
66
- if (sortConfig?.key !== index) return <ChevronDown size={14} className="ld-table-sort-icon ld-table-sort-icon--hidden" />;
67
- return sortConfig.direction === 'asc' ? <ChevronUp size={14} className="ld-table-sort-icon" /> : <ChevronDown size={14} className="ld-table-sort-icon" />;
68
- };
69
-
70
- const tableContent = children ? (
71
- children
72
- ) : (
73
- <>
74
- {headers && (
75
- <thead>
76
- <tr>
77
- {headers.map((header, i) => (
78
- <th
79
- key={i}
80
- onClick={() => requestSort(i)}
81
- className={sortable ? "ld-table-header--sortable" : ""}
82
- >
83
- <div className="ld-table-header-content">
84
- {header}
85
- {renderSortIcon(i)}
86
- </div>
87
- </th>
88
- ))}
89
- </tr>
90
- </thead>
91
- )}
92
- {paginatedData && (
93
- <tbody>
94
- {paginatedData.map((row, i) => (
95
- <tr key={i}>
96
- {row.map((cell, j) => (
97
- <td key={j}>{cell}</td>
98
- ))}
99
- </tr>
100
- ))}
101
- </tbody>
102
- )}
103
- </>
104
- );
105
-
106
- return (
107
- <div className={`ld-table-container ${className}`.trim()}>
108
- <div className="ld-table-wrapper">
109
- <table className="ld-table">{tableContent}</table>
110
- </div>
111
-
112
- {paginated && totalPages > 1 && (
113
- <div className="ld-table-pagination">
114
- <div className="ld-table-pagination-info">
115
- Page {currentPage} of {totalPages}
116
- </div>
117
- <div className="ld-table-pagination-controls">
118
- <button
119
- onClick={() => setCurrentPage(1)}
120
- disabled={currentPage === 1}
121
- className="ld-table-pagination-btn"
122
- >
123
- <ChevronsLeft size={16} />
124
- </button>
125
- <button
126
- onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
127
- disabled={currentPage === 1}
128
- className="ld-table-pagination-btn"
129
- >
130
- <ChevronLeft size={16} />
131
- </button>
132
- <button
133
- onClick={() => setCurrentPage(prev => Math.min(prev + 1, totalPages))}
134
- disabled={currentPage === totalPages}
135
- className="ld-table-pagination-btn"
136
- >
137
- <ChevronRight size={16} />
138
- </button>
139
- <button
140
- onClick={() => setCurrentPage(totalPages)}
141
- disabled={currentPage === totalPages}
142
- className="ld-table-pagination-btn"
143
- >
144
- <ChevronsRight size={16} />
145
- </button>
146
- </div>
147
- </div>
148
- )}
149
- </div>
150
- );
151
- }
@@ -1,123 +0,0 @@
1
- import React, { useState, Children, isValidElement, useRef } from "react";
2
- import { CodeBlock } from "../CodeBlock";
3
- import { NPM } from "../../icons/npm";
4
- import { Pnpm } from "../../icons/pnpm";
5
- import { Bun } from "../../icons/bun";
6
- import { Deno } from "../../icons/deno";
7
-
8
- /* ─── Tab (individual panel) ──────────────────────────────── */
9
- export interface TabProps {
10
- /** The label shown in the tab bar */
11
- label: string;
12
- children: React.ReactNode;
13
- }
14
-
15
- /**
16
- * A single tab panel. Must be used inside `<Tabs>`.
17
- *
18
- * ```mdx
19
- * <Tab label="npm">npm install boltdocs</Tab>
20
- * ```
21
- */
22
- export function Tab({ children }: TabProps) {
23
- // If children is a simple string, wrap it in a CodeBlock for syntax highlighting
24
- const content =
25
- typeof children === "string" ? (
26
- <CodeBlock className="language-bash">
27
- <code>{children.trim()}</code>
28
- </CodeBlock>
29
- ) : (
30
- children
31
- );
32
-
33
- return <div className="ld-tab-panel">{content}</div>;
34
- }
35
-
36
- /* ─── Tabs (container) ────────────────────────────────────── */
37
- export interface TabsProps {
38
- /** Which tab index is initially active (0-based, default 0) */
39
- defaultIndex?: number;
40
- children: React.ReactNode;
41
- }
42
-
43
- const getIconForLabel = (label: string) => {
44
- const l = label.toLowerCase();
45
- if (l.includes("pnpm")) return <Pnpm />;
46
- if (l.includes("npm")) return <NPM />;
47
- if (l.includes("bun")) return <Bun />;
48
- if (l.includes("deno")) return <Deno />;
49
- return null;
50
- };
51
-
52
- /**
53
- * Tab container that manages active state.
54
- *
55
- * ```mdx
56
- * <Tabs>
57
- * <Tab label="npm">npm install boltdocs</Tab>
58
- * <Tab label="pnpm">pnpm add boltdocs</Tab>
59
- * </Tabs>
60
- * ```
61
- */
62
- export function Tabs({ defaultIndex = 0, children }: TabsProps) {
63
- const [active, setActive] = useState(defaultIndex);
64
- const tabRefs = useRef<(HTMLButtonElement | null)[]>([]);
65
-
66
- // Extract Tab children
67
- const tabs = Children.toArray(children).filter(
68
- (child) => isValidElement(child) && (child as any).props?.label,
69
- );
70
-
71
- const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
72
- let newIndex = active;
73
- if (e.key === "ArrowRight") {
74
- newIndex = (active + 1) % tabs.length;
75
- } else if (e.key === "ArrowLeft") {
76
- newIndex = (active - 1 + tabs.length) % tabs.length;
77
- }
78
-
79
- if (newIndex !== active) {
80
- setActive(newIndex);
81
- tabRefs.current[newIndex]?.focus();
82
- }
83
- };
84
-
85
- return (
86
- <div className="ld-tabs">
87
- <div className="ld-tabs__bar" role="tablist" onKeyDown={handleKeyDown}>
88
- {tabs.map((child, i) => {
89
- const label = (child as React.ReactElement<TabProps>).props.label;
90
- const Icon = getIconForLabel(label);
91
- return (
92
- <button
93
- key={i}
94
- role="tab"
95
- aria-selected={i === active}
96
- aria-controls={`tabpanel-${i}`}
97
- id={`tab-${i}`}
98
- tabIndex={i === active ? 0 : -1}
99
- ref={(el) => {
100
- tabRefs.current[i] = el;
101
- }}
102
- className={`ld-tabs__trigger ${
103
- i === active ? "ld-tabs__trigger--active" : ""
104
- }`}
105
- onClick={() => setActive(i)}
106
- >
107
- {Icon}
108
- <span>{label}</span>
109
- </button>
110
- );
111
- })}
112
- </div>
113
- <div
114
- className="ld-tabs__content"
115
- role="tabpanel"
116
- id={`tabpanel-${active}`}
117
- aria-labelledby={`tab-${active}`}
118
- >
119
- {tabs[active]}
120
- </div>
121
- </div>
122
- );
123
- }
@@ -1,27 +0,0 @@
1
- // MDX UI Components — barrel export
2
- export { Button } from "./Button";
3
- export type { ButtonProps } from "./Button";
4
-
5
- export { Badge } from "./Badge";
6
- export type { BadgeProps } from "./Badge";
7
-
8
- export { Card, Cards } from "./Card";
9
- export type { CardProps, CardsProps } from "./Card";
10
-
11
- export { Tabs, Tab } from "./Tabs";
12
- export type { TabsProps, TabProps } from "./Tabs";
13
-
14
- export { Admonition, Note, Tip, Warning, Danger, InfoBox } from "./Admonition";
15
- export type { AdmonitionProps } from "./Admonition";
16
-
17
- export { List } from "./List";
18
- export type { ListProps } from "./List";
19
-
20
- export { FileTree } from "./FileTree";
21
- export type { FileTreeProps } from "./FileTree";
22
-
23
- export { Table } from "./Table";
24
- export type { TableProps } from "./Table";
25
-
26
- export { Field } from "./Field";
27
- export type { FieldProps } from "./Field";