@trebired/git-host 1.4.0 → 1.6.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.
@@ -1,19 +1,43 @@
1
- import { createElement, useDeferredValue, useEffect, useState, } from "react";
1
+ import { createElement, useDeferredValue, useState, } from "react";
2
2
  import { createGitApiClient } from "../react/client.js";
3
- import { GitApiClientProvider, applyGitStarOptimisticState, applyGitWatchOptimisticState, useGitActivity, useGitBlob, useGitCommit, useGitCommits, useGitCreateFork, useGitCreateRelease, useGitForks, useGitOverview, useGitRelease, useGitReleases, useGitSocialState, useGitStarRepository, useGitSyncFork, useGitTree, useGitUnstarRepository, useGitUnwatchRepository, useGitWatchRepository, } from "../react/index.js";
3
+ import { GitActivityList, GitApiClientProvider, GitBlameView, GitBlobView, GitBranchList, GitBranchSelector, GitCommitList, GitCopyCloneUrlButton, GitDeleteReleaseButton, GitDiffView, GitDownloadArchiveButton, GitEditReleaseButton, GitForkButton, GitForkList, GitPathBreadcrumbs, GitReleaseList, GitRepositoryActionBar, GitRepositoryShell, GitRepositorySocialButtons, GitRepositoryUiProvider, GitSearchResults, GitTagList, GitTagSelector, GitTreeView, useGitActivity, useGitBlame, useGitBlob, useGitBranches, useGitCommit, useGitCommits, useGitDiff, useGitForks, useGitCreateRelease, useGitOverview, useGitRelease, useGitReleases, useGitSearch, useGitTags, useGitTree, useGitUpdateRelease, } from "../react/index.js";
4
4
  import { text } from "../utils/text.js";
5
5
  const h = createElement;
6
6
  function joinClassNames(...values) {
7
7
  return values.filter(Boolean).join(" ");
8
8
  }
9
+ function findReadme(entries) {
10
+ const match = entries.find((entry) => entry.type === "blob" && /^readme(\.|$)/i.test(entry.name));
11
+ return match ? match.path : "";
12
+ }
13
+ function createClient(options) {
14
+ return options.client || createGitApiClient({
15
+ baseUrl: text(options.baseUrl),
16
+ headers: options.headers,
17
+ });
18
+ }
19
+ function resolveTheme(theme, unstyled) {
20
+ if (!unstyled)
21
+ return theme;
22
+ return {
23
+ ...(theme || {}),
24
+ unstyled: true,
25
+ };
26
+ }
9
27
  function GitBrowserProvider(props) {
10
- const [client] = useState(() => props.client || createGitApiClient({
11
- baseUrl: text(props.baseUrl),
12
- headers: props.headers,
13
- }));
28
+ const [client] = useState(() => createClient(props));
14
29
  return h(GitApiClientProvider, {
15
30
  client,
16
- children: props.children,
31
+ children: h(GitRepositoryUiProvider, {
32
+ branding: props.branding,
33
+ client,
34
+ diagnostics: props.diagnostics,
35
+ navigate: props.navigate,
36
+ policy: props.policy,
37
+ routeAdapter: props.routeAdapter,
38
+ theme: resolveTheme(props.theme, props.unstyled),
39
+ children: props.children,
40
+ }),
17
41
  });
18
42
  }
