blodemd 0.1.0 → 0.2.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 (289) hide show
  1. package/dist/cli.mjs +50 -174
  2. package/dist/cli.mjs.map +1 -1
  3. package/package.json +3 -36
  4. package/dev-server/app/[[...slug]]/page.tsx +0 -140
  5. package/dev-server/app/blodemd-dev/invalidate/route.ts +0 -12
  6. package/dev-server/app/blodemd-dev/static/[...path]/route.ts +0 -32
  7. package/dev-server/app/blodemd-dev/version/route.ts +0 -14
  8. package/dev-server/app/blodemd-internal/proxy/route.ts +0 -86
  9. package/dev-server/app/error.tsx +0 -24
  10. package/dev-server/app/favicon.ico +0 -0
  11. package/dev-server/app/globals.css +0 -4
  12. package/dev-server/app/layout.tsx +0 -38
  13. package/dev-server/app/not-found.tsx +0 -18
  14. package/dev-server/app/search/route.ts +0 -17
  15. package/dev-server/components/dev-reload-script.tsx +0 -86
  16. package/dev-server/components/providers.tsx +0 -15
  17. package/dev-server/lib/dev-state.ts +0 -8
  18. package/dev-server/lib/local-content-source.ts +0 -103
  19. package/dev-server/lib/local-runtime.tsx +0 -555
  20. package/dev-server/next-env.d.ts +0 -5
  21. package/dev-server/next.config.js +0 -54
  22. package/dev-server/package.json +0 -61
  23. package/dev-server/postcss.config.mjs +0 -7
  24. package/dev-server/public/glide-variable.woff2 +0 -0
  25. package/dev-server/tsconfig.json +0 -50
  26. package/docs/app/globals.css +0 -471
  27. package/docs/components/animate-ui/primitives/buttons/button.tsx +0 -14
  28. package/docs/components/api/api-playground.tsx +0 -467
  29. package/docs/components/api/api-reference.tsx +0 -157
  30. package/docs/components/content/collection-index.tsx +0 -114
  31. package/docs/components/docs/contextual-menu.tsx +0 -495
  32. package/docs/components/docs/copy-page-menu.tsx +0 -364
  33. package/docs/components/docs/doc-header.tsx +0 -223
  34. package/docs/components/docs/doc-shell.tsx +0 -355
  35. package/docs/components/docs/doc-sidebar.tsx +0 -256
  36. package/docs/components/docs/doc-toc.tsx +0 -46
  37. package/docs/components/docs/mobile-nav.tsx +0 -195
  38. package/docs/components/docs/sidebar-active-highlight.tsx +0 -34
  39. package/docs/components/docs/sidebar-scroll-area.tsx +0 -63
  40. package/docs/components/git/repo-picker.tsx +0 -529
  41. package/docs/components/icons/doc-icon.tsx +0 -96
  42. package/docs/components/mdx/accordion.tsx +0 -83
  43. package/docs/components/mdx/agent-instructions.tsx +0 -17
  44. package/docs/components/mdx/badge.tsx +0 -79
  45. package/docs/components/mdx/callout.tsx +0 -88
  46. package/docs/components/mdx/card.tsx +0 -110
  47. package/docs/components/mdx/code-block.tsx +0 -80
  48. package/docs/components/mdx/code-group.tsx +0 -203
  49. package/docs/components/mdx/color.tsx +0 -87
  50. package/docs/components/mdx/columns.tsx +0 -25
  51. package/docs/components/mdx/expandable.tsx +0 -45
  52. package/docs/components/mdx/field-layout.tsx +0 -77
  53. package/docs/components/mdx/frame.tsx +0 -23
  54. package/docs/components/mdx/get-text-content.ts +0 -18
  55. package/docs/components/mdx/icon.tsx +0 -12
  56. package/docs/components/mdx/iframe.tsx +0 -62
  57. package/docs/components/mdx/index.tsx +0 -121
  58. package/docs/components/mdx/installer.tsx +0 -20
  59. package/docs/components/mdx/panel.tsx +0 -11
  60. package/docs/components/mdx/param-field.tsx +0 -56
  61. package/docs/components/mdx/preview.tsx +0 -36
  62. package/docs/components/mdx/prompt.tsx +0 -63
  63. package/docs/components/mdx/request-example.tsx +0 -27
  64. package/docs/components/mdx/response-field.tsx +0 -42
  65. package/docs/components/mdx/steps.tsx +0 -92
  66. package/docs/components/mdx/tabs.tsx +0 -193
  67. package/docs/components/mdx/tile.tsx +0 -43
  68. package/docs/components/mdx/tooltip.tsx +0 -71
  69. package/docs/components/mdx/tree.tsx +0 -120
  70. package/docs/components/mdx/type-table.tsx +0 -71
  71. package/docs/components/mdx/update.tsx +0 -44
  72. package/docs/components/mdx/video.tsx +0 -45
  73. package/docs/components/mdx/view.tsx +0 -66
  74. package/docs/components/posthog-provider.tsx +0 -42
  75. package/docs/components/providers.tsx +0 -15
  76. package/docs/components/tenant-analytics.tsx +0 -49
  77. package/docs/components/third-parties.tsx +0 -32
  78. package/docs/components/ui/badge.tsx +0 -61
  79. package/docs/components/ui/breadcrumb.tsx +0 -112
  80. package/docs/components/ui/button-group.tsx +0 -83
  81. package/docs/components/ui/button.tsx +0 -65
  82. package/docs/components/ui/card.tsx +0 -92
  83. package/docs/components/ui/command.tsx +0 -167
  84. package/docs/components/ui/copy-button.tsx +0 -129
  85. package/docs/components/ui/dialog.tsx +0 -146
  86. package/docs/components/ui/field.tsx +0 -237
  87. package/docs/components/ui/input.tsx +0 -23
  88. package/docs/components/ui/kbd.tsx +0 -98
  89. package/docs/components/ui/label.tsx +0 -22
  90. package/docs/components/ui/morph-icon.tsx +0 -79
  91. package/docs/components/ui/popover.tsx +0 -267
  92. package/docs/components/ui/search-dialog.tsx +0 -431
  93. package/docs/components/ui/search.tsx +0 -101
  94. package/docs/components/ui/separator.tsx +0 -26
  95. package/docs/components/ui/sheet.tsx +0 -133
  96. package/docs/components/ui/sidebar.tsx +0 -758
  97. package/docs/components/ui/skeleton.tsx +0 -11
  98. package/docs/components/ui/switch.tsx +0 -32
  99. package/docs/components/ui/tabs.tsx +0 -138
  100. package/docs/components/ui/theme-toggle.tsx +0 -62
  101. package/docs/components/ui/tooltip.tsx +0 -53
  102. package/docs/components/web-mcp.tsx +0 -115
  103. package/docs/lib/agent-skills.ts +0 -48
  104. package/docs/lib/api-client.ts +0 -72
  105. package/docs/lib/config.ts +0 -6
  106. package/docs/lib/content-root.ts +0 -33
  107. package/docs/lib/content-source.ts +0 -70
  108. package/docs/lib/contextual-options.ts +0 -222
  109. package/docs/lib/dashboard-session.ts +0 -167
  110. package/docs/lib/db.ts +0 -13
  111. package/docs/lib/docs-collection.ts +0 -7
  112. package/docs/lib/docs-runtime.tsx +0 -745
  113. package/docs/lib/edge-config.ts +0 -95
  114. package/docs/lib/env.ts +0 -23
  115. package/docs/lib/etag.ts +0 -22
  116. package/docs/lib/github-install.ts +0 -33
  117. package/docs/lib/llms-full.ts +0 -82
  118. package/docs/lib/marketing-markdown.ts +0 -79
  119. package/docs/lib/marketing-site.ts +0 -31
  120. package/docs/lib/mdx.ts +0 -98
  121. package/docs/lib/navigation.ts +0 -288
  122. package/docs/lib/openapi-proxy.ts +0 -88
  123. package/docs/lib/openapi.ts +0 -158
  124. package/docs/lib/platform-config.ts +0 -6
  125. package/docs/lib/project-authz.ts +0 -46
  126. package/docs/lib/routes.ts +0 -103
  127. package/docs/lib/server-cache.ts +0 -83
  128. package/docs/lib/shiki.ts +0 -44
  129. package/docs/lib/supabase.ts +0 -37
  130. package/docs/lib/tenancy.ts +0 -364
  131. package/docs/lib/tenant-headers.ts +0 -43
  132. package/docs/lib/tenant-static.ts +0 -705
  133. package/docs/lib/tenant-utility-context.ts +0 -62
  134. package/docs/lib/tenants.ts +0 -72
  135. package/docs/lib/theme.ts +0 -29
  136. package/docs/lib/time-ago.ts +0 -24
  137. package/docs/lib/toc.ts +0 -2
  138. package/docs/lib/use-mobile.ts +0 -19
  139. package/docs/lib/use-tab-observer.ts +0 -71
  140. package/docs/lib/utils.ts +0 -5
  141. package/packages/@repo/common/dist/index.d.ts +0 -16
  142. package/packages/@repo/common/dist/index.d.ts.map +0 -1
  143. package/packages/@repo/common/dist/index.js +0 -84
  144. package/packages/@repo/common/package.json +0 -34
  145. package/packages/@repo/common/src/index.ts +0 -101
  146. package/packages/@repo/contracts/dist/analytics.d.ts +0 -21
  147. package/packages/@repo/contracts/dist/analytics.d.ts.map +0 -1
  148. package/packages/@repo/contracts/dist/analytics.js +0 -18
  149. package/packages/@repo/contracts/dist/api-key.d.ts +0 -27
  150. package/packages/@repo/contracts/dist/api-key.d.ts.map +0 -1
  151. package/packages/@repo/contracts/dist/api-key.js +0 -20
  152. package/packages/@repo/contracts/dist/dates.d.ts +0 -4
  153. package/packages/@repo/contracts/dist/dates.d.ts.map +0 -1
  154. package/packages/@repo/contracts/dist/dates.js +0 -2
  155. package/packages/@repo/contracts/dist/deployment.d.ts +0 -71
  156. package/packages/@repo/contracts/dist/deployment.d.ts.map +0 -1
  157. package/packages/@repo/contracts/dist/deployment.js +0 -46
  158. package/packages/@repo/contracts/dist/domain.d.ts +0 -94
  159. package/packages/@repo/contracts/dist/domain.d.ts.map +0 -1
  160. package/packages/@repo/contracts/dist/domain.js +0 -36
  161. package/packages/@repo/contracts/dist/git.d.ts +0 -28
  162. package/packages/@repo/contracts/dist/git.d.ts.map +0 -1
  163. package/packages/@repo/contracts/dist/git.js +0 -24
  164. package/packages/@repo/contracts/dist/ids.d.ts +0 -14
  165. package/packages/@repo/contracts/dist/ids.d.ts.map +0 -1
  166. package/packages/@repo/contracts/dist/ids.js +0 -11
  167. package/packages/@repo/contracts/dist/index.d.ts +0 -12
  168. package/packages/@repo/contracts/dist/index.d.ts.map +0 -1
  169. package/packages/@repo/contracts/dist/index.js +0 -13
  170. package/packages/@repo/contracts/dist/pagination.d.ts +0 -23
  171. package/packages/@repo/contracts/dist/pagination.d.ts.map +0 -1
  172. package/packages/@repo/contracts/dist/pagination.js +0 -15
  173. package/packages/@repo/contracts/dist/project.d.ts +0 -42
  174. package/packages/@repo/contracts/dist/project.d.ts.map +0 -1
  175. package/packages/@repo/contracts/dist/project.js +0 -25
  176. package/packages/@repo/contracts/dist/tenant.d.ts +0 -147
  177. package/packages/@repo/contracts/dist/tenant.d.ts.map +0 -1
  178. package/packages/@repo/contracts/dist/tenant.js +0 -58
  179. package/packages/@repo/contracts/dist/user.d.ts +0 -9
  180. package/packages/@repo/contracts/dist/user.d.ts.map +0 -1
  181. package/packages/@repo/contracts/dist/user.js +0 -9
  182. package/packages/@repo/contracts/package.json +0 -37
  183. package/packages/@repo/contracts/src/analytics.ts +0 -33
  184. package/packages/@repo/contracts/src/api-key.ts +0 -27
  185. package/packages/@repo/contracts/src/dates.ts +0 -4
  186. package/packages/@repo/contracts/src/deployment.ts +0 -73
  187. package/packages/@repo/contracts/src/domain.ts +0 -51
  188. package/packages/@repo/contracts/src/git.ts +0 -31
  189. package/packages/@repo/contracts/src/ids.ts +0 -23
  190. package/packages/@repo/contracts/src/index.ts +0 -13
  191. package/packages/@repo/contracts/src/pagination.ts +0 -21
  192. package/packages/@repo/contracts/src/project.ts +0 -32
  193. package/packages/@repo/contracts/src/tenant.ts +0 -94
  194. package/packages/@repo/contracts/src/user.ts +0 -12
  195. package/packages/@repo/models/dist/docs-config.d.ts +0 -961
  196. package/packages/@repo/models/dist/docs-config.d.ts.map +0 -1
  197. package/packages/@repo/models/dist/docs-config.js +0 -531
  198. package/packages/@repo/models/dist/index.d.ts +0 -3
  199. package/packages/@repo/models/dist/index.d.ts.map +0 -1
  200. package/packages/@repo/models/dist/index.js +0 -3
  201. package/packages/@repo/models/dist/tenant.d.ts +0 -37
  202. package/packages/@repo/models/dist/tenant.d.ts.map +0 -1
  203. package/packages/@repo/models/dist/tenant.js +0 -1
  204. package/packages/@repo/models/package.json +0 -37
  205. package/packages/@repo/models/src/docs-config.ts +0 -629
  206. package/packages/@repo/models/src/index.ts +0 -3
  207. package/packages/@repo/models/src/tenant.ts +0 -44
  208. package/packages/@repo/prebuild/dist/index.d.ts +0 -2
  209. package/packages/@repo/prebuild/dist/index.d.ts.map +0 -1
  210. package/packages/@repo/prebuild/dist/index.js +0 -2
  211. package/packages/@repo/prebuild/dist/openapi.d.ts +0 -43
  212. package/packages/@repo/prebuild/dist/openapi.d.ts.map +0 -1
  213. package/packages/@repo/prebuild/dist/openapi.js +0 -86
  214. package/packages/@repo/prebuild/package.json +0 -39
  215. package/packages/@repo/prebuild/src/index.ts +0 -2
  216. package/packages/@repo/prebuild/src/openapi.ts +0 -154
  217. package/packages/@repo/previewing/dist/blob-source.d.ts +0 -16
  218. package/packages/@repo/previewing/dist/blob-source.d.ts.map +0 -1
  219. package/packages/@repo/previewing/dist/blob-source.js +0 -128
  220. package/packages/@repo/previewing/dist/config-loader.d.ts +0 -134
  221. package/packages/@repo/previewing/dist/config-loader.d.ts.map +0 -1
  222. package/packages/@repo/previewing/dist/config-loader.js +0 -231
  223. package/packages/@repo/previewing/dist/constants.d.ts +0 -15
  224. package/packages/@repo/previewing/dist/constants.d.ts.map +0 -1
  225. package/packages/@repo/previewing/dist/constants.js +0 -14
  226. package/packages/@repo/previewing/dist/content-index.d.ts +0 -7
  227. package/packages/@repo/previewing/dist/content-index.d.ts.map +0 -1
  228. package/packages/@repo/previewing/dist/content-index.js +0 -291
  229. package/packages/@repo/previewing/dist/content-source.d.ts +0 -12
  230. package/packages/@repo/previewing/dist/content-source.d.ts.map +0 -1
  231. package/packages/@repo/previewing/dist/content-source.js +0 -1
  232. package/packages/@repo/previewing/dist/fs-source.d.ts +0 -11
  233. package/packages/@repo/previewing/dist/fs-source.d.ts.map +0 -1
  234. package/packages/@repo/previewing/dist/fs-source.js +0 -71
  235. package/packages/@repo/previewing/dist/index.d.ts +0 -16
  236. package/packages/@repo/previewing/dist/index.d.ts.map +0 -1
  237. package/packages/@repo/previewing/dist/index.js +0 -13
  238. package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts +0 -3
  239. package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts.map +0 -1
  240. package/packages/@repo/previewing/dist/markdown/agent-markdown.js +0 -176
  241. package/packages/@repo/previewing/dist/markdown/format.d.ts +0 -8
  242. package/packages/@repo/previewing/dist/markdown/format.d.ts.map +0 -1
  243. package/packages/@repo/previewing/dist/markdown/format.js +0 -43
  244. package/packages/@repo/previewing/dist/markdown/links.d.ts +0 -3
  245. package/packages/@repo/previewing/dist/markdown/links.d.ts.map +0 -1
  246. package/packages/@repo/previewing/dist/markdown/links.js +0 -31
  247. package/packages/@repo/previewing/dist/openapi-pages.d.ts +0 -7
  248. package/packages/@repo/previewing/dist/openapi-pages.d.ts.map +0 -1
  249. package/packages/@repo/previewing/dist/openapi-pages.js +0 -200
  250. package/packages/@repo/previewing/dist/search-index.d.ts +0 -4
  251. package/packages/@repo/previewing/dist/search-index.d.ts.map +0 -1
  252. package/packages/@repo/previewing/dist/search-index.js +0 -23
  253. package/packages/@repo/previewing/dist/serialization.d.ts +0 -13
  254. package/packages/@repo/previewing/dist/serialization.d.ts.map +0 -1
  255. package/packages/@repo/previewing/dist/serialization.js +0 -108
  256. package/packages/@repo/previewing/dist/toc-index.d.ts +0 -5
  257. package/packages/@repo/previewing/dist/toc-index.d.ts.map +0 -1
  258. package/packages/@repo/previewing/dist/toc-index.js +0 -53
  259. package/packages/@repo/previewing/dist/types.d.ts +0 -92
  260. package/packages/@repo/previewing/dist/types.d.ts.map +0 -1
  261. package/packages/@repo/previewing/dist/types.js +0 -1
  262. package/packages/@repo/previewing/dist/utility-index.d.ts +0 -7
  263. package/packages/@repo/previewing/dist/utility-index.d.ts.map +0 -1
  264. package/packages/@repo/previewing/dist/utility-index.js +0 -201
  265. package/packages/@repo/previewing/package.json +0 -41
  266. package/packages/@repo/previewing/src/blob-source.ts +0 -185
  267. package/packages/@repo/previewing/src/config-loader.ts +0 -316
  268. package/packages/@repo/previewing/src/constants.ts +0 -16
  269. package/packages/@repo/previewing/src/content-index.ts +0 -384
  270. package/packages/@repo/previewing/src/content-source.ts +0 -12
  271. package/packages/@repo/previewing/src/fs-source.ts +0 -103
  272. package/packages/@repo/previewing/src/index.ts +0 -71
  273. package/packages/@repo/previewing/src/markdown/agent-markdown.ts +0 -254
  274. package/packages/@repo/previewing/src/markdown/format.ts +0 -63
  275. package/packages/@repo/previewing/src/markdown/links.ts +0 -46
  276. package/packages/@repo/previewing/src/openapi-pages.ts +0 -319
  277. package/packages/@repo/previewing/src/search-index.ts +0 -38
  278. package/packages/@repo/previewing/src/serialization.ts +0 -191
  279. package/packages/@repo/previewing/src/toc-index.ts +0 -72
  280. package/packages/@repo/previewing/src/types.ts +0 -105
  281. package/packages/@repo/previewing/src/utility-index.ts +0 -304
  282. package/packages/@repo/validation/dist/index.d.ts +0 -12
  283. package/packages/@repo/validation/dist/index.d.ts.map +0 -1
  284. package/packages/@repo/validation/dist/index.js +0 -30
  285. package/packages/@repo/validation/package.json +0 -38
  286. package/packages/@repo/validation/src/blodemd-docs-schema.json +0 -3575
  287. package/packages/@repo/validation/src/index.ts +0 -59
  288. package/scripts/prepare-package.mjs +0 -53
  289. package/scripts/repo-packages.mjs +0 -8
