pxengine 0.1.115 → 0.1.116

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.cjs CHANGED
@@ -16133,6 +16133,8 @@ var SlideTypeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime147.jsxs)("svg",
16133
16133
  /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("rect", { x: "3", y: "4", width: "18", height: "14", rx: "2" }),
16134
16134
  /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
16135
16135
  ] });
16136
+ var ChevronUpIcon = () => /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("polyline", { points: "18 15 12 9 6 15" }) });
16137
+ var ChevronDownIcon = () => /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("polyline", { points: "6 9 12 15 18 9" }) });
16136
16138
  function formatTemplateLabel(templateId) {
16137
16139
  if (!templateId) return null;
16138
16140
  return templateId.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
@@ -16358,6 +16360,8 @@ var PresentationJobCard = ({
16358
16360
  shareUrl,
16359
16361
  approveUrl,
16360
16362
  approveOutlineUrl,
16363
+ reorderSlidesUrl,
16364
+ approveSlideUrl,
16361
16365
  regenerateUrl,
16362
16366
  hideApproval = false,
16363
16367
  className,
@@ -16389,6 +16393,8 @@ var PresentationJobCard = ({
16389
16393
  const [messageEdits, setMessageEdits] = (0, import_react78.useState)({});
16390
16394
  const [approvingOutline, setApprovingOutline] = (0, import_react78.useState)(false);
16391
16395
  const [outlineWritePollUrl, setOutlineWritePollUrl] = (0, import_react78.useState)(null);
16396
+ const [rowBusyIndex, setRowBusyIndex] = (0, import_react78.useState)(null);
16397
+ const [rowError, setRowError] = (0, import_react78.useState)(null);
16392
16398
  const [regenPollUrl, setRegenPollUrl] = (0, import_react78.useState)(null);
16393
16399
  const [currentSlide, setCurrentSlide] = (0, import_react78.useState)(1);
16394
16400
  const [previewScale, setPreviewScale] = (0, import_react78.useState)(1);
@@ -16621,6 +16627,76 @@ var PresentationJobCard = ({
16621
16627
  });
16622
16628
  return changed ? { ...outline, slides } : void 0;
16623
16629
  };
16630
+ const moveOutlineSlide = async (index, delta) => {
16631
+ if (!outline || !Array.isArray(outline.slides) || rowBusyIndex !== null) return;
16632
+ const slides = outline.slides;
16633
+ const target = index + delta;
16634
+ if (target < 0 || target >= slides.length) return;
16635
+ const order = slides.map((_, i) => i);
16636
+ [order[index], order[target]] = [order[target], order[index]];
16637
+ const reordered = order.map((i, newIndex) => ({ ...slides[i], n: newIndex + 1 }));
16638
+ const previousOutline = outline;
16639
+ const previousEdits = messageEdits;
16640
+ setOutline({ ...outline, slides: reordered });
16641
+ setMessageEdits((prev) => {
16642
+ const remapped = {};
16643
+ order.forEach((originalIndex, newIndex) => {
16644
+ if (prev[originalIndex] !== void 0) remapped[newIndex] = prev[originalIndex];
16645
+ });
16646
+ return remapped;
16647
+ });
16648
+ setRowBusyIndex(index);
16649
+ setRowError(null);
16650
+ try {
16651
+ const endpoint = reorderSlidesUrl || `/api/presentations/${_job_id}/outline/reorder-slides`;
16652
+ const headers = { "Content-Type": "application/json" };
16653
+ if (authToken) headers.Authorization = `Bearer ${authToken}`;
16654
+ const res = await fetch(endpoint, {
16655
+ method: "POST",
16656
+ headers,
16657
+ body: JSON.stringify({ order })
16658
+ });
16659
+ if (!res.ok) {
16660
+ const err = await res.json().catch(() => ({}));
16661
+ throw new Error(err.detail || err.error || `Reorder failed (${res.status})`);
16662
+ }
16663
+ } catch (e) {
16664
+ setOutline(previousOutline);
16665
+ setMessageEdits(previousEdits);
16666
+ setRowError(e instanceof Error ? e.message : "Could not reorder slides");
16667
+ } finally {
16668
+ setRowBusyIndex(null);
16669
+ }
16670
+ };
16671
+ const toggleSlideApproved = async (index) => {
16672
+ if (!outline || !Array.isArray(outline.slides) || rowBusyIndex !== null) return;
16673
+ const slides = outline.slides;
16674
+ const nextApproved = !slides[index]?.approved;
16675
+ const previousOutline = outline;
16676
+ const updated = slides.map((s, i) => i === index ? { ...s, approved: nextApproved } : s);
16677
+ setOutline({ ...outline, slides: updated });
16678
+ setRowBusyIndex(index);
16679
+ setRowError(null);
16680
+ try {
16681
+ const endpoint = approveSlideUrl || `/api/presentations/${_job_id}/outline/approve-slide`;
16682
+ const headers = { "Content-Type": "application/json" };
16683
+ if (authToken) headers.Authorization = `Bearer ${authToken}`;
16684
+ const res = await fetch(endpoint, {
16685
+ method: "POST",
16686
+ headers,
16687
+ body: JSON.stringify({ slide_index: index, approved: nextApproved })
16688
+ });
16689
+ if (!res.ok) {
16690
+ const err = await res.json().catch(() => ({}));
16691
+ throw new Error(err.detail || err.error || `Approve failed (${res.status})`);
16692
+ }
16693
+ } catch (e) {
16694
+ setOutline(previousOutline);
16695
+ setRowError(e instanceof Error ? e.message : "Could not update slide");
16696
+ } finally {
16697
+ setRowBusyIndex(null);
16698
+ }
16699
+ };
16624
16700
  const handleApproveOutline = async () => {
16625
16701
  if (!_job_id || approvingOutline) return;
16626
16702
  const endpoint = approveOutlineUrl || `/api/presentations/${_job_id}/approve-outline`;
@@ -16858,31 +16934,71 @@ var PresentationJobCard = ({
16858
16934
  ] })
16859
16935
  ] }),
16860
16936
  /* @__PURE__ */ (0, import_jsx_runtime147.jsxs)("div", { className: "mt-4 space-y-2", children: [
16861
- slides.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime147.jsxs)("div", { className: "flex items-center gap-2", children: [
16862
- /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("span", { className: "text-xs text-zinc-600 w-5 text-right tabular-nums flex-shrink-0", children: s.n ?? i + 1 }),
16863
- /* @__PURE__ */ (0, import_jsx_runtime147.jsxs)(
16864
- "span",
16865
- {
16866
- className: "flex items-center gap-1 text-[10px] uppercase tracking-wide text-zinc-500 w-20 flex-shrink-0 truncate",
16867
- title: s.type,
16868
- children: [
16869
- /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(SlideTypeIcon, {}),
16870
- s.type || "slide"
16871
- ]
16872
- }
16873
- ),
16874
- /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(
16875
- "input",
16876
- {
16877
- value: messageEdits[i] ?? s.message ?? "",
16878
- onChange: (e) => setMessageEdits((prev) => ({ ...prev, [i]: e.target.value })),
16879
- disabled: building,
16880
- className: "flex-1 min-w-0 bg-zinc-800/60 border border-zinc-700 rounded-lg px-3 h-8 text-xs text-zinc-200 focus:border-indigo-500 outline-none disabled:opacity-60"
16881
- }
16882
- )
16883
- ] }, i)),
16937
+ slides.map((s, i) => {
16938
+ const rowBusy = building || rowBusyIndex === i;
16939
+ return /* @__PURE__ */ (0, import_jsx_runtime147.jsxs)("div", { className: "flex items-center gap-1.5", children: [
16940
+ /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("span", { className: "text-xs text-zinc-600 w-5 text-right tabular-nums flex-shrink-0", children: s.n ?? i + 1 }),
16941
+ /* @__PURE__ */ (0, import_jsx_runtime147.jsxs)(
16942
+ "span",
16943
+ {
16944
+ className: "flex items-center gap-1 text-[10px] uppercase tracking-wide text-zinc-500 w-20 flex-shrink-0 truncate",
16945
+ title: s.type,
16946
+ children: [
16947
+ /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(SlideTypeIcon, {}),
16948
+ s.type || "slide"
16949
+ ]
16950
+ }
16951
+ ),
16952
+ /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(
16953
+ "input",
16954
+ {
16955
+ value: messageEdits[i] ?? s.message ?? "",
16956
+ onChange: (e) => setMessageEdits((prev) => ({ ...prev, [i]: e.target.value })),
16957
+ disabled: building,
16958
+ className: "flex-1 min-w-0 bg-zinc-800/60 border border-zinc-700 rounded-lg px-3 h-8 text-xs text-zinc-200 focus:border-indigo-500 outline-none disabled:opacity-60"
16959
+ }
16960
+ ),
16961
+ /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(
16962
+ "button",
16963
+ {
16964
+ type: "button",
16965
+ onClick: () => moveOutlineSlide(i, -1),
16966
+ disabled: rowBusy || i === 0,
16967
+ title: "Move up",
16968
+ className: "w-7 h-7 flex items-center justify-center rounded-md border border-zinc-700 text-zinc-400 hover:text-zinc-100 hover:border-zinc-500 disabled:opacity-30 disabled:hover:text-zinc-400 disabled:hover:border-zinc-700 flex-shrink-0",
16969
+ children: /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(ChevronUpIcon, {})
16970
+ }
16971
+ ),
16972
+ /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(
16973
+ "button",
16974
+ {
16975
+ type: "button",
16976
+ onClick: () => moveOutlineSlide(i, 1),
16977
+ disabled: rowBusy || i === slides.length - 1,
16978
+ title: "Move down",
16979
+ className: "w-7 h-7 flex items-center justify-center rounded-md border border-zinc-700 text-zinc-400 hover:text-zinc-100 hover:border-zinc-500 disabled:opacity-30 disabled:hover:text-zinc-400 disabled:hover:border-zinc-700 flex-shrink-0",
16980
+ children: /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(ChevronDownIcon, {})
16981
+ }
16982
+ ),
16983
+ /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(
16984
+ "button",
16985
+ {
16986
+ type: "button",
16987
+ onClick: () => toggleSlideApproved(i),
16988
+ disabled: rowBusy,
16989
+ title: s.approved ? "Marked reviewed" : "Mark as reviewed",
16990
+ className: cn(
16991
+ "w-7 h-7 flex items-center justify-center rounded-md border flex-shrink-0 disabled:opacity-40",
16992
+ s.approved ? "border-emerald-600/50 bg-emerald-950/40 text-emerald-300" : "border-zinc-700 text-zinc-500 hover:text-zinc-300 hover:border-zinc-500"
16993
+ ),
16994
+ children: /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(CheckIcon, {})
16995
+ }
16996
+ )
16997
+ ] }, i);
16998
+ }),
16884
16999
  slides.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("p", { className: "text-xs text-zinc-500", children: "No outline slides were returned; you can still build the deck." })
16885
17000
  ] }),
