@anthusai/papyrus 5.43.0 → 5.45.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/amplify/functions/category-action/handler.ts +2 -1
- package/amplify/functions/model-attachment-upload/handler.ts +1 -0
- package/amplify/functions/monitoring-view/schema.js +16 -0
- package/amplify/functions/monitoring-view/schema.ts +16 -0
- package/amplify/functions/procedure-action/handler.ts +2 -10
- package/amplify/functions/proposal-actions/proposals.py +20 -3
- package/amplify/plugins/reader-steering/function/handler.py +1 -3
- package/amplify/plugins/reader-steering/function/moderation.py +19 -0
- package/bin/papyrus-infra.mjs +21 -1
- package/components/dev-sandbox-editor-sign-in.tsx +2 -2
- package/components/monitoring-overview-view.tsx +143 -21
- package/components/monitoring-panel.tsx +64 -4
- package/components/news-desk-client-provider.tsx +24 -3
- package/components/news-desk-page.tsx +2 -1
- package/components/news-desk-taxonomy-client.ts +2 -1
- package/components/newsroom-access-gate.tsx +7 -5
- package/components/newsroom-client-shell.tsx +2 -1
- package/components/newsroom-ops-overview.tsx +6 -1
- package/components/newsroom-ops-shell.tsx +1 -1
- package/components/newsroom-organizer.css +48 -0
- package/components/newsroom-references-view.tsx +183 -24
- package/components/notification-center.tsx +345 -63
- package/components/papyrus-console-shell.tsx +2 -1
- package/components/proposals-panel.tsx +21 -24
- package/components/proposals-view.tsx +4 -2
- package/components/reference-feed.tsx +469 -0
- package/components/reference-review-card.tsx +90 -76
- package/components/references-page-loading.tsx +61 -0
- package/components/references-prefetch.ts +47 -0
- package/components/review-rating-grid.tsx +164 -0
- package/components/topic-steering-workspace.tsx +32 -8
- package/infra/amplify-app-shell.js +18 -2
- package/infra/amplify-app-shell.ts +18 -2
- package/infra/chat-stack.js +222 -0
- package/infra/chat-stack.ts +250 -0
- package/infra/chat.test.js +142 -0
- package/infra/chat.test.ts +151 -0
- package/infra/index.js +1 -0
- package/infra/site-config.js +58 -1
- package/infra/site-config.ts +78 -1
- package/lib/category-repository.ts +4 -1
- package/lib/local-preview-feed-fixture.ts +43 -0
- package/lib/local-preview-synthetic-rejects.ts +41 -0
- package/lib/monitoring-client.ts +29 -2
- package/lib/monitoring-overview.ts +52 -1
- package/lib/monitoring-paging.ts +58 -0
- package/lib/newsroom-chat-identity.ts +2 -1
- package/lib/newsroom-organizer-nav.ts +1 -0
- package/lib/proposals-client.ts +29 -0
- package/lib/reader-subject.ts +3 -2
- package/lib/reference-feed-cache.ts +133 -0
- package/lib/reference-feed-ranking.ts +191 -0
- package/lib/reference-preview.ts +112 -0
- package/lib/review-client.ts +38 -1
- package/lib/review-drafts.ts +231 -0
- package/lib/review-fixture.ts +36 -2
- package/lib/review-requests.ts +64 -24
- package/lib/staff-groups.ts +23 -0
- package/lib/staging-gate.ts +2 -2
- package/package.json +14 -1
- package/routes.manifest.json +1 -1
|
@@ -4,7 +4,7 @@ import type { PrimingPanelProps } from "cyclotron/components/priming-panel";
|
|
|
4
4
|
import { ReferenceAddEntry } from "./reference-add-entry";
|
|
5
5
|
import { ReferenceCurationControls, useReferenceImport } from "./reference-curation-controls";
|
|
6
6
|
|
|
7
|
-
import { ExternalLinkIcon } from "lucide-react";
|
|
7
|
+
import { ExternalLinkIcon, LayoutGridIcon, ListIcon, PlusIcon } from "lucide-react";
|
|
8
8
|
import { usePathname } from "next/navigation";
|
|
9
9
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
10
10
|
import { Badge } from "./ui/badge";
|
|
@@ -42,8 +42,17 @@ import {
|
|
|
42
42
|
import { normalizeReferenceCurationStatus, referenceReasonCode, type ReferenceRejectionReasonCode } from "../lib/reference-policy";
|
|
43
43
|
import { newsroomListRowClassName } from "../lib/newsroom-list-selection";
|
|
44
44
|
import { ReferenceSourcePreview } from "./reference-source-preview";
|
|
45
|
+
import { FEED_SURFACE_PROPS, FEED_SURFACE_STYLE, ReferenceFeed } from "./reference-feed";
|
|
46
|
+
import { partitionReferenceFeed, type ReferenceFeedTabKey } from "../lib/reference-feed-ranking";
|
|
47
|
+
import { referencePreviewsByLineage, type ReferencePreview } from "../lib/reference-preview";
|
|
48
|
+
import { isLocalPreviewEnabled } from "../lib/local-preview";
|
|
49
|
+
import { chooseSyntheticRejects, withSyntheticRejects } from "../lib/local-preview-synthetic-rejects";
|
|
50
|
+
import { cn } from "../lib/utils";
|
|
51
|
+
import { getKanbusTheme, SITE_BRAND } from "../lib/site-brand";
|
|
52
|
+
import { useResolvedPapyrusTheme } from "./use-resolved-papyrus-theme";
|
|
45
53
|
import {
|
|
46
54
|
ReviewCard,
|
|
55
|
+
predictionFromDecision,
|
|
47
56
|
ReviewQueueBar,
|
|
48
57
|
useQueueGestures,
|
|
49
58
|
type CardPrediction,
|
|
@@ -119,8 +128,14 @@ type NewsroomReferencesViewProps = {
|
|
|
119
128
|
onReview: (reference: ReferenceRecord, action: ReferenceCurationAction, options?: ReferenceReviewOptions) => Promise<void> | void;
|
|
120
129
|
referenceAttachments?: ReferenceAttachmentRecord[];
|
|
121
130
|
references: ReferenceRecord[];
|
|
131
|
+
/** True while the References are still being read: the feed shows card skeletons instead of an empty page. */
|
|
132
|
+
loading?: boolean;
|
|
133
|
+
/** The last view this browser saved. Shown, read only, until the live read arrives. */
|
|
134
|
+
savedCopy?: { references: ReferenceRecord[]; previews: Array<[string, ReferencePreview]>; decisions: Array<[string, RelevanceDecisionView]> } | null;
|
|
122
135
|
};
|
|
123
136
|
|
|
137
|
+
type ReferenceView = "feed" | "list";
|
|
138
|
+
|
|
124
139
|
type ReferenceListFilter = ReferenceStatusFilter | "needs_review";
|
|
125
140
|
|
|
126
141
|
const NEEDS_REVIEW_FILTER: { key: ReferenceListFilter; label: string } = { key: "needs_review", label: "Needs review" };
|
|
@@ -269,10 +284,7 @@ function summaryOf(reference: ReferenceRecord): string | null {
|
|
|
269
284
|
}
|
|
270
285
|
|
|
271
286
|
function cardPrediction(decision: RelevanceDecisionView | undefined, predictionState: PredictionState): CardPrediction {
|
|
272
|
-
if (decision)
|
|
273
|
-
const positive = decision.positiveLabel ?? "include";
|
|
274
|
-
return { state: "ready", choice: decision.label === positive ? "accept" : "reject", confidence: decision.confidence };
|
|
275
|
-
}
|
|
287
|
+
if (decision) return predictionFromDecision(decision);
|
|
276
288
|
if (predictionState === "loading") return { state: "loading" };
|
|
277
289
|
if (predictionState === "error") return { state: "error" };
|
|
278
290
|
return { state: "none" };
|
|
@@ -444,7 +456,7 @@ export function NewsroomReferencesView({
|
|
|
444
456
|
priming,
|
|
445
457
|
cyclotronStatus,
|
|
446
458
|
cyclotronPriming,
|
|
447
|
-
decisions,
|
|
459
|
+
decisions: liveDecisions,
|
|
448
460
|
humanCuratedReferenceLineageIds,
|
|
449
461
|
delegatedCurations,
|
|
450
462
|
shadowAgreement = null,
|
|
@@ -463,9 +475,14 @@ export function NewsroomReferencesView({
|
|
|
463
475
|
initialReferenceLineageId = null,
|
|
464
476
|
onReview,
|
|
465
477
|
referenceAttachments = [],
|
|
466
|
-
references,
|
|
478
|
+
references: liveReferences,
|
|
479
|
+
loading = false,
|
|
480
|
+
savedCopy = null,
|
|
467
481
|
}: NewsroomReferencesViewProps) {
|
|
468
482
|
const pathname = usePathname();
|
|
483
|
+
// The portaled mobile sheet sits outside the newsroom root, so it carries the theme attributes itself (same as useNewsroomThemeAttributes).
|
|
484
|
+
const themeMode = useResolvedPapyrusTheme();
|
|
485
|
+
const themeAttributes = { "data-kanbus-theme": getKanbusTheme(SITE_BRAND), "data-color-mode": themeMode };
|
|
469
486
|
const sessionImport = useReferenceImport(disabled);
|
|
470
487
|
const [importedCount, setImportedCount] = useState(0);
|
|
471
488
|
const isMobileDetail = useMediaQuery("(max-width: 767px)");
|
|
@@ -475,7 +492,66 @@ export function NewsroomReferencesView({
|
|
|
475
492
|
);
|
|
476
493
|
const routeLineageId = pathname ? pathnameLineageId ?? "" : initialReferenceLineageId ?? "";
|
|
477
494
|
|
|
495
|
+
// Until the live read arrives, a saved copy of the last view fills the page. It is display only.
|
|
496
|
+
const showingSavedCopy = loading && !liveReferences.length && Boolean(savedCopy?.references.length);
|
|
497
|
+
const references = showingSavedCopy ? savedCopy!.references : liveReferences;
|
|
498
|
+
const baseDecisions = useMemo(
|
|
499
|
+
() => (showingSavedCopy && !liveDecisions?.size ? new Map(savedCopy!.decisions) : liveDecisions),
|
|
500
|
+
[liveDecisions, savedCopy, showingSavedCopy],
|
|
501
|
+
);
|
|
502
|
+
// Preview only: ?feedSynthRejects=N makes the N weakest Accept predictions into made-up Rejects (the page says so).
|
|
503
|
+
const synthRejectCount = useMemo(() => {
|
|
504
|
+
if (typeof window === "undefined" || !isLocalPreviewEnabled()) return 0;
|
|
505
|
+
const requested = Number(new URLSearchParams(window.location.search).get("feedSynthRejects"));
|
|
506
|
+
return Number.isInteger(requested) && requested > 0 ? requested : 0;
|
|
507
|
+
}, []);
|
|
508
|
+
const syntheticChoice = useRef<string[] | null>(null);
|
|
509
|
+
if (synthRejectCount && syntheticChoice.current === null && baseDecisions?.size && references.length) {
|
|
510
|
+
syntheticChoice.current = chooseSyntheticRejects(
|
|
511
|
+
baseDecisions,
|
|
512
|
+
new Set(references.filter((reference) => normalizeReferenceCurationStatus(reference.curationStatus) === "pending").map(referenceLineageId)),
|
|
513
|
+
synthRejectCount,
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
const synthetic = useMemo(
|
|
517
|
+
() => (synthRejectCount && syntheticChoice.current ? withSyntheticRejects(baseDecisions, syntheticChoice.current) : null),
|
|
518
|
+
[baseDecisions, synthRejectCount],
|
|
519
|
+
);
|
|
520
|
+
const decisions = synthetic?.decisions ?? baseDecisions;
|
|
521
|
+
const previews = useMemo(() => {
|
|
522
|
+
const live = referencePreviewsByLineage(referenceAttachments);
|
|
523
|
+
return showingSavedCopy && !live.size ? new Map(savedCopy!.previews) : live;
|
|
524
|
+
}, [referenceAttachments, savedCopy, showingSavedCopy]);
|
|
525
|
+
const [view, setView] = useState<ReferenceView>("feed");
|
|
526
|
+
const [addOpen, setAddOpen] = useState(false);
|
|
527
|
+
const [feedTab, setFeedTab] = useState<ReferenceFeedTabKey>("feed");
|
|
528
|
+
const [visitRated, setVisitRated] = useState<ReadonlySet<string>>(() => new Set());
|
|
529
|
+
const [mountedAt] = useState(() => Date.now());
|
|
530
|
+
const markVisitRated = useCallback((lineageId: string) => {
|
|
531
|
+
setVisitRated((current) => (current.has(lineageId) ? current : new Set(current).add(lineageId)));
|
|
532
|
+
}, []);
|
|
533
|
+
// Preview only: ?feedTau=<days> stands in for the learned freshness period, to review the Earlier section on a young corpus.
|
|
534
|
+
const tauDaysOverride = useMemo(() => {
|
|
535
|
+
if (typeof window === "undefined" || !isLocalPreviewEnabled()) return null;
|
|
536
|
+
const requested = Number(new URLSearchParams(window.location.search).get("feedTau"));
|
|
537
|
+
return Number.isFinite(requested) && requested > 0 ? requested : null;
|
|
538
|
+
}, []);
|
|
539
|
+
|
|
540
|
+
// Preview only: ?feedState=loading holds the page in its loading state, to review the card skeletons.
|
|
541
|
+
const previewSkeleton = useMemo(
|
|
542
|
+
() => typeof window !== "undefined" && isLocalPreviewEnabled() && new URLSearchParams(window.location.search).get("feedState") === "loading",
|
|
543
|
+
[],
|
|
544
|
+
);
|
|
545
|
+
|
|
478
546
|
const canonicalReferences = useMemo(() => selectCanonicalReferenceRecords(references), [references]);
|
|
547
|
+
const partition = useMemo(
|
|
548
|
+
() => partitionReferenceFeed(canonicalReferences, decisions, { now: mountedAt, visitRated, tauDaysOverride }),
|
|
549
|
+
[canonicalReferences, decisions, mountedAt, tauDaysOverride, visitRated],
|
|
550
|
+
);
|
|
551
|
+
const feedOrderIds = useMemo(
|
|
552
|
+
() => (feedTab === "feed" ? [...partition.feed, ...partition.earlier] : feedTab === "rated" ? partition.rated : partition.earlier).map((item) => item.lineageId),
|
|
553
|
+
[feedTab, partition],
|
|
554
|
+
);
|
|
479
555
|
const statusCounts = useMemo(() => countReferencesByStatus(canonicalReferences), [canonicalReferences]);
|
|
480
556
|
|
|
481
557
|
const [statusFilter, setStatusFilter] = useState<ReferenceListFilter>(routeLineageId ? "all" : "pending");
|
|
@@ -506,14 +582,14 @@ export function NewsroomReferencesView({
|
|
|
506
582
|
// list, but keeps its place in the queue until they move on, so "3 of 29" does not jump under them.
|
|
507
583
|
const queueRef = useRef<string[]>([]);
|
|
508
584
|
const queue = useMemo(() => {
|
|
509
|
-
const ids = filteredReferences.map(referenceLineageId);
|
|
585
|
+
const ids = view === "feed" ? [...feedOrderIds] : filteredReferences.map(referenceLineageId);
|
|
510
586
|
const open = selectedReference ? referenceLineageId(selectedReference) : "";
|
|
511
587
|
if (open && !ids.includes(open)) {
|
|
512
588
|
const before = queueRef.current.indexOf(open);
|
|
513
589
|
if (before >= 0) ids.splice(Math.min(before, ids.length), 0, open);
|
|
514
590
|
}
|
|
515
591
|
return ids;
|
|
516
|
-
}, [filteredReferences, selectedReference]);
|
|
592
|
+
}, [feedOrderIds, filteredReferences, selectedReference, view]);
|
|
517
593
|
useEffect(() => { queueRef.current = queue; }, [queue]);
|
|
518
594
|
const [caughtUp, setCaughtUp] = useState(false);
|
|
519
595
|
const selectedIndex = selectedReference ? queue.indexOf(referenceLineageId(selectedReference)) : -1;
|
|
@@ -584,9 +660,21 @@ export function NewsroomReferencesView({
|
|
|
584
660
|
|
|
585
661
|
const runReview = (action: ReferenceCurationAction, options?: ReferenceReviewOptions) => {
|
|
586
662
|
if (!selectedReference) return;
|
|
663
|
+
if (action === "accept" || action === "reject") markVisitRated(referenceLineageId(selectedReference));
|
|
587
664
|
return onReview(selectedReference, action, options);
|
|
588
665
|
};
|
|
589
666
|
|
|
667
|
+
const rateFromFeed = async (reference: ReferenceRecord, choice: ReviewChoice, reasonCode: ReferenceRejectionReasonCode | null) => {
|
|
668
|
+
const decision = decisions?.get(referenceLineageId(reference));
|
|
669
|
+
await onReview(reference, choice, {
|
|
670
|
+
reasonCode: choice === "reject" ? reasonCode : null,
|
|
671
|
+
...(decision ? { decisionRelationId: decision.decisionRelationId, shareable: false } : {}),
|
|
672
|
+
});
|
|
673
|
+
};
|
|
674
|
+
const feedDisabledReason = disabled
|
|
675
|
+
? "Editor access is required to change this reference."
|
|
676
|
+
: showingSavedCopy ? "Confirming your sign-in. You can answer in a moment." : null;
|
|
677
|
+
|
|
590
678
|
const caughtUpPanel = (
|
|
591
679
|
<div className="space-y-2 p-6 text-center" data-review-caught-up>
|
|
592
680
|
<h3 className="text-lg font-semibold">All caught up</h3>
|
|
@@ -608,23 +696,64 @@ export function NewsroomReferencesView({
|
|
|
608
696
|
data-detail-open={selectedReference || routeLineageId ? "true" : "false"}
|
|
609
697
|
>
|
|
610
698
|
<div className="flex min-h-0 min-w-0 flex-1 flex-col gap-4 md:overflow-hidden">
|
|
611
|
-
<div className="shrink-0
|
|
612
|
-
<
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
699
|
+
<div className="flex shrink-0 items-center justify-between gap-3" {...FEED_SURFACE_PROPS}>
|
|
700
|
+
<div className="min-w-0 space-y-0.5">
|
|
701
|
+
<h2 className="text-2xl font-bold tracking-tight">References</h2>
|
|
702
|
+
<p className="hidden text-sm text-muted-foreground sm:block">
|
|
703
|
+
{view === "feed" ? "A feed ranked by what you are most likely to accept." : "Review source intake before it becomes accepted evidence."}
|
|
704
|
+
</p>
|
|
705
|
+
</div>
|
|
706
|
+
<div className="flex items-center gap-2">
|
|
707
|
+
<button
|
|
708
|
+
aria-controls="reference-add-panel"
|
|
709
|
+
aria-expanded={addOpen}
|
|
710
|
+
aria-label="Add a reference and prediction activity"
|
|
711
|
+
className={cn("inline-flex min-h-10 items-center justify-center gap-1.5 rounded-full px-3 text-sm font-medium outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring", addOpen ? "bg-[var(--feed-control)] text-foreground" : "bg-[var(--feed-card)] text-muted-foreground hover:text-foreground")}
|
|
712
|
+
data-reference-add-toggle
|
|
713
|
+
onClick={() => setAddOpen((open) => !open)}
|
|
714
|
+
title="Add a reference and prediction activity"
|
|
715
|
+
type="button"
|
|
716
|
+
>
|
|
717
|
+
<PlusIcon aria-hidden="true" className="size-4" />
|
|
718
|
+
<span className="hidden sm:inline">Add</span>
|
|
719
|
+
</button>
|
|
720
|
+
<div aria-label="Reference view" className="inline-flex rounded-full bg-[var(--feed-card)] p-1" role="group">
|
|
721
|
+
{([["feed", "Feed", LayoutGridIcon], ["list", "List", ListIcon]] as const).map(([key, label, Icon]) => (
|
|
722
|
+
<button
|
|
723
|
+
aria-label={label}
|
|
724
|
+
aria-pressed={view === key}
|
|
725
|
+
className={cn(
|
|
726
|
+
"inline-flex min-h-8 items-center justify-center gap-1.5 rounded-full px-3 text-sm font-medium outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring",
|
|
727
|
+
view === key ? "bg-[var(--feed-control)] text-foreground" : "text-muted-foreground hover:text-foreground",
|
|
728
|
+
)}
|
|
729
|
+
data-reference-view={key}
|
|
730
|
+
key={key}
|
|
731
|
+
onClick={() => { setView(key); setCaughtUp(false); }}
|
|
732
|
+
title={label}
|
|
733
|
+
type="button"
|
|
734
|
+
>
|
|
735
|
+
<Icon aria-hidden="true" className="size-4" />
|
|
736
|
+
<span className="hidden sm:inline">{label}</span>
|
|
737
|
+
</button>
|
|
738
|
+
))}
|
|
739
|
+
</div>
|
|
740
|
+
</div>
|
|
616
741
|
</div>
|
|
617
|
-
{
|
|
742
|
+
{synthetic?.changed ? (
|
|
743
|
+
<p className="rounded-2xl bg-[var(--feed-card)] p-3 text-sm" data-preview-synthetic role="status" {...FEED_SURFACE_PROPS}>
|
|
744
|
+
Preview only: {synthetic.changed} of these predictions are made up to show the Reject end of the feed. Real data has none yet.
|
|
745
|
+
</p>
|
|
746
|
+
) : null}
|
|
747
|
+
{predictionState === "loading" && view === "list" ? <p role="status">Loading predictions…</p> : null}
|
|
618
748
|
{predictionState === "error" ? (
|
|
619
|
-
<div role="alert" className="space-y-2 rounded-
|
|
749
|
+
<div role="alert" className="space-y-2 rounded-2xl bg-[var(--feed-card)] p-4" {...FEED_SURFACE_PROPS}>
|
|
620
750
|
<p>Predictions unavailable. {predictionError}</p>
|
|
621
751
|
<p className="text-sm">You can still review references. Existing suggestions may be out of date.</p>
|
|
622
752
|
{onRetryPredictions ? <Button onClick={onRetryPredictions} size="sm" type="button" variant="outline">Retry predictions</Button> : null}
|
|
623
753
|
</div>
|
|
624
754
|
) : null}
|
|
625
|
-
<
|
|
626
|
-
<
|
|
627
|
-
<div className="mt-3 space-y-4">
|
|
755
|
+
<div className="shrink-0 overflow-y-auto rounded-[20px] bg-[var(--feed-card)] p-4 text-sm" data-feed-flat="" data-feed-surface="" hidden={!addOpen} id="reference-add-panel" style={{ ...FEED_SURFACE_STYLE, maxHeight: "45dvh", overflowY: "auto" }}>
|
|
756
|
+
<div className="space-y-4">
|
|
628
757
|
<ReferenceLiveAgreement agreement={shadowAgreement} />
|
|
629
758
|
<ReferenceAddEntry
|
|
630
759
|
importOptions={disabled ? null : priming ?? sessionImport?.panel}
|
|
@@ -641,8 +770,31 @@ export function NewsroomReferencesView({
|
|
|
641
770
|
</div>
|
|
642
771
|
) : null}
|
|
643
772
|
</div>
|
|
644
|
-
</
|
|
773
|
+
</div>
|
|
645
774
|
|
|
775
|
+
{view === "feed" ? (
|
|
776
|
+
<ScrollArea className="min-h-0 flex-1" data-reference-feed-scroll>
|
|
777
|
+
<div className="pb-6 pr-1">
|
|
778
|
+
<ReferenceFeed
|
|
779
|
+
disabledReason={feedDisabledReason}
|
|
780
|
+
loading={previewSkeleton || (loading && !references.length)}
|
|
781
|
+
now={mountedAt}
|
|
782
|
+
onOpen={selectReference}
|
|
783
|
+
onRate={rateFromFeed}
|
|
784
|
+
onTabChange={(next) => { setFeedTab(next); setCaughtUp(false); }}
|
|
785
|
+
onVisitRated={markVisitRated}
|
|
786
|
+
partition={partition}
|
|
787
|
+
predictionLoading={predictionState === "loading"}
|
|
788
|
+
previews={previews}
|
|
789
|
+
selectedLineageId={selectedLineageId}
|
|
790
|
+
stale={showingSavedCopy || (loading && references.length > 0)}
|
|
791
|
+
tab={feedTab}
|
|
792
|
+
visitRated={visitRated}
|
|
793
|
+
/>
|
|
794
|
+
</div>
|
|
795
|
+
</ScrollArea>
|
|
796
|
+
) : (
|
|
797
|
+
<>
|
|
646
798
|
<Tabs
|
|
647
799
|
className="shrink-0"
|
|
648
800
|
defaultValue="pending"
|
|
@@ -718,15 +870,22 @@ export function NewsroomReferencesView({
|
|
|
718
870
|
)}
|
|
719
871
|
</div>
|
|
720
872
|
</ScrollArea>
|
|
873
|
+
</>
|
|
874
|
+
)}
|
|
721
875
|
</div>
|
|
722
876
|
|
|
723
877
|
<div
|
|
724
|
-
className=
|
|
878
|
+
className={cn(
|
|
879
|
+
"hidden min-h-0 w-full shrink-0 flex-col overflow-hidden rounded-[20px] bg-[var(--feed-card)] md:flex md:w-[min(100%,24rem)] lg:w-[min(100%,28rem)]",
|
|
880
|
+
view === "feed" && !selectedReference && "md:hidden",
|
|
881
|
+
)}
|
|
725
882
|
data-newsroom-list-detail-shell
|
|
726
883
|
data-news-desk-section="references"
|
|
727
884
|
data-detail-open={selectedReference ? "true" : "false"}
|
|
885
|
+
data-feed-flat=""
|
|
886
|
+
{...FEED_SURFACE_PROPS}
|
|
728
887
|
>
|
|
729
|
-
<div className="flex shrink-0 items-center justify-between gap-2
|
|
888
|
+
<div className="flex shrink-0 items-center justify-between gap-2 px-4 pt-3 pb-1">
|
|
730
889
|
<span className="text-sm font-medium text-foreground">Detail</span>
|
|
731
890
|
</div>
|
|
732
891
|
<div className="flex min-h-0 flex-1 flex-col" data-review-gestures onPointerDown={gestures.onPointerDown} onPointerUp={gestures.onPointerUp} style={gestures.style}>
|
|
@@ -768,12 +927,12 @@ export function NewsroomReferencesView({
|
|
|
768
927
|
}}
|
|
769
928
|
open={(mobileDetailOpen && Boolean(selectedReference)) || caughtUp}
|
|
770
929
|
>
|
|
771
|
-
<SheetContent className="gap-0 p-0" side="bottom">
|
|
930
|
+
<SheetContent className="gap-0 rounded-t-[24px] bg-[var(--feed-card)] p-0" data-feed-flat="" data-feed-surface="" side="bottom" {...themeAttributes}>
|
|
772
931
|
<SheetHeader className="border-b border-border px-4 py-3">
|
|
773
932
|
<SheetTitle className="text-left text-base">Reference</SheetTitle>
|
|
774
933
|
</SheetHeader>
|
|
775
934
|
{selectedReference ? (
|
|
776
|
-
<div data-review-gestures onPointerDown={gestures.onPointerDown} onPointerUp={gestures.onPointerUp} style={gestures.style}><ScrollArea className="max-h-[70dvh]">
|
|
935
|
+
<div className="min-w-0" data-review-gestures onPointerDown={gestures.onPointerDown} onPointerUp={gestures.onPointerUp} style={gestures.style}><ScrollArea className="max-h-[70dvh]">
|
|
777
936
|
<ReferenceDetailPanel
|
|
778
937
|
key={referenceLineageId(selectedReference)}
|
|
779
938
|
predictionState={predictionState}
|