@@ -1,529 +0,0 @@
1
- "use client";
2
-
3
- // oxlint-disable eslint-plugin-react-perf/jsx-no-new-function-as-prop -- deferred useCallback refactor
4
- import type { GitConnection } from "@repo/contracts";
5
- import {
6
- CheckIcon,
7
- ChevronDownIcon,
8
- GithubIcon,
9
- LockIcon,
10
- PlusIcon,
11
- SearchIcon,
12
- } from "blode-icons-react";
13
- import Image from "next/image";
14
- import { useRouter } from "next/navigation";
15
- import { useEffect, useState } from "react";
16
-
17
- import { Button } from "@/components/ui/button";
18
- import {
19
- Card,
20
- CardContent,
21
- CardDescription,
22
- CardHeader,
23
- CardTitle,
24
- } from "@/components/ui/card";
25
- import {
26
- Command,
27
- CommandEmpty,
28
- CommandGroup,
29
- CommandInput,
30
- CommandItem,
31
- CommandList,
32
- CommandSeparator,
33
- } from "@/components/ui/command";
34
- import {
35
- Field,
36
- FieldDescription,
37
- FieldError,
38
- FieldGroup,
39
- FieldLabel,
40
- } from "@/components/ui/field";
41
- import { Input } from "@/components/ui/input";
42
- import {
43
- Popover,
44
- PopoverContent,
45
- PopoverTrigger,
46
- } from "@/components/ui/popover";
47
- import { ApiError, apiFetch } from "@/lib/api-client";
48
- import { GITHUB_INSTALL_STATE_KEY } from "@/lib/github-install";
49
- import { timeAgo } from "@/lib/time-ago";
50
- import { cn } from "@/lib/utils";
51
-
52
- interface RepoPickerInstallation {
53
- id: number;
54
- accountLogin: string;
55
- accountType: string;
56
- }
57
-
58
- interface RepoPickerProps {
59
- accessToken: string;
60
- installations: RepoPickerInstallation[];
61
- onAddAccount: () => void;
62
- projectId: string;
63
- projectSlug: string;
64
- addAccountPending?: boolean;
65
- initialInstallationId?: number | null;
66
- onConnected?: (connection: GitConnection) => void;
67
- }
68
-
69
- interface RepoSummary {
70
- defaultBranch: string;
71
- fullName: string;
72
- private: boolean;
73
- pushedAt: string | null;
74
- }
75
-
76
- const GithubAvatar = ({
77
- className,
78
- login,
79
- size = 24,
80
- }: {
81
- className?: string;
82
- login: string;
83
- size?: number;
84
- }) => (
85
- <Image
86
- alt=""
87
- className={cn(
88
- "shrink-0 rounded-full bg-muted ring-1 ring-black/5",
89
- className
90
- )}
91
- height={size}
92
- src={`https://github.com/${login}.png?size=${size * 2}`}
93
- unoptimized
94
- width={size}
95
- />
96
- );
97
-
98
- const ConfigureRepoCard = ({
99
- branch,
100
- docsPath,
101
- formError,
102
- onBranchChange,
103
- onChangeRepo,
104
- onConnect,
105
- onDocsPathChange,
106
- selected,
107
- submitting,
108
- }: {
109
- branch: string;
110
- docsPath: string;
111
- formError: string | null;
112
- onBranchChange: (value: string) => void;
113
- onChangeRepo: () => void;
114
- onConnect: () => void;
115
- onDocsPathChange: (value: string) => void;
116
- selected: RepoSummary;
117
- submitting: boolean;
118
- }) => (
119
- <Card>
120
- <CardHeader>
121
- <CardTitle>Configure repository</CardTitle>
122
- <CardDescription>
123
- Set the branch and docs folder for this project.
124
- </CardDescription>
125
- </CardHeader>
126
- <CardContent className="flex flex-col gap-4">
127
- <div className="flex items-center gap-4 rounded-md border border-border bg-card px-4 py-3">
128
- <GithubAvatar
129
- className="size-6"
130
- login={selected.fullName.split("/")[0] ?? ""}
131
- />
132
- <div className="flex min-w-0 flex-1 items-center gap-1.5">
133
- <span className="truncate text-sm font-medium">
134
- {selected.fullName}
135
- </span>
136
- {selected.private && (
137
- <LockIcon className="size-3.5 shrink-0 text-muted-foreground" />
138
- )}
139
- </div>
140
- <Button onClick={onChangeRepo} size="sm" type="button" variant="ghost">
141
- Change
142
- </Button>
143
- </div>
144
- <FieldGroup>
145
- <Field>
146
- <FieldLabel htmlFor="branch">Branch</FieldLabel>
147
- <Input
148
- id="branch"
149
- onChange={(event) => onBranchChange(event.target.value)}
150
- value={branch}
151
- />
152
- </Field>
153
- <Field>
154
- <FieldLabel htmlFor="docs-path">Docs path</FieldLabel>
155
- <Input
156
- id="docs-path"
157
- onChange={(event) => onDocsPathChange(event.target.value)}
158
- value={docsPath}
159
- />
160
- <FieldDescription>
161
- Folder inside the repo with your <code>docs.json</code>.
162
- </FieldDescription>
163
- </Field>
164
- </FieldGroup>
165
- {formError && <FieldError>{formError}</FieldError>}
166
- <div>
167
- <Button disabled={submitting} onClick={onConnect} type="button">
168
- {submitting ? "Connecting..." : "Connect repository"}
169
- </Button>
170
- </div>
171
- </CardContent>
172
- </Card>
173
- );
174
-
175
- const RepoRow = ({
176
- onImport,
177
- repo,
178
- }: {
179
- onImport: () => void;
180
- repo: RepoSummary;
181
- }) => {
182
- const name = repo.fullName.split("/")[1] ?? repo.fullName;
183
- const ago = timeAgo(repo.pushedAt);
184
- return (
185
- <div className="flex items-center gap-4 bg-card px-4 py-3">
186
- <GithubAvatar
187
- className="size-6"
188
- login={repo.fullName.split("/")[0] ?? ""}
189
- />
190
- <div className="flex min-w-0 flex-1 items-center gap-1.5">
191
- <span className="truncate text-sm font-medium" title={repo.fullName}>
192
- {name}
193
- </span>
194
- {repo.private && (
195
- <LockIcon className="size-3.5 shrink-0 text-muted-foreground" />
196
- )}
197
- {ago && (
198
- <>
199
- <span
200
- aria-hidden="true"
201
- className="hidden text-muted-foreground sm:inline"
202
- >
203
- ·
204
- </span>
205
- <span className="hidden text-xs text-muted-foreground sm:inline">
206
- {ago}
207
- </span>
208
- </>
209
- )}
210
- </div>
211
- <Button
212
- aria-label={`Import ${repo.fullName}`}
213
- onClick={onImport}
214
- size="sm"
215
- type="button"
216
- >
217
- Import
218
- </Button>
219
- </div>
220
- );
221
- };
222
-
223
- const AccountPicker = ({
224
- addAccountPending,
225
- installations,
226
- onAddAccount,
227
- onSelect,
228
- selectedId,
229
- }: {
230
- addAccountPending?: boolean;
231
- installations: RepoPickerInstallation[];
232
- onAddAccount: () => void;
233
- onSelect: (id: number) => void;
234
- selectedId: number | null;
235
- }) => {
236
- const [open, setOpen] = useState(false);
237
- const selected =
238
- installations.find((installation) => installation.id === selectedId) ??
239
- null;
240
-
241
- return (
242
- <Popover onOpenChange={setOpen} open={open}>
243
- <PopoverTrigger
244
- aria-label="Select GitHub account"
245
- className="flex h-9 w-full items-center gap-2 rounded-md border border-border bg-background px-3 text-sm outline-none transition hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring"
246
- type="button"
247
- >
248
- {selected ? (
249
- <GithubAvatar className="size-5" login={selected.accountLogin} />
250
- ) : (
251
- <GithubIcon className="size-4 shrink-0 text-muted-foreground" />
252
- )}
253
- <span className="truncate font-medium">
254
- {selected?.accountLogin ?? "Select account"}
255
- </span>
256
- <ChevronDownIcon className="ml-auto size-4 shrink-0 text-muted-foreground" />
257
- </PopoverTrigger>
258
- <PopoverContent
259
- align="start"
260
- className="w-[min(20rem,var(--available-width,20rem))] p-0"
261
- >
262
- <Command>
263
- <CommandInput placeholder="Search accounts…" />
264
- <CommandList>
265
- <CommandEmpty>No accounts match.</CommandEmpty>
266
- {installations.length > 0 && (
267
- <CommandGroup>
268
- {installations.map((installation) => (
269
- <CommandItem
270
- key={installation.id}
271
- onSelect={() => {
272
- onSelect(installation.id);
273
- setOpen(false);
274
- }}
275
- value={installation.accountLogin}
276
- >
277
- <GithubAvatar
278
- className="size-5"
279
- login={installation.accountLogin}
280
- />
281
- <span className="truncate">
282
- {installation.accountLogin}
283
- </span>
284
- <CheckIcon
285
- className={cn(
286
- "ml-auto size-4",
287
- installation.id === selectedId
288
- ? "opacity-100"
289
- : "opacity-0"
290
- )}
291
- />
292
- </CommandItem>
293
- ))}
294
- </CommandGroup>
295
- )}
296
- {installations.length > 0 && <CommandSeparator />}
297
- <CommandGroup forceMount>
298
- <CommandItem
299
- disabled={addAccountPending}
300
- forceMount
301
- onSelect={() => {
302
- setOpen(false);
303
- onAddAccount();
304
- }}
305
- value="Add GitHub Account"
306
- >
307
- <PlusIcon className="size-4" />
308
- <span>
309
- {addAccountPending ? "Redirecting…" : "Add GitHub Account"}
310
- </span>
311
- </CommandItem>
312
- </CommandGroup>
313
- </CommandList>
314
- </Command>
315
- </PopoverContent>
316
- </Popover>
317
- );
318
- };
319
-
320
- export const RepoPicker = ({
321
- accessToken,
322
- addAccountPending,
323
- initialInstallationId = null,
324
- installations,
325
- onAddAccount,
326
- onConnected,
327
- projectId,
328
- projectSlug,
329
- }: RepoPickerProps) => {
330
- const router = useRouter();
331
- const preselected =
332
- initialInstallationId !== null &&
333
- installations.some((i) => i.id === initialInstallationId)
334
- ? initialInstallationId
335
- : (installations[0]?.id ?? null);
336
- const [selectedInstallationId, setSelectedInstallationId] = useState<
337
- number | null
338
- >(preselected);
339
- const [repos, setRepos] = useState<RepoSummary[] | null>(null);
340
- const [formError, setError] = useState<string | null>(null);
341
- const [selected, setSelected] = useState<RepoSummary | null>(null);
342
- const [branch, setBranch] = useState("main");
343
- const [docsPath, setDocsPath] = useState("docs");
344
- const [submitting, setSubmitting] = useState(false);
345
- const [search, setSearch] = useState("");
346
-
347
- useEffect(() => {
348
- if (!installations.some((i) => i.id === selectedInstallationId)) {
349
- setSelectedInstallationId(installations[0]?.id ?? null);
350
- }
351
- }, [installations, selectedInstallationId]);
352
-
353
- useEffect(() => {
354
- if (selectedInstallationId === null) {
355
- setRepos(null);
356
- return;
357
- }
358
- let cancelled = false;
359
- setRepos(null);
360
- setSelected(null);
361
- setError(null);
362
- const run = async () => {
363
- try {
364
- const reposResult = await apiFetch<{ repos: RepoSummary[] }>(
365
- `/git/installations/${selectedInstallationId}/repos`,
366
- { accessToken }
367
- );
368
- if (!cancelled) {
369
- setRepos(reposResult.repos);
370
- }
371
- } catch (error) {
372
- const message =
373
- error instanceof ApiError
374
- ? error.message
375
- : "Failed to load repositories.";
376
- if (!cancelled) {
377
- setError(message);
378
- }
379
- }
380
- };
381
- run();
382
- return () => {
383
- cancelled = true;
384
- };
385
- }, [accessToken, selectedInstallationId]);
386
-
387
- const handlePick = (repo: RepoSummary) => {
388
- setSelected(repo);
389
- setBranch(repo.defaultBranch || "main");
390
- // Reset the docs path so an edit made for a previous repo doesn't carry
391
- // over to a freshly picked one.
392
- setDocsPath("docs");
393
- setError(null);
394
- };
395
-
396
- const handleConnect = async () => {
397
- if (!(selected && selectedInstallationId !== null)) {
398
- return;
399
- }
400
- setSubmitting(true);
401
- setError(null);
402
- try {
403
- const connection = await apiFetch<GitConnection>(
404
- `/projects/${projectId}/git`,
405
- {
406
- accessToken,
407
- body: {
408
- branch: branch.trim() || "main",
409
- docsPath: docsPath.trim() || "docs",
410
- installationId: selectedInstallationId,
411
- repository: selected.fullName,
412
- },
413
- method: "POST",
414
- }
415
- );
416
- sessionStorage.removeItem(GITHUB_INSTALL_STATE_KEY);
417
- if (onConnected) {
418
- onConnected(connection);
419
- } else {
420
- router.push(`/app/${projectSlug}/git`);
421
- router.refresh();
422
- }
423
- } catch (error) {
424
- const message =
425
- error instanceof ApiError
426
- ? error.message
427
- : "Could not save connection.";
428
- setError(message);
429
- setSubmitting(false);
430
- }
431
- };
432
-
433
- const filtered =
434
- repos?.filter((repo) =>
435
- repo.fullName.toLowerCase().includes(search.trim().toLowerCase())
436
- ) ?? [];
437
-
438
- if (selected) {
439
- return (
440
- <ConfigureRepoCard
441
- branch={branch}
442
- docsPath={docsPath}
443
- formError={formError}
444
- onBranchChange={setBranch}
445
- onChangeRepo={() => setSelected(null)}
446
- onConnect={handleConnect}
447
- onDocsPathChange={setDocsPath}
448
- selected={selected}
449
- submitting={submitting}
450
- />
451
- );
452
- }
453
-
454
- return (
455
- <Card>
456
- <CardHeader>
457
- <CardTitle>Import Git repository</CardTitle>
458
- <CardDescription>
459
- Choose the repo with your docs. We&apos;ll deploy on every push to the
460
- selected branch.
461
- </CardDescription>
462
- </CardHeader>
463
- <CardContent className="flex flex-col gap-4">
464
- <div className="flex gap-2">
465
- <div className="flex-1">
466
- <AccountPicker
467
- addAccountPending={addAccountPending}
468
- installations={installations}
469
- onAddAccount={onAddAccount}
470
- onSelect={setSelectedInstallationId}
471
- selectedId={selectedInstallationId}
472
- />
473
- </div>
474
- <div className="relative flex-1">
475
- <SearchIcon
476
- aria-hidden="true"
477
- className="-translate-y-1/2 pointer-events-none absolute top-1/2 left-3 size-4 text-muted-foreground"
478
- />
479
- <Input
480
- aria-label="Search repositories"
481
- className="pl-9"
482
- onChange={(event) => setSearch(event.target.value)}
483
- placeholder="Search…"
484
- type="search"
485
- value={search}
486
- />
487
- </div>
488
- </div>
489
-
490
- {formError && <FieldError>{formError}</FieldError>}
491
-
492
- {selectedInstallationId === null && (
493
- <p className="text-sm text-muted-foreground">
494
- Select a GitHub account to see repositories.
495
- </p>
496
- )}
497
-
498
- {selectedInstallationId !== null && repos === null && !formError && (
499
- <p className="text-sm text-muted-foreground">Loading…</p>
500
- )}
501
-
502
- {repos?.length === 0 && (
503
- <p className="text-sm text-muted-foreground">
504
- The Blode.md app isn&apos;t installed on any repos in this account
505
- yet. Add at least one in GitHub and refresh.
506
- </p>
507
- )}
508
-
509
- {repos && repos.length > 0 && filtered.length === 0 && (
510
- <p className="text-sm text-muted-foreground">
511
- No repositories match &quot;{search}&quot;.
512
- </p>
513
- )}
514
-
515
- {filtered.length > 0 && (
516
- <div className="divide-y divide-border overflow-hidden rounded-md border border-border">
517
- {filtered.map((repo) => (
518
- <RepoRow
519
- key={repo.fullName}
520
- onImport={() => handlePick(repo)}
521
- repo={repo}
522
- />
523
- ))}
524
- </div>
525
- )}
526
- </CardContent>
527
- </Card>
528
- );
529
- };
@@ -1,96 +0,0 @@
1
- import ArrowRightIcon from "blode-icons-react/icons/arrow-right";
2
- import ArrowUpRightIcon from "blode-icons-react/icons/arrow-up-right";
3
- import CheckIcon from "blode-icons-react/icons/check";
4
- import CodeIcon from "blode-icons-react/icons/code";
5
- import ConsoleIcon from "blode-icons-react/icons/console";
6
- import FlagIcon from "blode-icons-react/icons/flag-1";
7
- import FolderAddRightIcon from "blode-icons-react/icons/folder-add-right";
8
- import GlobusIcon from "blode-icons-react/icons/globus";
9
- import ImacIcon from "blode-icons-react/icons/imac";
10
- import InfoIcon from "blode-icons-react/icons/info";
11
- import KeyIcon from "blode-icons-react/icons/key";
12
- import LockIcon from "blode-icons-react/icons/lock";
13
- import MagnifyingGlassIcon from "blode-icons-react/icons/magnifying-glass";
14
- import PlayIcon from "blode-icons-react/icons/play";
15
- import PuzzleIcon from "blode-icons-react/icons/puzzle";
16
- import RocketIcon from "blode-icons-react/icons/rocket";
17
- import SparkleIcon from "blode-icons-react/icons/sparkle";
18
- import StarIcon from "blode-icons-react/icons/star";
19
- import TriangleExclamationIcon from "blode-icons-react/icons/triangle-exclamation";
20
- import type { ComponentType, ReactElement, SVGProps } from "react";
21
-
22
- import { cn } from "@/lib/utils";
23
-
24
- type IconComponent = ComponentType<SVGProps<SVGSVGElement>>;
25
- interface DocIconProps {
26
- icon: string;
27
- color?: string;
28
- size?: number;
29
- className?: string;
30
- }
31
-
32
- const DOC_ICON_MAP: Record<string, IconComponent> = {
33
- "alert-triangle": TriangleExclamationIcon,
34
- "arrow-right": ArrowRightIcon,
35
- check: CheckIcon,
36
- code: CodeIcon,
37
- "external-link": ArrowUpRightIcon,
38
- flag: FlagIcon,
39
- "folder-plus": FolderAddRightIcon,
40
- globe: GlobusIcon,
41
- info: InfoIcon,
42
- key: KeyIcon,
43
- lock: LockIcon,
44
- monitor: ImacIcon,
45
- play: PlayIcon,
46
- puzzle: PuzzleIcon,
47
- rocket: RocketIcon,
48
- search: MagnifyingGlassIcon,
49
- sparkles: SparkleIcon,
50
- star: StarIcon,
51
- terminal: ConsoleIcon,
52
- };
53
-
54
- const getIconComponent = (icon: string): IconComponent | null =>
55
- DOC_ICON_MAP[icon.trim().toLowerCase()] ?? null;
56
-
57
- export const DocIcon = ({
58
- icon,
59
- color,
60
- size = 16,
61
- className,
62
- }: DocIconProps): ReactElement => {
63
- const IconComponent = getIconComponent(icon);
64
-
65
- if (!IconComponent) {
66
- return (
67
- <span
68
- aria-hidden
69
- className={cn(
70
- "inline-flex items-center justify-center font-medium uppercase leading-none",
71
- className
72
- )}
73
- style={{
74
- color: color ?? undefined,
75
- fontSize: Math.max(10, Math.round(size * 0.55)),
76
- height: size,
77
- width: size,
78
- }}
79
- >
80
- {icon.slice(0, 2)}
81
- </span>
82
- );
83
- }
84
-
85
- return (
86
- <IconComponent
87
- aria-hidden
88
- className={cn("shrink-0", className)}
89
- style={{
90
- color: color ?? undefined,
91
- height: size,
92
- width: size,
93
- }}
94
- />
95
- );
96
- };
@@ -1,83 +0,0 @@
1
- "use client";
2
-
3
- import { useCallback, useState } from "react";
4
- import type { ReactNode } from "react";
5
-
6
- import { cn } from "@/lib/utils";
7
-
8
- interface AccordionProps {
9
- title: string;
10
- description?: string;
11
- defaultOpen?: boolean;
12
- id?: string;
13
- icon?: ReactNode;
14
- children: ReactNode;
15
- }
16
-
17
- export const Accordion = ({
18
- title,
19
- description,
20
- defaultOpen = false,
21
- id,
22
- icon,
23
- children,
24
- }: AccordionProps) => {
25
- const [open, setOpen] = useState(defaultOpen);
26
- const anchorId = id ?? title.toLowerCase().replaceAll(/\s+/g, "-");
27
-
28
- const toggle = useCallback(() => setOpen((prev) => !prev), []);
29
-
30
- return (
31
- <div className="border-b border-border last:border-b-0" id={anchorId}>
32
- <button
33
- aria-expanded={open}
34
- className="flex w-full items-center gap-3 py-4 text-left"
35
- onClick={toggle}
36
- type="button"
37
- >
38
- {icon ? (
39
- <span className="flex size-5 shrink-0 items-center justify-center text-muted-foreground">
40
- {icon}
41
- </span>
42
- ) : null}
43
- <div className="min-w-0 flex-1">
44
- <div className="font-medium">{title}</div>
45
- {description ? (
46
- <div className="mt-0.5 text-sm text-muted-foreground">
47
- {description}
48
- </div>
49
- ) : null}
50
- </div>
51
- <svg
52
- aria-hidden
53
- className={cn(
54
- "size-4 shrink-0 text-muted-foreground transition-transform duration-200",
55
- open && "rotate-180"
56
- )}
57
- fill="none"
58
- stroke="currentColor"
59
- strokeWidth={2}
60
- viewBox="0 0 24 24"
61
- >
62
- <path d="m6 9 6 6 6-6" strokeLinecap="round" strokeLinejoin="round" />
63
- </svg>
64
- </button>
65
- <div
66
- className={cn(
67
- "grid transition-[grid-template-rows] duration-200",
68
- open ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
69
- )}
70
- >
71
- <div className="overflow-hidden">
72
- <div className="pb-4 text-sm text-muted-foreground">{children}</div>
73
- </div>
74
- </div>
75
- </div>
76
- );
77
- };
78
-
79
- export const AccordionGroup = ({ children }: { children: ReactNode }) => (
80
- <div className="my-4 divide-y divide-border rounded-xl border border-border px-4">
81
- {children}
82
- </div>
83
- );