version-pill-react 1.2.7 → 1.3.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
@@ -42,7 +42,11 @@ var COLUMN_LABELS = {
42
42
  backlog: "Backlog",
43
43
  todo: "Planned",
44
44
  "in-progress": "In Progress",
45
- done: "Shipped"
45
+ "in progress": "In Progress",
46
+ inProgress: "In Progress",
47
+ done: "Shipped",
48
+ shipped: "Shipped",
49
+ completed: "Shipped"
46
50
  };
47
51
  function useTheme(theme) {
48
52
  const [resolved, setResolved] = useState("light");
@@ -81,6 +85,13 @@ function VersionPill({
81
85
  const [isOpen, setIsOpen] = useState(false);
82
86
  const [activeTab, setActiveTab] = useState("changelog");
83
87
  const [hasNewVersion, setHasNewVersion] = useState(false);
88
+ const [showIdeaForm, setShowIdeaForm] = useState(false);
89
+ const [ideaTitle, setIdeaTitle] = useState("");
90
+ const [ideaDescription, setIdeaDescription] = useState("");
91
+ const [ideaAuthorName, setIdeaAuthorName] = useState("");
92
+ const [ideaAuthorEmail, setIdeaAuthorEmail] = useState("");
93
+ const [submittingIdea, setSubmittingIdea] = useState(false);
94
+ const [ideaSubmitMessage, setIdeaSubmitMessage] = useState(null);
84
95
  const resolvedTheme = useTheme(theme);
85
96
  const isLight = resolvedTheme === "light";
86
97
  const sizeConfig = SIZE_CONFIG[size];
@@ -126,7 +137,26 @@ function VersionPill({
126
137
  const response = await fetch(`${baseUrl}/api/roadmap/${projectId}`);
127
138
  if (!response.ok) return;
128
139
  const data = await response.json();
129
- setRoadmapTasks(data.tasks || []);
140
+ let tasks = [];
141
+ if (Array.isArray(data.tasks)) {
142
+ tasks = data.tasks;
143
+ } else if (data.tasks && typeof data.tasks === "object") {
144
+ const grouped = data.tasks;
145
+ const mapTask = (t, defaultColumn) => ({
146
+ id: t.id || t._id,
147
+ title: t.title,
148
+ description: t.description,
149
+ type: t.type || "feature",
150
+ priority: t.priority || "medium",
151
+ column: t.columnId || defaultColumn,
152
+ columnId: t.columnId,
153
+ columnName: t.columnName
154
+ });
155
+ const inProgress = (grouped.inProgress || []).map((t) => mapTask(t, "in-progress"));
156
+ const planned = (grouped.planned || []).map((t) => mapTask(t, "todo"));
157
+ tasks = [...inProgress, ...planned];
158
+ }
159
+ setRoadmapTasks(tasks);
130
160
  } catch {
131
161
  }
132
162
  }, [projectId, baseUrl]);
@@ -139,6 +169,36 @@ function VersionPill({
139
169
  } catch {
140
170
  }
141
171
  }, [projectId, baseUrl]);
172
+ const submitIdea = useCallback(async () => {
173
+ if (!ideaTitle.trim()) return;
174
+ setSubmittingIdea(true);
175
+ setIdeaSubmitMessage(null);
176
+ try {
177
+ const response = await fetch(`${baseUrl}/api/ideas/${projectId}`, {
178
+ method: "POST",
179
+ headers: { "Content-Type": "application/json" },
180
+ body: JSON.stringify({
181
+ title: ideaTitle.trim(),
182
+ description: ideaDescription.trim() || void 0,
183
+ authorName: ideaAuthorName.trim() || void 0,
184
+ authorEmail: ideaAuthorEmail.trim() || void 0
185
+ })
186
+ });
187
+ if (!response.ok) {
188
+ const error = await response.json().catch(() => ({ error: "Failed to submit" }));
189
+ throw new Error(error.error || "Failed to submit idea");
190
+ }
191
+ setIdeaSubmitMessage({ type: "success", text: "Thanks! Your idea has been submitted." });
192
+ setIdeaTitle("");
193
+ setIdeaDescription("");
194
+ setShowIdeaForm(false);
195
+ fetchIdeas();
196
+ } catch (err) {
197
+ setIdeaSubmitMessage({ type: "error", text: err.message || "Failed to submit idea" });
198
+ } finally {
199
+ setSubmittingIdea(false);
200
+ }
201
+ }, [baseUrl, projectId, ideaTitle, ideaDescription, ideaAuthorName, ideaAuthorEmail, fetchIdeas]);
142
202
  useEffect(() => {
143
203
  fetchVersion();
144
204
  }, [fetchVersion]);
@@ -410,92 +470,288 @@ function VersionPill({
410
470
  feature
411
471
  ] }, i)) })
