@arbidocs/blocks 0.4.22 → 0.4.24
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/agents/index.cjs +210 -210
- package/dist/agents/index.js +4 -4
- package/dist/{chunk-OEQXYWUO.cjs → chunk-4UAEHDC6.cjs} +3 -3
- package/dist/{chunk-OEQXYWUO.cjs.map → chunk-4UAEHDC6.cjs.map} +1 -1
- package/dist/{chunk-JLOYWXRB.js → chunk-557EU3G4.js} +3 -3
- package/dist/{chunk-JLOYWXRB.js.map → chunk-557EU3G4.js.map} +1 -1
- package/dist/{chunk-YVIOCITQ.cjs → chunk-DCEI37AX.cjs} +3 -3
- package/dist/{chunk-YVIOCITQ.cjs.map → chunk-DCEI37AX.cjs.map} +1 -1
- package/dist/{chunk-MLJDOH3B.js → chunk-JL34XP37.js} +3 -3
- package/dist/{chunk-MLJDOH3B.js.map → chunk-JL34XP37.js.map} +1 -1
- package/dist/connect/index.cjs +25 -24
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.js +4 -3
- package/dist/connect/index.js.map +1 -1
- package/dist/facts/index.cjs +1 -1
- package/dist/facts/index.js +1 -1
- package/dist/files/index.cjs +3 -3
- package/dist/files/index.js +3 -3
- package/dist/home/index.cjs +1 -1
- package/dist/home/index.js +1 -1
- package/dist/index.cjs +426 -426
- package/dist/index.js +8 -8
- package/dist/settings/index.cjs +32 -32
- package/dist/settings/index.js +3 -3
- package/dist/shell/index.cjs +1 -1
- package/dist/shell/index.js +1 -1
- package/dist/studio/index.cjs +1 -1
- package/dist/studio/index.js +1 -1
- package/dist/workspaces/index.cjs +1 -1
- package/dist/workspaces/index.js +1 -1
- package/package.json +3 -3
package/dist/connect/index.cjs
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var chunkEUOGPUMJ_cjs = require('../chunk-EUOGPUMJ.cjs');
|
|
5
|
-
var
|
|
5
|
+
var chunkDCEI37AX_cjs = require('../chunk-DCEI37AX.cjs');
|
|
6
6
|
var chunkQVBZESYQ_cjs = require('../chunk-QVBZESYQ.cjs');
|
|
7
7
|
require('../chunk-ADOKTJHV.cjs');
|
|
8
|
+
require('../chunk-DCDVWPMB.cjs');
|
|
8
9
|
require('../chunk-J22DXUJY.cjs');
|
|
9
10
|
require('../chunk-VGOFFCMT.cjs');
|
|
10
11
|
require('../chunk-PPCATBOY.cjs');
|
|
11
12
|
var chunkKDG6FER6_cjs = require('../chunk-KDG6FER6.cjs');
|
|
12
|
-
require('../chunk-DCDVWPMB.cjs');
|
|
13
13
|
var chunkJCVZKCXC_cjs = require('../chunk-JCVZKCXC.cjs');
|
|
14
14
|
require('../chunk-MHVNT4J3.cjs');
|
|
15
15
|
var react = require('react');
|
|
@@ -19,6 +19,7 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
19
19
|
var artifacts = require('@arbidocs/react/artifacts');
|
|
20
20
|
var lucideReact = require('lucide-react');
|
|
21
21
|
var ui = require('@arbidocs/react/ui');
|
|
22
|
+
var shell = require('@arbidocs/react/shell');
|
|
22
23
|
|
|
23
24
|
function ConnectionBoundWebSocket({ children }) {
|
|
24
25
|
const { status } = chunkJCVZKCXC_cjs.useConnection();
|
|
@@ -180,12 +181,12 @@ function ConnectedProfileCard({ notify: notify2, title = "Profile" }) {
|
|
|
180
181
|
}
|
|
181
182
|
});
|
|
182
183
|
const display = profile?.fullName || user?.name || "Unnamed";
|
|
183
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
184
|
-
|
|
184
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkDCEI37AX_cjs.SettingsSection, { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserCircle, {}), title, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
185
|
+
chunkDCEI37AX_cjs.ProfileCard,
|
|
185
186
|
{
|
|
186
187
|
avatar: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
187
188
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
188
|
-
|
|
189
|
+
chunkDCEI37AX_cjs.AvatarPicker,
|
|
189
190
|
{
|
|
190
191
|
pictureUrl: profile?.picture ?? user?.picture,
|
|
191
192
|
initials: chunkKDG6FER6_cjs.initials(display),
|
|
@@ -243,10 +244,10 @@ function ConnectedSecuritySection({
|
|
|
243
244
|
},
|
|
244
245
|
onClose: () => setOpen(false)
|
|
245
246
|
});
|
|
246
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
247
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
247
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(chunkDCEI37AX_cjs.SettingsSection, { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.KeyRound, {}), title: "Security", children: [
|
|
248
|
+
/* @__PURE__ */ jsxRuntime.jsxs(chunkDCEI37AX_cjs.SettingsCard, { padding: "sm", children: [
|
|
248
249
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
249
|
-
|
|
250
|
+
chunkDCEI37AX_cjs.SettingsActionRow,
|
|
250
251
|
{
|
|
251
252
|
title: "Change password",
|
|
252
253
|
description: "Used to sign in and to encrypt your data. Changing it re-encrypts everything in your account.",
|
|
@@ -257,7 +258,7 @@ function ConnectedSecuritySection({
|
|
|
257
258
|
children
|
|
258
259
|
] }),
|
|
259
260
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
260
|
-
|
|
261
|
+
chunkDCEI37AX_cjs.PasswordChangeDialog,
|
|
261
262
|
{
|
|
262
263
|
open,
|
|
263
264
|
onClose: form.onCancel,
|
|
@@ -281,23 +282,23 @@ function ConnectedSecuritySection({
|
|
|
281
282
|
] });
|
|
282
283
|
}
|
|
283
284
|
function ConnectedNotificationPreferences({
|
|
284
|
-
categories =
|
|
285
|
+
categories = chunkDCEI37AX_cjs.EMAIL_NOTIFICATION_CATEGORIES,
|
|
285
286
|
title = "Notifications"
|
|
286
287
|
}) {
|
|
287
288
|
const keys = react.useMemo(
|
|
288
|
-
() => categories ===
|
|
289
|
+
() => categories === chunkDCEI37AX_cjs.EMAIL_NOTIFICATION_CATEGORIES ? chunkDCEI37AX_cjs.EMAIL_NOTIFICATION_KEYS : categories.map((c) => c.key),
|
|
289
290
|
[categories]
|
|
290
291
|
);
|
|
291
292
|
const prefs = react$1.useNotificationPreferences(keys);
|
|
292
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
293
|
-
|
|
293
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkDCEI37AX_cjs.SettingsSection, { title, children: /* @__PURE__ */ jsxRuntime.jsx(chunkDCEI37AX_cjs.SettingsCard, { className: "space-y-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
294
|
+
chunkDCEI37AX_cjs.NotificationCategoryList,
|
|
294
295
|
{
|
|
295
296
|
masterId: "emailNotifications",
|
|
296
297
|
masterTitle: "Email Notifications",
|
|
297
298
|
masterDescription: "Email me about activity when I\u2019m away",
|
|
298
299
|
masterChecked: prefs.masterChecked,
|
|
299
300
|
onMasterChange: prefs.setAll,
|
|
300
|
-
categories:
|
|
301
|
+
categories: chunkDCEI37AX_cjs.toNotificationCategories(prefs.checked, categories),
|
|
301
302
|
onCategoryChange: prefs.setCategory
|
|
302
303
|
}
|
|
303
304
|
) }) });
|
|
@@ -311,14 +312,14 @@ function ConnectedSessionsRow({
|
|
|
311
312
|
const sessions = react$1.useSessions({ enabled: open });
|
|
312
313
|
const currentSessionId = react$1.useCurrentSessionId();
|
|
313
314
|
const terminate = react$1.useTerminateSession();
|
|
314
|
-
const views =
|
|
315
|
+
const views = chunkDCEI37AX_cjs.toActiveSessionViews(sessions.data ?? [], {
|
|
315
316
|
currentSessionId,
|
|
316
317
|
terminatingId: terminate.isPending ? terminate.variables : null,
|
|
317
318
|
renderIcon: renderSessionIcon
|
|
318
319
|
});
|
|
319
320
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
320
321
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
321
|
-
|
|
322
|
+
chunkDCEI37AX_cjs.SettingsRow,
|
|
322
323
|
{
|
|
323
324
|
label: "Active sessions",
|
|
324
325
|
description: "Devices and agents currently signed in to your account.",
|
|
@@ -340,7 +341,7 @@ function ConnectedSessionsRow({
|
|
|
340
341
|
}
|
|
341
342
|
),
|
|
342
343
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
343
|
-
|
|
344
|
+
chunkDCEI37AX_cjs.ActiveSessionsDialog,
|
|
344
345
|
{
|
|
345
346
|
open,
|
|
346
347
|
onOpenChange: setOpen,
|
|
@@ -375,7 +376,7 @@ function ConnectedLogoutDialog({
|
|
|
375
376
|
const sessions = react$1.useSessions({ enabled: open });
|
|
376
377
|
const logoutAll = react$1.useLogoutAllSessions();
|
|
377
378
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
378
|
-
|
|
379
|
+
chunkDCEI37AX_cjs.LogoutDialog,
|
|
379
380
|
{
|
|
380
381
|
open,
|
|
381
382
|
onClose,
|
|
@@ -389,7 +390,7 @@ function ConnectedLogoutDialog({
|
|
|
389
390
|
},
|
|
390
391
|
canLogoutAll: true,
|
|
391
392
|
isOnline,
|
|
392
|
-
sessions:
|
|
393
|
+
sessions: chunkDCEI37AX_cjs.toLogoutSessionViews(sessions.data ?? []),
|
|
393
394
|
renderSessionIcon
|
|
394
395
|
}
|
|
395
396
|
);
|
|
@@ -408,7 +409,7 @@ function ConnectedDangerZone({ notify: notify2, renderSubscriptionLink }) {
|
|
|
408
409
|
});
|
|
409
410
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
410
411
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
411
|
-
|
|
412
|
+
chunkDCEI37AX_cjs.SettingsDangerZone,
|
|
412
413
|
{
|
|
413
414
|
isOpen: zoneOpen,
|
|
414
415
|
onToggle: () => setZoneOpen((o) => !o),
|
|
@@ -428,12 +429,12 @@ function ConnectedDangerZone({ notify: notify2, renderSubscriptionLink }) {
|
|
|
428
429
|
}
|
|
429
430
|
),
|
|
430
431
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
431
|
-
|
|
432
|
+
chunkDCEI37AX_cjs.DeleteAccountDialog,
|
|
432
433
|
{
|
|
433
434
|
open: dialogOpen,
|
|
434
435
|
onClose: flow.onClose,
|
|
435
436
|
step: flow.step,
|
|
436
|
-
blockers:
|
|
437
|
+
blockers: chunkDCEI37AX_cjs.toDeleteBlockerViews(flow.blockers, renderSubscriptionLink),
|
|
437
438
|
onContinue: flow.onContinue,
|
|
438
439
|
onBack: flow.onBack,
|
|
439
440
|
userEmail: user?.email ?? "",
|
|
@@ -488,8 +489,8 @@ function useConnectedDocxNotifications(onOpen) {
|
|
|
488
489
|
} catch {
|
|
489
490
|
}
|
|
490
491
|
}
|
|
491
|
-
|
|
492
|
-
return () =>
|
|
492
|
+
shell.useNotify.getState().syncSource(source, items);
|
|
493
|
+
return () => shell.useNotify.getState().syncSource(source, []);
|
|
493
494
|
}, [data, status, user?.externalId, source, onOpen]);
|
|
494
495
|
const markRead = async (ids) => {
|
|
495
496
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/connection/ArbiAppProvider.tsx","../../src/connection/StreamedArtifact.tsx","../../src/connection/useConnectedShellWorkspaces.ts","../../src/connection/ConnectedSettings.tsx","../../src/connection/useConnectedDocxNotifications.ts"],"names":["useConnection","jsx","ArbiWebSocketProvider","useState","QueryClient","QueryClientProvider","ArbiProvider","ConnectionProvider","lazy","artifacts","useStreamedArtifact","ArtifactCanvas","StreamedArtifactFrame","Suspense","useWorkspaces","useShellWorkspaces","notify","useProfile","useUpdateProfile","useRequestEmailChange","useConfirmEmailChange","useNameEditor","useAvatarCrop","useEmailChange","SettingsSection","UserCircle","ProfileCard","jsxs","Fragment","AvatarPicker","initials","ImageCropModal","usePasswordChange","usePasswordChangeForm","KeyRound","SettingsCard","SettingsActionRow","PasswordChangeDialog","EMAIL_NOTIFICATION_CATEGORIES","useMemo","EMAIL_NOTIFICATION_KEYS","useNotificationPreferences","NotificationCategoryList","toNotificationCategories","useSessions","useCurrentSessionId","useTerminateSession","toActiveSessionViews","SettingsRow","Button","Radio","ActiveSessionsDialog","useLogoutAllSessions","LogoutDialog","toLogoutSessionViews","useDeleteAccount","useDeleteAccountFlow","SettingsDangerZone","DeleteAccountDialog","toDeleteBlockerViews","useArbi","useQueryClient","useQuery","useArbiWebSocket","useEffect","useNotify"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Composition root for a host app on the ARBI React SDK.\n *\n * QueryClientProvider → react-query cache shared with the SDK\n * ArbiProvider → the SDK's Arbi instance (no network until login)\n * ConnectionProvider → demo/live auth + workspace layer\n *\n * With no live `apiUrl`, ArbiProvider is still mounted (cheap, inert) against\n * `demoApiUrl` and the app runs entirely in seeded demo mode.\n */\nimport { useState, type ReactNode } from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ArbiProvider, ArbiWebSocketProvider } from '@arbidocs/react'\nimport { ConnectionProvider, useConnection } from './ConnectionProvider'\nimport type { ArbiConnectionConfig } from './types'\n\n/**\n * Opens the shared SDK WebSocket once the app is live-authenticated (demo /\n * logged-out sessions have no backend, so they stay disconnected). Lives inside\n * ConnectionProvider so it can read the live status.\n */\nfunction ConnectionBoundWebSocket({ children }: { children: ReactNode }) {\n const { status } = useConnection()\n return (\n <ArbiWebSocketProvider enabled={status === 'authenticated'}>{children}</ArbiWebSocketProvider>\n )\n}\n\nexport function ArbiAppProvider({\n config,\n children,\n}: {\n config: ArbiConnectionConfig\n children: ReactNode\n}) {\n const [queryClient] = useState(\n () =>\n new QueryClient({\n defaultOptions: { queries: { staleTime: 30_000, retry: 1, refetchOnWindowFocus: false } },\n })\n )\n\n const providerUrl = config.apiUrl || config.demoApiUrl || 'https://demo.arbi.local'\n\n return (\n <QueryClientProvider client={queryClient}>\n <ArbiProvider url={providerUrl}>\n <ConnectionProvider config={config}>\n <ConnectionBoundWebSocket>{children}</ConnectionBoundWebSocket>\n </ConnectionProvider>\n </ArbiProvider>\n </QueryClientProvider>\n )\n}\n","import { lazy, Suspense } from 'react'\nimport { ArtifactCanvas } from '@arbidocs/react'\nimport { useStreamedArtifact, type UseStreamedArtifactOptions } from '@arbidocs/react/artifacts'\nimport {\n StreamedArtifactFrame,\n type StreamedArtifactFrameLabels,\n type StreamedArtifactFrameTestIds,\n} from '../artifacts/StreamedArtifactFrame'\nimport type { ArtifactEvent } from './ai'\nimport type { StreamedArtifactEditorProps } from './StreamedArtifactEditor'\n\n// The editor (MDXEditor, Lexical) stays out of the bundle until a draft is ready to edit.\nconst StreamedArtifactEditor = lazy(() => import('./StreamedArtifactEditor'))\n\nexport interface StreamedArtifactProps\n extends\n Pick<UseStreamedArtifactOptions, 'configId' | 'parseRetry' | 'clean'>,\n Pick<\n StreamedArtifactEditorProps,\n 'editorProps' | 'onSaved' | 'onSaveError' | 'actions' | 'hideDefaultActions'\n > {\n /** The artifacts of the agent run (`useConnectedAiTask().artifacts`). */\n artifacts: ArtifactEvent[]\n workspaceId: string | undefined\n /** The agent is still working: show the live canvas. */\n busy: boolean\n /** The run failed; with no draft the canvas shows it. */\n error?: string | null\n stepCount?: number\n busyHint?: string\n emptyHint?: string\n className?: string\n /** Root test id of the editor; the preparing state is `${testId}-preparing`. */\n testId?: string\n labels?: Partial<StreamedArtifactFrameLabels>\n testIds?: Partial<StreamedArtifactFrameTestIds>\n}\n\n/**\n * An agent-drafted artifact from stream to editor, in one part. Pass the run's `artifacts` and\n * whether it is `busy`; it shows\n *\n * 1. the live `ArtifactCanvas` while the agent streams;\n * 2. \"Preparing editor...\" (the canvas stays readable underneath) while the finished draft is\n * cleaned (`cleanDraftMarkdown`), stored as version 1 of the artifact (`wpType: 'artifact'`)\n * and parsed by the backend, which can take up to about a minute;\n * 3. `ArtifactEditor` on the stored version (edit, save a new version, version list, compare\n * with track changes) when its text is ready;\n * 4. an error with Retry when storing or parsing fails.\n *\n * Needs `<ArbiProvider>` + React Query. The host imports the editor stylesheet\n * (`@mdxeditor/editor/style.css`) and defines the global `Prism` in a module it imports at app\n * start (see the Artifacts section of docs/design/blocks-package.md).\n *\n * ```tsx\n * const task = useConnectedAiTask()\n * <StreamedArtifact artifacts={task.artifacts} workspaceId={workspaceId} busy={task.status === 'running'} error={task.error} />\n * ```\n */\nexport function StreamedArtifact({\n artifacts,\n workspaceId,\n busy,\n error = null,\n stepCount,\n busyHint,\n emptyHint,\n className,\n testId = 'streamed-artifact',\n configId,\n parseRetry,\n clean,\n editorProps,\n onSaved,\n onSaveError,\n actions,\n hideDefaultActions,\n labels,\n testIds,\n}: StreamedArtifactProps) {\n const streamed = useStreamedArtifact({\n artifacts,\n workspaceId,\n settled: !busy && !error,\n configId,\n parseRetry,\n clean,\n })\n const canvas = (\n <ArtifactCanvas\n artifacts={artifacts}\n className={streamed.phase === 'streaming' ? className : undefined}\n busy={busy}\n busyHint={busyHint}\n stepCount={stepCount}\n error={error}\n emptyHint={emptyHint}\n />\n )\n return (\n <StreamedArtifactFrame\n phase={streamed.phase}\n canvas={canvas}\n className={className}\n error={streamed.error?.message}\n onRetry={streamed.retry}\n labels={labels}\n testIds={{ preparing: `${testId}-preparing`, error: `${testId}-error`, ...testIds }}\n >\n <Suspense fallback={canvas}>\n {streamed.docId && (\n <StreamedArtifactEditor\n key={streamed.docId}\n workspaceId={workspaceId}\n docId={streamed.docId}\n title={streamed.artifact?.title ?? 'Draft'}\n testId={testId}\n className={className}\n editorProps={editorProps}\n onSaved={onSaved}\n onSaveError={onSaveError}\n actions={actions}\n hideDefaultActions={hideDefaultActions}\n />\n )}\n </Suspense>\n </StreamedArtifactFrame>\n )\n}\n","import {\n useShellWorkspaces,\n useWorkspaces,\n type ShellWorkspaceSource,\n type UseShellWorkspacesOptions,\n type UseShellWorkspacesResult,\n} from '@arbidocs/react'\nimport { useConnection } from './ConnectionProvider'\n\nexport type UseConnectedShellWorkspacesOptions = Omit<\n UseShellWorkspacesOptions,\n 'workspaces' | 'isLoading' | 'loadError' | 'selectedId' | 'select'\n>\n\n/**\n * `useShellWorkspaces` wired to the connection layer: the account's live workspaces, the\n * connection's single selection as the active workspace, and `open` = `setWorkspace` (opens it on\n * the server, remembers it for the next login) then `onOpened`.\n *\n * ```tsx\n * const { active, recent, open } = useConnectedShellWorkspaces({\n * seed: { workspaces: demoWorkspaces, activeId: 'demo-1' },\n * onOpened: () => navigate('/app/documents'),\n * })\n * ```\n */\nexport function useConnectedShellWorkspaces(\n options: UseConnectedShellWorkspacesOptions = {}\n): UseShellWorkspacesResult {\n const { workspaceId, setWorkspace } = useConnection()\n const query = useWorkspaces()\n return useShellWorkspaces({\n ...options,\n workspaces: Array.isArray(query.data) ? (query.data as ShellWorkspaceSource[]) : undefined,\n isLoading: query.isLoading,\n loadError: query.error,\n selectedId: workspaceId,\n select: (workspace) => setWorkspace(workspace.id),\n })\n}\n","/**\n * The account area of a settings page, bound to the ARBI SDK: each section is a blocks part wired\n * to its `@arbidocs/react` hook, so a host drops them in a `SettingsPanel` and owns only the\n * layout (see the \"Settings page recipe\" in docs/design/blocks-package.md).\n *\n * Every section takes an optional `notify` for toasts and renders the default test ids of its\n * part. Anything the hooks cannot know (the recovery-key download, the billing link of a blocked\n * deletion, the password policy) is a prop.\n */\nimport { useMemo, useState, type ReactNode } from 'react'\nimport { KeyRound, Radio, UserCircle } from 'lucide-react'\nimport {\n ImageCropModal,\n useAvatarCrop,\n useConfirmEmailChange,\n useCurrentSessionId,\n useDeleteAccount,\n useDeleteAccountFlow,\n useEmailChange,\n useLogoutAllSessions,\n useNameEditor,\n useNotificationPreferences,\n usePasswordChange,\n usePasswordChangeForm,\n useProfile,\n useRequestEmailChange,\n useSessions,\n useTerminateSession,\n useUpdateProfile,\n useWorkspaces,\n type AvatarFileProblem,\n type PasswordChangeResult,\n} from '@arbidocs/react'\nimport { Button } from '@arbidocs/react/ui'\nimport { initials } from '../lib/format'\nimport { AvatarPicker } from '../settings/AvatarPicker'\nimport { ProfileCard } from '../settings/ProfileCard'\nimport {\n SettingsActionRow,\n SettingsCard,\n SettingsDangerZone,\n SettingsRow,\n SettingsSection,\n} from '../settings/SettingsPanel'\nimport { PasswordChangeDialog } from '../settings/PasswordChangeDialog'\nimport { ActiveSessionsDialog, DeleteAccountDialog } from '../settings/AccountDialogs'\nimport { LogoutDialog } from '../settings/LogoutDialog'\nimport { NotificationCategoryList } from '../settings/NotificationCategoryList'\nimport {\n EMAIL_NOTIFICATION_CATEGORIES,\n EMAIL_NOTIFICATION_KEYS,\n toActiveSessionViews,\n toDeleteBlockerViews,\n toLogoutSessionViews,\n toNotificationCategories,\n type EmailNotificationCategoryDef,\n} from '../settings/account-views'\nimport { useConnection } from './ConnectionProvider'\n\nexport type SettingsNotify = (message: string, kind: 'success' | 'error') => void\n\n/** The error text of a failed call: the backend `detail` when it sent one. */\nfunction errorText(error: unknown, fallback: string): string {\n const body = (error as { apiError?: { detail?: unknown } } | null)?.apiError\n return typeof body?.detail === 'string' ? body.detail : fallback\n}\n\nconst AVATAR_PROBLEMS: Record<AvatarFileProblem, string> = {\n 'not-image': 'Please choose an image file',\n 'too-large': 'Image must be 5 MB or smaller',\n unreadable: \"Couldn't read that image — try a different file\",\n}\n\n// ── Profile ─────────────────────────────────────────────────────────────────\n\nexport interface ConnectedProfileCardProps {\n notify?: SettingsNotify\n /** Section heading; default `Profile`. */\n title?: ReactNode\n}\n\n/** Avatar, editable name and email change of the signed-in user (`ProfileCard`). */\nexport function ConnectedProfileCard({ notify, title = 'Profile' }: ConnectedProfileCardProps) {\n const { data: profile } = useProfile()\n const updateProfile = useUpdateProfile()\n const requestEmailChange = useRequestEmailChange()\n const confirmEmailChange = useConfirmEmailChange()\n const { user } = useConnection()\n\n const name = useNameEditor({\n givenName: profile?.givenName,\n familyName: profile?.familyName,\n save: async (next) => {\n try {\n await updateProfile.mutateAsync(next)\n notify?.('Name updated', 'success')\n } catch (e) {\n notify?.('Failed to update name', 'error')\n throw e\n }\n },\n })\n const avatar = useAvatarCrop({\n upload: async (picture) => {\n try {\n await updateProfile.mutateAsync({ picture })\n notify?.('Profile picture updated', 'success')\n } catch (e) {\n notify?.('Failed to update picture', 'error')\n throw e\n }\n },\n onProblem: (problem) => notify?.(AVATAR_PROBLEMS[problem], 'error'),\n })\n const email = useEmailChange({\n requestCode: async (address) => {\n try {\n await requestEmailChange.mutateAsync(address)\n notify?.('Verification code sent to your new email', 'success')\n } catch (e) {\n notify?.(errorText(e, 'Failed to send verification code'), 'error')\n throw e\n }\n },\n confirm: async (args) => {\n try {\n await confirmEmailChange.mutateAsync(args)\n notify?.('Email address updated', 'success')\n } catch (e) {\n notify?.(errorText(e, 'Invalid or expired verification code'), 'error')\n throw e\n }\n },\n })\n\n const display = profile?.fullName || user?.name || 'Unnamed'\n return (\n <SettingsSection icon={<UserCircle />} title={title}>\n <ProfileCard\n avatar={\n <>\n <AvatarPicker\n pictureUrl={profile?.picture ?? user?.picture}\n initials={initials(display)}\n fallbackClassName=\"bg-primary text-primary-foreground\"\n isUploading={avatar.isUploading}\n onFileChosen={avatar.onFileChosen}\n />\n <ImageCropModal\n open={avatar.pendingImage !== null}\n image={avatar.pendingImage}\n title=\"Crop your photo\"\n aspect={1}\n cropShape=\"round\"\n output={{ maxSize: 128, mimeType: 'image/jpeg', quality: 0.85 }}\n onComplete={avatar.onCropComplete}\n onCancel={avatar.onCropCancel}\n />\n </>\n }\n name={{ ...name, display, isSaving: name.isSaving }}\n email={profile?.email ?? user?.email ?? ''}\n isSso={profile?.isSso ?? false}\n onStartEmailChange={email.onStart}\n emailChange={email.isOpen ? email : undefined}\n />\n </SettingsSection>\n )\n}\n\n// ── Security: password ──────────────────────────────────────────────────────\n\n/** The default password policy: 8 characters, an uppercase letter or symbol, a digit. */\nexport function defaultUnmetPasswordRequirement(password: string): string | null {\n if (password.length < 8) return 'Minimum 8 characters'\n if (!/[A-Z!@#$%^&*()_+\\-=[\\]{};':\"\\\\|,.<>/?]/.test(password)) {\n return 'At least one uppercase letter or special character'\n }\n if (!/[0-9]/.test(password)) return 'At least one number'\n return null\n}\n\nexport interface ConnectedSecuritySectionProps {\n notify?: SettingsNotify\n /** The host's password policy; default is {@link defaultUnmetPasswordRequirement}. */\n getUnmetRequirement?: (password: string) => string | null\n /** The recovery-key download for the key the new password produced (shown on success). */\n renderRecoveryKey?: (result: PasswordChangeResult) => ReactNode\n /** Extra rows under \"Change password\" (e.g. \"Save recovery key\"). */\n children?: ReactNode\n}\n\n/** The Security card: \"Change password\" and the dialog behind it (`PasswordChangeDialog`). */\nexport function ConnectedSecuritySection({\n notify,\n getUnmetRequirement = defaultUnmetPasswordRequirement,\n renderRecoveryKey,\n children,\n}: ConnectedSecuritySectionProps) {\n const [open, setOpen] = useState(false)\n const change = usePasswordChange()\n // Only workspaces the user belongs to are re-keyed.\n const { data: workspaces } = useWorkspaces({ enabled: open })\n const workspaceCount = (workspaces ?? []).filter((w) => w.is_member).length\n const form = usePasswordChangeForm<PasswordChangeResult>({\n getUnmetRequirement,\n submit: async (vars) => {\n const result = await change.mutateAsync(vars)\n notify?.('Password changed successfully', 'success')\n return result\n },\n onClose: () => setOpen(false),\n })\n\n return (\n <SettingsSection icon={<KeyRound />} title=\"Security\">\n <SettingsCard padding=\"sm\">\n <SettingsActionRow\n title=\"Change password\"\n description=\"Used to sign in and to encrypt your data. Changing it re-encrypts everything in your account.\"\n onClick={() => setOpen(true)}\n testId=\"change-password-button\"\n />\n {children}\n </SettingsCard>\n <PasswordChangeDialog\n open={open}\n onClose={form.onCancel}\n recoveryMode={false}\n currentPassword={form.currentPassword}\n onCurrentPasswordChange={form.onCurrentPasswordChange}\n newPassword={form.newPassword}\n onNewPasswordChange={form.onNewPasswordChange}\n confirmPassword={form.confirmPassword}\n onConfirmPasswordChange={form.onConfirmPasswordChange}\n getUnmetRequirement={getUnmetRequirement}\n workspaceCount={workspaceCount}\n error={form.error}\n isProcessing={form.isProcessing}\n isSubmitDisabled={form.isSubmitDisabled}\n onSubmit={form.onSubmit}\n success={form.result ? (renderRecoveryKey?.(form.result) ?? <></>) : null}\n onDone={form.onDone}\n />\n </SettingsSection>\n )\n}\n\n// ── Notifications ───────────────────────────────────────────────────────────\n\nexport interface ConnectedNotificationPreferencesProps {\n /** Categories to offer; default {@link EMAIL_NOTIFICATION_CATEGORIES}. */\n categories?: readonly EmailNotificationCategoryDef[]\n title?: ReactNode\n}\n\n/** The email-notification switches (`NotificationCategoryList`) over the user settings. */\nexport function ConnectedNotificationPreferences({\n categories = EMAIL_NOTIFICATION_CATEGORIES,\n title = 'Notifications',\n}: ConnectedNotificationPreferencesProps) {\n const keys = useMemo(\n () =>\n categories === EMAIL_NOTIFICATION_CATEGORIES\n ? EMAIL_NOTIFICATION_KEYS\n : categories.map((c) => c.key),\n [categories]\n )\n const prefs = useNotificationPreferences(keys)\n return (\n <SettingsSection title={title}>\n <SettingsCard className=\"space-y-0\">\n <NotificationCategoryList\n masterId=\"emailNotifications\"\n masterTitle=\"Email Notifications\"\n masterDescription=\"Email me about activity when I’m away\"\n masterChecked={prefs.masterChecked}\n onMasterChange={prefs.setAll}\n categories={toNotificationCategories(prefs.checked, categories)}\n onCategoryChange={prefs.setCategory}\n />\n </SettingsCard>\n </SettingsSection>\n )\n}\n\n// ── Sessions ────────────────────────────────────────────────────────────────\n\nexport interface ConnectedSessionsRowProps {\n notify?: SettingsNotify\n /** Ask before ending a session; resolve `false` to cancel. Default: end at once. */\n confirm?: (message: string) => Promise<boolean> | boolean\n /** Glyph per session status. */\n renderSessionIcon?: (status: string) => ReactNode\n}\n\n/** \"Active sessions\" row with the manage dialog (`ActiveSessionsDialog`); end any but this device. */\nexport function ConnectedSessionsRow({\n notify,\n confirm,\n renderSessionIcon,\n}: ConnectedSessionsRowProps) {\n const [open, setOpen] = useState(false)\n const sessions = useSessions({ enabled: open })\n const currentSessionId = useCurrentSessionId()\n const terminate = useTerminateSession()\n const views = toActiveSessionViews(sessions.data ?? [], {\n currentSessionId,\n terminatingId: terminate.isPending ? terminate.variables : null,\n renderIcon: renderSessionIcon,\n })\n return (\n <>\n <SettingsRow\n label=\"Active sessions\"\n description=\"Devices and agents currently signed in to your account.\"\n >\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setOpen(true)}\n className=\"flex items-center gap-2\"\n data-testid=\"active-sessions-button\"\n >\n <Radio className=\"h-4 w-4\" />\n Manage\n </Button>\n </SettingsRow>\n <ActiveSessionsDialog\n open={open}\n onOpenChange={setOpen}\n isLoading={sessions.isLoading}\n sessions={views}\n onTerminate={(id) => {\n void (async () => {\n const view = views.find((v) => v.id === id)\n const label = view?.detail.split(' · ')[0]\n const ok =\n (await confirm?.(\n `End the session on ${label}? It will be signed out immediately.`\n )) ?? true\n if (!ok) return\n try {\n await terminate.mutateAsync(id)\n } catch {\n notify?.('Failed to end session. Please try again.', 'error')\n }\n })()\n }}\n />\n </>\n )\n}\n\nexport interface ConnectedLogoutDialogProps {\n open: boolean\n onClose: () => void\n isOnline?: boolean\n renderSessionIcon?: (status: string) => ReactNode\n}\n\n/** Sign out of this device or all devices (`LogoutDialog`), listing the active sessions. */\nexport function ConnectedLogoutDialog({\n open,\n onClose,\n isOnline = true,\n renderSessionIcon,\n}: ConnectedLogoutDialogProps) {\n const { logout } = useConnection()\n const sessions = useSessions({ enabled: open })\n const logoutAll = useLogoutAllSessions()\n return (\n <LogoutDialog\n open={open}\n onClose={onClose}\n onLogoutThis={() => {\n onClose()\n logout()\n }}\n onLogoutAll={() => {\n onClose()\n // The server drops every session first; the connection then forgets this one.\n void logoutAll.mutateAsync().finally(logout)\n }}\n canLogoutAll\n isOnline={isOnline}\n sessions={toLogoutSessionViews(sessions.data ?? [])}\n renderSessionIcon={renderSessionIcon}\n />\n )\n}\n\n// ── Danger zone ─────────────────────────────────────────────────────────────\n\nexport interface ConnectedDangerZoneProps {\n notify?: SettingsNotify\n /** Link to the billing page for a deletion blocked by an active subscription. */\n renderSubscriptionLink?: () => ReactNode\n}\n\n/** \"Delete your account\": the collapsed danger zone and the two-step dialog (`DeleteAccountDialog`). */\nexport function ConnectedDangerZone({ notify, renderSubscriptionLink }: ConnectedDangerZoneProps) {\n const [zoneOpen, setZoneOpen] = useState(false)\n const [dialogOpen, setDialogOpen] = useState(false)\n const { user, logout } = useConnection()\n const remove = useDeleteAccount()\n const flow = useDeleteAccountFlow({\n userEmail: user?.email ?? '',\n remove: () => remove.mutateAsync(),\n onClose: () => setDialogOpen(false),\n onDeleted: logout,\n onError: () => notify?.('Failed to delete account. Please try again.', 'error'),\n })\n return (\n <>\n <SettingsDangerZone\n isOpen={zoneOpen}\n onToggle={() => setZoneOpen((o) => !o)}\n title=\"Delete your account\"\n description=\"Once deleted, your account will be immediately closed and you will be logged out. This action cannot be undone.\"\n action={\n <Button\n variant=\"destructive\"\n size=\"sm\"\n disabled={!user?.email}\n onClick={() => setDialogOpen(true)}\n data-testid=\"delete-account-button\"\n >\n Delete Account\n </Button>\n }\n />\n <DeleteAccountDialog\n open={dialogOpen}\n onClose={flow.onClose}\n step={flow.step}\n blockers={toDeleteBlockerViews(flow.blockers, renderSubscriptionLink)}\n onContinue={flow.onContinue}\n onBack={flow.onBack}\n userEmail={user?.email ?? ''}\n confirmEmail={flow.confirmEmail}\n onConfirmEmailChange={flow.onConfirmEmailChange}\n isDeleting={flow.isDeleting}\n onSubmit={flow.onSubmit}\n />\n </>\n )\n}\n","import { useEffect } from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useArbi, useArbiWebSocket, useNotify, notify, type AppNotification } from '@arbidocs/react'\nimport { useConnection } from './ConnectionProvider'\n\n/** Bridge persisted document mentions to the shared bell; hosts own routing. */\nexport function useConnectedDocxNotifications(\n onOpen: (target: {\n workspaceId: string\n documentId: string\n commentId: string\n }) => void | Promise<void>\n) {\n const arbi = useArbi()\n const { status, user, apiUrl } = useConnection()\n const queries = useQueryClient()\n const source = `docx-mentions:${apiUrl}:${user?.externalId || ''}`\n const queryKey = ['docx-mentions', apiUrl, user?.externalId]\n const { data = [] } = useQuery({\n queryKey,\n queryFn: () => arbi.notifications.list('docx_mention'),\n enabled: status === 'authenticated',\n refetchInterval: 30_000,\n })\n useArbiWebSocket((message) => {\n if (message.type === 'docx_mention') void queries.invalidateQueries({ queryKey })\n })\n useEffect(() => {\n const items: AppNotification[] = []\n if (status === 'authenticated')\n for (const note of data) {\n if (note.recipient.external_id !== user?.externalId || !note.workspace_ext_id) continue\n try {\n const target = JSON.parse(note.content || '{}') as {\n document_id?: string\n comment_id?: string\n }\n if (!target.document_id?.startsWith('doc-') || !target.comment_id) continue\n const documentId = target.document_id,\n commentId = target.comment_id,\n workspaceId = note.workspace_ext_id\n items.push({\n id: `docx:${note.external_id}`,\n title: 'Mentioned you in a document comment',\n description: [note.sender.given_name, note.sender.family_name]\n .filter(Boolean)\n .join(' '),\n variant: 'info',\n ts: Date.parse(note.created_at),\n read: note.read,\n source,\n onSelect: () => {\n void Promise.resolve(onOpen({ documentId, commentId, workspaceId })).catch((error) =>\n notify.error(\n error instanceof Error ? error.message : 'Could not open the document.'\n )\n )\n },\n })\n } catch {\n /* Ignore invalid legacy payloads. */\n }\n }\n useNotify.getState().syncSource(source, items)\n return () => useNotify.getState().syncSource(source, [])\n }, [data, status, user?.externalId, source, onOpen])\n const markRead = async (ids: string[]) => {\n try {\n await arbi.notifications.markRead(ids)\n await queries.invalidateQueries({ queryKey })\n } catch {\n notify.error('Could not mark document mentions read.')\n }\n }\n return {\n onMarkRead: (id: string) => {\n if (id.startsWith('docx:')) void markRead([id.slice(5)])\n },\n onMarkAllRead: () => {\n void markRead(\n data\n .filter((note) => !note.read && note.recipient.external_id === user?.externalId)\n .map((note) => note.external_id)\n )\n },\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/connection/ArbiAppProvider.tsx","../../src/connection/StreamedArtifact.tsx","../../src/connection/useConnectedShellWorkspaces.ts","../../src/connection/ConnectedSettings.tsx","../../src/connection/useConnectedDocxNotifications.ts"],"names":["useConnection","jsx","ArbiWebSocketProvider","useState","QueryClient","QueryClientProvider","ArbiProvider","ConnectionProvider","lazy","artifacts","useStreamedArtifact","ArtifactCanvas","StreamedArtifactFrame","Suspense","useWorkspaces","useShellWorkspaces","notify","useProfile","useUpdateProfile","useRequestEmailChange","useConfirmEmailChange","useNameEditor","useAvatarCrop","useEmailChange","SettingsSection","UserCircle","ProfileCard","jsxs","Fragment","AvatarPicker","initials","ImageCropModal","usePasswordChange","usePasswordChangeForm","KeyRound","SettingsCard","SettingsActionRow","PasswordChangeDialog","EMAIL_NOTIFICATION_CATEGORIES","useMemo","EMAIL_NOTIFICATION_KEYS","useNotificationPreferences","NotificationCategoryList","toNotificationCategories","useSessions","useCurrentSessionId","useTerminateSession","toActiveSessionViews","SettingsRow","Button","Radio","ActiveSessionsDialog","useLogoutAllSessions","LogoutDialog","toLogoutSessionViews","useDeleteAccount","useDeleteAccountFlow","SettingsDangerZone","DeleteAccountDialog","toDeleteBlockerViews","useArbi","useQueryClient","useQuery","useArbiWebSocket","useEffect","useNotify"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Composition root for a host app on the ARBI React SDK.\n *\n * QueryClientProvider → react-query cache shared with the SDK\n * ArbiProvider → the SDK's Arbi instance (no network until login)\n * ConnectionProvider → demo/live auth + workspace layer\n *\n * With no live `apiUrl`, ArbiProvider is still mounted (cheap, inert) against\n * `demoApiUrl` and the app runs entirely in seeded demo mode.\n */\nimport { useState, type ReactNode } from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ArbiProvider, ArbiWebSocketProvider } from '@arbidocs/react'\nimport { ConnectionProvider, useConnection } from './ConnectionProvider'\nimport type { ArbiConnectionConfig } from './types'\n\n/**\n * Opens the shared SDK WebSocket once the app is live-authenticated (demo /\n * logged-out sessions have no backend, so they stay disconnected). Lives inside\n * ConnectionProvider so it can read the live status.\n */\nfunction ConnectionBoundWebSocket({ children }: { children: ReactNode }) {\n const { status } = useConnection()\n return (\n <ArbiWebSocketProvider enabled={status === 'authenticated'}>{children}</ArbiWebSocketProvider>\n )\n}\n\nexport function ArbiAppProvider({\n config,\n children,\n}: {\n config: ArbiConnectionConfig\n children: ReactNode\n}) {\n const [queryClient] = useState(\n () =>\n new QueryClient({\n defaultOptions: { queries: { staleTime: 30_000, retry: 1, refetchOnWindowFocus: false } },\n })\n )\n\n const providerUrl = config.apiUrl || config.demoApiUrl || 'https://demo.arbi.local'\n\n return (\n <QueryClientProvider client={queryClient}>\n <ArbiProvider url={providerUrl}>\n <ConnectionProvider config={config}>\n <ConnectionBoundWebSocket>{children}</ConnectionBoundWebSocket>\n </ConnectionProvider>\n </ArbiProvider>\n </QueryClientProvider>\n )\n}\n","import { lazy, Suspense } from 'react'\nimport { ArtifactCanvas } from '@arbidocs/react'\nimport { useStreamedArtifact, type UseStreamedArtifactOptions } from '@arbidocs/react/artifacts'\nimport {\n StreamedArtifactFrame,\n type StreamedArtifactFrameLabels,\n type StreamedArtifactFrameTestIds,\n} from '../artifacts/StreamedArtifactFrame'\nimport type { ArtifactEvent } from './ai'\nimport type { StreamedArtifactEditorProps } from './StreamedArtifactEditor'\n\n// The editor (MDXEditor, Lexical) stays out of the bundle until a draft is ready to edit.\nconst StreamedArtifactEditor = lazy(() => import('./StreamedArtifactEditor'))\n\nexport interface StreamedArtifactProps\n extends\n Pick<UseStreamedArtifactOptions, 'configId' | 'parseRetry' | 'clean'>,\n Pick<\n StreamedArtifactEditorProps,\n 'editorProps' | 'onSaved' | 'onSaveError' | 'actions' | 'hideDefaultActions'\n > {\n /** The artifacts of the agent run (`useConnectedAiTask().artifacts`). */\n artifacts: ArtifactEvent[]\n workspaceId: string | undefined\n /** The agent is still working: show the live canvas. */\n busy: boolean\n /** The run failed; with no draft the canvas shows it. */\n error?: string | null\n stepCount?: number\n busyHint?: string\n emptyHint?: string\n className?: string\n /** Root test id of the editor; the preparing state is `${testId}-preparing`. */\n testId?: string\n labels?: Partial<StreamedArtifactFrameLabels>\n testIds?: Partial<StreamedArtifactFrameTestIds>\n}\n\n/**\n * An agent-drafted artifact from stream to editor, in one part. Pass the run's `artifacts` and\n * whether it is `busy`; it shows\n *\n * 1. the live `ArtifactCanvas` while the agent streams;\n * 2. \"Preparing editor...\" (the canvas stays readable underneath) while the finished draft is\n * cleaned (`cleanDraftMarkdown`), stored as version 1 of the artifact (`wpType: 'artifact'`)\n * and parsed by the backend, which can take up to about a minute;\n * 3. `ArtifactEditor` on the stored version (edit, save a new version, version list, compare\n * with track changes) when its text is ready;\n * 4. an error with Retry when storing or parsing fails.\n *\n * Needs `<ArbiProvider>` + React Query. The host imports the editor stylesheet\n * (`@mdxeditor/editor/style.css`) and defines the global `Prism` in a module it imports at app\n * start (see the Artifacts section of docs/design/blocks-package.md).\n *\n * ```tsx\n * const task = useConnectedAiTask()\n * <StreamedArtifact artifacts={task.artifacts} workspaceId={workspaceId} busy={task.status === 'running'} error={task.error} />\n * ```\n */\nexport function StreamedArtifact({\n artifacts,\n workspaceId,\n busy,\n error = null,\n stepCount,\n busyHint,\n emptyHint,\n className,\n testId = 'streamed-artifact',\n configId,\n parseRetry,\n clean,\n editorProps,\n onSaved,\n onSaveError,\n actions,\n hideDefaultActions,\n labels,\n testIds,\n}: StreamedArtifactProps) {\n const streamed = useStreamedArtifact({\n artifacts,\n workspaceId,\n settled: !busy && !error,\n configId,\n parseRetry,\n clean,\n })\n const canvas = (\n <ArtifactCanvas\n artifacts={artifacts}\n className={streamed.phase === 'streaming' ? className : undefined}\n busy={busy}\n busyHint={busyHint}\n stepCount={stepCount}\n error={error}\n emptyHint={emptyHint}\n />\n )\n return (\n <StreamedArtifactFrame\n phase={streamed.phase}\n canvas={canvas}\n className={className}\n error={streamed.error?.message}\n onRetry={streamed.retry}\n labels={labels}\n testIds={{ preparing: `${testId}-preparing`, error: `${testId}-error`, ...testIds }}\n >\n <Suspense fallback={canvas}>\n {streamed.docId && (\n <StreamedArtifactEditor\n key={streamed.docId}\n workspaceId={workspaceId}\n docId={streamed.docId}\n title={streamed.artifact?.title ?? 'Draft'}\n testId={testId}\n className={className}\n editorProps={editorProps}\n onSaved={onSaved}\n onSaveError={onSaveError}\n actions={actions}\n hideDefaultActions={hideDefaultActions}\n />\n )}\n </Suspense>\n </StreamedArtifactFrame>\n )\n}\n","import {\n useShellWorkspaces,\n useWorkspaces,\n type ShellWorkspaceSource,\n type UseShellWorkspacesOptions,\n type UseShellWorkspacesResult,\n} from '@arbidocs/react'\nimport { useConnection } from './ConnectionProvider'\n\nexport type UseConnectedShellWorkspacesOptions = Omit<\n UseShellWorkspacesOptions,\n 'workspaces' | 'isLoading' | 'loadError' | 'selectedId' | 'select'\n>\n\n/**\n * `useShellWorkspaces` wired to the connection layer: the account's live workspaces, the\n * connection's single selection as the active workspace, and `open` = `setWorkspace` (opens it on\n * the server, remembers it for the next login) then `onOpened`.\n *\n * ```tsx\n * const { active, recent, open } = useConnectedShellWorkspaces({\n * seed: { workspaces: demoWorkspaces, activeId: 'demo-1' },\n * onOpened: () => navigate('/app/documents'),\n * })\n * ```\n */\nexport function useConnectedShellWorkspaces(\n options: UseConnectedShellWorkspacesOptions = {}\n): UseShellWorkspacesResult {\n const { workspaceId, setWorkspace } = useConnection()\n const query = useWorkspaces()\n return useShellWorkspaces({\n ...options,\n workspaces: Array.isArray(query.data) ? (query.data as ShellWorkspaceSource[]) : undefined,\n isLoading: query.isLoading,\n loadError: query.error,\n selectedId: workspaceId,\n select: (workspace) => setWorkspace(workspace.id),\n })\n}\n","/**\n * The account area of a settings page, bound to the ARBI SDK: each section is a blocks part wired\n * to its `@arbidocs/react` hook, so a host drops them in a `SettingsPanel` and owns only the\n * layout (see the \"Settings page recipe\" in docs/design/blocks-package.md).\n *\n * Every section takes an optional `notify` for toasts and renders the default test ids of its\n * part. Anything the hooks cannot know (the recovery-key download, the billing link of a blocked\n * deletion, the password policy) is a prop.\n */\nimport { useMemo, useState, type ReactNode } from 'react'\nimport { KeyRound, Radio, UserCircle } from 'lucide-react'\nimport {\n ImageCropModal,\n useAvatarCrop,\n useConfirmEmailChange,\n useCurrentSessionId,\n useDeleteAccount,\n useDeleteAccountFlow,\n useEmailChange,\n useLogoutAllSessions,\n useNameEditor,\n useNotificationPreferences,\n usePasswordChange,\n usePasswordChangeForm,\n useProfile,\n useRequestEmailChange,\n useSessions,\n useTerminateSession,\n useUpdateProfile,\n useWorkspaces,\n type AvatarFileProblem,\n type PasswordChangeResult,\n} from '@arbidocs/react'\nimport { Button } from '@arbidocs/react/ui'\nimport { initials } from '../lib/format'\nimport { AvatarPicker } from '../settings/AvatarPicker'\nimport { ProfileCard } from '../settings/ProfileCard'\nimport {\n SettingsActionRow,\n SettingsCard,\n SettingsDangerZone,\n SettingsRow,\n SettingsSection,\n} from '../settings/SettingsPanel'\nimport { PasswordChangeDialog } from '../settings/PasswordChangeDialog'\nimport { ActiveSessionsDialog, DeleteAccountDialog } from '../settings/AccountDialogs'\nimport { LogoutDialog } from '../settings/LogoutDialog'\nimport { NotificationCategoryList } from '../settings/NotificationCategoryList'\nimport {\n EMAIL_NOTIFICATION_CATEGORIES,\n EMAIL_NOTIFICATION_KEYS,\n toActiveSessionViews,\n toDeleteBlockerViews,\n toLogoutSessionViews,\n toNotificationCategories,\n type EmailNotificationCategoryDef,\n} from '../settings/account-views'\nimport { useConnection } from './ConnectionProvider'\n\nexport type SettingsNotify = (message: string, kind: 'success' | 'error') => void\n\n/** The error text of a failed call: the backend `detail` when it sent one. */\nfunction errorText(error: unknown, fallback: string): string {\n const body = (error as { apiError?: { detail?: unknown } } | null)?.apiError\n return typeof body?.detail === 'string' ? body.detail : fallback\n}\n\nconst AVATAR_PROBLEMS: Record<AvatarFileProblem, string> = {\n 'not-image': 'Please choose an image file',\n 'too-large': 'Image must be 5 MB or smaller',\n unreadable: \"Couldn't read that image — try a different file\",\n}\n\n// ── Profile ─────────────────────────────────────────────────────────────────\n\nexport interface ConnectedProfileCardProps {\n notify?: SettingsNotify\n /** Section heading; default `Profile`. */\n title?: ReactNode\n}\n\n/** Avatar, editable name and email change of the signed-in user (`ProfileCard`). */\nexport function ConnectedProfileCard({ notify, title = 'Profile' }: ConnectedProfileCardProps) {\n const { data: profile } = useProfile()\n const updateProfile = useUpdateProfile()\n const requestEmailChange = useRequestEmailChange()\n const confirmEmailChange = useConfirmEmailChange()\n const { user } = useConnection()\n\n const name = useNameEditor({\n givenName: profile?.givenName,\n familyName: profile?.familyName,\n save: async (next) => {\n try {\n await updateProfile.mutateAsync(next)\n notify?.('Name updated', 'success')\n } catch (e) {\n notify?.('Failed to update name', 'error')\n throw e\n }\n },\n })\n const avatar = useAvatarCrop({\n upload: async (picture) => {\n try {\n await updateProfile.mutateAsync({ picture })\n notify?.('Profile picture updated', 'success')\n } catch (e) {\n notify?.('Failed to update picture', 'error')\n throw e\n }\n },\n onProblem: (problem) => notify?.(AVATAR_PROBLEMS[problem], 'error'),\n })\n const email = useEmailChange({\n requestCode: async (address) => {\n try {\n await requestEmailChange.mutateAsync(address)\n notify?.('Verification code sent to your new email', 'success')\n } catch (e) {\n notify?.(errorText(e, 'Failed to send verification code'), 'error')\n throw e\n }\n },\n confirm: async (args) => {\n try {\n await confirmEmailChange.mutateAsync(args)\n notify?.('Email address updated', 'success')\n } catch (e) {\n notify?.(errorText(e, 'Invalid or expired verification code'), 'error')\n throw e\n }\n },\n })\n\n const display = profile?.fullName || user?.name || 'Unnamed'\n return (\n <SettingsSection icon={<UserCircle />} title={title}>\n <ProfileCard\n avatar={\n <>\n <AvatarPicker\n pictureUrl={profile?.picture ?? user?.picture}\n initials={initials(display)}\n fallbackClassName=\"bg-primary text-primary-foreground\"\n isUploading={avatar.isUploading}\n onFileChosen={avatar.onFileChosen}\n />\n <ImageCropModal\n open={avatar.pendingImage !== null}\n image={avatar.pendingImage}\n title=\"Crop your photo\"\n aspect={1}\n cropShape=\"round\"\n output={{ maxSize: 128, mimeType: 'image/jpeg', quality: 0.85 }}\n onComplete={avatar.onCropComplete}\n onCancel={avatar.onCropCancel}\n />\n </>\n }\n name={{ ...name, display, isSaving: name.isSaving }}\n email={profile?.email ?? user?.email ?? ''}\n isSso={profile?.isSso ?? false}\n onStartEmailChange={email.onStart}\n emailChange={email.isOpen ? email : undefined}\n />\n </SettingsSection>\n )\n}\n\n// ── Security: password ──────────────────────────────────────────────────────\n\n/** The default password policy: 8 characters, an uppercase letter or symbol, a digit. */\nexport function defaultUnmetPasswordRequirement(password: string): string | null {\n if (password.length < 8) return 'Minimum 8 characters'\n if (!/[A-Z!@#$%^&*()_+\\-=[\\]{};':\"\\\\|,.<>/?]/.test(password)) {\n return 'At least one uppercase letter or special character'\n }\n if (!/[0-9]/.test(password)) return 'At least one number'\n return null\n}\n\nexport interface ConnectedSecuritySectionProps {\n notify?: SettingsNotify\n /** The host's password policy; default is {@link defaultUnmetPasswordRequirement}. */\n getUnmetRequirement?: (password: string) => string | null\n /** The recovery-key download for the key the new password produced (shown on success). */\n renderRecoveryKey?: (result: PasswordChangeResult) => ReactNode\n /** Extra rows under \"Change password\" (e.g. \"Save recovery key\"). */\n children?: ReactNode\n}\n\n/** The Security card: \"Change password\" and the dialog behind it (`PasswordChangeDialog`). */\nexport function ConnectedSecuritySection({\n notify,\n getUnmetRequirement = defaultUnmetPasswordRequirement,\n renderRecoveryKey,\n children,\n}: ConnectedSecuritySectionProps) {\n const [open, setOpen] = useState(false)\n const change = usePasswordChange()\n // Only workspaces the user belongs to are re-keyed.\n const { data: workspaces } = useWorkspaces({ enabled: open })\n const workspaceCount = (workspaces ?? []).filter((w) => w.is_member).length\n const form = usePasswordChangeForm<PasswordChangeResult>({\n getUnmetRequirement,\n submit: async (vars) => {\n const result = await change.mutateAsync(vars)\n notify?.('Password changed successfully', 'success')\n return result\n },\n onClose: () => setOpen(false),\n })\n\n return (\n <SettingsSection icon={<KeyRound />} title=\"Security\">\n <SettingsCard padding=\"sm\">\n <SettingsActionRow\n title=\"Change password\"\n description=\"Used to sign in and to encrypt your data. Changing it re-encrypts everything in your account.\"\n onClick={() => setOpen(true)}\n testId=\"change-password-button\"\n />\n {children}\n </SettingsCard>\n <PasswordChangeDialog\n open={open}\n onClose={form.onCancel}\n recoveryMode={false}\n currentPassword={form.currentPassword}\n onCurrentPasswordChange={form.onCurrentPasswordChange}\n newPassword={form.newPassword}\n onNewPasswordChange={form.onNewPasswordChange}\n confirmPassword={form.confirmPassword}\n onConfirmPasswordChange={form.onConfirmPasswordChange}\n getUnmetRequirement={getUnmetRequirement}\n workspaceCount={workspaceCount}\n error={form.error}\n isProcessing={form.isProcessing}\n isSubmitDisabled={form.isSubmitDisabled}\n onSubmit={form.onSubmit}\n success={form.result ? (renderRecoveryKey?.(form.result) ?? <></>) : null}\n onDone={form.onDone}\n />\n </SettingsSection>\n )\n}\n\n// ── Notifications ───────────────────────────────────────────────────────────\n\nexport interface ConnectedNotificationPreferencesProps {\n /** Categories to offer; default {@link EMAIL_NOTIFICATION_CATEGORIES}. */\n categories?: readonly EmailNotificationCategoryDef[]\n title?: ReactNode\n}\n\n/** The email-notification switches (`NotificationCategoryList`) over the user settings. */\nexport function ConnectedNotificationPreferences({\n categories = EMAIL_NOTIFICATION_CATEGORIES,\n title = 'Notifications',\n}: ConnectedNotificationPreferencesProps) {\n const keys = useMemo(\n () =>\n categories === EMAIL_NOTIFICATION_CATEGORIES\n ? EMAIL_NOTIFICATION_KEYS\n : categories.map((c) => c.key),\n [categories]\n )\n const prefs = useNotificationPreferences(keys)\n return (\n <SettingsSection title={title}>\n <SettingsCard className=\"space-y-0\">\n <NotificationCategoryList\n masterId=\"emailNotifications\"\n masterTitle=\"Email Notifications\"\n masterDescription=\"Email me about activity when I’m away\"\n masterChecked={prefs.masterChecked}\n onMasterChange={prefs.setAll}\n categories={toNotificationCategories(prefs.checked, categories)}\n onCategoryChange={prefs.setCategory}\n />\n </SettingsCard>\n </SettingsSection>\n )\n}\n\n// ── Sessions ────────────────────────────────────────────────────────────────\n\nexport interface ConnectedSessionsRowProps {\n notify?: SettingsNotify\n /** Ask before ending a session; resolve `false` to cancel. Default: end at once. */\n confirm?: (message: string) => Promise<boolean> | boolean\n /** Glyph per session status. */\n renderSessionIcon?: (status: string) => ReactNode\n}\n\n/** \"Active sessions\" row with the manage dialog (`ActiveSessionsDialog`); end any but this device. */\nexport function ConnectedSessionsRow({\n notify,\n confirm,\n renderSessionIcon,\n}: ConnectedSessionsRowProps) {\n const [open, setOpen] = useState(false)\n const sessions = useSessions({ enabled: open })\n const currentSessionId = useCurrentSessionId()\n const terminate = useTerminateSession()\n const views = toActiveSessionViews(sessions.data ?? [], {\n currentSessionId,\n terminatingId: terminate.isPending ? terminate.variables : null,\n renderIcon: renderSessionIcon,\n })\n return (\n <>\n <SettingsRow\n label=\"Active sessions\"\n description=\"Devices and agents currently signed in to your account.\"\n >\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setOpen(true)}\n className=\"flex items-center gap-2\"\n data-testid=\"active-sessions-button\"\n >\n <Radio className=\"h-4 w-4\" />\n Manage\n </Button>\n </SettingsRow>\n <ActiveSessionsDialog\n open={open}\n onOpenChange={setOpen}\n isLoading={sessions.isLoading}\n sessions={views}\n onTerminate={(id) => {\n void (async () => {\n const view = views.find((v) => v.id === id)\n const label = view?.detail.split(' · ')[0]\n const ok =\n (await confirm?.(\n `End the session on ${label}? It will be signed out immediately.`\n )) ?? true\n if (!ok) return\n try {\n await terminate.mutateAsync(id)\n } catch {\n notify?.('Failed to end session. Please try again.', 'error')\n }\n })()\n }}\n />\n </>\n )\n}\n\nexport interface ConnectedLogoutDialogProps {\n open: boolean\n onClose: () => void\n isOnline?: boolean\n renderSessionIcon?: (status: string) => ReactNode\n}\n\n/** Sign out of this device or all devices (`LogoutDialog`), listing the active sessions. */\nexport function ConnectedLogoutDialog({\n open,\n onClose,\n isOnline = true,\n renderSessionIcon,\n}: ConnectedLogoutDialogProps) {\n const { logout } = useConnection()\n const sessions = useSessions({ enabled: open })\n const logoutAll = useLogoutAllSessions()\n return (\n <LogoutDialog\n open={open}\n onClose={onClose}\n onLogoutThis={() => {\n onClose()\n logout()\n }}\n onLogoutAll={() => {\n onClose()\n // The server drops every session first; the connection then forgets this one.\n void logoutAll.mutateAsync().finally(logout)\n }}\n canLogoutAll\n isOnline={isOnline}\n sessions={toLogoutSessionViews(sessions.data ?? [])}\n renderSessionIcon={renderSessionIcon}\n />\n )\n}\n\n// ── Danger zone ─────────────────────────────────────────────────────────────\n\nexport interface ConnectedDangerZoneProps {\n notify?: SettingsNotify\n /** Link to the billing page for a deletion blocked by an active subscription. */\n renderSubscriptionLink?: () => ReactNode\n}\n\n/** \"Delete your account\": the collapsed danger zone and the two-step dialog (`DeleteAccountDialog`). */\nexport function ConnectedDangerZone({ notify, renderSubscriptionLink }: ConnectedDangerZoneProps) {\n const [zoneOpen, setZoneOpen] = useState(false)\n const [dialogOpen, setDialogOpen] = useState(false)\n const { user, logout } = useConnection()\n const remove = useDeleteAccount()\n const flow = useDeleteAccountFlow({\n userEmail: user?.email ?? '',\n remove: () => remove.mutateAsync(),\n onClose: () => setDialogOpen(false),\n onDeleted: logout,\n onError: () => notify?.('Failed to delete account. Please try again.', 'error'),\n })\n return (\n <>\n <SettingsDangerZone\n isOpen={zoneOpen}\n onToggle={() => setZoneOpen((o) => !o)}\n title=\"Delete your account\"\n description=\"Once deleted, your account will be immediately closed and you will be logged out. This action cannot be undone.\"\n action={\n <Button\n variant=\"destructive\"\n size=\"sm\"\n disabled={!user?.email}\n onClick={() => setDialogOpen(true)}\n data-testid=\"delete-account-button\"\n >\n Delete Account\n </Button>\n }\n />\n <DeleteAccountDialog\n open={dialogOpen}\n onClose={flow.onClose}\n step={flow.step}\n blockers={toDeleteBlockerViews(flow.blockers, renderSubscriptionLink)}\n onContinue={flow.onContinue}\n onBack={flow.onBack}\n userEmail={user?.email ?? ''}\n confirmEmail={flow.confirmEmail}\n onConfirmEmailChange={flow.onConfirmEmailChange}\n isDeleting={flow.isDeleting}\n onSubmit={flow.onSubmit}\n />\n </>\n )\n}\n","import { useEffect } from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useArbi, useArbiWebSocket, notify, type AppNotification } from '@arbidocs/react'\nimport { useNotify } from '@arbidocs/react/shell'\nimport { useConnection } from './ConnectionProvider'\n\n/** Bridge persisted document mentions to the shared bell; hosts own routing. */\nexport function useConnectedDocxNotifications(\n onOpen: (target: {\n workspaceId: string\n documentId: string\n commentId: string\n }) => void | Promise<void>\n) {\n const arbi = useArbi()\n const { status, user, apiUrl } = useConnection()\n const queries = useQueryClient()\n const source = `docx-mentions:${apiUrl}:${user?.externalId || ''}`\n const queryKey = ['docx-mentions', apiUrl, user?.externalId]\n const { data = [] } = useQuery({\n queryKey,\n queryFn: () => arbi.notifications.list('docx_mention'),\n enabled: status === 'authenticated',\n refetchInterval: 30_000,\n })\n useArbiWebSocket((message) => {\n if (message.type === 'docx_mention') void queries.invalidateQueries({ queryKey })\n })\n useEffect(() => {\n const items: AppNotification[] = []\n if (status === 'authenticated')\n for (const note of data) {\n if (note.recipient.external_id !== user?.externalId || !note.workspace_ext_id) continue\n try {\n const target = JSON.parse(note.content || '{}') as {\n document_id?: string\n comment_id?: string\n }\n if (!target.document_id?.startsWith('doc-') || !target.comment_id) continue\n const documentId = target.document_id,\n commentId = target.comment_id,\n workspaceId = note.workspace_ext_id\n items.push({\n id: `docx:${note.external_id}`,\n title: 'Mentioned you in a document comment',\n description: [note.sender.given_name, note.sender.family_name]\n .filter(Boolean)\n .join(' '),\n variant: 'info',\n ts: Date.parse(note.created_at),\n read: note.read,\n source,\n onSelect: () => {\n void Promise.resolve(onOpen({ documentId, commentId, workspaceId })).catch((error) =>\n notify.error(\n error instanceof Error ? error.message : 'Could not open the document.'\n )\n )\n },\n })\n } catch {\n /* Ignore invalid legacy payloads. */\n }\n }\n useNotify.getState().syncSource(source, items)\n return () => useNotify.getState().syncSource(source, [])\n }, [data, status, user?.externalId, source, onOpen])\n const markRead = async (ids: string[]) => {\n try {\n await arbi.notifications.markRead(ids)\n await queries.invalidateQueries({ queryKey })\n } catch {\n notify.error('Could not mark document mentions read.')\n }\n }\n return {\n onMarkRead: (id: string) => {\n if (id.startsWith('docx:')) void markRead([id.slice(5)])\n },\n onMarkAllRead: () => {\n void markRead(\n data\n .filter((note) => !note.read && note.recipient.external_id === user?.externalId)\n .map((note) => note.external_id)\n )\n },\n }\n}\n"]}
|
package/dist/connect/index.js
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
export { ConnectedAssistantDock, redlineStats, textToArtifact, toRedlineMarkdown, useConnectedAiTask, useConnectedChat, useSemanticSearch, useWorkspaceDocs } from '../chunk-5TRALRWN.js';
|
|
3
|
-
import { SettingsSection, ProfileCard, AvatarPicker, SettingsCard, SettingsActionRow, PasswordChangeDialog, EMAIL_NOTIFICATION_KEYS, EMAIL_NOTIFICATION_CATEGORIES, NotificationCategoryList, toNotificationCategories, toActiveSessionViews, SettingsRow, ActiveSessionsDialog, LogoutDialog, toLogoutSessionViews, SettingsDangerZone, DeleteAccountDialog, toDeleteBlockerViews } from '../chunk-
|
|
3
|
+
import { SettingsSection, ProfileCard, AvatarPicker, SettingsCard, SettingsActionRow, PasswordChangeDialog, EMAIL_NOTIFICATION_KEYS, EMAIL_NOTIFICATION_CATEGORIES, NotificationCategoryList, toNotificationCategories, toActiveSessionViews, SettingsRow, ActiveSessionsDialog, LogoutDialog, toLogoutSessionViews, SettingsDangerZone, DeleteAccountDialog, toDeleteBlockerViews } from '../chunk-557EU3G4.js';
|
|
4
4
|
import { StreamedArtifactFrame } from '../chunk-LOJVUGBJ.js';
|
|
5
5
|
import '../chunk-VILAPTCB.js';
|
|
6
|
+
import '../chunk-TJMKFY5P.js';
|
|
6
7
|
import '../chunk-JLPYOPCX.js';
|
|
7
8
|
import '../chunk-KZJAG7T3.js';
|
|
8
9
|
import '../chunk-NPLYHR2E.js';
|
|
9
10
|
import { initials } from '../chunk-OXF2IFXG.js';
|
|
10
|
-
import '../chunk-TJMKFY5P.js';
|
|
11
11
|
import { ConnectionProvider, useConnection } from '../chunk-ZEIOREJY.js';
|
|
12
12
|
export { ConnectionProvider, SESSION_EXPIRED_MESSAGE, isAuthenticated, useConnection } from '../chunk-ZEIOREJY.js';
|
|
13
13
|
import '../chunk-7F6CBP3Z.js';
|
|
14
14
|
import { lazy, useState, Suspense, useMemo, useEffect } from 'react';
|
|
15
15
|
import { QueryClient, QueryClientProvider, useQueryClient, useQuery } from '@tanstack/react-query';
|
|
16
|
-
import { ArbiProvider, ArtifactCanvas, useWorkspaces, useShellWorkspaces, useProfile, useUpdateProfile, useRequestEmailChange, useConfirmEmailChange, useNameEditor, useAvatarCrop, useEmailChange, ImageCropModal, usePasswordChange, usePasswordChangeForm, useNotificationPreferences, useSessions, useCurrentSessionId, useTerminateSession, useLogoutAllSessions, useDeleteAccount, useDeleteAccountFlow, useArbi, useArbiWebSocket, notify,
|
|
16
|
+
import { ArbiProvider, ArtifactCanvas, useWorkspaces, useShellWorkspaces, useProfile, useUpdateProfile, useRequestEmailChange, useConfirmEmailChange, useNameEditor, useAvatarCrop, useEmailChange, ImageCropModal, usePasswordChange, usePasswordChangeForm, useNotificationPreferences, useSessions, useCurrentSessionId, useTerminateSession, useLogoutAllSessions, useDeleteAccount, useDeleteAccountFlow, useArbi, useArbiWebSocket, notify, ArbiWebSocketProvider } from '@arbidocs/react';
|
|
17
17
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
18
18
|
import { useStreamedArtifact } from '@arbidocs/react/artifacts';
|
|
19
19
|
import { UserCircle, KeyRound, Radio } from 'lucide-react';
|
|
20
20
|
import { Button } from '@arbidocs/react/ui';
|
|
21
|
+
import { useNotify } from '@arbidocs/react/shell';
|
|
21
22
|
|
|
22
23
|
function ConnectionBoundWebSocket({ children }) {
|
|
23
24
|
const { status } = useConnection();
|