version-pill-react 1.2.7 → 1.5.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/dist/index.mjs CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  // src/index.tsx
4
4
  import { useState, useEffect, useCallback } from "react";
5
+ import { createPortal } from "react-dom";
5
6
  import clsx from "clsx";
6
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
8
  var DEFAULT_BASE_URL = "https://www.versionpill.com";
@@ -38,12 +39,37 @@ var TYPE_COLORS = {
38
39
  improvement: "#3b82f6",
39
40
  chore: "#71717a"
40
41
  };
41
- var COLUMN_LABELS = {
42
- backlog: "Backlog",
43
- todo: "Planned",
44
- "in-progress": "In Progress",
45
- done: "Shipped"
42
+ var TYPE_EMOJIS = {
43
+ feature: "\u2728",
44
+ bug: "\u{1F41B}",
45
+ improvement: "\u{1F4C8}",
46
+ chore: "\u{1F527}",
47
+ idea: "\u{1F4A1}"
46
48
  };
49
+ var PRIORITY_COLORS = {
50
+ urgent: "#ef4444",
51
+ high: "#f97316",
52
+ medium: "#3b82f6",
53
+ low: "#9ca3af"
54
+ };
55
+ var STATUS_CONFIG = {
56
+ new: { color: "#3b82f6", label: "New" },
57
+ "under review": { color: "#f59e0b", label: "Under Review" },
58
+ planned: { color: "#8b5cf6", label: "Planned" },
59
+ "in progress": { color: "#3b82f6", label: "In Progress" },
60
+ shipped: { color: "#22c55e", label: "Shipped" },
61
+ declined: { color: "#ef4444", label: "Declined" }
62
+ };
63
+ var FADE_IN_KEYFRAMES = `
64
+ @keyframes vpFadeIn {
65
+ from { opacity: 0; }
66
+ to { opacity: 1; }
67
+ }
68
+ @keyframes vpSlideUp {
69
+ from { opacity: 0; transform: translateY(8px); }
70
+ to { opacity: 1; transform: translateY(0); }
71
+ }
72
+ `;
47
73
  function useTheme(theme) {
48
74
  const [resolved, setResolved] = useState("light");
49
75
  useEffect(() => {
@@ -76,11 +102,24 @@ function VersionPill({
76
102
  const [project, setProject] = useState(null);
77
103
  const [versions, setVersions] = useState([]);
78
104
  const [roadmapTasks, setRoadmapTasks] = useState([]);
105
+ const [roadmapColumns, setRoadmapColumns] = useState([]);
106
+ const [roadmapItems, setRoadmapItems] = useState([]);
79
107
  const [ideas, setIdeas] = useState([]);
80
108
  const [loading, setLoading] = useState(true);
81
109
  const [isOpen, setIsOpen] = useState(false);
82
110
  const [activeTab, setActiveTab] = useState("changelog");
83
111
  const [hasNewVersion, setHasNewVersion] = useState(false);
112
+ const [showIdeaForm, setShowIdeaForm] = useState(false);
113
+ const [ideaTitle, setIdeaTitle] = useState("");
114
+ const [ideaDescription, setIdeaDescription] = useState("");
115
+ const [ideaAuthorName, setIdeaAuthorName] = useState("");
116
+ const [ideaAuthorEmail, setIdeaAuthorEmail] = useState("");
117
+ const [submittingIdea, setSubmittingIdea] = useState(false);
118
+ const [ideaSubmitMessage, setIdeaSubmitMessage] = useState(null);
119
+ const [roadmapView, setRoadmapView] = useState("board");
120
+ const [isMobile, setIsMobile] = useState(false);
121
+ const [votedIdeas, setVotedIdeas] = useState(/* @__PURE__ */ new Set());
122
+ const [collapsedColumns, setCollapsedColumns] = useState(/* @__PURE__ */ new Set());
84
123
  const resolvedTheme = useTheme(theme);
85
124
  const isLight = resolvedTheme === "light";
86
125
  const sizeConfig = SIZE_CONFIG[size];
@@ -126,7 +165,45 @@ function VersionPill({
126
165
  const response = await fetch(`${baseUrl}/api/roadmap/${projectId}`);
127
166
  if (!response.ok) return;
128
167
  const data = await response.json();
129
- setRoadmapTasks(data.tasks || []);
168
+ if (data.columns && data.items) {
169
+ setRoadmapColumns(data.columns);
170
+ setRoadmapItems(data.items);
171
+ return;
172
+ }
173
+ let tasks = [];
174
+ if (Array.isArray(data.tasks)) {
175
+ tasks = data.tasks;
176
+ } else if (data.tasks && typeof data.tasks === "object") {
177
+ const grouped = data.tasks;
178
+ const mapTask = (t, defaultColumn) => ({
179
+ id: t.id || t._id,
180
+ title: t.title,
181
+ description: t.description,
182
+ type: t.type || "feature",
183
+ priority: t.priority || "medium",
184
+ column: t.columnId || defaultColumn,
185
+ columnId: t.columnId,
186
+ columnName: t.columnName
187
+ });
188
+ const inProgress = (grouped.inProgress || []).map((t) => mapTask(t, "in-progress"));
189
+ const planned = (grouped.planned || []).map((t) => mapTask(t, "todo"));
190
+ tasks = [...inProgress, ...planned];
191
+ }
192
+ setRoadmapColumns([
193
+ { id: "planned", name: "Planned" },
194
+ { id: "in_progress", name: "In Progress" },
195
+ { id: "completed", name: "Completed" }
196
+ ]);
197
+ setRoadmapItems(tasks.map((t) => ({
198
+ id: t.id,
199
+ title: t.title,
200
+ description: t.description,
201
+ type: t.type,
202
+ priority: t.priority,
203
+ itemType: "task",
204
+ columnId: t.column === "in-progress" ? "in_progress" : t.column === "done" || t.column === "shipped" ? "completed" : "planned"
205
+ })));
206
+ setRoadmapTasks(tasks);
130
207
  } catch {
131
208
  }
132
209
  }, [projectId, baseUrl]);
@@ -139,9 +216,93 @@ function VersionPill({
139
216
  } catch {
140
217
  }
141
218
  }, [projectId, baseUrl]);
219
+ const submitIdea = useCallback(async () => {
220
+ if (!ideaTitle.trim()) return;
221
+ setSubmittingIdea(true);
222
+ setIdeaSubmitMessage(null);
223
+ try {
224
+ const response = await fetch(`${baseUrl}/api/ideas/${projectId}`, {
225
+ method: "POST",
226
+ headers: { "Content-Type": "application/json" },
227
+ body: JSON.stringify({
228
+ title: ideaTitle.trim(),
229
+ description: ideaDescription.trim() || void 0,
230
+ authorName: ideaAuthorName.trim() || void 0,
231
+ authorEmail: ideaAuthorEmail.trim() || void 0
232
+ })
233
+ });
234
+ if (!response.ok) {
235
+ const error = await response.json().catch(() => ({ error: "Failed to submit" }));
236
+ throw new Error(error.error || "Failed to submit idea");
237
+ }
238
+ setIdeaSubmitMessage({ type: "success", text: "Thanks! Your idea has been submitted." });
239
+ setIdeaTitle("");
240
+ setIdeaDescription("");
241
+ setShowIdeaForm(false);
242
+ fetchIdeas();
243
+ } catch (err) {
244
+ setIdeaSubmitMessage({ type: "error", text: err.message || "Failed to submit idea" });
245
+ } finally {
246
+ setSubmittingIdea(false);
247
+ }
248
+ }, [baseUrl, projectId, ideaTitle, ideaDescription, ideaAuthorName, ideaAuthorEmail, fetchIdeas]);
249
+ const voteIdea = useCallback(async (ideaId) => {
250
+ if (votedIdeas.has(ideaId)) return;
251
+ setIdeas((prev) => prev.map((i) => i.id === ideaId ? { ...i, votes: i.votes + 1 } : i));
252
+ setVotedIdeas((prev) => new Set(prev).add(ideaId));
253
+ try {
254
+ await fetch(`${baseUrl}/api/ideas/${projectId}/vote`, {
255
+ method: "POST",
256
+ headers: { "Content-Type": "application/json" },
257
+ body: JSON.stringify({ ideaId })
258
+ });
259
+ } catch {
260
+ setIdeas((prev) => prev.map((i) => i.id === ideaId ? { ...i, votes: i.votes - 1 } : i));
261
+ setVotedIdeas((prev) => {
262
+ const s = new Set(prev);
263
+ s.delete(ideaId);
264
+ return s;
265
+ });
266
+ }
267
+ }, [baseUrl, projectId, votedIdeas]);
142
268
  useEffect(() => {
143
269
  fetchVersion();
144
270
  }, [fetchVersion]);
271
+ useEffect(() => {
272
+ if (isOpen) {
273
+ const prev = document.body.style.overflow;
274
+ document.body.style.overflow = "hidden";
275
+ return () => {
276
+ document.body.style.overflow = prev;
277
+ };
278
+ }
279
+ }, [isOpen]);
280
+ useEffect(() => {
281
+ if (!isOpen) return;
282
+ const handleKey = (e) => {
283
+ if (e.key === "Escape") setIsOpen(false);
284
+ };
285
+ document.addEventListener("keydown", handleKey);
286
+ return () => document.removeEventListener("keydown", handleKey);
287
+ }, [isOpen]);
288
+ useEffect(() => {
289
+ const check = () => setIsMobile(window.innerWidth < 640);
290
+ check();
291
+ window.addEventListener("resize", check);
292
+ return () => window.removeEventListener("resize", check);
293
+ }, []);
294
+ useEffect(() => {
295
+ if (!isOpen) return;
296
+ const id = "vp-modal-keyframes";
297
+ if (document.getElementById(id)) return;
298
+ const style2 = document.createElement("style");
299
+ style2.id = id;
300
+ style2.textContent = FADE_IN_KEYFRAMES;
301
+ document.head.appendChild(style2);
302
+ return () => {
303
+ document.getElementById(id)?.remove();
304
+ };
305
+ }, [isOpen]);
145
306
  const handleOpen = () => {
146
307
  if (onClick) {
147
308
  onClick();
@@ -258,298 +419,842 @@ function VersionPill({
258
419
  );
259
420
  };
260
421
  const versionsArray = Array.isArray(versions) ? versions : [];
261
- const tasksArray = Array.isArray(roadmapTasks) ? roadmapTasks : [];
262
422
  const ideasArray = Array.isArray(ideas) ? ideas : [];
263
- const groupedTasks = tasksArray.reduce((acc, task) => {
264
- const col = task.column || "backlog";
265
- if (!acc[col]) acc[col] = [];
266
- acc[col].push(task);
267
- return acc;
268
- }, {});
269
423
  return /* @__PURE__ */ jsxs(Fragment, { children: [
270
424
  /* @__PURE__ */ jsx("div", { className: clsx(positionStyles[position], className), style: { display: "inline-flex" }, children: renderBadge() }),
271
- isOpen && /* @__PURE__ */ jsx("div", { style: {
272
- position: "fixed",
273
- top: 0,
274
- left: 0,
275
- right: 0,
276
- bottom: 0,
277
- width: "100vw",
278
- height: "100vh",
279
- zIndex: 2147483647,
280
- display: "flex",
281
- flexDirection: "column",
282
- boxSizing: "border-box",
283
- background: isLight ? "#fff" : "#0a0a0a"
284
- }, children: /* @__PURE__ */ jsxs(
285
- "div",
286
- {
287
- style: {
288
- display: "flex",
289
- flexDirection: "column",
290
- width: "100%",
291
- height: "100%",
292
- borderRadius: 12,
293
- overflow: "hidden"
294
- },
295
- children: [
296
- /* @__PURE__ */ jsxs(
297
- "div",
298
- {
299
- style: {
300
- flexShrink: 0,
301
- padding: "16px 20px",
302
- borderBottom: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`,
303
- display: "flex",
304
- alignItems: "center",
305
- justifyContent: "space-between"
306
- },
307
- children: [
308
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
309
- project?.icon && /* @__PURE__ */ jsx("span", { style: { fontSize: 24 }, children: project.icon }),
310
- /* @__PURE__ */ jsxs("div", { children: [
311
- /* @__PURE__ */ jsx("h2", { style: { fontWeight: 600, fontSize: 18, color: isLight ? "#18181b" : "#fff", margin: 0 }, children: project?.name || "What's New" }),
312
- /* @__PURE__ */ jsxs("p", { style: { fontSize: 13, color: isLight ? "#71717a" : "#a1a1aa", margin: 0 }, children: [
313
- "v",
314
- currentVersion
315
- ] })
316
- ] })
317
- ] }),
318
- /* @__PURE__ */ jsx(
319
- "button",
320
- {
321
- onClick: () => setIsOpen(false),
322
- style: {
323
- width: 36,
324
- height: 36,
325
- display: "flex",
326
- alignItems: "center",
327
- justifyContent: "center",
328
- borderRadius: 8,
329
- background: isLight ? "#f5f5f5" : "#1f1f1f",
330
- border: "none",
331
- cursor: "pointer",
332
- color: isLight ? "#71717a" : "#a1a1aa",
333
- transition: "background 150ms"
334
- },
335
- onMouseEnter: (e) => e.currentTarget.style.background = isLight ? "#e5e5e5" : "#2a2a2a",
336
- onMouseLeave: (e) => e.currentTarget.style.background = isLight ? "#f5f5f5" : "#1f1f1f",
337
- children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" }) })
338
- }
339
- )
340
- ]
425
+ isOpen && createPortal(
426
+ /* @__PURE__ */ jsxs(Fragment, { children: [
427
+ /* @__PURE__ */ jsx(
428
+ "div",
429
+ {
430
+ onClick: () => setIsOpen(false),
431
+ style: {
432
+ position: "fixed",
433
+ top: 0,
434
+ left: 0,
435
+ right: 0,
436
+ bottom: 0,
437
+ zIndex: 2147483646,
438
+ background: "rgba(0,0,0,0.5)",
439
+ animation: "vpFadeIn 200ms ease-out"
341
440
  }
342
- ),
343
- /* @__PURE__ */ jsx(
344
- "div",
345
- {
346
- style: {
347
- flexShrink: 0,
348
- display: "flex",
349
- gap: 4,
350
- padding: "12px 20px",
351
- borderBottom: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`
352
- },
353
- children: ["changelog", "roadmap", "ideas"].map((tab) => /* @__PURE__ */ jsxs(
354
- "button",
441
+ }
442
+ ),
443
+ /* @__PURE__ */ jsxs(
444
+ "div",
445
+ {
446
+ onClick: (e) => e.stopPropagation(),
447
+ style: {
448
+ position: "fixed",
449
+ top: isMobile ? 0 : 20,
450
+ left: isMobile ? 0 : 20,
451
+ right: isMobile ? 0 : 20,
452
+ bottom: isMobile ? 0 : 20,
453
+ zIndex: 2147483647,
454
+ display: "flex",
455
+ flexDirection: "column",
456
+ boxSizing: "border-box",
457
+ background: isLight ? "#fff" : "#0a0a0a",
458
+ borderRadius: isMobile ? 0 : 16,
459
+ overflow: "hidden",
460
+ boxShadow: "0 25px 50px -12px rgba(0,0,0,0.25)",
461
+ animation: "vpSlideUp 250ms ease-out"
462
+ },
463
+ children: [
464
+ /* @__PURE__ */ jsxs(
465
+ "div",
355
466
  {
356
- onClick: () => setActiveTab(tab),
357
467
  style: {
358
- padding: "10px 16px",
359
- borderRadius: 8,
360
- border: "none",
361
- cursor: "pointer",
362
- fontSize: 14,
363
- fontWeight: 500,
364
- background: activeTab === tab ? isLight ? "#18181b" : "#fff" : "transparent",
365
- color: activeTab === tab ? isLight ? "#fff" : "#18181b" : isLight ? "#71717a" : "#71717a",
366
- transition: "all 150ms"
468
+ flexShrink: 0,
469
+ padding: isMobile ? "12px 16px" : "16px 20px",
470
+ borderBottom: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`,
471
+ display: "flex",
472
+ alignItems: "center",
473
+ justifyContent: "space-between"
367
474
  },
368
475
  children: [
369
- tab === "changelog" && "\u{1F680} Changelog",
370
- tab === "roadmap" && "\u{1F5FA}\uFE0F Roadmap",
371
- tab === "ideas" && "\u{1F4A1} Ideas"
476
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: isMobile ? 8 : 12 }, children: [
477
+ project?.icon && /* @__PURE__ */ jsx("span", { style: { fontSize: isMobile ? 20 : 24 }, children: project.icon }),
478
+ /* @__PURE__ */ jsxs("div", { children: [
479
+ /* @__PURE__ */ jsx("h2", { style: { fontWeight: 600, fontSize: isMobile ? 16 : 18, color: isLight ? "#18181b" : "#fff", margin: 0 }, children: project?.name || "What's New" }),
480
+ /* @__PURE__ */ jsxs("p", { style: { fontSize: 12, color: isLight ? "#71717a" : "#a1a1aa", margin: 0 }, children: [
481
+ "v",
482
+ currentVersion
483
+ ] })
484
+ ] })
485
+ ] }),
486
+ /* @__PURE__ */ jsx(
487
+ "button",
488
+ {
489
+ onClick: () => setIsOpen(false),
490
+ style: {
491
+ width: 36,
492
+ height: 36,
493
+ display: "flex",
494
+ alignItems: "center",
495
+ justifyContent: "center",
496
+ borderRadius: 8,
497
+ background: isLight ? "#f5f5f5" : "#1f1f1f",
498
+ border: "none",
499
+ cursor: "pointer",
500
+ color: isLight ? "#71717a" : "#a1a1aa",
501
+ transition: "background 150ms"
502
+ },
503
+ onMouseEnter: (e) => e.currentTarget.style.background = isLight ? "#e5e5e5" : "#2a2a2a",
504
+ onMouseLeave: (e) => e.currentTarget.style.background = isLight ? "#f5f5f5" : "#1f1f1f",
505
+ children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" }) })
506
+ }
507
+ )
372
508
  ]
373
- },
374
- tab
375
- ))
376
- }
377
- ),
378
- /* @__PURE__ */ jsxs("div", { style: { flex: 1, overflowY: "auto", padding: "20px 24px", minHeight: 0 }, children: [
379
- activeTab === "changelog" && /* @__PURE__ */ jsx("div", { style: { maxWidth: 640 }, children: versionsArray.length === 0 ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: 60, color: isLight ? "#71717a" : "#a1a1aa" }, children: [
380
- /* @__PURE__ */ jsx("div", { style: { fontSize: 48, marginBottom: 12 }, children: "\u{1F680}" }),
381
- /* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: "No releases yet" })
382
- ] }) : versionsArray.slice(0, 10).map((version, idx) => /* @__PURE__ */ jsxs("div", { style: { marginBottom: 24, paddingBottom: 24, borderBottom: idx < versionsArray.length - 1 && idx < 9 ? `1px solid ${isLight ? "#f0f0f0" : "#1f1f1f"}` : "none" }, children: [
383
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }, children: [
384
- /* @__PURE__ */ jsx("span", { style: { fontSize: 20 }, children: version.emoji || "\u{1F4E6}" }),
385
- /* @__PURE__ */ jsx("span", { style: { fontWeight: 600, fontSize: 18, color: isLight ? "#18181b" : "#fff" }, children: version.title }),
386
- /* @__PURE__ */ jsx(
387
- "span",
388
- {
389
- style: {
390
- padding: "3px 8px",
391
- fontSize: 11,
392
- fontWeight: 500,
393
- borderRadius: 4,
394
- background: version.type === "major" ? "#f3e8ff" : version.type === "minor" ? "#dbeafe" : isLight ? "#f4f4f5" : "#1f1f1f",
395
- color: version.type === "major" ? "#7c3aed" : version.type === "minor" ? "#2563eb" : isLight ? "#52525b" : "#a1a1aa"
396
- },
397
- children: version.type
398
- }
399
- )
400
- ] }),
401
- /* @__PURE__ */ jsxs("div", { style: { fontSize: 13, color: isLight ? "#71717a" : "#71717a", marginBottom: 10 }, children: [
402
- "v",
403
- version.version,
404
- " \xB7 ",
405
- new Date(version.date).toLocaleDateString()
406
- ] }),
407
- version.description && /* @__PURE__ */ jsx("p", { style: { fontSize: 15, color: isLight ? "#52525b" : "#a1a1aa", margin: "0 0 12px 0", lineHeight: 1.6 }, children: version.description }),
408
- version.features && version.features.length > 0 && /* @__PURE__ */ jsx("ul", { style: { margin: 0, paddingLeft: 0, listStyle: "none" }, children: version.features.map((feature, i) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", alignItems: "flex-start", gap: 10, fontSize: 14, color: isLight ? "#52525b" : "#a1a1aa", marginBottom: 6, lineHeight: 1.5 }, children: [
409
- /* @__PURE__ */ jsx("span", { style: { color: "#22c55e", fontSize: 14, marginTop: 2 }, children: "\u2713" }),
410
- feature
411
- ] }, i)) })
412
- ] }, idx)) }),
413
- activeTab === "roadmap" && /* @__PURE__ */ jsx("div", { style: { maxWidth: 640 }, children: Object.keys(groupedTasks).length === 0 ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: 60, color: isLight ? "#71717a" : "#a1a1aa" }, children: [
414
- /* @__PURE__ */ jsx("div", { style: { fontSize: 48, marginBottom: 12 }, children: "\u{1F5FA}\uFE0F" }),
415
- /* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: "No public roadmap items" })
416
- ] }) : ["in-progress", "todo", "backlog"].map((col) => {
417
- const tasks = groupedTasks[col];
418
- if (!tasks || tasks.length === 0) return null;
419
- return /* @__PURE__ */ jsxs("div", { style: { marginBottom: 24 }, children: [
420
- /* @__PURE__ */ jsxs("h3", { style: { fontSize: 12, fontWeight: 600, color: isLight ? "#a1a1aa" : "#71717a", marginBottom: 12, textTransform: "uppercase", letterSpacing: "0.5px" }, children: [
421
- COLUMN_LABELS[col] || col,
422
- " (",
423
- tasks.length,
424
- ")"
425
- ] }),
426
- tasks.map((task) => /* @__PURE__ */ jsx(
427
- "div",
428
- {
429
- style: {
430
- padding: "12px 16px",
431
- marginBottom: 8,
432
- borderRadius: 8,
433
- background: isLight ? "#f5f5f5" : "#151515",
434
- border: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`
509
+ }
510
+ ),
511
+ /* @__PURE__ */ jsx(
512
+ "div",
513
+ {
514
+ style: {
515
+ flexShrink: 0,
516
+ display: "flex",
517
+ justifyContent: "center",
518
+ gap: 2,
519
+ padding: isMobile ? "8px 12px" : "10px 20px",
520
+ borderBottom: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`,
521
+ overflowX: "auto"
522
+ },
523
+ children: ["changelog", "roadmap", "ideas"].map((tab) => /* @__PURE__ */ jsxs(
524
+ "button",
525
+ {
526
+ onClick: () => setActiveTab(tab),
527
+ style: {
528
+ padding: isMobile ? "8px 16px" : "8px 20px",
529
+ borderRadius: 999,
530
+ border: "none",
531
+ cursor: "pointer",
532
+ fontSize: isMobile ? 13 : 14,
533
+ fontWeight: 500,
534
+ whiteSpace: "nowrap",
535
+ background: activeTab === tab ? isLight ? "#18181b" : "#fff" : "transparent",
536
+ color: activeTab === tab ? isLight ? "#fff" : "#18181b" : isLight ? "#71717a" : "#71717a",
537
+ transition: "all 150ms"
538
+ },
539
+ onMouseEnter: (e) => {
540
+ if (activeTab !== tab) {
541
+ e.currentTarget.style.background = isLight ? "#f4f4f5" : "#1f1f1f";
542
+ }
543
+ },
544
+ onMouseLeave: (e) => {
545
+ if (activeTab !== tab) {
546
+ e.currentTarget.style.background = "transparent";
547
+ }
548
+ },
549
+ children: [
550
+ tab === "changelog" && "\u{1F680} Changelog",
551
+ tab === "roadmap" && "\u{1F5FA}\uFE0F Roadmap",
552
+ tab === "ideas" && "\u{1F4A1} Ideas"
553
+ ]
435
554
  },
436
- children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10 }, children: [
437
- /* @__PURE__ */ jsx(
438
- "span",
555
+ tab
556
+ ))
557
+ }
558
+ ),
559
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, overflow: activeTab === "roadmap" ? "hidden" : "auto", padding: isMobile ? "16px" : "20px 24px", minHeight: 0, display: "flex", flexDirection: "column", alignItems: "center" }, children: [
560
+ activeTab === "changelog" && /* @__PURE__ */ jsx("div", { style: { maxWidth: 640, width: "100%", overflowY: "auto", flex: 1 }, children: versionsArray.length === 0 ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: 60, color: isLight ? "#71717a" : "#a1a1aa" }, children: [
561
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 48, marginBottom: 12 }, children: "\u{1F680}" }),
562
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: "No releases yet" })
563
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
564
+ versionsArray.slice(0, 10).map((version, idx) => {
565
+ const isLatest = idx === 0;
566
+ return /* @__PURE__ */ jsxs("div", { style: {
567
+ marginBottom: 24,
568
+ paddingBottom: 24,
569
+ paddingLeft: isLatest ? 16 : 0,
570
+ borderLeft: isLatest ? `3px solid #22c55e` : "none",
571
+ borderBottom: idx < versionsArray.length - 1 && idx < 9 ? `1px solid ${isLight ? "#f0f0f0" : "#1f1f1f"}` : "none"
572
+ }, children: [
573
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 6, flexWrap: "wrap" }, children: [
574
+ /* @__PURE__ */ jsx("span", { style: { fontSize: isLatest ? 22 : 20 }, children: version.emoji || "\u{1F4E6}" }),
575
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 600, fontSize: isLatest ? 20 : 18, color: isLight ? "#18181b" : "#fff" }, children: version.title }),
576
+ isLatest && /* @__PURE__ */ jsx("span", { style: {
577
+ padding: "2px 8px",
578
+ fontSize: 10,
579
+ fontWeight: 600,
580
+ borderRadius: 999,
581
+ background: isLight ? "#dcfce7" : "rgba(34,197,94,0.15)",
582
+ color: "#22c55e",
583
+ textTransform: "uppercase",
584
+ letterSpacing: "0.5px"
585
+ }, children: "Latest" }),
586
+ /* @__PURE__ */ jsx(
587
+ "span",
588
+ {
589
+ style: {
590
+ padding: "3px 10px",
591
+ fontSize: 11,
592
+ fontWeight: 500,
593
+ borderRadius: 999,
594
+ background: version.type === "major" ? isLight ? "#f3e8ff" : "rgba(147,51,234,0.15)" : version.type === "minor" ? isLight ? "#dbeafe" : "rgba(59,130,246,0.15)" : isLight ? "#f4f4f5" : "#1f1f1f",
595
+ color: version.type === "major" ? "#7c3aed" : version.type === "minor" ? "#2563eb" : isLight ? "#52525b" : "#a1a1aa"
596
+ },
597
+ children: version.type
598
+ }
599
+ )
600
+ ] }),
601
+ /* @__PURE__ */ jsxs("div", { style: { fontSize: 13, color: isLight ? "#71717a" : "#71717a", marginBottom: 10 }, children: [
602
+ "v",
603
+ version.version,
604
+ " \xB7 ",
605
+ new Date(version.date).toLocaleDateString()
606
+ ] }),
607
+ version.description && /* @__PURE__ */ jsx("p", { style: { fontSize: 15, color: isLight ? "#52525b" : "#a1a1aa", margin: "0 0 12px 0", lineHeight: 1.6 }, children: version.description }),
608
+ version.features && version.features.length > 0 && /* @__PURE__ */ jsx("ul", { style: { margin: 0, paddingLeft: 0, listStyle: "none" }, children: version.features.map((feature, i) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", alignItems: "flex-start", gap: 10, fontSize: 14, color: isLight ? "#52525b" : "#a1a1aa", marginBottom: 6, lineHeight: 1.5 }, children: [
609
+ /* @__PURE__ */ jsx("span", { style: { color: "#22c55e", fontSize: 14, marginTop: 2 }, children: "\u2713" }),
610
+ feature
611
+ ] }, i)) }),
612
+ version.tasks && version.tasks.length > 0 && /* @__PURE__ */ jsx("div", { style: { marginTop: 10, paddingTop: 10, borderTop: `1px solid ${isLight ? "#f0f0f0" : "#1f1f1f"}` }, children: version.tasks.map((task, i) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: isLight ? "#71717a" : "#a1a1aa", marginBottom: 4 }, children: [
613
+ /* @__PURE__ */ jsx("span", { style: {
614
+ width: 6,
615
+ height: 6,
616
+ borderRadius: "50%",
617
+ background: TYPE_COLORS[task.type] || "#71717a",
618
+ flexShrink: 0
619
+ } }),
620
+ task.title
621
+ ] }, i)) })
622
+ ] }, idx);
623
+ }),
624
+ versionsArray.length > 10 && /* @__PURE__ */ jsx(
625
+ "a",
626
+ {
627
+ href: `${baseUrl}/${projectId}/changelog`,
628
+ target: "_blank",
629
+ rel: "noopener noreferrer",
630
+ style: {
631
+ display: "block",
632
+ textAlign: "center",
633
+ padding: 12,
634
+ fontSize: 14,
635
+ color: "#22c55e",
636
+ textDecoration: "none"
637
+ },
638
+ children: "View all releases \u2192"
639
+ }
640
+ )
641
+ ] }) }),
642
+ activeTab === "roadmap" && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", flex: 1, minHeight: 0, width: "100%" }, children: roadmapItems.length === 0 ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: 60, color: isLight ? "#71717a" : "#a1a1aa" }, children: [
643
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 48, marginBottom: 12 }, children: "\u{1F5FA}\uFE0F" }),
644
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: "No public roadmap items" })
645
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
646
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 4, marginBottom: 12, flexShrink: 0 }, children: [
647
+ /* @__PURE__ */ jsxs(
648
+ "button",
649
+ {
650
+ onClick: () => setRoadmapView("board"),
651
+ style: {
652
+ padding: "6px 10px",
653
+ borderRadius: 6,
654
+ border: `1px solid ${roadmapView === "board" ? isLight ? "#18181b" : "#fff" : isLight ? "#e5e5e5" : "#2a2a2a"}`,
655
+ background: roadmapView === "board" ? isLight ? "#18181b" : "#fff" : "transparent",
656
+ color: roadmapView === "board" ? isLight ? "#fff" : "#18181b" : isLight ? "#71717a" : "#a1a1aa",
657
+ cursor: "pointer",
658
+ fontSize: 12,
659
+ fontWeight: 500,
660
+ display: "flex",
661
+ alignItems: "center",
662
+ gap: 4
663
+ },
664
+ children: [
665
+ /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
666
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "7", height: "7" }),
667
+ /* @__PURE__ */ jsx("rect", { x: "14", y: "3", width: "7", height: "7" }),
668
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "14", width: "7", height: "7" }),
669
+ /* @__PURE__ */ jsx("rect", { x: "14", y: "14", width: "7", height: "7" })
670
+ ] }),
671
+ "Board"
672
+ ]
673
+ }
674
+ ),
675
+ /* @__PURE__ */ jsxs(
676
+ "button",
677
+ {
678
+ onClick: () => setRoadmapView("list"),
679
+ style: {
680
+ padding: "6px 10px",
681
+ borderRadius: 6,
682
+ border: `1px solid ${roadmapView === "list" ? isLight ? "#18181b" : "#fff" : isLight ? "#e5e5e5" : "#2a2a2a"}`,
683
+ background: roadmapView === "list" ? isLight ? "#18181b" : "#fff" : "transparent",
684
+ color: roadmapView === "list" ? isLight ? "#fff" : "#18181b" : isLight ? "#71717a" : "#a1a1aa",
685
+ cursor: "pointer",
686
+ fontSize: 12,
687
+ fontWeight: 500,
688
+ display: "flex",
689
+ alignItems: "center",
690
+ gap: 4
691
+ },
692
+ children: [
693
+ /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
694
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "6", x2: "21", y2: "6" }),
695
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "12", x2: "21", y2: "12" }),
696
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "18", x2: "21", y2: "18" }),
697
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "6", x2: "3.01", y2: "6" }),
698
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "3.01", y2: "12" }),
699
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "18", x2: "3.01", y2: "18" })
700
+ ] }),
701
+ "List"
702
+ ]
703
+ }
704
+ )
705
+ ] }),
706
+ roadmapView === "board" && /* @__PURE__ */ jsx("div", { style: {
707
+ display: "flex",
708
+ gap: 12,
709
+ flex: 1,
710
+ minHeight: 0,
711
+ overflow: "hidden",
712
+ flexDirection: isMobile ? "column" : "row",
713
+ overflowY: isMobile ? "auto" : "hidden"
714
+ }, children: roadmapColumns.map((col) => {
715
+ const colItems = roadmapItems.filter((item) => item.columnId === col.id);
716
+ const isCollapsed = isMobile && collapsedColumns.has(col.id);
717
+ return /* @__PURE__ */ jsxs("div", { style: {
718
+ flex: isMobile ? "none" : 1,
719
+ minWidth: 0,
720
+ display: "flex",
721
+ flexDirection: "column",
722
+ minHeight: isMobile ? "auto" : 0
723
+ }, children: [
724
+ /* @__PURE__ */ jsxs(
725
+ "button",
439
726
  {
727
+ onClick: () => isMobile && setCollapsedColumns((prev) => {
728
+ const s = new Set(prev);
729
+ s.has(col.id) ? s.delete(col.id) : s.add(col.id);
730
+ return s;
731
+ }),
440
732
  style: {
441
- width: 8,
442
- height: 8,
443
- borderRadius: "50%",
444
- background: TYPE_COLORS[task.type] || "#71717a",
445
- flexShrink: 0
446
- }
733
+ display: "flex",
734
+ alignItems: "center",
735
+ gap: 6,
736
+ fontSize: 12,
737
+ fontWeight: 600,
738
+ color: isLight ? "#a1a1aa" : "#71717a",
739
+ marginBottom: 8,
740
+ textTransform: "uppercase",
741
+ letterSpacing: "0.5px",
742
+ flexShrink: 0,
743
+ background: "none",
744
+ border: "none",
745
+ cursor: isMobile ? "pointer" : "default",
746
+ padding: 0,
747
+ width: "100%",
748
+ textAlign: "left"
749
+ },
750
+ children: [
751
+ isMobile && /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", style: { transform: isCollapsed ? "rotate(-90deg)" : "rotate(0)", transition: "transform 150ms" }, children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6" }) }),
752
+ col.name,
753
+ /* @__PURE__ */ jsx("span", { style: {
754
+ padding: "1px 6px",
755
+ fontSize: 11,
756
+ fontWeight: 500,
757
+ borderRadius: 999,
758
+ background: isLight ? "#f4f4f5" : "#1f1f1f",
759
+ color: isLight ? "#71717a" : "#a1a1aa"
760
+ }, children: colItems.length })
761
+ ]
447
762
  }
448
763
  ),
449
- /* @__PURE__ */ jsx("span", { style: { fontSize: 14, color: isLight ? "#18181b" : "#fff" }, children: task.title })
450
- ] })
451
- },
452
- task.id
453
- ))
454
- ] }, col);
455
- }) }),
456
- activeTab === "ideas" && /* @__PURE__ */ jsx("div", { style: { maxWidth: 640 }, children: ideasArray.length === 0 ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: 60, color: isLight ? "#71717a" : "#a1a1aa" }, children: [
457
- /* @__PURE__ */ jsx("div", { style: { fontSize: 48, marginBottom: 12 }, children: "\u{1F4A1}" }),
458
- /* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: "No feature requests yet" })
459
- ] }) : ideasArray.map((idea) => /* @__PURE__ */ jsxs(
460
- "div",
461
- {
462
- style: {
463
- padding: 16,
464
- marginBottom: 12,
465
- borderRadius: 8,
466
- background: isLight ? "#f5f5f5" : "#151515",
467
- border: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`,
468
- display: "flex",
469
- alignItems: "flex-start",
470
- gap: 16
471
- },
472
- children: [
473
- /* @__PURE__ */ jsxs(
474
- "div",
764
+ !isCollapsed && /* @__PURE__ */ jsxs("div", { style: {
765
+ display: "flex",
766
+ flexDirection: "column",
767
+ gap: 8,
768
+ flex: isMobile ? "none" : 1,
769
+ overflowY: isMobile ? "visible" : "auto",
770
+ minHeight: 0,
771
+ paddingRight: isMobile ? 0 : 2,
772
+ paddingBottom: isMobile ? 12 : 0
773
+ }, children: [
774
+ colItems.map((item) => {
775
+ const priorityColor = PRIORITY_COLORS[item.priority || ""] || "transparent";
776
+ return /* @__PURE__ */ jsx(
777
+ "div",
778
+ {
779
+ style: {
780
+ padding: "12px 14px",
781
+ borderRadius: 8,
782
+ background: isLight ? "#f9fafb" : "#151515",
783
+ border: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`,
784
+ borderLeft: `3px solid ${priorityColor}`,
785
+ transition: "border-color 150ms"
786
+ },
787
+ onMouseEnter: (e) => e.currentTarget.style.borderColor = isLight ? "#d4d4d8" : "#3f3f46",
788
+ onMouseLeave: (e) => e.currentTarget.style.borderColor = isLight ? "#e5e5e5" : "#1f1f1f",
789
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "flex-start", gap: 8 }, children: [
790
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
791
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 4 }, children: [
792
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 13 }, children: TYPE_EMOJIS[item.type || ""] || "\u{1F4CB}" }),
793
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: 500, color: isLight ? "#18181b" : "#fff" }, children: item.title })
794
+ ] }),
795
+ item.description && /* @__PURE__ */ jsx("p", { style: {
796
+ fontSize: 12,
797
+ color: isLight ? "#71717a" : "#a1a1aa",
798
+ margin: "0 0 0 0",
799
+ lineHeight: 1.4,
800
+ overflow: "hidden",
801
+ display: "-webkit-box",
802
+ WebkitLineClamp: 2,
803
+ WebkitBoxOrient: "vertical"
804
+ }, children: item.description })
805
+ ] }),
806
+ item.itemType === "idea" && /* @__PURE__ */ jsxs("span", { style: {
807
+ fontSize: 11,
808
+ fontWeight: 600,
809
+ color: isLight ? "#ea580c" : "#fb923c",
810
+ background: isLight ? "rgba(249,115,22,0.1)" : "rgba(249,115,22,0.15)",
811
+ padding: "2px 6px",
812
+ borderRadius: 4,
813
+ flexShrink: 0
814
+ }, children: [
815
+ item.votes ?? 0,
816
+ "\u2191"
817
+ ] })
818
+ ] })
819
+ },
820
+ item.id
821
+ );
822
+ }),
823
+ colItems.length === 0 && /* @__PURE__ */ jsx("div", { style: {
824
+ padding: 20,
825
+ textAlign: "center",
826
+ fontSize: 13,
827
+ color: isLight ? "#a1a1aa" : "#525252",
828
+ borderRadius: 8,
829
+ border: `1px dashed ${isLight ? "#e5e5e5" : "#1f1f1f"}`
830
+ }, children: "No items" })
831
+ ] })
832
+ ] }, col.id);
833
+ }) }),
834
+ roadmapView === "list" && /* @__PURE__ */ jsx("div", { style: { flex: 1, overflowY: "auto", minHeight: 0 }, children: roadmapColumns.map((col) => {
835
+ const colItems = roadmapItems.filter((item) => item.columnId === col.id);
836
+ if (colItems.length === 0) return null;
837
+ return /* @__PURE__ */ jsxs("div", { style: { marginBottom: 20 }, children: [
838
+ /* @__PURE__ */ jsxs("h3", { style: {
839
+ fontSize: 12,
840
+ fontWeight: 600,
841
+ color: isLight ? "#a1a1aa" : "#71717a",
842
+ marginBottom: 8,
843
+ textTransform: "uppercase",
844
+ letterSpacing: "0.5px",
845
+ display: "flex",
846
+ alignItems: "center",
847
+ gap: 6
848
+ }, children: [
849
+ col.name,
850
+ /* @__PURE__ */ jsx("span", { style: {
851
+ padding: "1px 6px",
852
+ fontSize: 11,
853
+ fontWeight: 500,
854
+ borderRadius: 999,
855
+ background: isLight ? "#f4f4f5" : "#1f1f1f",
856
+ color: isLight ? "#71717a" : "#a1a1aa"
857
+ }, children: colItems.length })
858
+ ] }),
859
+ colItems.map((item) => /* @__PURE__ */ jsxs(
860
+ "div",
861
+ {
862
+ style: {
863
+ display: "flex",
864
+ alignItems: "center",
865
+ gap: 10,
866
+ padding: "10px 12px",
867
+ borderRadius: 6,
868
+ marginBottom: 4,
869
+ background: isLight ? "#f9fafb" : "#151515",
870
+ border: `1px solid ${isLight ? "#f0f0f0" : "#1a1a1a"}`
871
+ },
872
+ children: [
873
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 13, flexShrink: 0 }, children: TYPE_EMOJIS[item.type || ""] || "\u{1F4CB}" }),
874
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: 500, color: isLight ? "#18181b" : "#fff", flex: 1, minWidth: 0 }, children: item.title }),
875
+ item.priority && /* @__PURE__ */ jsx("span", { style: {
876
+ padding: "2px 8px",
877
+ fontSize: 10,
878
+ fontWeight: 500,
879
+ borderRadius: 999,
880
+ background: isLight ? "#f4f4f5" : "#1f1f1f",
881
+ color: PRIORITY_COLORS[item.priority] || (isLight ? "#71717a" : "#a1a1aa"),
882
+ flexShrink: 0
883
+ }, children: item.priority })
884
+ ]
885
+ },
886
+ item.id
887
+ ))
888
+ ] }, col.id);
889
+ }) })
890
+ ] }) }),
891
+ activeTab === "ideas" && /* @__PURE__ */ jsxs("div", { style: { maxWidth: 640, width: "100%", overflowY: "auto", flex: 1 }, children: [
892
+ !showIdeaForm ? /* @__PURE__ */ jsxs(
893
+ "button",
475
894
  {
895
+ onClick: () => setShowIdeaForm(true),
476
896
  style: {
477
897
  display: "flex",
478
- flexDirection: "column",
479
898
  alignItems: "center",
480
- padding: "8px 12px",
481
- borderRadius: 6,
482
- background: isLight ? "#fff" : "#0a0a0a",
483
- minWidth: 50
899
+ justifyContent: "center",
900
+ gap: 8,
901
+ width: "100%",
902
+ padding: "12px 16px",
903
+ marginBottom: 20,
904
+ borderRadius: 999,
905
+ border: `1px dashed ${isLight ? "#d4d4d8" : "#3f3f46"}`,
906
+ background: "transparent",
907
+ color: isLight ? "#71717a" : "#a1a1aa",
908
+ fontSize: 14,
909
+ fontWeight: 500,
910
+ cursor: "pointer",
911
+ transition: "all 150ms"
912
+ },
913
+ onMouseEnter: (e) => {
914
+ e.currentTarget.style.borderColor = isLight ? "#a1a1aa" : "#71717a";
915
+ e.currentTarget.style.color = isLight ? "#52525b" : "#d4d4d8";
916
+ },
917
+ onMouseLeave: (e) => {
918
+ e.currentTarget.style.borderColor = isLight ? "#d4d4d8" : "#3f3f46";
919
+ e.currentTarget.style.color = isLight ? "#71717a" : "#a1a1aa";
484
920
  },
485
921
  children: [
486
- /* @__PURE__ */ jsx("span", { style: { fontSize: 18, fontWeight: 600, color: isLight ? "#18181b" : "#fff" }, children: idea.votes }),
487
- /* @__PURE__ */ jsx("span", { style: { fontSize: 11, color: isLight ? "#71717a" : "#71717a" }, children: "votes" })
922
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 18 }, children: "\u{1F4A1}" }),
923
+ "Suggest a feature"
924
+ ]
925
+ }
926
+ ) : /* @__PURE__ */ jsxs(
927
+ "div",
928
+ {
929
+ style: {
930
+ padding: 16,
931
+ marginBottom: 20,
932
+ borderRadius: 12,
933
+ background: isLight ? "#f5f5f5" : "#151515",
934
+ border: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`
935
+ },
936
+ children: [
937
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 12 }, children: [
938
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 600, color: isLight ? "#18181b" : "#fff" }, children: "Suggest a Feature" }),
939
+ /* @__PURE__ */ jsx(
940
+ "button",
941
+ {
942
+ onClick: () => {
943
+ setShowIdeaForm(false);
944
+ setIdeaSubmitMessage(null);
945
+ },
946
+ style: {
947
+ background: "transparent",
948
+ border: "none",
949
+ color: isLight ? "#71717a" : "#a1a1aa",
950
+ cursor: "pointer",
951
+ fontSize: 18
952
+ },
953
+ children: "\xD7"
954
+ }
955
+ )
956
+ ] }),
957
+ /* @__PURE__ */ jsx(
958
+ "input",
959
+ {
960
+ type: "text",
961
+ value: ideaTitle,
962
+ onChange: (e) => setIdeaTitle(e.target.value),
963
+ placeholder: "Feature title *",
964
+ style: {
965
+ width: "100%",
966
+ padding: "10px 12px",
967
+ marginBottom: 8,
968
+ borderRadius: 6,
969
+ border: `1px solid ${isLight ? "#e5e5e5" : "#2a2a2a"}`,
970
+ background: isLight ? "#fff" : "#0a0a0a",
971
+ color: isLight ? "#18181b" : "#fff",
972
+ fontSize: 14,
973
+ outline: "none",
974
+ boxSizing: "border-box"
975
+ }
976
+ }
977
+ ),
978
+ /* @__PURE__ */ jsx(
979
+ "textarea",
980
+ {
981
+ value: ideaDescription,
982
+ onChange: (e) => setIdeaDescription(e.target.value),
983
+ placeholder: "Describe your idea...",
984
+ rows: 3,
985
+ style: {
986
+ width: "100%",
987
+ padding: "10px 12px",
988
+ marginBottom: 8,
989
+ borderRadius: 6,
990
+ border: `1px solid ${isLight ? "#e5e5e5" : "#2a2a2a"}`,
991
+ background: isLight ? "#fff" : "#0a0a0a",
992
+ color: isLight ? "#18181b" : "#fff",
993
+ fontSize: 14,
994
+ outline: "none",
995
+ resize: "none",
996
+ boxSizing: "border-box"
997
+ }
998
+ }
999
+ ),
1000
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: 8, marginBottom: 12 }, children: [
1001
+ /* @__PURE__ */ jsx(
1002
+ "input",
1003
+ {
1004
+ type: "text",
1005
+ value: ideaAuthorName,
1006
+ onChange: (e) => setIdeaAuthorName(e.target.value),
1007
+ placeholder: "Name (optional)",
1008
+ style: {
1009
+ width: "100%",
1010
+ padding: "8px 12px",
1011
+ borderRadius: 6,
1012
+ border: `1px solid ${isLight ? "#e5e5e5" : "#2a2a2a"}`,
1013
+ background: isLight ? "#fff" : "#0a0a0a",
1014
+ color: isLight ? "#18181b" : "#fff",
1015
+ fontSize: 13,
1016
+ outline: "none",
1017
+ boxSizing: "border-box"
1018
+ }
1019
+ }
1020
+ ),
1021
+ /* @__PURE__ */ jsx(
1022
+ "input",
1023
+ {
1024
+ type: "email",
1025
+ value: ideaAuthorEmail,
1026
+ onChange: (e) => setIdeaAuthorEmail(e.target.value),
1027
+ placeholder: "Email *",
1028
+ style: {
1029
+ width: "100%",
1030
+ padding: "8px 12px",
1031
+ borderRadius: 6,
1032
+ border: `1px solid ${isLight ? "#e5e5e5" : "#2a2a2a"}`,
1033
+ background: isLight ? "#fff" : "#0a0a0a",
1034
+ color: isLight ? "#18181b" : "#fff",
1035
+ fontSize: 13,
1036
+ outline: "none",
1037
+ boxSizing: "border-box"
1038
+ }
1039
+ }
1040
+ )
1041
+ ] }),
1042
+ ideaSubmitMessage && /* @__PURE__ */ jsx("div", { style: {
1043
+ padding: "8px 12px",
1044
+ marginBottom: 12,
1045
+ borderRadius: 6,
1046
+ background: ideaSubmitMessage.type === "success" ? isLight ? "#dcfce7" : "#14532d" : isLight ? "#fee2e2" : "#450a0a",
1047
+ color: ideaSubmitMessage.type === "success" ? isLight ? "#166534" : "#86efac" : isLight ? "#dc2626" : "#fca5a5",
1048
+ fontSize: 13
1049
+ }, children: ideaSubmitMessage.text }),
1050
+ /* @__PURE__ */ jsx(
1051
+ "button",
1052
+ {
1053
+ onClick: submitIdea,
1054
+ disabled: submittingIdea || !ideaTitle.trim() || !ideaAuthorEmail.trim(),
1055
+ style: {
1056
+ width: "100%",
1057
+ padding: "10px 16px",
1058
+ borderRadius: 999,
1059
+ border: "none",
1060
+ background: "#22c55e",
1061
+ color: "#fff",
1062
+ fontSize: 14,
1063
+ fontWeight: 500,
1064
+ cursor: submittingIdea || !ideaTitle.trim() || !ideaAuthorEmail.trim() ? "not-allowed" : "pointer",
1065
+ opacity: submittingIdea || !ideaTitle.trim() || !ideaAuthorEmail.trim() ? 0.6 : 1,
1066
+ transition: "opacity 150ms"
1067
+ },
1068
+ children: submittingIdea ? "Submitting..." : "Submit Idea"
1069
+ }
1070
+ )
488
1071
  ]
489
1072
  }
490
1073
  ),
491
- /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
492
- /* @__PURE__ */ jsx("div", { style: { fontSize: 16, fontWeight: 500, color: isLight ? "#18181b" : "#fff", marginBottom: 4 }, children: idea.title }),
493
- idea.description && /* @__PURE__ */ jsx("div", { style: { fontSize: 14, color: isLight ? "#71717a" : "#71717a", lineHeight: 1.5 }, children: idea.description })
494
- ] })
495
- ]
496
- },
497
- idea.id
498
- )) })
499
- ] }),
500
- /* @__PURE__ */ jsxs(
501
- "div",
502
- {
503
- style: {
504
- flexShrink: 0,
505
- padding: "16px 24px",
506
- borderTop: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`,
507
- display: "flex",
508
- alignItems: "center",
509
- justifyContent: "space-between"
510
- },
511
- children: [
512
- showBranding && /* @__PURE__ */ jsx(
513
- "a",
514
- {
515
- href: "https://versionpill.com",
516
- target: "_blank",
517
- rel: "noopener noreferrer",
518
- style: { fontSize: 12, color: isLight ? "#a1a1aa" : "#525252", textDecoration: "none" },
519
- children: "Powered by Version Pill"
520
- }
521
- ),
522
- /* @__PURE__ */ jsxs(
523
- "a",
524
- {
525
- href: `${baseUrl}/${projectId}/${activeTab === "ideas" ? "feature-requests" : activeTab}`,
526
- target: "_blank",
527
- rel: "noopener noreferrer",
528
- style: {
529
- padding: "10px 20px",
530
- fontSize: 14,
531
- fontWeight: 500,
532
- borderRadius: 8,
533
- background: "#22c55e",
534
- color: "#fff",
535
- textDecoration: "none",
536
- transition: "background 150ms"
537
- },
538
- onMouseEnter: (e) => e.currentTarget.style.background = "#16a34a",
539
- onMouseLeave: (e) => e.currentTarget.style.background = "#22c55e",
540
- children: [
541
- "View Full ",
542
- activeTab === "changelog" ? "Changelog" : activeTab === "roadmap" ? "Roadmap" : "Ideas",
543
- " \u2192"
544
- ]
545
- }
546
- )
547
- ]
548
- }
549
- )
550
- ]
551
- }
552
- ) })
1074
+ ideasArray.length === 0 && !showIdeaForm ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: 60, color: isLight ? "#71717a" : "#a1a1aa" }, children: [
1075
+ /* @__PURE__ */ jsx("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", style: { marginBottom: 12, opacity: 0.5 }, children: /* @__PURE__ */ jsx("path", { d: "M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" }) }),
1076
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 16, fontWeight: 500, marginBottom: 8 }, children: "No feature requests yet" }),
1077
+ /* @__PURE__ */ jsx(
1078
+ "button",
1079
+ {
1080
+ onClick: () => setShowIdeaForm(true),
1081
+ style: {
1082
+ padding: "8px 20px",
1083
+ borderRadius: 999,
1084
+ border: "none",
1085
+ background: "#22c55e",
1086
+ color: "#fff",
1087
+ fontSize: 14,
1088
+ fontWeight: 500,
1089
+ cursor: "pointer"
1090
+ },
1091
+ children: "Suggest a feature"
1092
+ }
1093
+ )
1094
+ ] }) : (() => {
1095
+ const statusOrder = ["under review", "planned", "in progress", "new", "shipped"];
1096
+ const grouped = {};
1097
+ ideasArray.forEach((idea) => {
1098
+ const status = (idea.status || "new").toLowerCase();
1099
+ if (!grouped[status]) grouped[status] = [];
1100
+ grouped[status].push(idea);
1101
+ });
1102
+ return statusOrder.map((status) => {
1103
+ const items = grouped[status];
1104
+ if (!items || items.length === 0) return null;
1105
+ const cfg = STATUS_CONFIG[status] || { color: "#71717a", label: status };
1106
+ return /* @__PURE__ */ jsxs("div", { style: { marginBottom: 20 }, children: [
1107
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 10 }, children: [
1108
+ /* @__PURE__ */ jsx("span", { style: {
1109
+ width: 8,
1110
+ height: 8,
1111
+ borderRadius: "50%",
1112
+ background: cfg.color,
1113
+ flexShrink: 0
1114
+ } }),
1115
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: 600, color: isLight ? "#52525b" : "#a1a1aa", textTransform: "uppercase", letterSpacing: "0.5px" }, children: cfg.label }),
1116
+ /* @__PURE__ */ jsx("span", { style: {
1117
+ padding: "1px 6px",
1118
+ fontSize: 11,
1119
+ fontWeight: 500,
1120
+ borderRadius: 999,
1121
+ background: isLight ? "#f4f4f5" : "#1f1f1f",
1122
+ color: isLight ? "#71717a" : "#a1a1aa"
1123
+ }, children: items.length })
1124
+ ] }),
1125
+ items.map((idea) => {
1126
+ const hasVoted = votedIdeas.has(idea.id) || idea.hasVoted;
1127
+ return /* @__PURE__ */ jsxs(
1128
+ "div",
1129
+ {
1130
+ style: {
1131
+ padding: isMobile ? 12 : 16,
1132
+ marginBottom: 8,
1133
+ borderRadius: 10,
1134
+ background: isLight ? "#f9fafb" : "#151515",
1135
+ border: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`,
1136
+ display: "flex",
1137
+ alignItems: "flex-start",
1138
+ gap: isMobile ? 10 : 16
1139
+ },
1140
+ children: [
1141
+ /* @__PURE__ */ jsxs(
1142
+ "button",
1143
+ {
1144
+ onClick: () => voteIdea(idea.id),
1145
+ disabled: hasVoted,
1146
+ style: {
1147
+ display: "flex",
1148
+ flexDirection: "column",
1149
+ alignItems: "center",
1150
+ padding: "8px 12px",
1151
+ borderRadius: 8,
1152
+ background: hasVoted ? isLight ? "#dcfce7" : "rgba(34,197,94,0.15)" : isLight ? "#fff" : "#0a0a0a",
1153
+ border: `1px solid ${hasVoted ? "#22c55e" : isLight ? "#e5e5e5" : "#2a2a2a"}`,
1154
+ minWidth: 48,
1155
+ cursor: hasVoted ? "default" : "pointer",
1156
+ transition: "all 150ms"
1157
+ },
1158
+ onMouseEnter: (e) => {
1159
+ if (!hasVoted) {
1160
+ e.currentTarget.style.borderColor = "#22c55e";
1161
+ e.currentTarget.style.background = isLight ? "#f0fdf4" : "rgba(34,197,94,0.1)";
1162
+ }
1163
+ },
1164
+ onMouseLeave: (e) => {
1165
+ if (!hasVoted) {
1166
+ e.currentTarget.style.borderColor = isLight ? "#e5e5e5" : "#2a2a2a";
1167
+ e.currentTarget.style.background = isLight ? "#fff" : "#0a0a0a";
1168
+ }
1169
+ },
1170
+ children: [
1171
+ /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: hasVoted ? "#22c55e" : "none", stroke: hasVoted ? "#22c55e" : isLight ? "#71717a" : "#a1a1aa", strokeWidth: "2", children: /* @__PURE__ */ jsx("path", { d: "M18 15l-6-6-6 6" }) }),
1172
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 16, fontWeight: 600, color: hasVoted ? "#22c55e" : isLight ? "#18181b" : "#fff" }, children: idea.votes })
1173
+ ]
1174
+ }
1175
+ ),
1176
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
1177
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 4, flexWrap: "wrap" }, children: [
1178
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 15, fontWeight: 500, color: isLight ? "#18181b" : "#fff" }, children: idea.title }),
1179
+ idea.status && /* @__PURE__ */ jsx("span", { style: {
1180
+ padding: "2px 8px",
1181
+ fontSize: 10,
1182
+ fontWeight: 500,
1183
+ borderRadius: 999,
1184
+ background: isLight ? `${cfg.color}15` : `${cfg.color}20`,
1185
+ color: cfg.color,
1186
+ textTransform: "uppercase",
1187
+ letterSpacing: "0.3px"
1188
+ }, children: cfg.label })
1189
+ ] }),
1190
+ idea.description && /* @__PURE__ */ jsx("div", { style: { fontSize: 14, color: isLight ? "#71717a" : "#a1a1aa", lineHeight: 1.5 }, children: idea.description })
1191
+ ] })
1192
+ ]
1193
+ },
1194
+ idea.id
1195
+ );
1196
+ })
1197
+ ] }, status);
1198
+ });
1199
+ })()
1200
+ ] })
1201
+ ] }),
1202
+ /* @__PURE__ */ jsxs(
1203
+ "div",
1204
+ {
1205
+ style: {
1206
+ flexShrink: 0,
1207
+ padding: "16px 24px",
1208
+ borderTop: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`,
1209
+ display: "flex",
1210
+ alignItems: "center",
1211
+ justifyContent: "space-between"
1212
+ },
1213
+ children: [
1214
+ showBranding && /* @__PURE__ */ jsx(
1215
+ "a",
1216
+ {
1217
+ href: "https://versionpill.com",
1218
+ target: "_blank",
1219
+ rel: "noopener noreferrer",
1220
+ style: { fontSize: 12, color: isLight ? "#a1a1aa" : "#525252", textDecoration: "none" },
1221
+ children: "Powered by Version Pill"
1222
+ }
1223
+ ),
1224
+ /* @__PURE__ */ jsxs(
1225
+ "a",
1226
+ {
1227
+ href: `${baseUrl}/${projectId}/${activeTab === "ideas" ? "feature-requests" : activeTab}`,
1228
+ target: "_blank",
1229
+ rel: "noopener noreferrer",
1230
+ style: {
1231
+ padding: "10px 20px",
1232
+ fontSize: 14,
1233
+ fontWeight: 500,
1234
+ borderRadius: 8,
1235
+ background: "#22c55e",
1236
+ color: "#fff",
1237
+ textDecoration: "none",
1238
+ transition: "background 150ms"
1239
+ },
1240
+ onMouseEnter: (e) => e.currentTarget.style.background = "#16a34a",
1241
+ onMouseLeave: (e) => e.currentTarget.style.background = "#22c55e",
1242
+ children: [
1243
+ "View Full ",
1244
+ activeTab === "changelog" ? "Changelog" : activeTab === "roadmap" ? "Roadmap" : "Ideas",
1245
+ " \u2192"
1246
+ ]
1247
+ }
1248
+ )
1249
+ ]
1250
+ }
1251
+ )
1252
+ ]
1253
+ }
1254
+ )
1255
+ ] }),
1256
+ document.body
1257
+ )
553
1258
  ] });
554
1259
  }
555
1260
  function VersionBadge({