19
43
  function withBrowserProvider(props, render) {
@@ -21,206 +45,185 @@ function withBrowserProvider(props, render) {
21
45
  return render();
22
46
  return h(GitBrowserProvider, {
23
47
  baseUrl: props.baseUrl,
48
+ branding: props.branding,
24
49
  client: props.client,
50
+ diagnostics: props.diagnostics,
25
51
  headers: props.headers,
52
+ navigate: props.navigate,
53
+ policy: props.policy,
54
+ routeAdapter: props.routeAdapter,
55
+ theme: resolveTheme(props.theme, props.unstyled),
56
+ unstyled: props.unstyled,
26
57
  children: render(),
27
58
  });
28
59
  }
29
- function formatDate(value) {
30
- const next = text(value);
31
- if (!next)
32
- return "Unknown";
33
- try {
34
- return new Date(next).toLocaleString("en-US", {
35
- dateStyle: "medium",
36
- timeStyle: "short",
37
- });
38
- }
39
- catch {
40
- return next;
41
- }
42
- }
43
- function LinkButton(props) {
44
- return h("button", {
45
- className: joinClassNames("git-browser-nav-link", props.active && "is-active"),
46
- onClick: () => props.navigate && props.navigate(props.to),
47
- type: "button",
48
- children: props.children,
49
- });
50
- }
51
- function StatusBlock(props) {
52
- if (props.loading)
53
- return h("div", { className: "git-browser-status", children: "Loading repository data..." });
54
- if (props.error)
55
- return h("div", { className: "git-browser-status is-error", children: props.error.message });
56
- return h("div", { children: props.children });
57
- }
58
- function RepositoryNav(props) {
59
- return h("div", {
60
- className: "git-browser-nav",
60
+ function overviewStats(overview) {
61
+ if (!overview)
62
+ return [];
63
+ return [
64
+ { label: "Branch", value: overview.repository.repository.current_branch },
65
+ { label: "Head", value: overview.repository.repository.head_short },
66
+ { label: "Stars", value: String(overview.social.star_count) },
67
+ { label: "Watchers", value: String(overview.social.watcher_count) },
68
+ { label: "Releases", value: String(overview.release_count) },
69
+ { label: "Forks", value: String(overview.fork_count) },
70
+ ];
71
+ }
72
+ function defaultSubtitle(repositoryKey, overview) {
73
+ if (!overview)
74
+ return `Repository workspace for ${repositoryKey}`;
75
+ return `${overview.repository.repository.current_branch} branch · ${overview.release_count} releases · ${overview.fork_count} forks`;
76
+ }
77
+ function defaultActionBar(repositoryKey, headers) {
78
+ return h(GitRepositoryActionBar, {
61
79
  children: [
62
- h(LinkButton, { active: props.current === "overview", key: "overview", navigate: props.navigate, to: `/repositories/${props.repositoryKey}/overview`, children: "Overview" }),
63
- h(LinkButton, { active: props.current === "code", key: "code", navigate: props.navigate, to: `/repositories/${props.repositoryKey}/code`, children: "Code" }),
64
- h(LinkButton, { active: props.current === "commits", key: "commits", navigate: props.navigate, to: `/repositories/${props.repositoryKey}/commits`, children: "Commits" }),
65
- h(LinkButton, { active: props.current === "releases", key: "releases", navigate: props.navigate, to: `/repositories/${props.repositoryKey}/releases`, children: "Releases" }),
66
- h(LinkButton, { active: props.current === "forks", key: "forks", navigate: props.navigate, to: `/repositories/${props.repositoryKey}/forks`, children: "Forks" }),
67
- h(LinkButton, { active: props.current === "activity", key: "activity", navigate: props.navigate, to: `/repositories/${props.repositoryKey}/activity`, children: "Activity" }),
80
+ h(GitRepositorySocialButtons, { headers, key: "social", repositoryKey }),
81
+ h(GitForkButton, { headers, key: "fork", repositoryKey }),
82
+ h(GitCopyCloneUrlButton, { key: "clone", repositoryKey }),
83
+ h(GitDownloadArchiveButton, { key: "archive", repositoryKey }),
68
84
  ],
69
85
  });
70
86
  }
71
- function SocialControls(props) {
72
- const [optimistic, setOptimistic] = useState(props.social);
73
- useEffect(() => {
74
- setOptimistic(props.social);
75
- }, [props.social]);
76
- const star = useGitStarRepository(props.repositoryKey, { headers: props.headers });
77
- const unstar = useGitUnstarRepository(props.repositoryKey, { headers: props.headers });
78
- const watch = useGitWatchRepository(props.repositoryKey, { headers: props.headers });
79
- const unwatch = useGitUnwatchRepository(props.repositoryKey, { headers: props.headers });
80
- const social = optimistic;
81
- return h("div", {
82
- className: "git-browser-actions",
87
+ function GitReleaseComposerCard(props) {
88
+ const createRelease = useGitCreateRelease(props.repositoryKey, { headers: props.headers });
89
+ const [title, setTitle] = useState("");
90
+ const [tagName, setTagName] = useState("");
91
+ const [notes, setNotes] = useState("");
92
+ return h("section", {
93
+ className: "git-browser-card",
83
94
  children: [
84
- h("button", {
85
- className: joinClassNames("git-browser-action-button", social?.viewer_has_starred && "is-active"),
86
- disabled: star.loading || unstar.loading,
87
- key: "star",
88
- onClick: async () => {
89
- const next = social?.viewer_has_starred !== true;
90
- setOptimistic(applyGitStarOptimisticState(social, next));
91
- try {
92
- setOptimistic(next ? await star.mutate() : await unstar.mutate());
93
- }
94
- catch {
95
- setOptimistic(props.social);
96
- }
97
- },
98
- type: "button",
99
- children: `${social?.viewer_has_starred ? "Starred" : "Star"} ${social?.star_count ?? 0}`,
100
- }),
101
- h("button", {
102
- className: joinClassNames("git-browser-action-button", social?.viewer_is_watching && "is-active"),
103
- disabled: watch.loading || unwatch.loading,
104
- key: "watch",
105
- onClick: async () => {
106
- const next = social?.viewer_is_watching !== true;
107
- setOptimistic(applyGitWatchOptimisticState(social, next));
108
- try {
109
- setOptimistic(next ? await watch.mutate() : await unwatch.mutate());
110
- }
111
- catch {
112
- setOptimistic(props.social);
113
- }
95
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Publish a Release" }) }),
96
+ h("form", {
97
+ className: "git-browser-form",
98
+ key: "form",
99
+ onSubmit: async (event) => {
100
+ event.preventDefault();
101
+ await createRelease.mutate({
102
+ createTag: {
103
+ annotatedMessage: notes || title,
104
+ name: tagName,
105
+ targetRef: "HEAD",
106
+ },
107
+ notes,
108
+ title,
109
+ });
110
+ setTitle("");
111
+ setTagName("");
112
+ setNotes("");
113
+ props.onCreated?.();
114
114
  },
115
- type: "button",
116
- children: `${social?.viewer_is_watching ? "Watching" : "Watch"} ${social?.watcher_count ?? 0}`,
115
+ children: [
116
+ h("input", {
117
+ className: "git-browser-input",
118
+ key: "title",
119
+ onChange: (event) => setTitle(text(event.target?.value)),
120
+ placeholder: "Release title",
121
+ value: title,
122
+ }),
123
+ h("input", {
124
+ className: "git-browser-input",
125
+ key: "tag",
126
+ onChange: (event) => setTagName(text(event.target?.value)),
127
+ placeholder: "Tag name",
128
+ value: tagName,
129
+ }),
130
+ h("textarea", {
131
+ className: "git-browser-input git-browser-textarea",
132
+ key: "notes",
133
+ onChange: (event) => setNotes(text(event.target?.value)),
134
+ placeholder: "Release notes",
135
+ value: notes,
136
+ }),
137
+ h("button", {
138
+ className: "git-browser-action-button is-primary",
139
+ disabled: createRelease.loading || !title || !tagName,
140
+ key: "submit",
141
+ type: "submit",
142
+ children: createRelease.loading ? "Publishing..." : "Publish Release",
143
+ }),
144
+ ],
117
145
  }),
118
146
  ],
119
147
  });
120
148
  }
121
- function RepositoryHeader(props) {
122
- const socialQuery = useGitSocialState(props.repositoryKey, {
123
- headers: props.headers,
124
- initialData: props.overview?.social || null,
125
- });
126
- const createFork = useGitCreateFork(props.repositoryKey, { headers: props.headers });
149
+ function GitReleaseEditorCard(props) {
150
+ const updateRelease = useGitUpdateRelease(props.repositoryKey, text(props.release?.id), { headers: props.headers });
151
+ const [editing, setEditing] = useState(false);
152
+ const [title, setTitle] = useState(text(props.release?.title));
153
+ const [notes, setNotes] = useState(text(props.release?.notes));
154
+ if (!props.release)
155
+ return null;
127
156
  return h("section", {
128
- className: "git-browser-hero",
157
+ className: "git-browser-card",
129
158
  children: [
130
159
  h("div", {
131
- className: "git-browser-hero-top",
132
- key: "title",
160
+ className: "git-browser-card-header",
161
+ key: "header",
133
162
  children: [
163
+ h("h2", { className: "git-browser-card-title", key: "title", children: "Release Actions" }),
134
164
  h("div", {
135
- className: "git-browser-title-block",
136
- key: "block",
137
- children: [
138
- h("div", { className: "git-browser-badge", key: "badge", children: "Embeddable Forge" }),
139
- h("h1", { className: "git-browser-title", key: "title", children: props.repositoryKey }),
140
- h("p", {
141
- className: "git-browser-subtitle",
142
- key: "subtitle",
143
- children: props.overview
144
- ? `${props.overview.repository.repository.current_branch} branch, ${props.overview.release_count} releases, ${props.overview.fork_count} forks`
145
- : "Repository browser",
146
- }),
147
- ],
148
- }),
149
- h("div", {
150
- className: "git-browser-header-actions",
165
+ className: "git-browser-actions",
151
166
  key: "actions",
152
167
  children: [
153
- h(SocialControls, {
168
+ h(GitEditReleaseButton, {
169
+ key: "edit",
170
+ onClick: () => setEditing((current) => !current),
171
+ }),
172
+ h(GitDeleteReleaseButton, {
154
173
  headers: props.headers,
155
- key: "social",
174
+ key: "delete",
175
+ onDeleted: props.onDeleted,
176
+ releaseId: props.release.id,
156
177
  repositoryKey: props.repositoryKey,
157
- social: socialQuery.data,
158
- }),
159
- h("button", {
160
- className: "git-browser-action-button is-primary",
161
- disabled: createFork.loading,
162
- key: "fork",
163
- onClick: async () => {
164
- await createFork.mutate();
165
- },
166
- type: "button",
167
- children: createFork.loading ? "Forking..." : "Create Fork",
168
178
  }),
169
179
  ],
170
180
  }),
171
181
  ],
172
182
  }),
173
- h(RepositoryNav, {
174
- current: props.current,
175
- navigate: props.navigate,
176
- repositoryKey: props.repositoryKey,
177
- key: "nav",
178
- }),
179
- ],
180
- });
181
- }
182
- function Card(props) {
183
- return h("section", {
184
- className: joinClassNames("git-browser-card", props.className),
185
- children: [
186
- h("div", {
187
- className: "git-browser-card-header",
188
- key: "header",
189
- children: [
190
- h("h2", { className: "git-browser-card-title", key: "title", children: props.title }),
191
- props.subtitle ? h("div", { className: "git-browser-card-subtitle", key: "subtitle", children: props.subtitle }) : null,
192
- ],
193
- }),
194
- h("div", {
195
- className: "git-browser-card-body",
196
- key: "body",
197
- children: props.children,
198
- }),
183
+ editing
184
+ ? h("div", {
185
+ className: "git-browser-form",
186
+ key: "editor",
187
+ children: [
188
+ h("input", {
189
+ className: "git-browser-input",
190
+ key: "title",
191
+ onChange: (event) => setTitle(text(event.target?.value)),
192
+ value: title,
193
+ }),
194
+ h("textarea", {
195
+ className: "git-browser-input git-browser-textarea",
196
+ key: "notes",
197
+ onChange: (event) => setNotes(text(event.target?.value)),
198
+ value: notes,
199
+ }),
200
+ h("button", {
201
+ className: "git-browser-action-button is-primary",
202
+ disabled: updateRelease.loading,
203
+ key: "save",
204
+ onClick: async () => {
205
+ await updateRelease.mutate({ notes, title });
206
+ setEditing(false);
207
+ props.onUpdated?.();
208
+ },
209
+ type: "button",
210
+ children: updateRelease.loading ? "Saving..." : "Save Release",
211
+ }),
212
+ ],
213
+ })
214
+ : h("p", { className: "git-browser-note", key: "summary", children: "Toggle edit mode to rename or rewrite release notes." }),
199
215
  ],
200
216
  });
201
217
  }
202
- function DefinitionGrid(props) {
203
- return h("dl", {
204
- className: "git-browser-definition-grid",
205
- children: props.rows.flatMap((row) => ([
206
- h("dt", { key: `${row.label}:label`, children: row.label }),
207
- h("dd", { key: `${row.label}:value`, children: row.value }),
208
- ])),
209
- });
210
- }
211
- function findReadme(entries) {
212
- const match = entries.find((entry) => entry.type === "blob" && /^readme(\.|$)/i.test(entry.name));
213
- return match ? match.path : "";
214
- }
215
218
  function GitRepositoryOverviewPageInner(props) {
216
219
  const overview = useGitOverview(props.repositoryKey, {
217
220
  headers: props.headers,
218
- initialData: props.initialData || null,
221
+ initialData: props.initialData?.overview || null,
219
222
  });
220
223
  const tree = useGitTree(props.repositoryKey, {
224
+ enabled: Boolean(overview.data),
221
225
  headers: props.headers,
222
226
  icons: true,
223
- path: "",
224
227
  recursive: true,
225
228
  ref: overview.data?.repository.repository.current_branch || "HEAD",
226
229
  });
@@ -231,512 +234,505 @@ function GitRepositoryOverviewPageInner(props) {
231
234
  path: readmePath,
232
235
  ref: overview.data?.repository.repository.current_branch || "HEAD",
233
236
  });
234
- return h("div", {
235
- className: joinClassNames("git-browser-page", props.className),
236
- children: [
237
- h(RepositoryHeader, {
238
- current: "overview",
239
- headers: props.headers,
240
- key: "header",
241
- navigate: props.navigate,
242
- overview: overview.data,
243
- repositoryKey: props.repositoryKey,
244
- }),
245
- h(StatusBlock, {
246
- error: overview.error,
247
- key: "status",
248
- loading: overview.loading,
249
- children: overview.data ? h("div", {
250
- className: "git-browser-grid",
237
+ return h(GitRepositoryShell, {
238
+ actions: defaultActionBar(props.repositoryKey, props.headers),
239
+ className: props.className,
240
+ error: overview.error,
241
+ loading: overview.loading,
242
+ page: "overview",
243
+ repositoryKey: props.repositoryKey,
244
+ social: overview.data?.social,
245
+ stats: overviewStats(overview.data),
246
+ subtitle: defaultSubtitle(props.repositoryKey, overview.data),
247
+ children: h("div", {
248
+ className: "git-browser-grid",
249
+ children: [
250
+ h("section", {
251
+ className: "git-browser-card git-browser-span-2",
252
+ key: "summary",
251
253
  children: [
252
- h(Card, {
253
- className: "git-browser-span-2",
254
- key: "summary",
255
- title: "Repository Summary",
256
- subtitle: overview.data.repository.repository.path,
257
- children: h(DefinitionGrid, {
258
- rows: [
259
- { label: "Branch", value: overview.data.repository.repository.current_branch },
260
- { label: "Head", value: overview.data.repository.repository.head_short },
261
- { label: "Releases", value: String(overview.data.release_count) },
262
- { label: "Forks", value: String(overview.data.fork_count) },
263
- { label: "Activity", value: String(overview.data.activity_count) },
264
- ],
265
- }),
266
- }),
267
- h(Card, {
268
- key: "latest-release",
269
- title: "Latest Release",
270
- children: overview.data.latest_release
271
- ? [
272
- h("div", { className: "git-browser-inline-meta", key: "title", children: `${overview.data.latest_release.title} · ${overview.data.latest_release.tag_name}` }),
273
- h("p", { className: "git-browser-note", key: "notes", children: overview.data.latest_release.notes || "No notes yet." }),
274
- ]
275
- : "No releases published yet.",
276
- }),
277
- h(Card, {
278
- className: "git-browser-span-3",
279
- key: "readme",
280
- title: "README",
281
- children: readme.data
282
- ? h("pre", { className: "git-browser-code-block", children: readme.data.content })
283
- : "README content not available.",
284
- }),
254
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Repository Summary" }) }),
255
+ h("p", { className: "git-browser-note", key: "path", children: overview.data?.repository.repository.path || "" }),
285
256
  ],
286
- }) : null,
287
- }),
288
- ],
257
+ }),
258
+ h("section", {
259
+ className: "git-browser-card",
260
+ key: "latest-release",
261
+ children: [
262
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Latest Release" }) }),
263
+ overview.data?.latest_release
264
+ ? h(GitReleaseList, { key: "list", releases: [overview.data.latest_release], repositoryKey: props.repositoryKey })
265
+ : h("p", { className: "git-browser-note", key: "empty", children: "No releases published yet." }),
266
+ ],
267
+ }),
268
+ h("section", {
269
+ className: "git-browser-card git-browser-span-3",
270
+ key: "readme",
271
+ children: [
272
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "README" }) }),
273
+ h(GitBlobView, { content: readme.data?.content, key: "blob", path: readmePath || "README" }),
274
+ ],
275
+ }),
276
+ ],
277
+ }),
289
278
  });
290
279
  }
291
280
  function GitRepositoryCodePageInner(props) {
292
281
  const overview = useGitOverview(props.repositoryKey, {
293
282
  headers: props.headers,
294
- initialData: props.initialData || null,
283
+ initialData: props.initialData?.overview || null,
295
284
  });
296
- const deferredPath = useDeferredValue(text(props.path));
285
+ const [selectedPath, setSelectedPath] = useState(text(props.path));
286
+ const deferredPath = useDeferredValue(selectedPath);
287
+ const refName = props.refName || overview.data?.repository.repository.current_branch || "HEAD";
297
288
  const tree = useGitTree(props.repositoryKey, {
298
289
  headers: props.headers,
299
290
  icons: true,
300
291
  linguist: true,
301
292
  recursive: true,
302
- ref: props.refName || overview.data?.repository.repository.current_branch || "HEAD",
293
+ ref: refName,
303
294
  });
304
- const selectedPath = deferredPath || (tree.data || []).find((entry) => entry.type === "blob")?.path || "";
305
- const selectedEntry = (tree.data || []).find((entry) => entry.path === selectedPath) || null;
295
+ const resolvedPath = deferredPath || (tree.data || []).find((entry) => entry.type === "blob")?.path || "";
296
+ const selectedEntry = (tree.data || []).find((entry) => entry.path === resolvedPath) || null;
306
297
  const blob = useGitBlob(props.repositoryKey, {
307
298
  enabled: Boolean(selectedEntry && selectedEntry.type === "blob"),
308
299
  headers: props.headers,
309
- path: selectedPath,
310
- ref: props.refName || overview.data?.repository.repository.current_branch || "HEAD",
311
- });
312
- return h("div", {
313
- className: joinClassNames("git-browser-page", props.className),
314
- children: [
315
- h(RepositoryHeader, {
316
- current: "code",
317
- headers: props.headers,
318
- key: "header",
319
- navigate: props.navigate,
320
- overview: overview.data,
321
- repositoryKey: props.repositoryKey,
322
- }),
323
- h(StatusBlock, {
324
- error: tree.error || blob.error,
325
- key: "status",
326
- loading: overview.loading || tree.loading || blob.loading,
327
- children: h("div", {
328
- className: "git-browser-split",
300
+ path: resolvedPath,
301
+ ref: refName,
302
+ });
303
+ return h(GitRepositoryShell, {
304
+ actions: h(GitRepositoryActionBar, {
305
+ children: [
306
+ h(GitBranchSelector, { headers: props.headers, key: "branch", repositoryKey: props.repositoryKey, selectedBranch: overview.data?.repository.repository.current_branch }),
307
+ h(GitTagSelector, { headers: props.headers, key: "tag", repositoryKey: props.repositoryKey }),
308
+ ],
309
+ }),
310
+ className: props.className,
311
+ error: tree.error || blob.error,
312
+ loading: overview.loading || tree.loading,
313
+ page: "code",
314
+ repositoryKey: props.repositoryKey,
315
+ social: overview.data?.social,
316
+ stats: overviewStats(overview.data),
317
+ subtitle: defaultSubtitle(props.repositoryKey, overview.data),
318
+ children: h("div", {
319
+ className: "git-browser-split",
320
+ children: [
321
+ h("section", {
322
+ className: "git-browser-card",
323
+ key: "tree",
329
324
  children: [
330
- h(Card, {
331
- key: "tree",
332
- title: "Repository Tree",
333
- subtitle: props.refName || overview.data?.repository.repository.current_branch || "HEAD",
334
- children: h("ul", {
335
- className: "git-browser-list",
336
- children: (tree.data || []).map((entry) => (h("li", {
337
- className: joinClassNames("git-browser-list-item", entry.path === selectedPath && "is-selected"),
338
- key: entry.path,
339
- children: `${entry.type === "tree" ? "dir" : "file"} · ${entry.path}${entry.language ? ` · ${entry.language}` : ""}`,
340
- }))),
341
- }),
325
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Repository Tree" }) }),
326
+ h(GitTreeView, {
327
+ entries: tree.data || [],
328
+ key: "body",
329
+ onSelectPath: setSelectedPath,
330
+ selectedPath: resolvedPath,
342
331
  }),
343
- h(Card, {
344
- className: "git-browser-span-2",
345
- key: "blob",
346
- title: selectedPath || "File Preview",
332
+ ],
333
+ }),
334
+ h("div", {
335
+ className: "git-browser-grid",
336
+ key: "blob",
337
+ children: [
338
+ h(GitPathBreadcrumbs, { key: "crumbs", path: resolvedPath, refName, repositoryKey: props.repositoryKey }),
339
+ h(GitBlobView, {
340
+ content: blob.data?.content,
341
+ key: "view",
342
+ path: resolvedPath,
347
343
  subtitle: selectedEntry?.language || "Plain text",
348
- children: blob.data
349
- ? h("pre", { className: "git-browser-code-block", children: blob.data.content })
350
- : "Select a file path to preview blob content.",
351
344
  }),
352
345
  ],
353
346
  }),
354
- }),
355
- ],
347
+ ],
348
+ }),
356
349
  });
357
350
  }
358
351
  function GitRepositoryCommitsPageInner(props) {
359
352
  const overview = useGitOverview(props.repositoryKey, {
360
353
  headers: props.headers,
361
- initialData: props.initialData || null,
354
+ initialData: props.initialData?.overview || null,
362
355
  });
356
+ const [limit, setLimit] = useState(20);
363
357
  const commits = useGitCommits(props.repositoryKey, {
364
358
  headers: props.headers,
359
+ initialData: props.initialData?.commits || null,
360
+ limit,
365
361
  path: props.path,
366
362
  ref: props.refName || overview.data?.repository.repository.current_branch || "HEAD",
367
363
  });
368
- return h("div", {
369
- className: joinClassNames("git-browser-page", props.className),
370
- children: [
371
- h(RepositoryHeader, {
372
- current: "commits",
373
- headers: props.headers,
374
- key: "header",
375
- navigate: props.navigate,
376
- overview: overview.data,
377
- repositoryKey: props.repositoryKey,
378
- }),
379
- h(StatusBlock, {
380
- error: commits.error,
381
- key: "status",
382
- loading: overview.loading || commits.loading,
383
- children: h(Card, {
384
- title: "Commit History",
385
- subtitle: props.path ? `Filtered to ${props.path}` : "Latest repository activity",
386
- children: h("ul", {
387
- className: "git-browser-list",
388
- children: (commits.data || []).map((commit) => (h("li", {
389
- className: "git-browser-list-item",
390
- key: commit.hash,
391
- children: `${commit.short_hash} · ${commit.subject} · ${commit.author_name} · ${formatDate(commit.authored_at)}`,
392
- }))),
393
- }),
394
- }),
395
- }),
396
- ],
364
+ return h(GitRepositoryShell, {
365
+ actions: h(GitRepositoryActionBar, {
366
+ children: h(GitBranchSelector, { headers: props.headers, repositoryKey: props.repositoryKey, selectedBranch: overview.data?.repository.repository.current_branch }),
367
+ }),
368
+ className: props.className,
369
+ error: commits.error,
370
+ loading: overview.loading || commits.loading,
371
+ page: "commits",
372
+ repositoryKey: props.repositoryKey,
373
+ social: overview.data?.social,
374
+ stats: overviewStats(overview.data),
375
+ subtitle: props.path ? `History filtered to ${props.path}` : defaultSubtitle(props.repositoryKey, overview.data),
376
+ children: h("section", {
377
+ className: "git-browser-card",
378
+ children: [
379
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Commit History" }) }),
380
+ h(GitCommitList, { commits: commits.data || [], key: "list", repositoryKey: props.repositoryKey }),
381
+ (commits.data || []).length >= limit
382
+ ? h("button", {
383
+ className: "git-browser-action-button",
384
+ key: "more",
385
+ onClick: () => setLimit((current) => current + 20),
386
+ type: "button",
387
+ children: "Load More Commits",
388
+ })
389
+ : null,
390
+ ],
391
+ }),
397
392
  });
398
393
  }
399
394
  function GitRepositoryCommitPageInner(props) {
400
395
  const overview = useGitOverview(props.repositoryKey, {
401
396
  headers: props.headers,
402
- initialData: props.initialData || null,
397
+ initialData: props.initialData?.overview || null,
403
398
  });
404
399
  const commit = useGitCommit(props.repositoryKey, props.commitRef, {
405
400
  headers: props.headers,
406
- });
407
- return h("div", {
408
- className: joinClassNames("git-browser-page", props.className),
409
- children: [
410
- h(RepositoryHeader, {
411
- current: "commits",
412
- headers: props.headers,
413
- key: "header",
414
- navigate: props.navigate,
415
- overview: overview.data,
416
- repositoryKey: props.repositoryKey,
417
- }),
418
- h(StatusBlock, {
419
- error: commit.error,
420
- key: "status",
421
- loading: overview.loading || commit.loading,
422
- children: commit.data ? h("div", {
423
- className: "git-browser-grid",
401
+ initialData: props.initialData?.commit || null,
402
+ });
403
+ return h(GitRepositoryShell, {
404
+ className: props.className,
405
+ error: commit.error,
406
+ loading: overview.loading || commit.loading,
407
+ page: "commit",
408
+ repositoryKey: props.repositoryKey,
409
+ social: overview.data?.social,
410
+ stats: overviewStats(overview.data),
411
+ subtitle: defaultSubtitle(props.repositoryKey, overview.data),
412
+ children: commit.data ? h("div", {
413
+ className: "git-browser-grid",
414
+ children: [
415
+ h("section", {
416
+ className: "git-browser-card git-browser-span-3",
417
+ key: "meta",
424
418
  children: [
425
- h(Card, {
426
- className: "git-browser-span-3",
427
- key: "meta",
428
- title: commit.data.commit.subject,
429
- subtitle: `${commit.data.commit.short_hash} by ${commit.data.commit.author_name}`,
430
- children: h(DefinitionGrid, {
431
- rows: [
432
- { label: "Authored", value: formatDate(commit.data.commit.authored_at) },
433
- { label: "Files", value: String(commit.data.file_count) },
434
- { label: "Added", value: String(commit.data.lines_added) },
435
- { label: "Removed", value: String(commit.data.lines_removed) },
436
- ],
437
- }),
438
- }),
439
- h(Card, {
440
- className: "git-browser-span-3",
441
- key: "diff",
442
- title: "Diff",
443
- children: h("pre", { className: "git-browser-code-block", children: commit.data.diff }),
444
- }),
419
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: commit.data.commit.subject }) }),
420
+ h("p", { className: "git-browser-note", key: "meta", children: `${commit.data.commit.short_hash} · ${commit.data.commit.author_name} · ${commit.data.file_count} files` }),
421
+ h("pre", { className: "git-browser-code-block", key: "diff", children: commit.data.diff }),
445
422
  ],
446
- }) : null,
447
- }),
448
- ],
449
- });
450
- }
451
- function ReleaseComposer(props) {
452
- const createRelease = useGitCreateRelease(props.repositoryKey, { headers: props.headers });
453
- const [title, setTitle] = useState("");
454
- const [tagName, setTagName] = useState("");
455
- const [notes, setNotes] = useState("");
456
- return h("form", {
457
- className: "git-browser-form",
458
- onSubmit: async (event) => {
459
- event.preventDefault();
460
- const release = await createRelease.mutate({
461
- createTag: {
462
- annotatedMessage: notes || title,
463
- name: tagName,
464
- targetRef: "HEAD",
465
- },
466
- notes,
467
- title,
468
- });
469
- setTitle("");
470
- setTagName("");
471
- setNotes("");
472
- props.onCreated(release);
473
- },
474
- children: [
475
- h("input", {
476
- className: "git-browser-input",
477
- key: "title",
478
- onChange: (event) => setTitle(text(event.target?.value)),
479
- placeholder: "Release title",
480
- value: title,
481
- }),
482
- h("input", {
483
- className: "git-browser-input",
484
- key: "tag",
485
- onChange: (event) => setTagName(text(event.target?.value)),
486
- placeholder: "Tag name",
487
- value: tagName,
488
- }),
489
- h("textarea", {
490
- className: "git-browser-input git-browser-textarea",
491
- key: "notes",
492
- onChange: (event) => setNotes(text(event.target?.value)),
493
- placeholder: "Release notes",
494
- value: notes,
495
- }),
496
- h("button", {
497
- className: "git-browser-action-button is-primary",
498
- disabled: createRelease.loading || !title || !tagName,
499
- key: "submit",
500
- type: "submit",
501
- children: createRelease.loading ? "Publishing..." : "Publish Release",
502
- }),
503
- ],
423
+ }),
424
+ ],
425
+ }) : null,
504
426
  });
505
427
  }
506
428
  function GitRepositoryReleasesPageInner(props) {
507
429
  const overview = useGitOverview(props.repositoryKey, {
508
430
  headers: props.headers,
509
- initialData: props.initialData || null,
431
+ initialData: props.initialData?.overview || null,
510
432
  });
511
433
  const releases = useGitReleases(props.repositoryKey, {
512
434
  headers: props.headers,
513
- });
514
- const [createdRelease, setCreatedRelease] = useState(null);
515
- useEffect(() => {
516
- if (createdRelease)
517
- releases.reload();
518
- }, [createdRelease]);
519
- return h("div", {
520
- className: joinClassNames("git-browser-page", props.className),
521
- children: [
522
- h(RepositoryHeader, {
523
- current: "releases",
524
- headers: props.headers,
525
- key: "header",
526
- navigate: props.navigate,
527
- overview: overview.data,
528
- repositoryKey: props.repositoryKey,
529
- }),
530
- h(StatusBlock, {
531
- error: releases.error,
532
- key: "status",
533
- loading: overview.loading || releases.loading,
534
- children: h("div", {
535
- className: "git-browser-grid",
435
+ initialData: props.initialData?.releases || null,
436
+ });
437
+ return h(GitRepositoryShell, {
438
+ actions: defaultActionBar(props.repositoryKey, props.headers),
439
+ className: props.className,
440
+ error: releases.error,
441
+ loading: overview.loading || releases.loading,
442
+ page: "releases",
443
+ repositoryKey: props.repositoryKey,
444
+ social: overview.data?.social,
445
+ stats: overviewStats(overview.data),
446
+ subtitle: defaultSubtitle(props.repositoryKey, overview.data),
447
+ children: h("div", {
448
+ className: "git-browser-grid",
449
+ children: [
450
+ h(GitReleaseComposerCard, {
451
+ headers: props.headers,
452
+ key: "composer",
453
+ onCreated: releases.reload,
454
+ repositoryKey: props.repositoryKey,
455
+ }),
456
+ h("section", {
457
+ className: "git-browser-card git-browser-span-2",
458
+ key: "list-card",
536
459
  children: [
537
- h(Card, {
538
- key: "composer",
539
- title: "Publish a Release",
540
- subtitle: "This creates an annotated tag when needed.",
541
- children: h(ReleaseComposer, {
542
- headers: props.headers,
543
- onCreated: setCreatedRelease,
544
- repositoryKey: props.repositoryKey,
545
- }),
546
- }),
547
- h(Card, {
548
- className: "git-browser-span-2",
549
- key: "list",
550
- title: "Releases",
551
- children: h("ul", {
552
- className: "git-browser-list",
553
- children: (releases.data || []).map((release) => (h("li", {
554
- className: "git-browser-list-item",
555
- key: release.id,
556
- children: [
557
- h("strong", { key: "title", children: `${release.title} · ${release.tag_name}` }),
558
- h("div", { className: "git-browser-note", key: "meta", children: `${release.prerelease ? "Prerelease" : "Stable"} · ${formatDate(release.published_at || release.created_at)}` }),
559
- h("p", { className: "git-browser-note", key: "notes", children: release.notes || "No release notes." }),
560
- ],
561
- }))),
562
- }),
563
- }),
460
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Releases" }) }),
461
+ h(GitReleaseList, { key: "list", releases: releases.data || [], repositoryKey: props.repositoryKey }),
564
462
  ],
565
463
  }),
566
- }),
567
- ],
464
+ ],
465
+ }),
568
466
  });
569
467
  }
570
468
  function GitRepositoryReleasePageInner(props) {
571
469
  const overview = useGitOverview(props.repositoryKey, {
572
470
  headers: props.headers,
573
- initialData: props.initialData || null,
471
+ initialData: props.initialData?.overview || null,
574
472
  });
575
473
  const release = useGitRelease(props.repositoryKey, props.releaseId, {
576
474
  headers: props.headers,
577
- });
578
- return h("div", {
579
- className: joinClassNames("git-browser-page", props.className),
580
- children: [
581
- h(RepositoryHeader, {
582
- current: "releases",
583
- headers: props.headers,
584
- key: "header",
585
- navigate: props.navigate,
586
- overview: overview.data,
587
- repositoryKey: props.repositoryKey,
588
- }),
589
- h(StatusBlock, {
590
- error: release.error,
591
- key: "status",
592
- loading: overview.loading || release.loading,
593
- children: release.data ? h("div", {
594
- className: "git-browser-grid",
475
+ initialData: props.initialData?.release || null,
476
+ });
477
+ return h(GitRepositoryShell, {
478
+ actions: defaultActionBar(props.repositoryKey, props.headers),
479
+ className: props.className,
480
+ error: release.error,
481
+ loading: overview.loading || release.loading,
482
+ page: "release",
483
+ repositoryKey: props.repositoryKey,
484
+ social: overview.data?.social,
485
+ stats: overviewStats(overview.data),
486
+ subtitle: defaultSubtitle(props.repositoryKey, overview.data),
487
+ children: release.data ? h("div", {
488
+ className: "git-browser-grid",
489
+ children: [
490
+ h("section", {
491
+ className: "git-browser-card git-browser-span-2",
492
+ key: "details",
595
493
  children: [
596
- h(Card, {
597
- className: "git-browser-span-2",
598
- key: "details",
599
- title: release.data.title,
600
- subtitle: `${release.data.tag_name} · ${release.data.prerelease ? "Prerelease" : "Release"}`,
601
- children: [
602
- h("p", { className: "git-browser-note", key: "notes", children: release.data.notes || "No release notes." }),
603
- h(DefinitionGrid, {
604
- key: "meta",
605
- rows: [
606
- { label: "Published", value: formatDate(release.data.published_at || release.data.created_at) },
607
- { label: "Target", value: release.data.target_ref },
608
- { label: "Assets", value: String(release.data.assets.length) },
609
- ],
610
- }),
611
- ],
612
- }),
613
- h(Card, {
614
- key: "assets",
615
- title: "Assets",
616
- children: release.data.assets.length
617
- ? h("ul", {
618
- className: "git-browser-list",
619
- children: release.data.assets.map((asset) => (h("li", {
620
- className: "git-browser-list-item",
621
- key: asset.id,
622
- children: `${asset.name}${asset.size ? ` · ${asset.size} bytes` : ""}`,
623
- }))),
624
- })
625
- : "No assets attached.",
494
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: `${release.data.title} · ${release.data.tag_name}` }) }),
495
+ h("p", { className: "git-browser-note", key: "notes", children: release.data.notes || "No release notes." }),
496
+ ],
497
+ }),
498
+ h("section", {
499
+ className: "git-browser-card",
500
+ key: "assets",
501
+ children: [
502
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Assets" }) }),
503
+ h("ul", {
504
+ className: "git-browser-list",
505
+ key: "list",
506
+ children: release.data.assets.map((asset) => h("li", {
507
+ className: "git-browser-list-item",
508
+ key: asset.id,
509
+ children: `${asset.name}${asset.size ? ` · ${asset.size} bytes` : ""}`,
510
+ })),
626
511
  }),
627
512
  ],
628
- }) : null,
629
- }),
630
- ],
631
- });
632
- }
633
- function ForkRow(props) {
634
- const syncFork = useGitSyncFork(props.repositoryKey, props.fork.fork_repository_id, { headers: props.headers });
635
- const [currentFork, setCurrentFork] = useState(props.fork);
636
- useEffect(() => {
637
- setCurrentFork(props.fork);
638
- }, [props.fork]);
639
- return h("li", {
640
- className: "git-browser-list-item",
641
- children: [
642
- h("strong", { key: "name", children: currentFork.fork_repository_id }),
643
- h("div", {
644
- className: "git-browser-note",
645
- key: "status",
646
- children: `Ahead ${currentFork.fork_status.ahead} · Behind ${currentFork.fork_status.behind} · ${currentFork.fork_status.fork_branch} vs ${currentFork.fork_status.upstream_branch}`,
647
- }),
648
- h("button", {
649
- className: "git-browser-action-button",
650
- disabled: syncFork.loading,
651
- key: "sync",
652
- onClick: async () => {
653
- setCurrentFork(await syncFork.mutate({ strategy: "ff-only" }));
654
- },
655
- type: "button",
656
- children: syncFork.loading ? "Syncing..." : "Sync Fork",
657
- }),
658
- ],
513
+ }),
514
+ h(GitReleaseEditorCard, {
515
+ headers: props.headers,
516
+ key: "editor",
517
+ onDeleted: release.reload,
518
+ onUpdated: release.reload,
519
+ release: release.data,
520
+ repositoryKey: props.repositoryKey,
521
+ }),
522
+ ],
523
+ }) : null,
659
524
  });
660
525
  }
661
526
  function GitRepositoryForksPageInner(props) {
662
527
  const overview = useGitOverview(props.repositoryKey, {
663
528
  headers: props.headers,
664
- initialData: props.initialData || null,
529
+ initialData: props.initialData?.overview || null,
665
530
  });
666
531
  const forks = useGitForks(props.repositoryKey, {
667
532
  headers: props.headers,
668
- });
669
- return h("div", {
670
- className: joinClassNames("git-browser-page", props.className),
671
- children: [
672
- h(RepositoryHeader, {
673
- current: "forks",
674
- headers: props.headers,
675
- key: "header",
676
- navigate: props.navigate,
677
- overview: overview.data,
678
- repositoryKey: props.repositoryKey,
679
- }),
680
- h(StatusBlock, {
681
- error: forks.error,
682
- key: "status",
683
- loading: overview.loading || forks.loading,
684
- children: h(Card, {
685
- title: "Fork Network",
686
- subtitle: "Create forks, then sync them against upstream from this page.",
687
- children: h("ul", {
688
- className: "git-browser-list",
689
- children: (forks.data || []).map((fork) => h(ForkRow, {
690
- fork,
691
- headers: props.headers,
692
- key: fork.fork_repository_id,
693
- repositoryKey: props.repositoryKey,
694
- })),
695
- }),
696
- }),
697
- }),
698
- ],
533
+ initialData: props.initialData?.forks || null,
534
+ });
535
+ return h(GitRepositoryShell, {
536
+ actions: defaultActionBar(props.repositoryKey, props.headers),
537
+ className: props.className,
538
+ error: forks.error,
539
+ loading: overview.loading || forks.loading,
540
+ page: "forks",
541
+ repositoryKey: props.repositoryKey,
542
+ social: overview.data?.social,
543
+ stats: overviewStats(overview.data),
544
+ subtitle: defaultSubtitle(props.repositoryKey, overview.data),
545
+ children: h("section", {
546
+ className: "git-browser-card",
547
+ children: [
548
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Fork Network" }) }),
549
+ h(GitForkList, { forks: forks.data || [], headers: props.headers, key: "list", repositoryKey: props.repositoryKey }),
550
+ ],
551
+ }),
699
552
  });
700
553
  }
701
554
  function GitRepositoryActivityPageInner(props) {
702
555
  const overview = useGitOverview(props.repositoryKey, {
703
556
  headers: props.headers,
704
- initialData: props.initialData || null,
557
+ initialData: props.initialData?.overview || null,
705
558
  });
706
559
  const activity = useGitActivity(props.repositoryKey, {
707
560
  headers: props.headers,
561
+ initialData: props.initialData?.activity || null,
562
+ });
563
+ return h(GitRepositoryShell, {
564
+ className: props.className,
565
+ error: activity.error,
566
+ loading: overview.loading || activity.loading,
567
+ page: "activity",
568
+ repositoryKey: props.repositoryKey,
569
+ social: overview.data?.social,
570
+ stats: overviewStats(overview.data),
571
+ subtitle: defaultSubtitle(props.repositoryKey, overview.data),
572
+ children: h("section", {
573
+ className: "git-browser-card",
574
+ children: [
575
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Activity Timeline" }) }),
576
+ h(GitActivityList, { activity: activity.data || [], key: "body" }),
577
+ ],
578
+ }),
708
579
  });
709
- return h("div", {
710
- className: joinClassNames("git-browser-page", props.className),
711
- children: [
712
- h(RepositoryHeader, {
713
- current: "activity",
714
- headers: props.headers,
715
- key: "header",
716
- navigate: props.navigate,
717
- overview: overview.data,
718
- repositoryKey: props.repositoryKey,
719
- }),
720
- h(StatusBlock, {
721
- error: activity.error,
722
- key: "status",
723
- loading: overview.loading || activity.loading,
724
- children: h(Card, {
725
- title: "Activity Timeline",
726
- children: h("ul", {
727
- className: "git-browser-list",
728
- children: (activity.data || []).map((entry) => (h("li", {
729
- className: "git-browser-list-item",
730
- key: entry.id,
731
- children: [
732
- h("strong", { key: "summary", children: entry.summary }),
733
- h("div", { className: "git-browser-note", key: "meta", children: `${entry.kind} · actor ${entry.actor_id} · ${formatDate(entry.created_at)}` }),
734
- ],
735
- }))),
736
- }),
580
+ }
581
+ function GitRepositoryBranchesPageInner(props) {
582
+ const overview = useGitOverview(props.repositoryKey, {
583
+ headers: props.headers,
584
+ initialData: props.initialData?.overview || null,
585
+ });
586
+ const branches = useGitBranches(props.repositoryKey, {
587
+ headers: props.headers,
588
+ initialData: props.initialData?.branches || null,
589
+ });
590
+ return h(GitRepositoryShell, {
591
+ actions: h(GitRepositoryActionBar, {
592
+ children: h(GitBranchSelector, { headers: props.headers, repositoryKey: props.repositoryKey, selectedBranch: overview.data?.repository.repository.current_branch }),
593
+ }),
594
+ className: props.className,
595
+ error: branches.error,
596
+ loading: overview.loading || branches.loading,
597
+ page: "branches",
598
+ repositoryKey: props.repositoryKey,
599
+ social: overview.data?.social,
600
+ stats: overviewStats(overview.data),
601
+ subtitle: defaultSubtitle(props.repositoryKey, overview.data),
602
+ children: h("section", {
603
+ className: "git-browser-card",
604
+ children: [
605
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Branches" }) }),
606
+ h(GitBranchList, { branches: branches.data || [], key: "list", repositoryKey: props.repositoryKey }),
607
+ ],
608
+ }),
609
+ });
610
+ }
611
+ function GitRepositoryTagsPageInner(props) {
612
+ const overview = useGitOverview(props.repositoryKey, {
613
+ headers: props.headers,
614
+ initialData: props.initialData?.overview || null,
615
+ });
616
+ const tags = useGitTags(props.repositoryKey, {
617
+ headers: props.headers,
618
+ initialData: props.initialData?.tags || null,
619
+ });
620
+ return h(GitRepositoryShell, {
621
+ actions: h(GitRepositoryActionBar, {
622
+ children: h(GitTagSelector, { headers: props.headers, repositoryKey: props.repositoryKey }),
623
+ }),
624
+ className: props.className,
625
+ error: tags.error,
626
+ loading: overview.loading || tags.loading,
627
+ page: "tags",
628
+ repositoryKey: props.repositoryKey,
629
+ social: overview.data?.social,
630
+ stats: overviewStats(overview.data),
631
+ subtitle: defaultSubtitle(props.repositoryKey, overview.data),
632
+ children: h("section", {
633
+ className: "git-browser-card",
634
+ children: [
635
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Tags" }) }),
636
+ h(GitTagList, { key: "list", repositoryKey: props.repositoryKey, tags: tags.data || [] }),
637
+ ],
638
+ }),
639
+ });
640
+ }
641
+ function GitRepositorySearchPageInner(props) {
642
+ const overview = useGitOverview(props.repositoryKey, {
643
+ headers: props.headers,
644
+ initialData: props.initialData?.overview || null,
645
+ });
646
+ const [query, setQuery] = useState(text(props.query));
647
+ const results = useGitSearch(props.repositoryKey, {
648
+ enabled: Boolean(query),
649
+ headers: props.headers,
650
+ initialData: props.initialData?.search || null,
651
+ path: props.path,
652
+ query,
653
+ ref: props.refName || overview.data?.repository.repository.current_branch || "HEAD",
654
+ });
655
+ return h(GitRepositoryShell, {
656
+ className: props.className,
657
+ error: results.error,
658
+ loading: overview.loading || results.loading,
659
+ page: "search",
660
+ repositoryKey: props.repositoryKey,
661
+ social: overview.data?.social,
662
+ stats: overviewStats(overview.data),
663
+ subtitle: defaultSubtitle(props.repositoryKey, overview.data),
664
+ children: h("section", {
665
+ className: "git-browser-card",
666
+ children: [
667
+ h("div", {
668
+ className: "git-browser-card-header",
669
+ key: "header",
670
+ children: [
671
+ h("h2", { className: "git-browser-card-title", key: "title", children: "Search" }),
672
+ h("input", {
673
+ className: "git-browser-input",
674
+ key: "input",
675
+ onChange: (event) => setQuery(text(event.target?.value)),
676
+ placeholder: "Search this repository",
677
+ value: query,
678
+ }),
679
+ ],
737
680
  }),
738
- }),
739
- ],
681
+ h(GitSearchResults, { key: "results", repositoryKey: props.repositoryKey, results: results.data }),
682
+ ],
683
+ }),
684
+ });
685
+ }
686
+ function GitRepositoryBlamePageInner(props) {
687
+ const overview = useGitOverview(props.repositoryKey, {
688
+ headers: props.headers,
689
+ initialData: props.initialData?.overview || null,
690
+ });
691
+ const blame = useGitBlame(props.repositoryKey, {
692
+ headers: props.headers,
693
+ path: props.path,
694
+ ref: props.refName || overview.data?.repository.repository.current_branch || "HEAD",
695
+ });
696
+ return h(GitRepositoryShell, {
697
+ className: props.className,
698
+ error: blame.error,
699
+ loading: overview.loading || blame.loading,
700
+ page: "blame",
701
+ repositoryKey: props.repositoryKey,
702
+ social: overview.data?.social,
703
+ stats: overviewStats(overview.data),
704
+ subtitle: props.path ? `Blame for ${props.path}` : defaultSubtitle(props.repositoryKey, overview.data),
705
+ children: h("section", {
706
+ className: "git-browser-card",
707
+ children: [
708
+ h("div", { className: "git-browser-card-header", key: "header", children: h("h2", { className: "git-browser-card-title", children: "Blame" }) }),
709
+ h(GitBlameView, { blame: blame.data, key: "view", refName: props.refName, repositoryKey: props.repositoryKey }),
710
+ ],
711
+ }),
712
+ });
713
+ }
714
+ function GitRepositoryComparePageInner(props) {
715
+ const overview = useGitOverview(props.repositoryKey, {
716
+ headers: props.headers,
717
+ initialData: props.initialData?.overview || null,
718
+ });
719
+ const diff = useGitDiff(props.repositoryKey, {
720
+ baseRef: props.baseRef,
721
+ headRef: props.headRef,
722
+ headers: props.headers,
723
+ initialData: props.initialData?.compare || null,
724
+ path: props.path,
725
+ });
726
+ return h(GitRepositoryShell, {
727
+ className: props.className,
728
+ error: diff.error,
729
+ loading: overview.loading || diff.loading,
730
+ page: "compare",
731
+ repositoryKey: props.repositoryKey,
732
+ social: overview.data?.social,
733
+ stats: overviewStats(overview.data),
734
+ subtitle: `${props.baseRef} → ${props.headRef}`,
735
+ children: h(GitDiffView, { diff: diff.data }),
740
736
  });
741
737
  }
742
738
  function GitRepositoryOverviewPage(props) {
@@ -763,5 +759,20 @@ function GitRepositoryForksPage(props) {
763
759
  function GitRepositoryActivityPage(props) {
764
760
  return withBrowserProvider(props, () => h(GitRepositoryActivityPageInner, props));
765
761
  }
766
- export { GitBrowserProvider, GitRepositoryActivityPage, GitRepositoryCodePage, GitRepositoryCommitPage, GitRepositoryCommitsPage, GitRepositoryForksPage, GitRepositoryOverviewPage, GitRepositoryReleasePage, GitRepositoryReleasesPage, };
762
+ function GitRepositoryBranchesPage(props) {
763
+ return withBrowserProvider(props, () => h(GitRepositoryBranchesPageInner, props));
764
+ }
765
+ function GitRepositoryTagsPage(props) {
766
+ return withBrowserProvider(props, () => h(GitRepositoryTagsPageInner, props));
767
+ }
768
+ function GitRepositorySearchPage(props) {
769
+ return withBrowserProvider(props, () => h(GitRepositorySearchPageInner, props));
770
+ }
771
+ function GitRepositoryBlamePage(props) {
772
+ return withBrowserProvider(props, () => h(GitRepositoryBlamePageInner, props));
773
+ }
774
+ function GitRepositoryComparePage(props) {
775
+ return withBrowserProvider(props, () => h(GitRepositoryComparePageInner, props));
776
+ }
777
+ export { GitBrowserProvider, GitRepositoryActivityPage, GitRepositoryBlamePage, GitRepositoryBranchesPage, GitRepositoryCodePage, GitRepositoryCommitPage, GitRepositoryCommitsPage, GitRepositoryComparePage, GitRepositoryForksPage, GitRepositoryOverviewPage, GitRepositoryReleasePage, GitRepositoryReleasesPage, GitRepositorySearchPage, GitRepositoryTagsPage, };
767
778
  //# sourceMappingURL=index.js.map