412
472
  ] }, 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: [
473
+ activeTab === "roadmap" && /* @__PURE__ */ jsx("div", { style: { maxWidth: 640 }, children: Object.keys(groupedTasks).length === 0 || tasksArray.length === 0 ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: 60, color: isLight ? "#71717a" : "#a1a1aa" }, children: [
414
474
  /* @__PURE__ */ jsx("div", { style: { fontSize: 48, marginBottom: 12 }, children: "\u{1F5FA}\uFE0F" }),
415
475
  /* @__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"}`
476
+ ] }) : (
477
+ // Show all columns that have tasks, prioritizing known columns first
478
+ [.../* @__PURE__ */ new Set([
479
+ ...["in-progress", "todo", "backlog"].filter((c) => groupedTasks[c]?.length > 0),
480
+ ...Object.keys(groupedTasks).filter((c) => !["in-progress", "todo", "backlog", "done"].includes(c))
481
+ ])].map((col) => {
482
+ const tasks = groupedTasks[col];
483
+ if (!tasks || tasks.length === 0) return null;
484
+ const columnLabel = tasks[0]?.columnName || COLUMN_LABELS[col] || col;
485
+ return /* @__PURE__ */ jsxs("div", { style: { marginBottom: 24 }, children: [
486
+ /* @__PURE__ */ jsxs("h3", { style: { fontSize: 12, fontWeight: 600, color: isLight ? "#a1a1aa" : "#71717a", marginBottom: 12, textTransform: "uppercase", letterSpacing: "0.5px" }, children: [
487
+ columnLabel,
488
+ " (",
489
+ tasks.length,
490
+ ")"
491
+ ] }),
492
+ tasks.map((task) => /* @__PURE__ */ jsx(
493
+ "div",
494
+ {
495
+ style: {
496
+ padding: "12px 16px",
497
+ marginBottom: 8,
498
+ borderRadius: 8,
499
+ background: isLight ? "#f5f5f5" : "#151515",
500
+ border: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`
501
+ },
502
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "flex-start", gap: 10 }, children: [
503
+ /* @__PURE__ */ jsx(
504
+ "span",
505
+ {
506
+ style: {
507
+ width: 8,
508
+ height: 8,
509
+ borderRadius: "50%",
510
+ background: TYPE_COLORS[task.type] || "#71717a",
511
+ flexShrink: 0,
512
+ marginTop: 5
513
+ }
514
+ }
515
+ ),
516
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
517
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 14, color: isLight ? "#18181b" : "#fff" }, children: task.title }),
518
+ task.description && /* @__PURE__ */ jsx("p", { style: { fontSize: 13, color: isLight ? "#71717a" : "#a1a1aa", margin: "4px 0 0 0", lineHeight: 1.5 }, children: task.description })
519
+ ] })
520
+ ] })
435
521
  },
436
- children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10 }, children: [
522
+ task.id
523
+ ))
524
+ ] }, col);
525
+ })
526
+ ) }),
527
+ activeTab === "ideas" && /* @__PURE__ */ jsxs("div", { style: { maxWidth: 640 }, children: [
528
+ !showIdeaForm ? /* @__PURE__ */ jsxs(
529
+ "button",
530
+ {
531
+ onClick: () => setShowIdeaForm(true),
532
+ style: {
533
+ display: "flex",
534
+ alignItems: "center",
535
+ justifyContent: "center",
536
+ gap: 8,
537
+ width: "100%",
538
+ padding: "12px 16px",
539
+ marginBottom: 20,
540
+ borderRadius: 8,
541
+ border: `1px dashed ${isLight ? "#d4d4d8" : "#3f3f46"}`,
542
+ background: "transparent",
543
+ color: isLight ? "#71717a" : "#a1a1aa",
544
+ fontSize: 14,
545
+ fontWeight: 500,
546
+ cursor: "pointer",
547
+ transition: "all 150ms"
548
+ },
549
+ onMouseEnter: (e) => {
550
+ e.currentTarget.style.borderColor = isLight ? "#a1a1aa" : "#71717a";
551
+ e.currentTarget.style.color = isLight ? "#52525b" : "#d4d4d8";
552
+ },
553
+ onMouseLeave: (e) => {
554
+ e.currentTarget.style.borderColor = isLight ? "#d4d4d8" : "#3f3f46";
555
+ e.currentTarget.style.color = isLight ? "#71717a" : "#a1a1aa";
556
+ },
557
+ children: [
558
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 18 }, children: "\u{1F4A1}" }),
559
+ "Suggest a feature"
560
+ ]
561
+ }
562
+ ) : /* @__PURE__ */ jsxs(
563
+ "div",
564
+ {
565
+ style: {
566
+ padding: 16,
567
+ marginBottom: 20,
568
+ borderRadius: 8,
569
+ background: isLight ? "#f5f5f5" : "#151515",
570
+ border: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`
571
+ },
572
+ children: [
573
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 12 }, children: [
574
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 600, color: isLight ? "#18181b" : "#fff" }, children: "Suggest a Feature" }),
437
575
  /* @__PURE__ */ jsx(
438
- "span",
576
+ "button",
439
577
  {
578
+ onClick: () => {
579
+ setShowIdeaForm(false);
580
+ setIdeaSubmitMessage(null);
581
+ },
440
582
  style: {
441
- width: 8,
442
- height: 8,
443
- borderRadius: "50%",
444
- background: TYPE_COLORS[task.type] || "#71717a",
445
- flexShrink: 0
583
+ background: "transparent",
584
+ border: "none",
585
+ color: isLight ? "#71717a" : "#a1a1aa",
586
+ cursor: "pointer",
587
+ fontSize: 18
588
+ },
589
+ children: "\xD7"
590
+ }
591
+ )
592
+ ] }),
593
+ /* @__PURE__ */ jsx(
594
+ "input",
595
+ {
596
+ type: "text",
597
+ value: ideaTitle,
598
+ onChange: (e) => setIdeaTitle(e.target.value),
599
+ placeholder: "Feature title *",
600
+ style: {
601
+ width: "100%",
602
+ padding: "10px 12px",
603
+ marginBottom: 8,
604
+ borderRadius: 6,
605
+ border: `1px solid ${isLight ? "#e5e5e5" : "#2a2a2a"}`,
606
+ background: isLight ? "#fff" : "#0a0a0a",
607
+ color: isLight ? "#18181b" : "#fff",
608
+ fontSize: 14,
609
+ outline: "none",
610
+ boxSizing: "border-box"
611
+ }
612
+ }
613
+ ),
614
+ /* @__PURE__ */ jsx(
615
+ "textarea",
616
+ {
617
+ value: ideaDescription,
618
+ onChange: (e) => setIdeaDescription(e.target.value),
619
+ placeholder: "Describe your idea...",
620
+ rows: 3,
621
+ style: {
622
+ width: "100%",
623
+ padding: "10px 12px",
624
+ marginBottom: 8,
625
+ borderRadius: 6,
626
+ border: `1px solid ${isLight ? "#e5e5e5" : "#2a2a2a"}`,
627
+ background: isLight ? "#fff" : "#0a0a0a",
628
+ color: isLight ? "#18181b" : "#fff",
629
+ fontSize: 14,
630
+ outline: "none",
631
+ resize: "none",
632
+ boxSizing: "border-box"
633
+ }
634
+ }
635
+ ),
636
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 12 }, children: [
637
+ /* @__PURE__ */ jsx(
638
+ "input",
639
+ {
640
+ type: "text",
641
+ value: ideaAuthorName,
642
+ onChange: (e) => setIdeaAuthorName(e.target.value),
643
+ placeholder: "Name (optional)",
644
+ style: {
645
+ width: "100%",
646
+ padding: "8px 12px",
647
+ borderRadius: 6,
648
+ border: `1px solid ${isLight ? "#e5e5e5" : "#2a2a2a"}`,
649
+ background: isLight ? "#fff" : "#0a0a0a",
650
+ color: isLight ? "#18181b" : "#fff",
651
+ fontSize: 13,
652
+ outline: "none",
653
+ boxSizing: "border-box"
446
654
  }
447
655
  }
448
656
  ),
449
- /* @__PURE__ */ jsx("span", { style: { fontSize: 14, color: isLight ? "#18181b" : "#fff" }, children: task.title })
450
- ] })
657
+ /* @__PURE__ */ jsx(
658
+ "input",
659
+ {
660
+ type: "email",
661
+ value: ideaAuthorEmail,
662
+ onChange: (e) => setIdeaAuthorEmail(e.target.value),
663
+ placeholder: "Email (optional)",
664
+ style: {
665
+ width: "100%",
666
+ padding: "8px 12px",
667
+ borderRadius: 6,
668
+ border: `1px solid ${isLight ? "#e5e5e5" : "#2a2a2a"}`,
669
+ background: isLight ? "#fff" : "#0a0a0a",
670
+ color: isLight ? "#18181b" : "#fff",
671
+ fontSize: 13,
672
+ outline: "none",
673
+ boxSizing: "border-box"
674
+ }
675
+ }
676
+ )
677
+ ] }),
678
+ ideaSubmitMessage && /* @__PURE__ */ jsx("div", { style: {
679
+ padding: "8px 12px",
680
+ marginBottom: 12,
681
+ borderRadius: 6,
682
+ background: ideaSubmitMessage.type === "success" ? isLight ? "#dcfce7" : "#14532d" : isLight ? "#fee2e2" : "#450a0a",
683
+ color: ideaSubmitMessage.type === "success" ? isLight ? "#166534" : "#86efac" : isLight ? "#dc2626" : "#fca5a5",
684
+ fontSize: 13
685
+ }, children: ideaSubmitMessage.text }),
686
+ /* @__PURE__ */ jsx(
687
+ "button",
688
+ {
689
+ onClick: submitIdea,
690
+ disabled: submittingIdea || !ideaTitle.trim(),
691
+ style: {
692
+ width: "100%",
693
+ padding: "10px 16px",
694
+ borderRadius: 6,
695
+ border: "none",
696
+ background: "#22c55e",
697
+ color: "#fff",
698
+ fontSize: 14,
699
+ fontWeight: 500,
700
+ cursor: submittingIdea || !ideaTitle.trim() ? "not-allowed" : "pointer",
701
+ opacity: submittingIdea || !ideaTitle.trim() ? 0.6 : 1,
702
+ transition: "opacity 150ms"
703
+ },
704
+ children: submittingIdea ? "Submitting..." : "Submit Idea"
705
+ }
706
+ )
707
+ ]
708
+ }
709
+ ),
710
+ ideasArray.length === 0 && !showIdeaForm ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: 60, color: isLight ? "#71717a" : "#a1a1aa" }, children: [
711
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 48, marginBottom: 12 }, children: "\u{1F4A1}" }),
712
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: "No feature requests yet" }),
713
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 14, marginTop: 8 }, children: "Be the first to suggest one!" })
714
+ ] }) : ideasArray.map((idea) => /* @__PURE__ */ jsxs(
715
+ "div",
716
+ {
717
+ style: {
718
+ padding: 16,
719
+ marginBottom: 12,
720
+ borderRadius: 8,
721
+ background: isLight ? "#f5f5f5" : "#151515",
722
+ border: `1px solid ${isLight ? "#e5e5e5" : "#1f1f1f"}`,
723
+ display: "flex",
724
+ alignItems: "flex-start",
725
+ gap: 16
451
726
  },
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
727
+ children: [
728
+ /* @__PURE__ */ jsxs(
729
+ "div",
730
+ {
731
+ style: {
732
+ display: "flex",
733
+ flexDirection: "column",
734
+ alignItems: "center",
735
+ padding: "8px 12px",
736
+ borderRadius: 6,
737
+ background: isLight ? "#fff" : "#0a0a0a",
738
+ minWidth: 50
739
+ },
740
+ children: [
741
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 18, fontWeight: 600, color: isLight ? "#18181b" : "#fff" }, children: idea.votes }),
742
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 11, color: isLight ? "#71717a" : "#71717a" }, children: "votes" })
743
+ ]
744
+ }
745
+ ),
746
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
747
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 16, fontWeight: 500, color: isLight ? "#18181b" : "#fff", marginBottom: 4 }, children: idea.title }),
748
+ idea.description && /* @__PURE__ */ jsx("div", { style: { fontSize: 14, color: isLight ? "#71717a" : "#71717a", lineHeight: 1.5 }, children: idea.description })
749
+ ] })
750
+ ]
471
751
  },
472
- children: [
473
- /* @__PURE__ */ jsxs(
474
- "div",
475
- {
476
- style: {
477
- display: "flex",
478
- flexDirection: "column",
479
- alignItems: "center",
480
- padding: "8px 12px",
481
- borderRadius: 6,
482
- background: isLight ? "#fff" : "#0a0a0a",
483
- minWidth: 50
484
- },
485
- 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" })
488
- ]
489
- }
490
- ),
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
- )) })
752
+ idea.id
753
+ ))
754
+ ] })
499
755
  ] }),
500
756
  /* @__PURE__ */ jsxs(
501
757
  "div",