17001
+ rowError && /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("p", { className: "mt-2 text-xs text-red-400/90", children: rowError }),
16886
17002
  approveError && /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("p", { className: "mt-3 text-xs text-red-400/90", children: approveError }),
16887
17003
  /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("div", { className: "mt-4 flex items-center justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime147.jsxs)(
16888
17004
  "button",
@@ -17132,6 +17248,8 @@ var ShareIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("svg", {
17132
17248
  /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
17133
17249
  ] });
17134
17250
  var CheckIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("polyline", { points: "20 6 9 17 4 12" }) });
17251
+ var ChevronUpIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("polyline", { points: "18 15 12 9 6 15" }) });
17252
+ var ChevronDownIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("polyline", { points: "6 9 12 15 18 9" }) });
17135
17253
  var RefreshIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
17136
17254
  /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("polyline", { points: "23 4 23 10 17 10" }),
17137
17255
  /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("path", { d: "M20.49 15a9 9 0 1 1-2.12-9.36L23 10" })
@@ -17214,6 +17332,8 @@ var ResearchReportJobCard = (props) => {
17214
17332
  shareUrl,
17215
17333
  approveUrl,
17216
17334
  approveOutlineUrl,
17335
+ reorderSectionsUrl,
17336
+ approveSectionUrl,
17217
17337
  regenerateUrl,
17218
17338
  hideApproval = false,
17219
17339
  className,
@@ -17251,6 +17371,8 @@ var ResearchReportJobCard = (props) => {
17251
17371
  const [approveError, setApproveError] = (0, import_react79.useState)(null);
17252
17372
  const [headingEdits, setHeadingEdits] = (0, import_react79.useState)({});
17253
17373
  const [approvingOutline, setApprovingOutline] = (0, import_react79.useState)(false);
17374
+ const [rowBusyIndex, setRowBusyIndex] = (0, import_react79.useState)(null);
17375
+ const [rowError, setRowError] = (0, import_react79.useState)(null);
17254
17376
  const [outlineWritePollUrl, setOutlineWritePollUrl] = (0, import_react79.useState)(null);
17255
17377
  const [regenPollUrl, setRegenPollUrl] = (0, import_react79.useState)(null);
17256
17378
  const previewRef = (0, import_react79.useRef)(null);
@@ -17506,6 +17628,76 @@ var ResearchReportJobCard = (props) => {
17506
17628
  });
17507
17629
  return changed ? { ...outline, sections } : void 0;
17508
17630
  };
