@plateerlab/xgen-gallery 0.1.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.
- package/README.md +61 -0
- package/dist/index.d.mts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +571 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +534 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +43 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
XgenGallery: () => XgenGallery
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
|
|
37
|
+
// src/XgenGallery.tsx
|
|
38
|
+
var import_react = require("react");
|
|
39
|
+
|
|
40
|
+
// src/api.ts
|
|
41
|
+
var API = "https://api.github.com";
|
|
42
|
+
function headers(token) {
|
|
43
|
+
const h = { Accept: "application/vnd.github.v3+json" };
|
|
44
|
+
if (token) h.Authorization = `Bearer ${token}`;
|
|
45
|
+
return h;
|
|
46
|
+
}
|
|
47
|
+
async function fetchRepos(org, token) {
|
|
48
|
+
try {
|
|
49
|
+
const res = await fetch(`${API}/orgs/${org}/repos?per_page=100&sort=updated`, {
|
|
50
|
+
headers: headers(token)
|
|
51
|
+
});
|
|
52
|
+
if (!res.ok) return [];
|
|
53
|
+
return res.json();
|
|
54
|
+
} catch {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function fetchReadme(org, repo, token) {
|
|
59
|
+
try {
|
|
60
|
+
const res = await fetch(`${API}/repos/${org}/${repo}/readme`, {
|
|
61
|
+
headers: { ...headers(token), Accept: "application/vnd.github.v3.raw" }
|
|
62
|
+
});
|
|
63
|
+
if (!res.ok) return null;
|
|
64
|
+
return res.text();
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function fetchDemoSnippets(org, repo, readme, token) {
|
|
70
|
+
for (const path of [".xgen-gallery/demo.json", "demo.json"]) {
|
|
71
|
+
try {
|
|
72
|
+
const res = await fetch(`${API}/repos/${org}/${repo}/contents/${path}`, {
|
|
73
|
+
headers: { ...headers(token), Accept: "application/vnd.github.v3.raw" }
|
|
74
|
+
});
|
|
75
|
+
if (!res.ok) continue;
|
|
76
|
+
const data = await res.json();
|
|
77
|
+
if (data.snippets?.length) return data.snippets;
|
|
78
|
+
} catch {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const res = await fetch(`${API}/repos/${org}/${repo}/contents/examples`, {
|
|
84
|
+
headers: headers(token)
|
|
85
|
+
});
|
|
86
|
+
if (res.ok) {
|
|
87
|
+
const files = await res.json();
|
|
88
|
+
const pyFiles = files.filter((f) => f.name.endsWith(".py")).slice(0, 5);
|
|
89
|
+
const snippets = [];
|
|
90
|
+
for (const f of pyFiles) {
|
|
91
|
+
try {
|
|
92
|
+
const r = await fetch(f.download_url);
|
|
93
|
+
if (r.ok) {
|
|
94
|
+
const code = await r.text();
|
|
95
|
+
snippets.push({ label: f.name.replace(/\.py$/, "").replace(/[_-]/g, " "), code: code.trim() });
|
|
96
|
+
}
|
|
97
|
+
} catch {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (snippets.length) return snippets;
|
|
102
|
+
}
|
|
103
|
+
} catch {
|
|
104
|
+
}
|
|
105
|
+
let md = readme;
|
|
106
|
+
if (!md) md = await fetchReadme(org, repo, token);
|
|
107
|
+
if (md) {
|
|
108
|
+
const blocks = extractPythonBlocks(md);
|
|
109
|
+
if (blocks.length) return blocks;
|
|
110
|
+
}
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
function extractPythonBlocks(readme) {
|
|
114
|
+
const snippets = [];
|
|
115
|
+
const lines = readme.split("\n");
|
|
116
|
+
let i = 0;
|
|
117
|
+
while (i < lines.length) {
|
|
118
|
+
if (/^```(?:python|py)\s*$/i.test(lines[i].trim())) {
|
|
119
|
+
let label = "";
|
|
120
|
+
for (let j = i - 1; j >= Math.max(0, i - 5); j--) {
|
|
121
|
+
const prev = lines[j].trim();
|
|
122
|
+
if (/^#{1,4}\s+/.test(prev)) {
|
|
123
|
+
label = prev.replace(/^#+\s+/, "");
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
if (prev && !label) label = prev;
|
|
127
|
+
}
|
|
128
|
+
const codeLines = [];
|
|
129
|
+
i++;
|
|
130
|
+
while (i < lines.length && !lines[i].trim().startsWith("```")) {
|
|
131
|
+
codeLines.push(lines[i]);
|
|
132
|
+
i++;
|
|
133
|
+
}
|
|
134
|
+
const code = codeLines.join("\n").trim();
|
|
135
|
+
if (code && code.split("\n").length >= 2 && !code.startsWith("pip ") && !code.startsWith("$ pip")) {
|
|
136
|
+
snippets.push({ label: label || `Example ${snippets.length + 1}`, code });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
i++;
|
|
140
|
+
}
|
|
141
|
+
return snippets;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/styles.ts
|
|
145
|
+
var themes = {
|
|
146
|
+
dark: {
|
|
147
|
+
bg: "#0a0a0f",
|
|
148
|
+
bgCard: "#12121a",
|
|
149
|
+
bgCardHover: "#1a1a25",
|
|
150
|
+
border: "#1e1e2e",
|
|
151
|
+
text: "#e8e8f0",
|
|
152
|
+
textSecondary: "#a0a0b8",
|
|
153
|
+
textMuted: "#6b6b80",
|
|
154
|
+
accent: "#6c63ff",
|
|
155
|
+
accentLight: "#8b83ff",
|
|
156
|
+
accentGlow: "rgba(108,99,255,0.15)"
|
|
157
|
+
},
|
|
158
|
+
light: {
|
|
159
|
+
bg: "#f8f9fa",
|
|
160
|
+
bgCard: "#ffffff",
|
|
161
|
+
bgCardHover: "#f0f0f5",
|
|
162
|
+
border: "#e0e0e8",
|
|
163
|
+
text: "#1a1a2e",
|
|
164
|
+
textSecondary: "#4a4a5a",
|
|
165
|
+
textMuted: "#8a8a9a",
|
|
166
|
+
accent: "#5b52e0",
|
|
167
|
+
accentLight: "#5b52e0",
|
|
168
|
+
accentGlow: "rgba(91,82,224,0.1)"
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
var LANG_COLORS = {
|
|
172
|
+
Python: "#3572A5",
|
|
173
|
+
TypeScript: "#3178c6",
|
|
174
|
+
JavaScript: "#f1e05a",
|
|
175
|
+
Rust: "#dea584",
|
|
176
|
+
HTML: "#e34c26",
|
|
177
|
+
CSS: "#563d7c",
|
|
178
|
+
Go: "#00ADD8",
|
|
179
|
+
Shell: "#89e051",
|
|
180
|
+
Java: "#b07219",
|
|
181
|
+
"C++": "#f34b7d",
|
|
182
|
+
C: "#555555",
|
|
183
|
+
Ruby: "#701516"
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// src/ReadmeView.tsx
|
|
187
|
+
var import_react_markdown = __toESM(require("react-markdown"));
|
|
188
|
+
var import_remark_gfm = __toESM(require("remark-gfm"));
|
|
189
|
+
var import_rehype_raw = __toESM(require("rehype-raw"));
|
|
190
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
191
|
+
function ReadmeView({
|
|
192
|
+
org,
|
|
193
|
+
repoName,
|
|
194
|
+
content,
|
|
195
|
+
t
|
|
196
|
+
}) {
|
|
197
|
+
if (!content) {
|
|
198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { textAlign: "center", padding: 40, color: t.textMuted }, children: "README not found" });
|
|
199
|
+
}
|
|
200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "xgen-markdown", style: { color: t.text, lineHeight: 1.7, fontSize: 14 }, children: [
|
|
201
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: markdownStyles(t) }),
|
|
202
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
203
|
+
import_react_markdown.default,
|
|
204
|
+
{
|
|
205
|
+
remarkPlugins: [import_remark_gfm.default],
|
|
206
|
+
rehypePlugins: [import_rehype_raw.default],
|
|
207
|
+
components: {
|
|
208
|
+
img: ({ src, alt, ...props }) => {
|
|
209
|
+
let resolved = src;
|
|
210
|
+
if (typeof src === "string" && !src.startsWith("http")) {
|
|
211
|
+
resolved = `https://raw.githubusercontent.com/${org}/${repoName}/main/${src}`;
|
|
212
|
+
}
|
|
213
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: resolved, alt: alt || "", style: { maxWidth: "100%" }, ...props });
|
|
214
|
+
},
|
|
215
|
+
a: ({ href, children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", style: { color: t.accentLight }, ...props, children }),
|
|
216
|
+
code: ({ children, className, ...props }) => {
|
|
217
|
+
const isBlock = className?.includes("language-");
|
|
218
|
+
if (isBlock) {
|
|
219
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
220
|
+
"code",
|
|
221
|
+
{
|
|
222
|
+
style: {
|
|
223
|
+
display: "block",
|
|
224
|
+
background: t.bg,
|
|
225
|
+
padding: 16,
|
|
226
|
+
borderRadius: 8,
|
|
227
|
+
overflow: "auto",
|
|
228
|
+
fontSize: 13,
|
|
229
|
+
lineHeight: 1.6
|
|
230
|
+
},
|
|
231
|
+
...props,
|
|
232
|
+
children
|
|
233
|
+
}
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { style: { background: t.accentGlow, padding: "2px 6px", borderRadius: 4, fontSize: 13 }, ...props, children });
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
children: content
|
|
240
|
+
}
|
|
241
|
+
)
|
|
242
|
+
] });
|
|
243
|
+
}
|
|
244
|
+
function markdownStyles(t) {
|
|
245
|
+
return `
|
|
246
|
+
.xgen-markdown h1, .xgen-markdown h2, .xgen-markdown h3 { color: ${t.text}; margin: 1.2em 0 0.5em; }
|
|
247
|
+
.xgen-markdown h1 { font-size: 1.8em; border-bottom: 1px solid ${t.border}; padding-bottom: 8px; }
|
|
248
|
+
.xgen-markdown h2 { font-size: 1.4em; border-bottom: 1px solid ${t.border}; padding-bottom: 6px; }
|
|
249
|
+
.xgen-markdown h3 { font-size: 1.15em; }
|
|
250
|
+
.xgen-markdown p { margin: 0.8em 0; }
|
|
251
|
+
.xgen-markdown ul, .xgen-markdown ol { padding-left: 24px; }
|
|
252
|
+
.xgen-markdown li { margin: 4px 0; }
|
|
253
|
+
.xgen-markdown pre { background: ${t.bg}; border: 1px solid ${t.border}; border-radius: 8px; padding: 16px; overflow: auto; margin: 12px 0; }
|
|
254
|
+
.xgen-markdown blockquote { border-left: 3px solid ${t.accent}; padding-left: 12px; color: ${t.textSecondary}; margin: 12px 0; }
|
|
255
|
+
.xgen-markdown table { border-collapse: collapse; width: 100%; margin: 12px 0; }
|
|
256
|
+
.xgen-markdown th, .xgen-markdown td { border: 1px solid ${t.border}; padding: 8px 12px; text-align: left; }
|
|
257
|
+
.xgen-markdown th { background: ${t.bgCard}; font-weight: 600; }
|
|
258
|
+
.xgen-markdown hr { border: none; border-top: 1px solid ${t.border}; margin: 16px 0; }
|
|
259
|
+
`;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/XgenGallery.tsx
|
|
263
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
264
|
+
function XgenGallery({ org, token, theme: themeName = "dark", limit, onRepoClick }) {
|
|
265
|
+
const t = themes[themeName];
|
|
266
|
+
const [repos, setRepos] = (0, import_react.useState)([]);
|
|
267
|
+
const [loading, setLoading] = (0, import_react.useState)(true);
|
|
268
|
+
const [search, setSearch] = (0, import_react.useState)("");
|
|
269
|
+
const [lang, setLang] = (0, import_react.useState)(null);
|
|
270
|
+
const [view, setView] = (0, import_react.useState)({ type: "list" });
|
|
271
|
+
(0, import_react.useEffect)(() => {
|
|
272
|
+
fetchRepos(org, token).then((data) => {
|
|
273
|
+
setRepos(limit ? data.slice(0, limit) : data);
|
|
274
|
+
setLoading(false);
|
|
275
|
+
});
|
|
276
|
+
}, [org, token, limit]);
|
|
277
|
+
const languages = [...new Set(repos.map((r) => r.language).filter(Boolean))];
|
|
278
|
+
const filtered = repos.filter((r) => {
|
|
279
|
+
if (lang && r.language !== lang) return false;
|
|
280
|
+
if (search) {
|
|
281
|
+
const q = search.toLowerCase();
|
|
282
|
+
return r.name.toLowerCase().includes(q) || (r.description || "").toLowerCase().includes(q);
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
});
|
|
286
|
+
const handleCardClick = (0, import_react.useCallback)((repo) => {
|
|
287
|
+
if (onRepoClick) {
|
|
288
|
+
onRepoClick(repo);
|
|
289
|
+
} else {
|
|
290
|
+
setView({ type: "detail", repo });
|
|
291
|
+
}
|
|
292
|
+
}, [onRepoClick]);
|
|
293
|
+
if (view.type === "detail") {
|
|
294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RepoDetail, { org, repo: view.repo, token, t, onBack: () => setView({ type: "list" }) });
|
|
295
|
+
}
|
|
296
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { background: t.bg, color: t.text, fontFamily: "system-ui, -apple-system, sans-serif", padding: 24 }, children: [
|
|
297
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: 24 }, children: [
|
|
298
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: { fontSize: 24, fontWeight: 700, margin: 0 }, children: org }),
|
|
299
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: { color: t.textMuted, fontSize: 14, margin: "4px 0 0" }, children: [
|
|
300
|
+
repos.length,
|
|
301
|
+
" repositories"
|
|
302
|
+
] })
|
|
303
|
+
] }),
|
|
304
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 16 }, children: [
|
|
305
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
306
|
+
"input",
|
|
307
|
+
{
|
|
308
|
+
type: "text",
|
|
309
|
+
placeholder: "Search...",
|
|
310
|
+
value: search,
|
|
311
|
+
onChange: (e) => setSearch(e.target.value),
|
|
312
|
+
style: {
|
|
313
|
+
background: t.bgCard,
|
|
314
|
+
border: `1px solid ${t.border}`,
|
|
315
|
+
borderRadius: 8,
|
|
316
|
+
padding: "8px 12px",
|
|
317
|
+
color: t.text,
|
|
318
|
+
fontSize: 14,
|
|
319
|
+
outline: "none",
|
|
320
|
+
flex: "1 1 200px"
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
),
|
|
324
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
325
|
+
"button",
|
|
326
|
+
{
|
|
327
|
+
onClick: () => setLang(null),
|
|
328
|
+
style: {
|
|
329
|
+
padding: "6px 12px",
|
|
330
|
+
borderRadius: 8,
|
|
331
|
+
fontSize: 12,
|
|
332
|
+
fontWeight: 500,
|
|
333
|
+
cursor: "pointer",
|
|
334
|
+
background: !lang ? t.accent : "transparent",
|
|
335
|
+
color: !lang ? "#fff" : t.textMuted,
|
|
336
|
+
border: `1px solid ${!lang ? t.accent : t.border}`
|
|
337
|
+
},
|
|
338
|
+
children: "All"
|
|
339
|
+
}
|
|
340
|
+
),
|
|
341
|
+
languages.map((l) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
342
|
+
"button",
|
|
343
|
+
{
|
|
344
|
+
onClick: () => setLang(lang === l ? null : l),
|
|
345
|
+
style: {
|
|
346
|
+
padding: "6px 12px",
|
|
347
|
+
borderRadius: 8,
|
|
348
|
+
fontSize: 12,
|
|
349
|
+
fontWeight: 500,
|
|
350
|
+
cursor: "pointer",
|
|
351
|
+
background: lang === l ? t.accent : "transparent",
|
|
352
|
+
color: lang === l ? "#fff" : t.textMuted,
|
|
353
|
+
border: `1px solid ${lang === l ? t.accent : t.border}`
|
|
354
|
+
},
|
|
355
|
+
children: l
|
|
356
|
+
},
|
|
357
|
+
l
|
|
358
|
+
))
|
|
359
|
+
] }),
|
|
360
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { textAlign: "center", padding: 60, color: t.textMuted }, children: "Loading..." }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(300px, 1fr))", gap: 16 }, children: filtered.map((repo) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RepoCard, { repo, t, onClick: () => handleCardClick(repo) }, repo.name)) }),
|
|
361
|
+
!loading && filtered.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { textAlign: "center", padding: 60, color: t.textMuted }, children: "No results" })
|
|
362
|
+
] });
|
|
363
|
+
}
|
|
364
|
+
function RepoCard({ repo, t, onClick }) {
|
|
365
|
+
const [hover, setHover] = (0, import_react.useState)(false);
|
|
366
|
+
const langColor = repo.language ? LANG_COLORS[repo.language] || "#888" : null;
|
|
367
|
+
const date = new Date(repo.updated_at).toLocaleDateString("ko-KR", { year: "numeric", month: "short", day: "numeric" });
|
|
368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
369
|
+
"div",
|
|
370
|
+
{
|
|
371
|
+
onClick,
|
|
372
|
+
onMouseEnter: () => setHover(true),
|
|
373
|
+
onMouseLeave: () => setHover(false),
|
|
374
|
+
style: {
|
|
375
|
+
background: hover ? t.bgCardHover : t.bgCard,
|
|
376
|
+
border: `1px solid ${hover ? t.accent : t.border}`,
|
|
377
|
+
borderRadius: 12,
|
|
378
|
+
padding: 20,
|
|
379
|
+
cursor: "pointer",
|
|
380
|
+
transform: hover ? "translateY(-2px)" : "none",
|
|
381
|
+
boxShadow: hover ? `0 0 20px ${t.accentGlow}` : "none",
|
|
382
|
+
transition: "all 0.2s"
|
|
383
|
+
},
|
|
384
|
+
children: [
|
|
385
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 8 }, children: [
|
|
386
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: 16, fontWeight: 600, color: t.accentLight }, children: repo.name }),
|
|
387
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
388
|
+
"button",
|
|
389
|
+
{
|
|
390
|
+
onClick: (e) => {
|
|
391
|
+
e.stopPropagation();
|
|
392
|
+
window.open(repo.html_url, "_blank");
|
|
393
|
+
},
|
|
394
|
+
style: {
|
|
395
|
+
fontSize: 11,
|
|
396
|
+
padding: "2px 8px",
|
|
397
|
+
borderRadius: 6,
|
|
398
|
+
cursor: "pointer",
|
|
399
|
+
border: `1px solid ${t.border}`,
|
|
400
|
+
background: "transparent",
|
|
401
|
+
color: t.textMuted
|
|
402
|
+
},
|
|
403
|
+
children: "GitHub \u2192"
|
|
404
|
+
}
|
|
405
|
+
)
|
|
406
|
+
] }),
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: 13, color: t.textSecondary, margin: "0 0 12px", lineHeight: 1.5, minHeight: 40 }, children: repo.description || "No description" }),
|
|
408
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 12, fontSize: 12, color: t.textMuted }, children: [
|
|
409
|
+
langColor && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
410
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { width: 10, height: 10, borderRadius: "50%", background: langColor, display: "inline-block" } }),
|
|
411
|
+
repo.language
|
|
412
|
+
] }),
|
|
413
|
+
repo.stargazers_count > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
414
|
+
"\u2605 ",
|
|
415
|
+
repo.stargazers_count
|
|
416
|
+
] }),
|
|
417
|
+
repo.forks_count > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
418
|
+
"Fork ",
|
|
419
|
+
repo.forks_count
|
|
420
|
+
] }),
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: date })
|
|
422
|
+
] })
|
|
423
|
+
]
|
|
424
|
+
}
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
function RepoDetail({ org, repo, token, t, onBack }) {
|
|
428
|
+
const [tab, setTab] = (0, import_react.useState)("readme");
|
|
429
|
+
const [readme, setReadme] = (0, import_react.useState)(null);
|
|
430
|
+
const [snippets, setSnippets] = (0, import_react.useState)([]);
|
|
431
|
+
const [loading, setLoading] = (0, import_react.useState)(true);
|
|
432
|
+
(0, import_react.useEffect)(() => {
|
|
433
|
+
Promise.all([
|
|
434
|
+
fetchReadme(org, repo.name, token),
|
|
435
|
+
fetchDemoSnippets(org, repo.name, void 0, token)
|
|
436
|
+
]).then(([md, s]) => {
|
|
437
|
+
setReadme(md);
|
|
438
|
+
setSnippets(s);
|
|
439
|
+
setLoading(false);
|
|
440
|
+
});
|
|
441
|
+
}, [org, repo.name, token]);
|
|
442
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { background: t.bg, color: t.text, fontFamily: "system-ui, -apple-system, sans-serif", padding: 24 }, children: [
|
|
443
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
444
|
+
"button",
|
|
445
|
+
{
|
|
446
|
+
onClick: onBack,
|
|
447
|
+
style: {
|
|
448
|
+
background: "transparent",
|
|
449
|
+
border: "none",
|
|
450
|
+
color: t.accentLight,
|
|
451
|
+
cursor: "pointer",
|
|
452
|
+
fontSize: 14,
|
|
453
|
+
padding: 0,
|
|
454
|
+
marginBottom: 16
|
|
455
|
+
},
|
|
456
|
+
children: "\u2190 Back"
|
|
457
|
+
}
|
|
458
|
+
),
|
|
459
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { background: t.bgCard, border: `1px solid ${t.border}`, borderRadius: 12, padding: 24, marginBottom: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: 16 }, children: [
|
|
460
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
461
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { style: { fontSize: 22, fontWeight: 700, margin: 0 }, children: repo.name }),
|
|
462
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { color: t.textSecondary, fontSize: 14, margin: "8px 0" }, children: repo.description || "No description" })
|
|
463
|
+
] }),
|
|
464
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
465
|
+
"a",
|
|
466
|
+
{
|
|
467
|
+
href: repo.html_url,
|
|
468
|
+
target: "_blank",
|
|
469
|
+
rel: "noopener noreferrer",
|
|
470
|
+
style: {
|
|
471
|
+
display: "inline-flex",
|
|
472
|
+
alignItems: "center",
|
|
473
|
+
gap: 8,
|
|
474
|
+
padding: "8px 16px",
|
|
475
|
+
borderRadius: 8,
|
|
476
|
+
fontSize: 14,
|
|
477
|
+
fontWeight: 500,
|
|
478
|
+
background: t.accent,
|
|
479
|
+
color: "#fff",
|
|
480
|
+
textDecoration: "none",
|
|
481
|
+
height: "fit-content"
|
|
482
|
+
},
|
|
483
|
+
children: "View on GitHub"
|
|
484
|
+
}
|
|
485
|
+
)
|
|
486
|
+
] }) }),
|
|
487
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: 4, borderBottom: `1px solid ${t.border}`, marginBottom: 16 }, children: ["readme", ...snippets.length > 0 ? ["demo"] : []].map((key) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
488
|
+
"button",
|
|
489
|
+
{
|
|
490
|
+
onClick: () => setTab(key),
|
|
491
|
+
style: {
|
|
492
|
+
padding: "10px 16px",
|
|
493
|
+
fontSize: 14,
|
|
494
|
+
fontWeight: 500,
|
|
495
|
+
cursor: "pointer",
|
|
496
|
+
background: "transparent",
|
|
497
|
+
border: "none",
|
|
498
|
+
color: tab === key ? t.accentLight : t.textMuted,
|
|
499
|
+
borderBottom: tab === key ? `2px solid ${t.accent}` : "2px solid transparent"
|
|
500
|
+
},
|
|
501
|
+
children: key === "readme" ? "README" : "Demo"
|
|
502
|
+
},
|
|
503
|
+
key
|
|
504
|
+
)) }),
|
|
505
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { background: t.bgCard, border: `1px solid ${t.border}`, borderRadius: 12, padding: 24 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { textAlign: "center", padding: 40, color: t.textMuted }, children: "Loading..." }) : tab === "readme" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReadmeView, { org, repoName: repo.name, content: readme, t }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DemoView, { snippets, t }) })
|
|
506
|
+
] });
|
|
507
|
+
}
|
|
508
|
+
function DemoView({ snippets, t }) {
|
|
509
|
+
const [idx, setIdx] = (0, import_react.useState)(0);
|
|
510
|
+
const snippet = snippets[idx];
|
|
511
|
+
if (!snippet) return null;
|
|
512
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
513
|
+
snippets.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: 6, marginBottom: 12, flexWrap: "wrap" }, children: snippets.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
514
|
+
"button",
|
|
515
|
+
{
|
|
516
|
+
onClick: () => setIdx(i),
|
|
517
|
+
style: {
|
|
518
|
+
padding: "4px 12px",
|
|
519
|
+
borderRadius: 99,
|
|
520
|
+
fontSize: 12,
|
|
521
|
+
cursor: "pointer",
|
|
522
|
+
background: i === idx ? t.accentGlow : "transparent",
|
|
523
|
+
color: i === idx ? t.accentLight : t.textMuted,
|
|
524
|
+
border: `1px solid ${i === idx ? t.accent : t.border}`
|
|
525
|
+
},
|
|
526
|
+
children: s.label
|
|
527
|
+
},
|
|
528
|
+
i
|
|
529
|
+
)) }),
|
|
530
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
531
|
+
"pre",
|
|
532
|
+
{
|
|
533
|
+
style: {
|
|
534
|
+
background: t.bg,
|
|
535
|
+
border: `1px solid ${t.border}`,
|
|
536
|
+
borderRadius: 8,
|
|
537
|
+
padding: 16,
|
|
538
|
+
fontSize: 13,
|
|
539
|
+
lineHeight: 1.6,
|
|
540
|
+
overflow: "auto",
|
|
541
|
+
color: t.textSecondary,
|
|
542
|
+
margin: 0
|
|
543
|
+
},
|
|
544
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { children: snippet.code })
|
|
545
|
+
}
|
|
546
|
+
),
|
|
547
|
+
snippet.expectedOutput && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginTop: 12 }, children: [
|
|
548
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: 12, color: t.textMuted }, children: "Expected Output:" }),
|
|
549
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
550
|
+
"pre",
|
|
551
|
+
{
|
|
552
|
+
style: {
|
|
553
|
+
background: t.bg,
|
|
554
|
+
border: `1px solid ${t.border}`,
|
|
555
|
+
borderRadius: 8,
|
|
556
|
+
padding: 12,
|
|
557
|
+
fontSize: 12,
|
|
558
|
+
color: t.textMuted,
|
|
559
|
+
margin: "4px 0 0"
|
|
560
|
+
},
|
|
561
|
+
children: snippet.expectedOutput
|
|
562
|
+
}
|
|
563
|
+
)
|
|
564
|
+
] })
|
|
565
|
+
] });
|
|
566
|
+
}
|
|
567
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
568
|
+
0 && (module.exports = {
|
|
569
|
+
XgenGallery
|
|
570
|
+
});
|
|
571
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/XgenGallery.tsx","../src/api.ts","../src/styles.ts","../src/ReadmeView.tsx"],"sourcesContent":["export { XgenGallery } from \"./XgenGallery\";\r\nexport type { GalleryProps, Repo, DemoSnippet } from \"./types\";\r\n","import { useEffect, useState, useCallback } from \"react\";\r\nimport type { Repo, GalleryProps, DemoSnippet } from \"./types\";\r\nimport { fetchRepos, fetchReadme, fetchDemoSnippets } from \"./api\";\r\nimport { themes, LANG_COLORS, Theme } from \"./styles\";\r\nimport { ReadmeView } from \"./ReadmeView\";\r\n\r\ntype View = { type: \"list\" } | { type: \"detail\"; repo: Repo };\r\n\r\nexport function XgenGallery({ org, token, theme: themeName = \"dark\", limit, onRepoClick }: GalleryProps) {\r\n const t = themes[themeName];\r\n const [repos, setRepos] = useState<Repo[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n const [search, setSearch] = useState(\"\");\r\n const [lang, setLang] = useState<string | null>(null);\r\n const [view, setView] = useState<View>({ type: \"list\" });\r\n\r\n useEffect(() => {\r\n fetchRepos(org, token).then((data) => {\r\n setRepos(limit ? data.slice(0, limit) : data);\r\n setLoading(false);\r\n });\r\n }, [org, token, limit]);\r\n\r\n const languages = [...new Set(repos.map((r) => r.language).filter(Boolean))] as string[];\r\n\r\n const filtered = repos.filter((r) => {\r\n if (lang && r.language !== lang) return false;\r\n if (search) {\r\n const q = search.toLowerCase();\r\n return r.name.toLowerCase().includes(q) || (r.description || \"\").toLowerCase().includes(q);\r\n }\r\n return true;\r\n });\r\n\r\n const handleCardClick = useCallback((repo: Repo) => {\r\n if (onRepoClick) {\r\n onRepoClick(repo);\r\n } else {\r\n setView({ type: \"detail\", repo });\r\n }\r\n }, [onRepoClick]);\r\n\r\n if (view.type === \"detail\") {\r\n return <RepoDetail org={org} repo={view.repo} token={token} t={t} onBack={() => setView({ type: \"list\" })} />;\r\n }\r\n\r\n return (\r\n <div style={{ background: t.bg, color: t.text, fontFamily: \"system-ui, -apple-system, sans-serif\", padding: 24 }}>\r\n {/* Header */}\r\n <div style={{ marginBottom: 24 }}>\r\n <h2 style={{ fontSize: 24, fontWeight: 700, margin: 0 }}>{org}</h2>\r\n <p style={{ color: t.textMuted, fontSize: 14, margin: \"4px 0 0\" }}>\r\n {repos.length} repositories\r\n </p>\r\n </div>\r\n\r\n {/* Search + Filter */}\r\n <div style={{ display: \"flex\", gap: 8, flexWrap: \"wrap\", marginBottom: 16 }}>\r\n <input\r\n type=\"text\"\r\n placeholder=\"Search...\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n style={{\r\n background: t.bgCard, border: `1px solid ${t.border}`, borderRadius: 8,\r\n padding: \"8px 12px\", color: t.text, fontSize: 14, outline: \"none\", flex: \"1 1 200px\",\r\n }}\r\n />\r\n <button\r\n onClick={() => setLang(null)}\r\n style={{\r\n padding: \"6px 12px\", borderRadius: 8, fontSize: 12, fontWeight: 500, cursor: \"pointer\",\r\n background: !lang ? t.accent : \"transparent\",\r\n color: !lang ? \"#fff\" : t.textMuted,\r\n border: `1px solid ${!lang ? t.accent : t.border}`,\r\n }}\r\n >\r\n All\r\n </button>\r\n {languages.map((l) => (\r\n <button\r\n key={l}\r\n onClick={() => setLang(lang === l ? null : l)}\r\n style={{\r\n padding: \"6px 12px\", borderRadius: 8, fontSize: 12, fontWeight: 500, cursor: \"pointer\",\r\n background: lang === l ? t.accent : \"transparent\",\r\n color: lang === l ? \"#fff\" : t.textMuted,\r\n border: `1px solid ${lang === l ? t.accent : t.border}`,\r\n }}\r\n >\r\n {l}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Grid */}\r\n {loading ? (\r\n <div style={{ textAlign: \"center\", padding: 60, color: t.textMuted }}>Loading...</div>\r\n ) : (\r\n <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(auto-fill, minmax(300px, 1fr))\", gap: 16 }}>\r\n {filtered.map((repo) => (\r\n <RepoCard key={repo.name} repo={repo} t={t} onClick={() => handleCardClick(repo)} />\r\n ))}\r\n </div>\r\n )}\r\n {!loading && filtered.length === 0 && (\r\n <div style={{ textAlign: \"center\", padding: 60, color: t.textMuted }}>No results</div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n/* ---------- RepoCard ---------- */\r\n\r\nfunction RepoCard({ repo, t, onClick }: { repo: Repo; t: Theme; onClick: () => void }) {\r\n const [hover, setHover] = useState(false);\r\n const langColor = repo.language ? LANG_COLORS[repo.language] || \"#888\" : null;\r\n const date = new Date(repo.updated_at).toLocaleDateString(\"ko-KR\", { year: \"numeric\", month: \"short\", day: \"numeric\" });\r\n\r\n return (\r\n <div\r\n onClick={onClick}\r\n onMouseEnter={() => setHover(true)}\r\n onMouseLeave={() => setHover(false)}\r\n style={{\r\n background: hover ? t.bgCardHover : t.bgCard,\r\n border: `1px solid ${hover ? t.accent : t.border}`,\r\n borderRadius: 12, padding: 20, cursor: \"pointer\",\r\n transform: hover ? \"translateY(-2px)\" : \"none\",\r\n boxShadow: hover ? `0 0 20px ${t.accentGlow}` : \"none\",\r\n transition: \"all 0.2s\",\r\n }}\r\n >\r\n <div style={{ display: \"flex\", justifyContent: \"space-between\", marginBottom: 8 }}>\r\n <span style={{ fontSize: 16, fontWeight: 600, color: t.accentLight }}>{repo.name}</span>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); window.open(repo.html_url, \"_blank\"); }}\r\n style={{\r\n fontSize: 11, padding: \"2px 8px\", borderRadius: 6, cursor: \"pointer\",\r\n border: `1px solid ${t.border}`, background: \"transparent\", color: t.textMuted,\r\n }}\r\n >\r\n GitHub →\r\n </button>\r\n </div>\r\n <p style={{ fontSize: 13, color: t.textSecondary, margin: \"0 0 12px\", lineHeight: 1.5, minHeight: 40 }}>\r\n {repo.description || \"No description\"}\r\n </p>\r\n <div style={{ display: \"flex\", gap: 12, fontSize: 12, color: t.textMuted }}>\r\n {langColor && (\r\n <span style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\r\n <span style={{ width: 10, height: 10, borderRadius: \"50%\", background: langColor, display: \"inline-block\" }} />\r\n {repo.language}\r\n </span>\r\n )}\r\n {repo.stargazers_count > 0 && <span>★ {repo.stargazers_count}</span>}\r\n {repo.forks_count > 0 && <span>Fork {repo.forks_count}</span>}\r\n <span>{date}</span>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n/* ---------- RepoDetail ---------- */\r\n\r\nfunction RepoDetail({ org, repo, token, t, onBack }: { org: string; repo: Repo; token?: string; t: Theme; onBack: () => void }) {\r\n const [tab, setTab] = useState<\"readme\" | \"demo\">(\"readme\");\r\n const [readme, setReadme] = useState<string | null>(null);\r\n const [snippets, setSnippets] = useState<DemoSnippet[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n Promise.all([\r\n fetchReadme(org, repo.name, token),\r\n fetchDemoSnippets(org, repo.name, undefined, token),\r\n ]).then(([md, s]) => {\r\n setReadme(md);\r\n setSnippets(s);\r\n setLoading(false);\r\n });\r\n }, [org, repo.name, token]);\r\n\r\n return (\r\n <div style={{ background: t.bg, color: t.text, fontFamily: \"system-ui, -apple-system, sans-serif\", padding: 24 }}>\r\n {/* Back */}\r\n <button\r\n onClick={onBack}\r\n style={{\r\n background: \"transparent\", border: \"none\", color: t.accentLight,\r\n cursor: \"pointer\", fontSize: 14, padding: 0, marginBottom: 16,\r\n }}\r\n >\r\n ← Back\r\n </button>\r\n\r\n {/* Header */}\r\n <div style={{ background: t.bgCard, border: `1px solid ${t.border}`, borderRadius: 12, padding: 24, marginBottom: 16 }}>\r\n <div style={{ display: \"flex\", justifyContent: \"space-between\", flexWrap: \"wrap\", gap: 16 }}>\r\n <div>\r\n <h1 style={{ fontSize: 22, fontWeight: 700, margin: 0 }}>{repo.name}</h1>\r\n <p style={{ color: t.textSecondary, fontSize: 14, margin: \"8px 0\" }}>{repo.description || \"No description\"}</p>\r\n </div>\r\n <a\r\n href={repo.html_url}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n style={{\r\n display: \"inline-flex\", alignItems: \"center\", gap: 8,\r\n padding: \"8px 16px\", borderRadius: 8, fontSize: 14, fontWeight: 500,\r\n background: t.accent, color: \"#fff\", textDecoration: \"none\",\r\n height: \"fit-content\",\r\n }}\r\n >\r\n View on GitHub\r\n </a>\r\n </div>\r\n </div>\r\n\r\n {/* Tabs */}\r\n <div style={{ display: \"flex\", gap: 4, borderBottom: `1px solid ${t.border}`, marginBottom: 16 }}>\r\n {([\"readme\", ...(snippets.length > 0 ? [\"demo\"] : [])] as const).map((key) => (\r\n <button\r\n key={key}\r\n onClick={() => setTab(key as typeof tab)}\r\n style={{\r\n padding: \"10px 16px\", fontSize: 14, fontWeight: 500, cursor: \"pointer\",\r\n background: \"transparent\", border: \"none\",\r\n color: tab === key ? t.accentLight : t.textMuted,\r\n borderBottom: tab === key ? `2px solid ${t.accent}` : \"2px solid transparent\",\r\n }}\r\n >\r\n {key === \"readme\" ? \"README\" : \"Demo\"}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Content */}\r\n <div style={{ background: t.bgCard, border: `1px solid ${t.border}`, borderRadius: 12, padding: 24 }}>\r\n {loading ? (\r\n <div style={{ textAlign: \"center\", padding: 40, color: t.textMuted }}>Loading...</div>\r\n ) : tab === \"readme\" ? (\r\n <ReadmeView org={org} repoName={repo.name} content={readme} t={t} />\r\n ) : (\r\n <DemoView snippets={snippets} t={t} />\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n/* ---------- DemoView ---------- */\r\n\r\nfunction DemoView({ snippets, t }: { snippets: DemoSnippet[]; t: Theme }) {\r\n const [idx, setIdx] = useState(0);\r\n const snippet = snippets[idx];\r\n\r\n if (!snippet) return null;\r\n\r\n return (\r\n <div>\r\n {snippets.length > 1 && (\r\n <div style={{ display: \"flex\", gap: 6, marginBottom: 12, flexWrap: \"wrap\" }}>\r\n {snippets.map((s, i) => (\r\n <button\r\n key={i}\r\n onClick={() => setIdx(i)}\r\n style={{\r\n padding: \"4px 12px\", borderRadius: 99, fontSize: 12, cursor: \"pointer\",\r\n background: i === idx ? t.accentGlow : \"transparent\",\r\n color: i === idx ? t.accentLight : t.textMuted,\r\n border: `1px solid ${i === idx ? t.accent : t.border}`,\r\n }}\r\n >\r\n {s.label}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n <pre\r\n style={{\r\n background: t.bg, border: `1px solid ${t.border}`, borderRadius: 8,\r\n padding: 16, fontSize: 13, lineHeight: 1.6, overflow: \"auto\",\r\n color: t.textSecondary, margin: 0,\r\n }}\r\n >\r\n <code>{snippet.code}</code>\r\n </pre>\r\n {snippet.expectedOutput && (\r\n <div style={{ marginTop: 12 }}>\r\n <span style={{ fontSize: 12, color: t.textMuted }}>Expected Output:</span>\r\n <pre\r\n style={{\r\n background: t.bg, border: `1px solid ${t.border}`, borderRadius: 8,\r\n padding: 12, fontSize: 12, color: t.textMuted, margin: \"4px 0 0\",\r\n }}\r\n >\r\n {snippet.expectedOutput}\r\n </pre>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import type { Repo, DemoSnippet } from \"./types\";\r\n\r\nconst API = \"https://api.github.com\";\r\n\r\nfunction headers(token?: string): HeadersInit {\r\n const h: Record<string, string> = { Accept: \"application/vnd.github.v3+json\" };\r\n if (token) h.Authorization = `Bearer ${token}`;\r\n return h;\r\n}\r\n\r\nexport async function fetchRepos(org: string, token?: string): Promise<Repo[]> {\r\n try {\r\n const res = await fetch(`${API}/orgs/${org}/repos?per_page=100&sort=updated`, {\r\n headers: headers(token),\r\n });\r\n if (!res.ok) return [];\r\n return res.json();\r\n } catch {\r\n return [];\r\n }\r\n}\r\n\r\nexport async function fetchReadme(org: string, repo: string, token?: string): Promise<string | null> {\r\n try {\r\n const res = await fetch(`${API}/repos/${org}/${repo}/readme`, {\r\n headers: { ...headers(token), Accept: \"application/vnd.github.v3.raw\" },\r\n });\r\n if (!res.ok) return null;\r\n return res.text();\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport async function fetchDemoSnippets(\r\n org: string,\r\n repo: string,\r\n readme?: string | null,\r\n token?: string,\r\n): Promise<DemoSnippet[]> {\r\n // 1. demo.json\r\n for (const path of [\".xgen-gallery/demo.json\", \"demo.json\"]) {\r\n try {\r\n const res = await fetch(`${API}/repos/${org}/${repo}/contents/${path}`, {\r\n headers: { ...headers(token), Accept: \"application/vnd.github.v3.raw\" },\r\n });\r\n if (!res.ok) continue;\r\n const data = await res.json();\r\n if (data.snippets?.length) return data.snippets;\r\n } catch {\r\n continue;\r\n }\r\n }\r\n\r\n // 2. examples/\r\n try {\r\n const res = await fetch(`${API}/repos/${org}/${repo}/contents/examples`, {\r\n headers: headers(token),\r\n });\r\n if (res.ok) {\r\n const files: { name: string; download_url: string }[] = await res.json();\r\n const pyFiles = files.filter((f) => f.name.endsWith(\".py\")).slice(0, 5);\r\n const snippets: DemoSnippet[] = [];\r\n for (const f of pyFiles) {\r\n try {\r\n const r = await fetch(f.download_url);\r\n if (r.ok) {\r\n const code = await r.text();\r\n snippets.push({ label: f.name.replace(/\\.py$/, \"\").replace(/[_-]/g, \" \"), code: code.trim() });\r\n }\r\n } catch { continue; }\r\n }\r\n if (snippets.length) return snippets;\r\n }\r\n } catch { /* ignore */ }\r\n\r\n // 3. README python blocks\r\n let md = readme;\r\n if (!md) md = await fetchReadme(org, repo, token);\r\n if (md) {\r\n const blocks = extractPythonBlocks(md);\r\n if (blocks.length) return blocks;\r\n }\r\n\r\n return [];\r\n}\r\n\r\nfunction extractPythonBlocks(readme: string): DemoSnippet[] {\r\n const snippets: DemoSnippet[] = [];\r\n const lines = readme.split(\"\\n\");\r\n let i = 0;\r\n while (i < lines.length) {\r\n if (/^```(?:python|py)\\s*$/i.test(lines[i].trim())) {\r\n let label = \"\";\r\n for (let j = i - 1; j >= Math.max(0, i - 5); j--) {\r\n const prev = lines[j].trim();\r\n if (/^#{1,4}\\s+/.test(prev)) { label = prev.replace(/^#+\\s+/, \"\"); break; }\r\n if (prev && !label) label = prev;\r\n }\r\n const codeLines: string[] = [];\r\n i++;\r\n while (i < lines.length && !lines[i].trim().startsWith(\"```\")) { codeLines.push(lines[i]); i++; }\r\n const code = codeLines.join(\"\\n\").trim();\r\n if (code && code.split(\"\\n\").length >= 2 && !code.startsWith(\"pip \") && !code.startsWith(\"$ pip\")) {\r\n snippets.push({ label: label || `Example ${snippets.length + 1}`, code });\r\n }\r\n }\r\n i++;\r\n }\r\n return snippets;\r\n}\r\n","export const themes = {\r\n dark: {\r\n bg: \"#0a0a0f\",\r\n bgCard: \"#12121a\",\r\n bgCardHover: \"#1a1a25\",\r\n border: \"#1e1e2e\",\r\n text: \"#e8e8f0\",\r\n textSecondary: \"#a0a0b8\",\r\n textMuted: \"#6b6b80\",\r\n accent: \"#6c63ff\",\r\n accentLight: \"#8b83ff\",\r\n accentGlow: \"rgba(108,99,255,0.15)\",\r\n },\r\n light: {\r\n bg: \"#f8f9fa\",\r\n bgCard: \"#ffffff\",\r\n bgCardHover: \"#f0f0f5\",\r\n border: \"#e0e0e8\",\r\n text: \"#1a1a2e\",\r\n textSecondary: \"#4a4a5a\",\r\n textMuted: \"#8a8a9a\",\r\n accent: \"#5b52e0\",\r\n accentLight: \"#5b52e0\",\r\n accentGlow: \"rgba(91,82,224,0.1)\",\r\n },\r\n};\r\n\r\nexport type Theme = {\r\n bg: string; bgCard: string; bgCardHover: string; border: string;\r\n text: string; textSecondary: string; textMuted: string;\r\n accent: string; accentLight: string; accentGlow: string;\r\n};\r\n\r\nexport const LANG_COLORS: Record<string, string> = {\r\n Python: \"#3572A5\",\r\n TypeScript: \"#3178c6\",\r\n JavaScript: \"#f1e05a\",\r\n Rust: \"#dea584\",\r\n HTML: \"#e34c26\",\r\n CSS: \"#563d7c\",\r\n Go: \"#00ADD8\",\r\n Shell: \"#89e051\",\r\n Java: \"#b07219\",\r\n \"C++\": \"#f34b7d\",\r\n C: \"#555555\",\r\n Ruby: \"#701516\",\r\n};\r\n","import ReactMarkdown from \"react-markdown\";\r\nimport remarkGfm from \"remark-gfm\";\r\nimport rehypeRaw from \"rehype-raw\";\r\nimport type { Theme } from \"./styles\";\r\n\r\nexport function ReadmeView({\r\n org,\r\n repoName,\r\n content,\r\n t,\r\n}: {\r\n org: string;\r\n repoName: string;\r\n content: string | null;\r\n t: Theme;\r\n}) {\r\n if (!content) {\r\n return <div style={{ textAlign: \"center\", padding: 40, color: t.textMuted }}>README not found</div>;\r\n }\r\n\r\n return (\r\n <div className=\"xgen-markdown\" style={{ color: t.text, lineHeight: 1.7, fontSize: 14 }}>\r\n <style>{markdownStyles(t)}</style>\r\n <ReactMarkdown\r\n remarkPlugins={[remarkGfm]}\r\n rehypePlugins={[rehypeRaw]}\r\n components={{\r\n img: ({ src, alt, ...props }) => {\r\n let resolved = src;\r\n if (typeof src === \"string\" && !src.startsWith(\"http\")) {\r\n resolved = `https://raw.githubusercontent.com/${org}/${repoName}/main/${src}`;\r\n }\r\n return <img src={resolved} alt={alt || \"\"} style={{ maxWidth: \"100%\" }} {...props} />;\r\n },\r\n a: ({ href, children, ...props }) => (\r\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" style={{ color: t.accentLight }} {...props}>\r\n {children}\r\n </a>\r\n ),\r\n code: ({ children, className, ...props }) => {\r\n const isBlock = className?.includes(\"language-\");\r\n if (isBlock) {\r\n return (\r\n <code\r\n style={{\r\n display: \"block\", background: t.bg, padding: 16, borderRadius: 8,\r\n overflow: \"auto\", fontSize: 13, lineHeight: 1.6,\r\n }}\r\n {...props}\r\n >\r\n {children}\r\n </code>\r\n );\r\n }\r\n return (\r\n <code style={{ background: t.accentGlow, padding: \"2px 6px\", borderRadius: 4, fontSize: 13 }} {...props}>\r\n {children}\r\n </code>\r\n );\r\n },\r\n }}\r\n >\r\n {content}\r\n </ReactMarkdown>\r\n </div>\r\n );\r\n}\r\n\r\nfunction markdownStyles(t: Theme): string {\r\n return `\r\n .xgen-markdown h1, .xgen-markdown h2, .xgen-markdown h3 { color: ${t.text}; margin: 1.2em 0 0.5em; }\r\n .xgen-markdown h1 { font-size: 1.8em; border-bottom: 1px solid ${t.border}; padding-bottom: 8px; }\r\n .xgen-markdown h2 { font-size: 1.4em; border-bottom: 1px solid ${t.border}; padding-bottom: 6px; }\r\n .xgen-markdown h3 { font-size: 1.15em; }\r\n .xgen-markdown p { margin: 0.8em 0; }\r\n .xgen-markdown ul, .xgen-markdown ol { padding-left: 24px; }\r\n .xgen-markdown li { margin: 4px 0; }\r\n .xgen-markdown pre { background: ${t.bg}; border: 1px solid ${t.border}; border-radius: 8px; padding: 16px; overflow: auto; margin: 12px 0; }\r\n .xgen-markdown blockquote { border-left: 3px solid ${t.accent}; padding-left: 12px; color: ${t.textSecondary}; margin: 12px 0; }\r\n .xgen-markdown table { border-collapse: collapse; width: 100%; margin: 12px 0; }\r\n .xgen-markdown th, .xgen-markdown td { border: 1px solid ${t.border}; padding: 8px 12px; text-align: left; }\r\n .xgen-markdown th { background: ${t.bgCard}; font-weight: 600; }\r\n .xgen-markdown hr { border: none; border-top: 1px solid ${t.border}; margin: 16px 0; }\r\n `;\r\n}\r\n"],"mappings":"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","names":["ReactMarkdown","remarkGfm","rehypeRaw","import_jsx_runtime"]}
|