@anthusai/papyrus 5.41.3 → 5.41.4
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/app/globals.css +14 -18
- package/components/newsroom-mobile-navigation.tsx +23 -0
- package/components/newsroom-ops-shell.tsx +8 -10
- package/components/newsroom-organizer.css +1 -0
- package/components/papyrus-console-frame.tsx +2 -4
- package/components/papyrus-console-shell.tsx +6 -31
- package/components/papyrus-private-chat-panel.tsx +9 -4
- package/components/use-console-visibility.ts +47 -0
- package/package.json +3 -1
- package/routes.manifest.json +1 -1
- package/src/with-papyrus.mjs +1 -1
package/app/globals.css
CHANGED
|
@@ -10171,26 +10171,8 @@ img {
|
|
|
10171
10171
|
}
|
|
10172
10172
|
|
|
10173
10173
|
|
|
10174
|
-
.papyrus-console-mobile-trigger { display: none; }
|
|
10175
10174
|
@media (max-width: 900px) {
|
|
10176
10175
|
.edition-progress__button--console { display: none; }
|
|
10177
|
-
.papyrus-console-mobile-trigger {
|
|
10178
|
-
display: inline-flex;
|
|
10179
|
-
align-items: center;
|
|
10180
|
-
justify-content: center;
|
|
10181
|
-
position: fixed;
|
|
10182
|
-
right: 16px;
|
|
10183
|
-
bottom: calc(76px + env(safe-area-inset-bottom));
|
|
10184
|
-
z-index: 1200;
|
|
10185
|
-
min-width: 64px;
|
|
10186
|
-
min-height: 44px;
|
|
10187
|
-
padding: 8px 16px;
|
|
10188
|
-
background: rgb(var(--paper-rgb));
|
|
10189
|
-
color: var(--ink);
|
|
10190
|
-
border: 1px solid currentColor;
|
|
10191
|
-
font: 600 14px Arial, sans-serif;
|
|
10192
|
-
}
|
|
10193
|
-
.papyrus-console-mobile-trigger:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }
|
|
10194
10176
|
.papyrus-console--open {
|
|
10195
10177
|
--papyrus-console-width: 100vw;
|
|
10196
10178
|
background: rgb(var(--paper-rgb));
|
|
@@ -10200,6 +10182,20 @@ img {
|
|
|
10200
10182
|
}
|
|
10201
10183
|
}
|
|
10202
10184
|
|
|
10185
|
+
.papyrus-console__access {
|
|
10186
|
+
display: flex;
|
|
10187
|
+
flex-direction: column;
|
|
10188
|
+
align-items: flex-start;
|
|
10189
|
+
gap: 16px;
|
|
10190
|
+
padding: 24px 18px;
|
|
10191
|
+
overflow-y: auto;
|
|
10192
|
+
color: var(--ink);
|
|
10193
|
+
font-size: 0.95rem;
|
|
10194
|
+
line-height: 1.5;
|
|
10195
|
+
}
|
|
10196
|
+
.papyrus-console__access strong { font-size: 1.15rem; }
|
|
10197
|
+
.papyrus-console__access button { min-height: 44px; padding: 10px 14px; font: inherit; text-transform: none; letter-spacing: normal; }
|
|
10198
|
+
|
|
10203
10199
|
@media (max-width: 900px) {
|
|
10204
10200
|
.papyrus-console__header button { min-width: 44px; min-height: 44px; }
|
|
10205
10201
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
import Link from "next/link";
|
|
5
|
+
import { BookOpen, ClipboardList, House, MessageCircle, MessagesSquare } from "lucide-react";
|
|
6
|
+
|
|
7
|
+
const ICONS = { overview: House, articles: ClipboardList, references: BookOpen, messages: MessagesSquare };
|
|
8
|
+
|
|
9
|
+
export function NewsroomMobileNavigation({ items, activeTab, chat, more }: {
|
|
10
|
+
items: readonly { key: string; label: string; description: string; href: string }[];
|
|
11
|
+
activeTab: string;
|
|
12
|
+
chat?: { open: boolean; onOpen: () => void };
|
|
13
|
+
more: ReactNode;
|
|
14
|
+
}) {
|
|
15
|
+
return <nav className="organizer-bottom-nav" aria-label="Primary newsroom navigation"><ul>
|
|
16
|
+
{items.map(item => {
|
|
17
|
+
if (item.key === "messages" && chat) return <li key="chat"><button className="organizer-chat" type="button" aria-label="Open private chat" aria-expanded={chat.open} aria-controls="papyrus-console-panel" onClick={chat.onOpen}><MessageCircle size={18} aria-hidden="true" /><span>Chat</span></button></li>;
|
|
18
|
+
const Icon = ICONS[item.key as keyof typeof ICONS];
|
|
19
|
+
return <li key={item.key}><Link href={item.href} title={item.description} aria-label={item.label} aria-current={activeTab === item.key ? "page" : undefined}><Icon size={18} aria-hidden="true" /><span>{item.label}</span></Link></li>;
|
|
20
|
+
})}
|
|
21
|
+
<li>{more}</li>
|
|
22
|
+
</ul></nav>;
|
|
23
|
+
}
|
|
@@ -8,7 +8,7 @@ import { cn } from "../lib/utils";
|
|
|
8
8
|
import { useEffect, useId, useState, type ReactNode } from "react";
|
|
9
9
|
import Link from "next/link";
|
|
10
10
|
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
|
11
|
-
import {
|
|
11
|
+
import { Menu, Search, PanelLeftClose, PanelLeftOpen, Settings, UserRound, LogIn, LogOut } from "lucide-react";
|
|
12
12
|
import { ORGANIZER_NAV_GROUPS, ORGANIZER_PRIMARY_NAV, ORGANIZER_SETTINGS_DESTINATION } from "../lib/newsroom-organizer-nav";
|
|
13
13
|
import { browserPathToInternalNewsroomPath } from "../lib/newsroom-base-path";
|
|
14
14
|
import { getNewsroomNavHref } from "../lib/newsroom-nav";
|
|
@@ -20,6 +20,8 @@ import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetTr
|
|
|
20
20
|
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator } from "./ui/dropdown-menu";
|
|
21
21
|
import "./newsroom-organizer.css";
|
|
22
22
|
import { NewsroomThemeFonts, useNewsroomThemeAttributes } from "./newsroom-theme";
|
|
23
|
+
import { NewsroomMobileNavigation } from "./newsroom-mobile-navigation";
|
|
24
|
+
import { usePapyrusConsole } from "./papyrus-console-shell";
|
|
23
25
|
|
|
24
26
|
export type NewsroomNavCount = {
|
|
25
27
|
count: number | null;
|
|
@@ -55,8 +57,6 @@ function OrganizerSearch({ demo }: { demo: boolean }) {
|
|
|
55
57
|
</form>;
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
const ICONS = { overview: House, articles: ClipboardList, references: BookOpen, messages: MessagesSquare };
|
|
59
|
-
|
|
60
60
|
/** Navigation is a presentation layer; existing route and server authorization still own access. */
|
|
61
61
|
function Navigation({ activePath, demo, admin, surface, onNavigate }: { activePath: string; demo: boolean; admin: boolean; surface: string; onNavigate?: () => void }) {
|
|
62
62
|
const id = useId();
|
|
@@ -105,6 +105,7 @@ function Account({ placement }: { placement: "sidebar" | "header" }) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
export function NewsroomOpsShell({ activeTab, appTitle, backHref = "/", backLabel, children, demo = false, headerActions, pageTitle, showNavigation = true }: NewsroomOpsShellProps) {
|
|
108
|
+
const consoleState = usePapyrusConsole();
|
|
108
109
|
const pathname = usePathname();
|
|
109
110
|
const themeAttributes = useNewsroomThemeAttributes();
|
|
110
111
|
const session = useOptionalNewsDeskClient();
|
|
@@ -166,16 +167,13 @@ export function NewsroomOpsShell({ activeTab, appTitle, backHref = "/", backLabe
|
|
|
166
167
|
</header>
|
|
167
168
|
<main className="organizer-main">{demo && <p className="organizer-demo-notice">Demo workspace · synthetic examples</p>}{children}</main>
|
|
168
169
|
</div>
|
|
169
|
-
{showNavigation && <
|
|
170
|
-
{
|
|
171
|
-
|
|
172
|
-
<Icon size={18} aria-hidden="true" /><span>{item.label}</span></Link></li>; })}
|
|
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
|
+
{showNavigation && <NewsroomMobileNavigation activeTab={activeTab} items={ORGANIZER_PRIMARY_NAV.map(item => ({ ...item, href: getNewsroomNavHref(item.path, demo) }))}
|
|
171
|
+
chat={consoleState?.shouldOfferConsole ? { open: consoleState.open, onOpen: consoleState.openConsole } : undefined}
|
|
172
|
+
more={<Sheet open={menuOpen} onOpenChange={setMenuOpen}><SheetTrigger className="organizer-more" aria-label="More"><Menu size={18} aria-hidden="true" /><span>More</span></SheetTrigger>
|
|
174
173
|
<SheetContent side="bottom" className="organizer-menu" {...themeAttributes}><SheetHeader><SheetTitle>Newsroom</SheetTitle><SheetDescription>Workspaces and administration</SheetDescription></SheetHeader>
|
|
175
174
|
<Navigation activePath={activePath} demo={demo} admin={admin} surface="menu" onNavigate={() => setMenuOpen(false)} />
|
|
176
175
|
</SheetContent>
|
|
177
|
-
</Sheet
|
|
178
|
-
</ul></nav>}
|
|
176
|
+
</Sheet>} />}
|
|
179
177
|
</div>;
|
|
180
178
|
}
|
|
181
179
|
|
|
@@ -33,6 +33,7 @@ body:has(.newsroom-organizer)>[data-staging-banner]{flex-shrink:0}
|
|
|
33
33
|
.organizer-account-popup{min-width:250px;max-width:calc(100vw - 32px);border:1px solid var(--org-line);padding:6px;border-radius:4px}
|
|
34
34
|
.organizer-account-popup [role=menuitem]{min-height:40px;font-size:12px}.organizer-account-popup .reader-auth{display:contents}.organizer-account-popup .reader-auth__error{display:block;white-space:normal;font-size:11px;padding:8px}
|
|
35
35
|
.organizer-bottom-nav{display:none}
|
|
36
|
+
.organizer-bottom-nav button{appearance:none;border:0;background:transparent;color:inherit}
|
|
36
37
|
.organizer-main:has(.organizer-native-board){display:flex;overflow:hidden}
|
|
37
38
|
.organizer-native-board{display:flex;flex-direction:column;flex:1;min-height:0;min-width:0;gap:8px}
|
|
38
39
|
.organizer-board-view-toggle{display:flex;gap:4px;flex-shrink:0}
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { useEffect, useRef, useState, type ReactNode } from "react";
|
|
4
4
|
|
|
5
|
-
export function PapyrusConsoleFrame({ available, open, reserveSpace,
|
|
5
|
+
export function PapyrusConsoleFrame({ available, open, reserveSpace, onClose, page, children }: {
|
|
6
6
|
available: boolean;
|
|
7
7
|
open: boolean;
|
|
8
8
|
reserveSpace: boolean;
|
|
9
|
-
onOpen: () => void;
|
|
10
9
|
onClose: () => void;
|
|
11
10
|
page: ReactNode;
|
|
12
11
|
children: ReactNode;
|
|
@@ -45,14 +44,13 @@ export function PapyrusConsoleFrame({ available, open, reserveSpace, onOpen, onC
|
|
|
45
44
|
cancelAnimationFrame(frame);
|
|
46
45
|
requestAnimationFrame(() => {
|
|
47
46
|
if (previous instanceof HTMLElement && previous !== document.body && previous.isConnected && !previous.closest("[inert]")) previous.focus();
|
|
48
|
-
else Array.from(document.querySelectorAll<HTMLElement>(".
|
|
47
|
+
else Array.from(document.querySelectorAll<HTMLElement>(".organizer-chat, .edition-progress__button--console, .papyrus-console__header button")).find(element => element.getClientRects().length > 0)?.focus();
|
|
49
48
|
});
|
|
50
49
|
};
|
|
51
50
|
}, [modal]);
|
|
52
51
|
|
|
53
52
|
return <>
|
|
54
53
|
<div className={reserveSpace ? "papyrus-console-page papyrus-console-page--open" : "papyrus-console-page"} inert={modal || undefined}>{page}</div>
|
|
55
|
-
{available && !open ? <button className="papyrus-console-mobile-trigger" type="button" aria-label="Open private chat" aria-expanded={false} aria-controls="papyrus-console-panel" onClick={onOpen}>Chat</button> : null}
|
|
56
54
|
{available ? <aside ref={panel} id="papyrus-console-panel" className={open ? "papyrus-console papyrus-console--open" : "papyrus-console"} aria-label="Papyrus console" role={modal ? "dialog" : undefined} aria-modal={modal || undefined}
|
|
57
55
|
style={modal && viewport ? { top: viewport.top, height: viewport.height, bottom: "auto" } : undefined}
|
|
58
56
|
onKeyDown={event => {
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
} from "./reader-settings";
|
|
37
37
|
import { PapyrusConsoleConversation, type ConsoleConversationMessage } from "./papyrus-console-conversation";
|
|
38
38
|
import { PapyrusConsoleFrame } from "./papyrus-console-frame";
|
|
39
|
+
import { useConsoleVisibility } from "./use-console-visibility";
|
|
39
40
|
import { PapyrusPrivateChatPanel } from "./papyrus-private-chat-panel";
|
|
40
41
|
import { ModelSelector } from "./ai-elements/model-selector";
|
|
41
42
|
import { Suggestion, Suggestions } from "./ai-elements/suggestion";
|
|
@@ -150,12 +151,12 @@ const PapyrusConsoleContext = createContext<PapyrusConsoleContextValue | null>(n
|
|
|
150
151
|
export function PapyrusConsoleShell({ children, privateChatEnabled = false }: PapyrusConsoleShellProps) {
|
|
151
152
|
const pathname = usePathname();
|
|
152
153
|
const [session, setSession] = useState<ReaderSessionSnapshot | null>(null);
|
|
153
|
-
const [open, setOpen] = useState(false);
|
|
154
154
|
const [openingReferenceChat, setOpeningReferenceChat] = useState(false);
|
|
155
155
|
const internalPathname = browserPathToInternalNewsroomPath(pathname);
|
|
156
156
|
const isNewsroomPath = internalPathname === "/newsroom" || internalPathname.startsWith("/newsroom/");
|
|
157
157
|
const canUseConsole = Boolean(session?.hasSession && session.groups.some((group) => group === "editor" || group === "admin"));
|
|
158
158
|
const shouldOfferConsole = isNewsroomPath && canUseConsole;
|
|
159
|
+
const { open, openConsole, closeConsole, toggleOpen } = useConsoleVisibility({ available: shouldOfferConsole });
|
|
159
160
|
|
|
160
161
|
useEffect(() => {
|
|
161
162
|
let active = true;
|
|
@@ -166,37 +167,11 @@ export function PapyrusConsoleShell({ children, privateChatEnabled = false }: Pa
|
|
|
166
167
|
.catch(() => {
|
|
167
168
|
if (active) setSession({ auth: { status: "signedOut", label: "Signed out" }, groups: [], hasSession: false });
|
|
168
169
|
});
|
|
169
|
-
try {
|
|
170
|
-
setOpen(window.localStorage.getItem("papyrus:console-open") === "true");
|
|
171
|
-
} catch {
|
|
172
|
-
setOpen(false);
|
|
173
|
-
}
|
|
174
170
|
return () => {
|
|
175
171
|
active = false;
|
|
176
172
|
};
|
|
177
173
|
}, []);
|
|
178
174
|
|
|
179
|
-
const toggleOpen = useCallback(() => {
|
|
180
|
-
setOpen((current) => {
|
|
181
|
-
const next = !current;
|
|
182
|
-
try {
|
|
183
|
-
window.localStorage.setItem("papyrus:console-open", String(next));
|
|
184
|
-
} catch {
|
|
185
|
-
// Ignore storage failures.
|
|
186
|
-
}
|
|
187
|
-
return next;
|
|
188
|
-
});
|
|
189
|
-
}, []);
|
|
190
|
-
|
|
191
|
-
const openConsole = useCallback(() => {
|
|
192
|
-
setOpen(true);
|
|
193
|
-
try {
|
|
194
|
-
window.localStorage.setItem("papyrus:console-open", "true");
|
|
195
|
-
} catch {
|
|
196
|
-
// Ignore storage failures.
|
|
197
|
-
}
|
|
198
|
-
}, []);
|
|
199
|
-
|
|
200
175
|
const startReferenceChat = useCallback(async (target: NewsroomKnowledgeQueryTarget) => {
|
|
201
176
|
if (!canUseConsole) {
|
|
202
177
|
throw new Error("Chat is only available to editor/admin sessions.");
|
|
@@ -359,13 +334,13 @@ export function PapyrusConsoleShell({ children, privateChatEnabled = false }: Pa
|
|
|
359
334
|
|
|
360
335
|
return (
|
|
361
336
|
<PapyrusConsoleContext.Provider value={consoleContext}>
|
|
362
|
-
<PapyrusConsoleFrame available={shouldOfferConsole} open={open} reserveSpace={canUseConsole && open} onClose={
|
|
337
|
+
<PapyrusConsoleFrame available={shouldOfferConsole} open={open} reserveSpace={canUseConsole && open} onClose={closeConsole} page={children}>
|
|
363
338
|
{open ? (
|
|
364
339
|
canUseConsole
|
|
365
340
|
? privateChatEnabled
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
: <ConsoleAccessPanel onClose={
|
|
341
|
+
? <PapyrusPrivateChatPanel onClose={closeConsole} />
|
|
342
|
+
: <ConsolePanel actorEmail={session?.auth.status === "signedIn" ? (session.auth.email ?? null) : null} actorLabel={session?.auth.label ?? "Papyrus editor"} onClose={closeConsole} />
|
|
343
|
+
: <ConsoleAccessPanel onClose={closeConsole} session={session} />
|
|
369
344
|
) : null}
|
|
370
345
|
</PapyrusConsoleFrame>
|
|
371
346
|
</PapyrusConsoleContext.Provider>
|
|
@@ -175,21 +175,26 @@ export function PapyrusPrivateChatPanel({ onClose }: { onClose: () => void }) {
|
|
|
175
175
|
<button className="papyrus-console__close" onClick={onClose} type="button" aria-label="Close console">×</button>
|
|
176
176
|
</header>
|
|
177
177
|
{channel ? <p className="papyrus-console__empty" role="status">Private conversation for your selected Account.</p> : null}
|
|
178
|
-
{!channel && !loading ? <div className="papyrus-
|
|
178
|
+
{!channel && !loading ? <div className="papyrus-console__access" role="alert">
|
|
179
179
|
{error === "chat_identity_connection_required" ? <>
|
|
180
180
|
<strong>Connect your publishing account</strong>
|
|
181
181
|
{connectionNotice ? <span>{connectionNotice}</span> : null}
|
|
182
182
|
<span>Continue with the same Google account you use in the newsroom, then choose the Account for this private conversation.</span>
|
|
183
183
|
<button className="papyrus-console__new-session" disabled={connecting} onClick={() => void connect()} type="button">{connecting ? "Connecting…" : "Connect publishing account"}</button>
|
|
184
184
|
</> : accountState?.status === "signedIn" ? <>
|
|
185
|
-
<strong>Choose your publishing Account</strong>
|
|
186
|
-
{accountState.publishingAccounts.length === 0 ?
|
|
185
|
+
<strong>{accountState.publishingAccounts.length === 0 ? "Chat access is unavailable" : "Choose your publishing Account"}</strong>
|
|
186
|
+
{accountState.publishingAccounts.length === 0 ? <>
|
|
187
|
+
<span>None of your Accounts is enabled for this publication. Publication setup must be resolved before you can chat.</span>
|
|
188
|
+
<span>You can return to the newsroom while this is resolved. Check again after access has been corrected.</span>
|
|
189
|
+
<button className="papyrus-console__new-session" onClick={() => void openConversation()} type="button">Check again</button>
|
|
190
|
+
</> : accountState.publishingAccounts.map(account => <button className="papyrus-console__new-session" disabled={connecting} key={account.accountId} onClick={() => void chooseAccount(account.accountId)} type="button">{account.name ?? account.accountId}</button>)}
|
|
187
191
|
{error !== "publishing_account_required" ? <span>{error}</span> : null}
|
|
188
192
|
</> : <>
|
|
189
193
|
<strong>Private chat could not be opened.</strong>
|
|
190
|
-
<span>{error === "sign_in_required" ? "Your newsroom session has expired.
|
|
194
|
+
<span>{error === "sign_in_required" ? "Your newsroom session has expired. Return to the newsroom and sign in from the account menu, then retry." : error === "chat_account_access_denied" ? "Your access to this conversation has changed. Retry to check your current access." : error === "publishing_account_required" ? "Publishing Account access could not be checked. Retry when your connection is available." : error}</span>
|
|
191
195
|
<button className="papyrus-console__new-session" onClick={() => void openConversation()} type="button">Retry</button>
|
|
192
196
|
</>}
|
|
197
|
+
<button className="papyrus-console__new-session" onClick={onClose} type="button">Back to newsroom</button>
|
|
193
198
|
</div> : <PapyrusConsoleConversation
|
|
194
199
|
messages={conversationMessages}
|
|
195
200
|
isSending={sending || loading || !channel}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
|
|
5
|
+
export function useConsoleVisibility({ available, persist = true }: { available: boolean; persist?: boolean }) {
|
|
6
|
+
const [open, setOpen] = useState(false);
|
|
7
|
+
const visible = useRef(false);
|
|
8
|
+
const entry = useRef<string | null>(null);
|
|
9
|
+
const setVisible = useCallback((next: boolean) => {
|
|
10
|
+
visible.current = next;
|
|
11
|
+
setOpen(next);
|
|
12
|
+
if (persist) try { localStorage.setItem("papyrus:console-open", String(next)); } catch { /* Optional preference. */ }
|
|
13
|
+
}, [persist]);
|
|
14
|
+
const openConsole = useCallback(() => {
|
|
15
|
+
if (!available || visible.current) return;
|
|
16
|
+
const existing = history.state?.papyrusMobileChat;
|
|
17
|
+
if (typeof existing === "string") entry.current = existing;
|
|
18
|
+
else if (matchMedia("(max-width: 900px)").matches) {
|
|
19
|
+
entry.current = crypto.randomUUID();
|
|
20
|
+
history.pushState({ ...history.state, papyrusMobileChat: entry.current }, "", location.href);
|
|
21
|
+
}
|
|
22
|
+
setVisible(true);
|
|
23
|
+
}, [available, setVisible]);
|
|
24
|
+
const closeConsole = useCallback(() => {
|
|
25
|
+
if (entry.current && history.state?.papyrusMobileChat === entry.current) history.back();
|
|
26
|
+
else setVisible(false);
|
|
27
|
+
}, [setVisible]);
|
|
28
|
+
const toggleOpen = useCallback(() => {
|
|
29
|
+
if (visible.current) closeConsole();
|
|
30
|
+
else openConsole();
|
|
31
|
+
}, [closeConsole, openConsole]);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!available) {
|
|
34
|
+
visible.current = false;
|
|
35
|
+
setOpen(false);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const pop = (event: PopStateEvent) => {
|
|
39
|
+
if (entry.current) setVisible(event.state?.papyrusMobileChat === entry.current);
|
|
40
|
+
};
|
|
41
|
+
window.addEventListener("popstate", pop);
|
|
42
|
+
if (typeof history.state?.papyrusMobileChat === "string") openConsole();
|
|
43
|
+
else if (persist) try { if (localStorage.getItem("papyrus:console-open") === "true") openConsole(); } catch { /* Optional preference. */ }
|
|
44
|
+
return () => window.removeEventListener("popstate", pop);
|
|
45
|
+
}, [available, openConsole, persist, setVisible]);
|
|
46
|
+
return { open, openConsole, closeConsole, toggleOpen };
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -106,6 +106,7 @@
|
|
|
106
106
|
"./components/newsroom-client-shell": "./components/newsroom-client-shell.tsx",
|
|
107
107
|
"./components/newsroom-curation-bootstrap": "./components/newsroom-curation-bootstrap.tsx",
|
|
108
108
|
"./components/newsroom-curation-provider": "./components/newsroom-curation-provider.tsx",
|
|
109
|
+
"./components/newsroom-mobile-navigation": "./components/newsroom-mobile-navigation.tsx",
|
|
109
110
|
"./components/newsroom-ops-overview": "./components/newsroom-ops-overview.tsx",
|
|
110
111
|
"./components/newsroom-ops-shell": "./components/newsroom-ops-shell.tsx",
|
|
111
112
|
"./components/newsroom-overview-skeleton": "./components/newsroom-overview-skeleton.tsx",
|
|
@@ -168,6 +169,7 @@
|
|
|
168
169
|
"./components/ui/tooltip": "./components/ui/tooltip.tsx",
|
|
169
170
|
"./components/use-blog-header-obstacles": "./components/use-blog-header-obstacles.ts",
|
|
170
171
|
"./components/use-brand-fonts-ready": "./components/use-brand-fonts-ready.ts",
|
|
172
|
+
"./components/use-console-visibility": "./components/use-console-visibility.ts",
|
|
171
173
|
"./components/use-editorial-checks": "./components/use-editorial-checks.ts",
|
|
172
174
|
"./components/use-near-viewport": "./components/use-near-viewport.ts",
|
|
173
175
|
"./components/use-paged-content-item-versions": "./components/use-paged-content-item-versions.ts",
|
|
@@ -459,7 +461,7 @@
|
|
|
459
461
|
"optional": true
|
|
460
462
|
}
|
|
461
463
|
},
|
|
462
|
-
"version": "5.41.
|
|
464
|
+
"version": "5.41.4",
|
|
463
465
|
"dependencies": {
|
|
464
466
|
"@aws-amplify/adapter-nextjs": "^1.7.3",
|
|
465
467
|
"@aws-crypto/sha256-js": "5.2.0",
|
package/routes.manifest.json
CHANGED
package/src/with-papyrus.mjs
CHANGED
|
@@ -50,7 +50,7 @@ export function staticGenerationSettings() {
|
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
export const DEFAULT_TRANSPILE_PACKAGES = ["@anthusai/papyrus", "cyclotron", "chatticus"];
|
|
53
|
+
export const DEFAULT_TRANSPILE_PACKAGES = ["@anthusai/papyrus", "cyclotron", "chatticus", "lucide-react"];
|
|
54
54
|
|
|
55
55
|
export function mergeTranspilePackages(existing = []) {
|
|
56
56
|
return [...new Set([...existing, ...DEFAULT_TRANSPILE_PACKAGES])];
|