17631
+ const moveOutlineSection = async (index, delta) => {
17632
+ if (!outline || !Array.isArray(outline.sections) || rowBusyIndex !== null) return;
17633
+ const sections = outline.sections;
17634
+ const target = index + delta;
17635
+ if (target < 0 || target >= sections.length) return;
17636
+ const order = sections.map((_, i) => i);
17637
+ [order[index], order[target]] = [order[target], order[index]];
17638
+ const reordered = order.map((i) => sections[i]);
17639
+ const previousOutline = outline;
17640
+ const previousEdits = headingEdits;
17641
+ setOutline({ ...outline, sections: reordered });
17642
+ setHeadingEdits((prev) => {
17643
+ const remapped = {};
17644
+ order.forEach((originalIndex, newIndex) => {
17645
+ if (prev[originalIndex] !== void 0) remapped[newIndex] = prev[originalIndex];
17646
+ });
17647
+ return remapped;
17648
+ });
17649
+ setRowBusyIndex(index);
17650
+ setRowError(null);
17651
+ try {
17652
+ const endpoint = reorderSectionsUrl || `/api/reports/${job_id}/outline/reorder-sections`;
17653
+ const headers = { "Content-Type": "application/json" };
17654
+ if (authToken) headers.Authorization = `Bearer ${authToken}`;
17655
+ const res = await fetch(endpoint, {
17656
+ method: "POST",
17657
+ headers,
17658
+ body: JSON.stringify({ order })
17659
+ });
17660
+ if (!res.ok) {
17661
+ const err = await res.json().catch(() => ({}));
17662
+ throw new Error(err.detail || err.error || `Reorder failed (${res.status})`);
17663
+ }
17664
+ } catch (e) {
17665
+ setOutline(previousOutline);
17666
+ setHeadingEdits(previousEdits);
17667
+ setRowError(e instanceof Error ? e.message : "Could not reorder sections");
17668
+ } finally {
17669
+ setRowBusyIndex(null);
17670
+ }
17671
+ };
17672
+ const toggleSectionApproved = async (index) => {
17673
+ if (!outline || !Array.isArray(outline.sections) || rowBusyIndex !== null) return;
17674
+ const sections = outline.sections;
17675
+ const nextApproved = !sections[index]?.approved;
17676
+ const previousOutline = outline;
17677
+ const updated = sections.map((s, i) => i === index ? { ...s, approved: nextApproved } : s);
17678
+ setOutline({ ...outline, sections: updated });
17679
+ setRowBusyIndex(index);
17680
+ setRowError(null);
17681
+ try {
17682
+ const endpoint = approveSectionUrl || `/api/reports/${job_id}/outline/approve-section`;
17683
+ const headers = { "Content-Type": "application/json" };
17684
+ if (authToken) headers.Authorization = `Bearer ${authToken}`;
17685
+ const res = await fetch(endpoint, {
17686
+ method: "POST",
17687
+ headers,
17688
+ body: JSON.stringify({ section_index: index, approved: nextApproved })
17689
+ });
17690
+ if (!res.ok) {
17691
+ const err = await res.json().catch(() => ({}));
17692
+ throw new Error(err.detail || err.error || `Approve failed (${res.status})`);
17693
+ }
17694
+ } catch (e) {
17695
+ setOutline(previousOutline);
17696
+ setRowError(e instanceof Error ? e.message : "Could not update section");
17697
+ } finally {
17698
+ setRowBusyIndex(null);
17699
+ }
17700
+ };
17509
17701
  const handleApproveOutline = async () => {
17510
17702
  if (!job_id || approvingOutline) return;
17511
17703
  const endpoint = approveOutlineUrl || `/api/reports/${job_id}/approve-outline`;
@@ -17665,20 +17857,60 @@ var ResearchReportJobCard = (props) => {
17665
17857
  ] })
