@anthusai/papyrus 2.0.2 → 3.0.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/plugins/editorial-checks/function/handler.py +11 -0
- package/amplify/plugins/editorial-checks/function/requirements.txt +1 -0
- package/amplify/plugins/editorial-checks/function/resource.js +43 -0
- package/amplify/plugins/editorial-checks/function/resource.ts +60 -0
- package/amplify/plugins/editorial-checks/papyrus.plugin.js +50 -0
- package/amplify/plugins/editorial-checks/papyrus.plugin.ts +63 -0
- package/amplify/plugins/editorial-checks/schema.js +94 -0
- package/amplify/plugins/editorial-checks/schema.ts +96 -0
- package/amplify/plugins/registry.js +2 -0
- package/amplify/plugins/registry.ts +2 -0
- package/components/editorial-checks-admin-panel.tsx +337 -0
- package/components/editorial-finding-card.tsx +162 -0
- package/components/editorial-findings-panel.tsx +91 -0
- package/components/editorial-preview-popover.tsx +103 -0
- package/components/markus-body-editor.tsx +213 -0
- package/components/markus-ir-preview.tsx +147 -6
- package/components/newsroom-article-editor.tsx +138 -11
- package/components/newsroom-board-view.tsx +2 -6
- package/components/newsroom-ops-shell.tsx +7 -3
- package/components/newsroom-organizer.css +57 -61
- package/components/newsroom-theme-fonts/broadsheet-green.css +10 -0
- package/components/newsroom-theme-fonts/broadsheet-green.tsx +6 -0
- package/components/newsroom-theme-fonts/newspaper-gothic.css +9 -0
- package/components/newsroom-theme-fonts/newspaper-gothic.tsx +6 -0
- package/components/newsroom-theme-fonts/night-desk.css +10 -0
- package/components/newsroom-theme-fonts/night-desk.tsx +6 -0
- package/components/newsroom-theme-fonts/refined-newsprint.css +11 -0
- package/components/newsroom-theme-fonts/refined-newsprint.tsx +6 -0
- package/components/newsroom-theme.css +39 -0
- package/components/newsroom-theme.tsx +33 -0
- package/components/topic-steering-workspace.tsx +19 -1
- package/components/use-editorial-checks.ts +131 -0
- package/lib/editorial-checks-backend.ts +16 -0
- package/lib/editorial-checks-client.ts +194 -0
- package/lib/editorial-checks-demo.ts +147 -0
- package/lib/editorial-checks-settings.ts +24 -0
- package/lib/editorial-checks.ts +178 -0
- package/lib/editorial-preview.ts +228 -0
- package/lib/site-brand.ts +17 -0
- package/package.json +34 -2
- package/routes.manifest.json +1 -1
- package/components/newsroom-fonts/playfair-display-700.ttf +0 -0
- package/components/newsroom-fonts/playfair-display-900.ttf +0 -0
- package/components/newsroom-fonts/playfair-display-OFL.txt +0 -93
- package/components/newsroom-fonts/plus-jakarta-sans-400.ttf +0 -0
- package/components/newsroom-fonts/plus-jakarta-sans-600.ttf +0 -0
- package/components/newsroom-fonts/plus-jakarta-sans-OFL.txt +0 -93
- package/components/newsroom-newsprint-board.css +0 -7
|
@@ -48,7 +48,17 @@ import {
|
|
|
48
48
|
import { getNewsroomNavHref } from "../lib/newsroom-nav";
|
|
49
49
|
import { SITE_BRAND } from "../lib/site-brand";
|
|
50
50
|
import { cn } from "../lib/utils";
|
|
51
|
+
import amplifyOutputs from "papyrus-amplify-outputs";
|
|
52
|
+
import { applyReplacement, editorialChecksEnabled, inlineFindings, visibleFindings } from "../lib/editorial-checks";
|
|
53
|
+
import { graphqlEditorialBackend } from "../lib/editorial-checks-client";
|
|
54
|
+
import { demoEditorialBackend } from "../lib/editorial-checks-demo";
|
|
55
|
+
import type { PluginOutputs } from "../lib/plugin-settings";
|
|
56
|
+
import type { FindingActions } from "./editorial-finding-card";
|
|
57
|
+
import { EditorialFindingsPanel } from "./editorial-findings-panel";
|
|
58
|
+
import { EditorialPreviewPopover, type PreviewPopoverTarget } from "./editorial-preview-popover";
|
|
59
|
+
import { MarkusBodyEditor, type MarkusBodyEditorHandle } from "./markus-body-editor";
|
|
51
60
|
import { MarkusIrPreview } from "./markus-ir-preview";
|
|
61
|
+
import { useEditorialChecks } from "./use-editorial-checks";
|
|
52
62
|
import { useOptionalNewsDeskClient } from "./news-desk-client-provider";
|
|
53
63
|
import { NewsDeskAccessGate } from "./newsroom-access-gate";
|
|
54
64
|
import { NewsroomOpsShell, NewsroomOpsStatusBanner } from "./newsroom-ops-shell";
|
|
@@ -118,6 +128,9 @@ export function NewsroomArticleEditor({ articleId, demo, embedded = false }: { a
|
|
|
118
128
|
const [notice, setNotice] = useState<Notice | null>(null);
|
|
119
129
|
const [conflictOpen, setConflictOpen] = useState(false);
|
|
120
130
|
const [unpublishOpen, setUnpublishOpen] = useState(false);
|
|
131
|
+
const [publishWarningOpen, setPublishWarningOpen] = useState(false);
|
|
132
|
+
const [previewPopover, setPreviewPopover] = useState<PreviewPopoverTarget | null>(null);
|
|
133
|
+
const previewRef = useRef<HTMLDivElement | null>(null);
|
|
121
134
|
const [mobileTab, setMobileTab] = useState<MobileTab>("preview");
|
|
122
135
|
const [focusedReferenceId, setFocusedReferenceId] = useState<string | null>(null);
|
|
123
136
|
const [lineageId, setLineageId] = useState<string | null>(null);
|
|
@@ -133,7 +146,7 @@ export function NewsroomArticleEditor({ articleId, demo, embedded = false }: { a
|
|
|
133
146
|
const [imageError, setImageError] = useState<string | null>(null);
|
|
134
147
|
|
|
135
148
|
const frontMatterRef = useRef<HTMLTextAreaElement | null>(null);
|
|
136
|
-
const bodyRef = useRef<
|
|
149
|
+
const bodyRef = useRef<MarkusBodyEditorHandle | null>(null);
|
|
137
150
|
const imageInputRef = useRef<HTMLInputElement | null>(null);
|
|
138
151
|
const mediaBackend = useMemo(() => resolveMediaBackend(previewMode), [previewMode]);
|
|
139
152
|
const validationSequence = useRef(0);
|
|
@@ -205,6 +218,21 @@ export function NewsroomArticleEditor({ articleId, demo, embedded = false }: { a
|
|
|
205
218
|
|
|
206
219
|
const frontMatterYaml = editor?.frontMatterYaml ?? null;
|
|
207
220
|
const bodyMarkus = editor?.bodyMarkus ?? null;
|
|
221
|
+
const editorialBackend = useMemo(
|
|
222
|
+
() => (demo ? demoEditorialBackend : !previewMode && editorialChecksEnabled(amplifyOutputs as PluginOutputs) ? graphqlEditorialBackend : null),
|
|
223
|
+
[demo, previewMode],
|
|
224
|
+
);
|
|
225
|
+
const editorial = useEditorialChecks({
|
|
226
|
+
backend: editorialBackend,
|
|
227
|
+
body: bodyMarkus,
|
|
228
|
+
section: editor?.section ?? "",
|
|
229
|
+
itemId: editor?.id ?? null,
|
|
230
|
+
});
|
|
231
|
+
const editorialOpen = useMemo(
|
|
232
|
+
() => (editorial.result ? visibleFindings(editorial.result.findings, editorial.dismissed) : []),
|
|
233
|
+
[editorial.result, editorial.dismissed],
|
|
234
|
+
);
|
|
235
|
+
const editorialMarks = useMemo(() => inlineFindings(editorialOpen), [editorialOpen]);
|
|
208
236
|
|
|
209
237
|
useEffect(() => {
|
|
210
238
|
if (frontMatterYaml === null || bodyMarkus === null) return;
|
|
@@ -381,7 +409,45 @@ export function NewsroomArticleEditor({ articleId, demo, embedded = false }: { a
|
|
|
381
409
|
}
|
|
382
410
|
}, [aliases, backend, demo, editor]);
|
|
383
411
|
|
|
412
|
+
const requestPublish = () => {
|
|
413
|
+
if (editorial.openWarnings.length > 0) {
|
|
414
|
+
setPublishWarningOpen(true);
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
void publish();
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
const applyEditorialRewrite = (
|
|
421
|
+
option: { span: { start: number; end: number }; replacement: string; expected: string },
|
|
422
|
+
finding: Parameters<typeof editorial.fixed>[0] | null,
|
|
423
|
+
) => {
|
|
424
|
+
if (!editor) return;
|
|
425
|
+
const next = applyReplacement(editor.bodyMarkus, option.span, option.expected, option.replacement);
|
|
426
|
+
if (next === null) {
|
|
427
|
+
setNotice({ tone: "info", text: "That text changed since the check. Check again, then apply the rewrite." });
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
patchEditor({ bodyMarkus: next });
|
|
431
|
+
if (finding) editorial.fixed(finding);
|
|
432
|
+
setPreviewPopover(null);
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
const editorialActions: FindingActions = {
|
|
436
|
+
onSelect: (finding) => {
|
|
437
|
+
editorial.setActiveFindingId(finding.id);
|
|
438
|
+
if (editorial.inlineResult && finding.excerpt) bodyRef.current?.reveal(finding.span.start, finding.span.end);
|
|
439
|
+
},
|
|
440
|
+
onDismiss: (finding, reason) => {
|
|
441
|
+
editorial.dismiss(finding, reason);
|
|
442
|
+
setPreviewPopover(null);
|
|
443
|
+
},
|
|
444
|
+
onAccept: editorial.accept,
|
|
445
|
+
onSuggest: editorial.suggest,
|
|
446
|
+
onApply: applyEditorialRewrite,
|
|
447
|
+
};
|
|
448
|
+
|
|
384
449
|
const publish = async () => {
|
|
450
|
+
setPublishWarningOpen(false);
|
|
385
451
|
if (!editor) return;
|
|
386
452
|
let id = editor.id;
|
|
387
453
|
if (editor.dirty || id === null) {
|
|
@@ -551,7 +617,7 @@ export function NewsroomArticleEditor({ articleId, demo, embedded = false }: { a
|
|
|
551
617
|
<Button
|
|
552
618
|
data-newsroom-article-publish
|
|
553
619
|
disabled={publishBlocked}
|
|
554
|
-
onClick={
|
|
620
|
+
onClick={requestPublish}
|
|
555
621
|
size="sm"
|
|
556
622
|
type="button"
|
|
557
623
|
>
|
|
@@ -714,18 +780,29 @@ export function NewsroomArticleEditor({ articleId, demo, embedded = false }: { a
|
|
|
714
780
|
{imageError}
|
|
715
781
|
</p>
|
|
716
782
|
) : null}
|
|
717
|
-
<
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
783
|
+
<MarkusBodyEditor
|
|
784
|
+
activeFindingId={editorial.activeFindingId}
|
|
785
|
+
findings={editorialMarks}
|
|
786
|
+
onChange={(value) => patchEditor({ bodyMarkus: value })}
|
|
787
|
+
onFindingClick={editorial.setActiveFindingId}
|
|
788
|
+
onSelectionChange={editorial.setSelection}
|
|
722
789
|
ref={bodyRef}
|
|
723
|
-
rows={28}
|
|
724
|
-
spellCheck={false}
|
|
725
790
|
value={editor.bodyMarkus}
|
|
726
791
|
/>
|
|
727
792
|
</div>
|
|
728
793
|
|
|
794
|
+
{editorial.enabled ? (
|
|
795
|
+
<EditorialFindingsPanel
|
|
796
|
+
{...editorialActions}
|
|
797
|
+
activeFindingId={editorial.activeFindingId}
|
|
798
|
+
dismissed={editorial.dismissed}
|
|
799
|
+
onCheck={() => void editorial.check()}
|
|
800
|
+
result={editorial.result}
|
|
801
|
+
selection={editorial.selection}
|
|
802
|
+
status={editorial.status}
|
|
803
|
+
/>
|
|
804
|
+
) : null}
|
|
805
|
+
|
|
729
806
|
{validation.status === "unavailable" ? (
|
|
730
807
|
<NewsroomOpsStatusBanner tone="error">{validation.message}</NewsroomOpsStatusBanner>
|
|
731
808
|
) : null}
|
|
@@ -763,7 +840,7 @@ export function NewsroomArticleEditor({ articleId, demo, embedded = false }: { a
|
|
|
763
840
|
className={cn("min-w-0", mobileTab === "preview" ? "block" : "hidden")}
|
|
764
841
|
data-newsroom-article-preview-column
|
|
765
842
|
>
|
|
766
|
-
<div className="rounded-xl border border-border bg-card p-4" data-newsroom-article-preview>
|
|
843
|
+
<div className="relative rounded-xl border border-border bg-card p-4" data-newsroom-article-preview ref={previewRef}>
|
|
767
844
|
{(readFrontMatterText(editor.frontMatterYaml, FRONT_MATTER_SUBTITLE_KEY) || readFrontMatterText(editor.frontMatterYaml, FRONT_MATTER_BLURB_KEY)) ? (
|
|
768
845
|
<div className="newsroom-article-summary" data-newsroom-article-summary>
|
|
769
846
|
{readFrontMatterText(editor.frontMatterYaml, FRONT_MATTER_SUBTITLE_KEY) ? <p className="newsroom-article-subtitle">{readFrontMatterText(editor.frontMatterYaml, FRONT_MATTER_SUBTITLE_KEY)}</p> : null}
|
|
@@ -774,12 +851,40 @@ export function NewsroomArticleEditor({ articleId, demo, embedded = false }: { a
|
|
|
774
851
|
<p className="mb-2 text-xs text-muted-foreground">Showing the last valid version.</p>
|
|
775
852
|
) : null}
|
|
776
853
|
{bodyIr ? (
|
|
777
|
-
<MarkusIrPreview
|
|
854
|
+
<MarkusIrPreview
|
|
855
|
+
bodyIr={bodyIr}
|
|
856
|
+
editorial={
|
|
857
|
+
editorial.inlineResult
|
|
858
|
+
? {
|
|
859
|
+
result: editorial.inlineResult,
|
|
860
|
+
findings: editorialOpen,
|
|
861
|
+
activeFindingIds: previewPopover?.kind === "findings" ? previewPopover.findingIds : editorial.activeFindingId ? [editorial.activeFindingId] : [],
|
|
862
|
+
onOpenMark: (findingIds, anchor) => {
|
|
863
|
+
editorial.setActiveFindingId(findingIds[0] ?? null);
|
|
864
|
+
setPreviewPopover({ kind: "findings", findingIds, anchor: anchor.getBoundingClientRect() });
|
|
865
|
+
},
|
|
866
|
+
onSelectSource: (source, anchor) => setPreviewPopover({ kind: "selection", source, anchor }),
|
|
867
|
+
}
|
|
868
|
+
: undefined
|
|
869
|
+
}
|
|
870
|
+
imageUrls={imageUrls}
|
|
871
|
+
/>
|
|
778
872
|
) : (
|
|
779
873
|
<p className="text-sm text-muted-foreground">
|
|
780
874
|
{invalid ? "Fix the errors to see a preview." : "The preview appears once the markup is valid."}
|
|
781
875
|
</p>
|
|
782
876
|
)}
|
|
877
|
+
{previewPopover && editorial.enabled ? (
|
|
878
|
+
<EditorialPreviewPopover
|
|
879
|
+
actions={editorialActions}
|
|
880
|
+
body={editor.bodyMarkus}
|
|
881
|
+
container={previewRef.current}
|
|
882
|
+
findings={editorialOpen}
|
|
883
|
+
key={previewPopover.kind === "findings" ? previewPopover.findingIds.join() : `${previewPopover.source.start}-${previewPopover.source.end}`}
|
|
884
|
+
onClose={() => setPreviewPopover(null)}
|
|
885
|
+
target={previewPopover}
|
|
886
|
+
/>
|
|
887
|
+
) : null}
|
|
783
888
|
</div>
|
|
784
889
|
</div>
|
|
785
890
|
</div>
|
|
@@ -801,6 +906,28 @@ export function NewsroomArticleEditor({ articleId, demo, embedded = false }: { a
|
|
|
801
906
|
</DialogContent>
|
|
802
907
|
</Dialog>
|
|
803
908
|
|
|
909
|
+
<Dialog onOpenChange={setPublishWarningOpen} open={publishWarningOpen}>
|
|
910
|
+
<DialogContent>
|
|
911
|
+
<DialogHeader>
|
|
912
|
+
<DialogTitle>Publish with open editorial findings?</DialogTitle>
|
|
913
|
+
<DialogDescription>
|
|
914
|
+
{editorial.openWarnings.length === 1
|
|
915
|
+
? "One editorial finding is still open."
|
|
916
|
+
: `${editorial.openWarnings.length} editorial findings are still open.`}{" "}
|
|
917
|
+
Findings are advice: you can publish anyway.
|
|
918
|
+
</DialogDescription>
|
|
919
|
+
</DialogHeader>
|
|
920
|
+
<ul className="max-h-48 list-disc space-y-1 overflow-auto pl-5 text-sm" data-newsroom-article-publish-warnings>
|
|
921
|
+
{editorial.openWarnings.slice(0, 8).map((finding) => (
|
|
922
|
+
<li key={finding.id}>{finding.message}{finding.excerpt ? `: “${finding.excerpt}”` : ""}</li>
|
|
923
|
+
))}
|
|
924
|
+
</ul>
|
|
925
|
+
<DialogFooter>
|
|
926
|
+
<Button onClick={() => setPublishWarningOpen(false)} type="button" variant="outline">Keep editing</Button>
|
|
927
|
+
<Button data-newsroom-article-publish-anyway onClick={() => void publish()} type="button">Publish anyway</Button>
|
|
928
|
+
</DialogFooter>
|
|
929
|
+
</DialogContent>
|
|
930
|
+
</Dialog>
|
|
804
931
|
<Dialog onOpenChange={setUnpublishOpen} open={unpublishOpen}>
|
|
805
932
|
<DialogContent>
|
|
806
933
|
<DialogHeader>
|
|
@@ -4,9 +4,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
|
4
4
|
import Link from "next/link";
|
|
5
5
|
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
|
6
6
|
import { IssueCollection, IssueDetailPanel, IssueTypeFilter, issueTypeFromFilter, useBoardColumnState } from "@kanbus/ui";
|
|
7
|
-
import "
|
|
8
|
-
import "@kanbus/ui/styles/newsprint.css";
|
|
9
|
-
import "./newsroom-newsprint-board.css";
|
|
7
|
+
import "./newsroom-theme";
|
|
10
8
|
import { PlusIcon } from "lucide-react";
|
|
11
9
|
import { newsroomHref } from "../lib/newsroom-base-path";
|
|
12
10
|
import {
|
|
@@ -35,7 +33,6 @@ import { isLocalPreviewEnabled } from "../lib/local-preview";
|
|
|
35
33
|
import { NewsroomArticleEditor } from "./newsroom-article-editor";
|
|
36
34
|
import { NewsroomAssignmentDetail } from "./newsroom-assignment-detail";
|
|
37
35
|
import { NewsroomOpsShell, NewsroomOpsStatusBanner } from "./newsroom-ops-shell";
|
|
38
|
-
import { useResolvedPapyrusTheme } from "./use-resolved-papyrus-theme";
|
|
39
36
|
import { readLocalReaderSettings, subscribeReaderSettingsChanges } from "./reader-settings";
|
|
40
37
|
|
|
41
38
|
/** A board with a story or assignment open lives at `?open=<id>`, distinct from the standalone page for that record. */
|
|
@@ -61,7 +58,6 @@ export type NewsroomBoardSubject = "contentItem" | "assignment" | "desk";
|
|
|
61
58
|
export function NewsroomBoardView({ subject, deskId }: { subject: NewsroomBoardSubject; deskId?: string }) {
|
|
62
59
|
const session = useOptionalNewsDeskClient();
|
|
63
60
|
const allowed = canReadNewsroomBoard(session?.shell.phase);
|
|
64
|
-
const theme = useResolvedPapyrusTheme();
|
|
65
61
|
const [lowMotion, setLowMotion] = useState(false);
|
|
66
62
|
const [assignmentBoardIssues, setAssignmentBoardIssues] = useState<NativeBoardIssue[]>([]);
|
|
67
63
|
const [publishedVersions, setPublishedVersions] = useState<ContentItemVersionRecord[]>([]);
|
|
@@ -172,7 +168,7 @@ export function NewsroomBoardView({ subject, deskId }: { subject: NewsroomBoardS
|
|
|
172
168
|
</Link>
|
|
173
169
|
)}
|
|
174
170
|
</>}>
|
|
175
|
-
<div className="organizer-native-board
|
|
171
|
+
<div className="organizer-native-board">
|
|
176
172
|
{error && <NewsroomOpsStatusBanner tone="error">{error}</NewsroomOpsStatusBanner>}
|
|
177
173
|
{subject === "desk" && <IssueTypeFilter config={config} value={typeFilter} onChange={setTypeFilter} name="Record type" className="organizer-board-type-filter" />}
|
|
178
174
|
<div className="organizer-board-body" data-detail-open={Boolean(issue)} ref={boardBodyRef} onScrollCapture={handleBoardScroll}>
|
|
@@ -19,6 +19,7 @@ import { ProspectusAccountChooser, useProspectusAccountSummary } from "./prospec
|
|
|
19
19
|
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetTrigger } from "./ui/sheet";
|
|
20
20
|
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator } from "./ui/dropdown-menu";
|
|
21
21
|
import "./newsroom-organizer.css";
|
|
22
|
+
import { NewsroomThemeFonts, useNewsroomThemeAttributes } from "./newsroom-theme";
|
|
22
23
|
|
|
23
24
|
export type NewsroomNavCount = {
|
|
24
25
|
count: number | null;
|
|
@@ -85,11 +86,12 @@ function Account({ placement }: { placement: "sidebar" | "header" }) {
|
|
|
85
86
|
media.addEventListener("change", close);
|
|
86
87
|
return () => media.removeEventListener("change", close);
|
|
87
88
|
}, []);
|
|
89
|
+
const themeAttributes = useNewsroomThemeAttributes();
|
|
88
90
|
return <DropdownMenu open={open} onOpenChange={setOpen}>
|
|
89
91
|
<DropdownMenuTrigger id={`organizer-account-trigger-${placement}`} className={`organizer-account organizer-account-${placement}`} aria-label="Account menu" title="Account menu">
|
|
90
92
|
<UserRound size={18} aria-hidden="true" /><span><strong>{auth.label}</strong><small>{accountSummary ?? (auth.status === "signedIn" ? "Account & preferences" : auth.status === "signedOut" ? "Not signed in" : "Checking session")}</small></span>
|
|
91
93
|
</DropdownMenuTrigger>
|
|
92
|
-
<DropdownMenuContent className="organizer-account-popup" side={placement === "sidebar" ? "top" : "bottom"} align="end">
|
|
94
|
+
<DropdownMenuContent className="organizer-account-popup" {...themeAttributes} side={placement === "sidebar" ? "top" : "bottom"} align="end">
|
|
93
95
|
<DropdownMenuGroup>
|
|
94
96
|
<DropdownMenuLabel>{auth.label}</DropdownMenuLabel><DropdownMenuSeparator />
|
|
95
97
|
<ProspectusAccountChooser />
|
|
@@ -104,6 +106,7 @@ function Account({ placement }: { placement: "sidebar" | "header" }) {
|
|
|
104
106
|
|
|
105
107
|
export function NewsroomOpsShell({ activeTab, appTitle, backHref = "/", backLabel, children, demo = false, headerActions, pageTitle, showNavigation = true }: NewsroomOpsShellProps) {
|
|
106
108
|
const pathname = usePathname();
|
|
109
|
+
const themeAttributes = useNewsroomThemeAttributes();
|
|
107
110
|
const session = useOptionalNewsDeskClient();
|
|
108
111
|
const admin = demo || session?.shell.dashboard?.canManageUsers === true;
|
|
109
112
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
@@ -145,7 +148,8 @@ export function NewsroomOpsShell({ activeTab, appTitle, backHref = "/", backLabe
|
|
|
145
148
|
aria-label={sidebarToggleLabel} aria-expanded={!collapsed} aria-controls="organizer-sidebar" onClick={() => setCollapsed(value => !value)}>
|
|
146
149
|
{collapsed ? <PanelLeftOpen size={16} aria-hidden="true" /> : <PanelLeftClose size={16} aria-hidden="true" />}
|
|
147
150
|
</button>;
|
|
148
|
-
return <div className="newsroom-organizer" data-news-desk data-newsroom-ops-shell="true" data-newsroom-chrome="organizer" data-sidebar-collapsed={collapsed || !showNavigation ? "true" : "false"}>
|
|
151
|
+
return <div className="newsroom-organizer" {...themeAttributes} data-news-desk data-newsroom-ops-shell="true" data-newsroom-chrome="organizer" data-sidebar-collapsed={collapsed || !showNavigation ? "true" : "false"}>
|
|
152
|
+
<NewsroomThemeFonts />
|
|
149
153
|
{showNavigation && <aside className="organizer-sidebar" hidden={collapsed} id="organizer-sidebar">
|
|
150
154
|
<div className="organizer-sidebar-head">
|
|
151
155
|
<Link className="organizer-brand" href={getNewsroomNavHref("/newsroom", demo)}>{SITE_BRAND.components?.NewsroomLogo ? <SITE_BRAND.components.NewsroomLogo className="organizer-brand-logo" /> : appTitle}<small>The newsroom</small></Link>
|
|
@@ -167,7 +171,7 @@ export function NewsroomOpsShell({ activeTab, appTitle, backHref = "/", backLabe
|
|
|
167
171
|
href={getNewsroomNavHref(item.path, demo)} title={item.description} aria-label={item.label} aria-current={activeTab === item.key ? "page" : undefined}>
|
|
168
172
|
<Icon size={18} aria-hidden="true" /><span>{item.label}</span></Link></li>; })}
|
|
169
173
|
<li><Sheet open={menuOpen} onOpenChange={setMenuOpen}><SheetTrigger className="organizer-more" aria-label="More"><Menu size={18} aria-hidden="true" /><span>More</span></SheetTrigger>
|
|
170
|
-
<SheetContent side="bottom" className="organizer-menu"><SheetHeader><SheetTitle>Newsroom</SheetTitle><SheetDescription>Workspaces and administration</SheetDescription></SheetHeader>
|
|
174
|
+
<SheetContent side="bottom" className="organizer-menu" {...themeAttributes}><SheetHeader><SheetTitle>Newsroom</SheetTitle><SheetDescription>Workspaces and administration</SheetDescription></SheetHeader>
|
|
171
175
|
<Navigation activePath={activePath} demo={demo} admin={admin} surface="menu" onNavigate={() => setMenuOpen(false)} />
|
|
172
176
|
</SheetContent>
|
|
173
177
|
</Sheet></li>
|