17666
17858
  ] }),
17667
17859
  /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "mt-4 space-y-2", children: [
17668
- sections.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "flex items-center gap-2", children: [
17669
- /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { className: "text-xs text-zinc-600 w-5 text-right tabular-nums flex-shrink-0", children: i + 1 }),
17670
- /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(
17671
- "input",
17672
- {
17673
- value: headingEdits[i] ?? s.heading ?? "",
17674
- onChange: (e) => setHeadingEdits((prev) => ({ ...prev, [i]: e.target.value })),
17675
- disabled: building,
17676
- className: "flex-1 min-w-0 bg-zinc-800/60 border border-zinc-700 rounded-lg px-3 h-8 text-xs text-zinc-200 focus:border-violet-500 outline-none disabled:opacity-60"
17677
- }
17678
- )
17679
- ] }, i)),
17860
+ sections.map((s, i) => {
17861
+ const rowBusy = building || rowBusyIndex === i;
17862
+ return /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "flex items-center gap-1.5", children: [
17863
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { className: "text-xs text-zinc-600 w-5 text-right tabular-nums flex-shrink-0", children: i + 1 }),
17864
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(
17865
+ "input",
17866
+ {
17867
+ value: headingEdits[i] ?? s.heading ?? "",
17868
+ onChange: (e) => setHeadingEdits((prev) => ({ ...prev, [i]: e.target.value })),
17869
+ disabled: building,
17870
+ className: "flex-1 min-w-0 bg-zinc-800/60 border border-zinc-700 rounded-lg px-3 h-8 text-xs text-zinc-200 focus:border-violet-500 outline-none disabled:opacity-60"
17871
+ }
17872
+ ),
17873
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(
17874
+ "button",
17875
+ {
17876
+ type: "button",
17877
+ onClick: () => moveOutlineSection(i, -1),
17878
+ disabled: rowBusy || i === 0,
17879
+ title: "Move up",
17880
+ className: "w-7 h-7 flex items-center justify-center rounded-md border border-zinc-700 text-zinc-400 hover:text-zinc-100 hover:border-zinc-500 disabled:opacity-30 disabled:hover:text-zinc-400 disabled:hover:border-zinc-700 flex-shrink-0",
17881
+ children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(ChevronUpIcon2, {})
17882
+ }
17883
+ ),
17884
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(
17885
+ "button",
17886
+ {
17887
+ type: "button",
17888
+ onClick: () => moveOutlineSection(i, 1),
17889
+ disabled: rowBusy || i === sections.length - 1,
17890
+ title: "Move down",
17891
+ className: "w-7 h-7 flex items-center justify-center rounded-md border border-zinc-700 text-zinc-400 hover:text-zinc-100 hover:border-zinc-500 disabled:opacity-30 disabled:hover:text-zinc-400 disabled:hover:border-zinc-700 flex-shrink-0",
17892
+ children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(ChevronDownIcon2, {})
17893
+ }
17894
+ ),
17895
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(
17896
+ "button",
17897
+ {
17898
+ type: "button",
17899
+ onClick: () => toggleSectionApproved(i),
17900
+ disabled: rowBusy,
17901
+ title: s.approved ? "Marked reviewed" : "Mark as reviewed",
17902
+ className: cn(
17903
+ "w-7 h-7 flex items-center justify-center rounded-md border flex-shrink-0 disabled:opacity-40",
17904
+ s.approved ? "border-emerald-600/50 bg-emerald-950/40 text-emerald-300" : "border-zinc-700 text-zinc-500 hover:text-zinc-300 hover:border-zinc-500"
17905
+ ),
17906
+ children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(CheckIcon2, {})
17907
+ }
17908
+ )
17909
+ ] }, i);
17910
+ }),
17680
17911
  sections.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: "text-xs text-zinc-500", children: "No outline sections were returned; you can still build the report." })
17681
17912
  ] }),
17913
+ rowError && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: "mt-2 text-xs text-red-400/90", children: rowError }),
17682
17914
  approveError && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: "mt-3 text-xs text-red-400/90", children: approveError }),
17683
17915
  /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("div", { className: "mt-4 flex items-center justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)(
17684
17916
  "button",