@arbidocs/blocks 0.4.21 → 0.4.22

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.
Files changed (82) hide show
  1. package/dist/agents/index.cjs +211 -211
  2. package/dist/agents/index.js +5 -5
  3. package/dist/chat/index.cjs +116 -115
  4. package/dist/chat/index.js +4 -3
  5. package/dist/chunk-5TRALRWN.js +42 -0
  6. package/dist/chunk-5TRALRWN.js.map +1 -0
  7. package/dist/chunk-7UTB4PHM.cjs +300 -0
  8. package/dist/chunk-7UTB4PHM.cjs.map +1 -0
  9. package/dist/chunk-AA3PT6KR.js +286 -0
  10. package/dist/chunk-AA3PT6KR.js.map +1 -0
  11. package/dist/{chunk-5LUI4G5R.js → chunk-BV7FEMSI.js} +3 -3
  12. package/dist/{chunk-5LUI4G5R.js.map → chunk-BV7FEMSI.js.map} +1 -1
  13. package/dist/{chunk-B6N5UXQX.js → chunk-CQ6CYPV4.js} +7 -281
  14. package/dist/chunk-CQ6CYPV4.js.map +1 -0
  15. package/dist/chunk-EUOGPUMJ.cjs +59 -0
  16. package/dist/chunk-EUOGPUMJ.cjs.map +1 -0
  17. package/dist/{chunk-BTDL4Q27.cjs → chunk-JCVZKCXC.cjs} +22 -69
  18. package/dist/chunk-JCVZKCXC.cjs.map +1 -0
  19. package/dist/{chunk-C7SMJ6GJ.js → chunk-MLJDOH3B.js} +5 -5
  20. package/dist/{chunk-C7SMJ6GJ.js.map → chunk-MLJDOH3B.js.map} +1 -1
  21. package/dist/chunk-NNH7N62N.cjs +876 -0
  22. package/dist/chunk-NNH7N62N.cjs.map +1 -0
  23. package/dist/{chunk-MLSRLLU7.cjs → chunk-OEQXYWUO.cjs} +5 -5
  24. package/dist/{chunk-MLSRLLU7.cjs.map → chunk-OEQXYWUO.cjs.map} +1 -1
  25. package/dist/{chunk-54WQYICJ.cjs → chunk-TL2DHSC5.cjs} +10 -296
  26. package/dist/chunk-TL2DHSC5.cjs.map +1 -0
  27. package/dist/chunk-UOLMFC5K.js +846 -0
  28. package/dist/chunk-UOLMFC5K.js.map +1 -0
  29. package/dist/{chunk-TO4FAMQP.cjs → chunk-XKSFJYOD.cjs} +3 -3
  30. package/dist/{chunk-TO4FAMQP.cjs.map → chunk-XKSFJYOD.cjs.map} +1 -1
  31. package/dist/{chunk-2T2ZMOA6.js → chunk-ZEIOREJY.js} +5 -36
  32. package/dist/chunk-ZEIOREJY.js.map +1 -0
  33. package/dist/connect/docx.cjs +86 -0
  34. package/dist/connect/docx.cjs.map +1 -0
  35. package/dist/connect/docx.d.ts +1 -0
  36. package/dist/connect/docx.js +84 -0
  37. package/dist/connect/docx.js.map +1 -0
  38. package/dist/connect/index.cjs +113 -46
  39. package/dist/connect/index.cjs.map +1 -1
  40. package/dist/connect/index.d.ts +1 -0
  41. package/dist/connect/index.js +88 -22
  42. package/dist/connect/index.js.map +1 -1
  43. package/dist/connection/ConnectedNativeDocxEditor.d.ts +5 -0
  44. package/dist/connection/useConnectedDocxNotifications.d.ts +9 -0
  45. package/dist/docx/DocxMentions.d.ts +17 -0
  46. package/dist/docx/NativeDocxComparison.d.ts +10 -0
  47. package/dist/docx/NativeDocxEditor.d.ts +50 -0
  48. package/dist/docx/export.d.ts +2 -0
  49. package/dist/docx/fonts.d.ts +2 -0
  50. package/dist/docx/index.cjs +116 -0
  51. package/dist/docx/index.cjs.map +1 -0
  52. package/dist/docx/index.d.ts +10 -0
  53. package/dist/docx/index.js +63 -0
  54. package/dist/docx/index.js.map +1 -0
  55. package/dist/docx/mentions.d.ts +8 -0
  56. package/dist/facts/index.cjs +2 -2
  57. package/dist/facts/index.js +2 -2
  58. package/dist/files/index.cjs +2 -2
  59. package/dist/files/index.js +2 -2
  60. package/dist/home/index.cjs +1 -1
  61. package/dist/home/index.js +1 -1
  62. package/dist/index.cjs +924 -923
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.js +16 -15
  65. package/dist/index.js.map +1 -1
  66. package/dist/settings/index.cjs +35 -35
  67. package/dist/settings/index.js +4 -4
  68. package/dist/shell/index.cjs +26 -26
  69. package/dist/shell/index.js +4 -4
  70. package/dist/studio/index.cjs +5 -4
  71. package/dist/studio/index.cjs.map +1 -1
  72. package/dist/studio/index.js +3 -2
  73. package/dist/studio/index.js.map +1 -1
  74. package/dist/workspaces/index.cjs +1 -1
  75. package/dist/workspaces/index.js +1 -1
  76. package/package.json +48 -7
  77. package/src/docx/README.md +68 -0
  78. package/src/docx/styles.css +36 -0
  79. package/dist/chunk-2T2ZMOA6.js.map +0 -1
  80. package/dist/chunk-54WQYICJ.cjs.map +0 -1
  81. package/dist/chunk-B6N5UXQX.js.map +0 -1
  82. package/dist/chunk-BTDL4Q27.cjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
+ var chunkEUOGPUMJ_cjs = require('../chunk-EUOGPUMJ.cjs');
4
5
  var chunkYVIOCITQ_cjs = require('../chunk-YVIOCITQ.cjs');
5
- var chunkBTDL4Q27_cjs = require('../chunk-BTDL4Q27.cjs');
6
6
  var chunkQVBZESYQ_cjs = require('../chunk-QVBZESYQ.cjs');
7
7
  require('../chunk-ADOKTJHV.cjs');
8
8
  require('../chunk-J22DXUJY.cjs');
@@ -10,6 +10,7 @@ require('../chunk-VGOFFCMT.cjs');
10
10
  require('../chunk-PPCATBOY.cjs');
11
11
  var chunkKDG6FER6_cjs = require('../chunk-KDG6FER6.cjs');
12
12
  require('../chunk-DCDVWPMB.cjs');
13
+ var chunkJCVZKCXC_cjs = require('../chunk-JCVZKCXC.cjs');
13
14
  require('../chunk-MHVNT4J3.cjs');
14
15
  var react = require('react');
15
16
  var reactQuery = require('@tanstack/react-query');
@@ -20,7 +21,7 @@ var lucideReact = require('lucide-react');
20
21
  var ui = require('@arbidocs/react/ui');
21
22
 
22
23
  function ConnectionBoundWebSocket({ children }) {
23
- const { status } = chunkBTDL4Q27_cjs.useConnection();
24
+ const { status } = chunkJCVZKCXC_cjs.useConnection();
24
25
  return /* @__PURE__ */ jsxRuntime.jsx(react$1.ArbiWebSocketProvider, { enabled: status === "authenticated", children });
25
26
  }
26
27
  function ArbiAppProvider({
@@ -33,7 +34,7 @@ function ArbiAppProvider({
33
34
  })
34
35
  );
35
36
  const providerUrl = config.apiUrl || config.demoApiUrl || "https://demo.arbi.local";
36
- return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.ArbiProvider, { url: providerUrl, children: /* @__PURE__ */ jsxRuntime.jsx(chunkBTDL4Q27_cjs.ConnectionProvider, { config, children: /* @__PURE__ */ jsxRuntime.jsx(ConnectionBoundWebSocket, { children }) }) }) });
37
+ return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.ArbiProvider, { url: providerUrl, children: /* @__PURE__ */ jsxRuntime.jsx(chunkJCVZKCXC_cjs.ConnectionProvider, { config, children: /* @__PURE__ */ jsxRuntime.jsx(ConnectionBoundWebSocket, { children }) }) }) });
37
38
  }
38
39
  var StreamedArtifactEditor = react.lazy(() => import('../StreamedArtifactEditor-L2AZZORU.cjs'));
39
40
  function StreamedArtifact({
@@ -107,7 +108,7 @@ function StreamedArtifact({
107
108
  );
108
109
  }
109
110
  function useConnectedShellWorkspaces(options = {}) {
110
- const { workspaceId, setWorkspace } = chunkBTDL4Q27_cjs.useConnection();
111
+ const { workspaceId, setWorkspace } = chunkJCVZKCXC_cjs.useConnection();
111
112
  const query = react$1.useWorkspaces();
112
113
  return react$1.useShellWorkspaces({
113
114
  ...options,
@@ -127,21 +128,21 @@ var AVATAR_PROBLEMS = {
127
128
  "too-large": "Image must be 5 MB or smaller",
128
129
  unreadable: "Couldn't read that image \u2014 try a different file"
129
130
  };
130
- function ConnectedProfileCard({ notify, title = "Profile" }) {
131
+ function ConnectedProfileCard({ notify: notify2, title = "Profile" }) {
131
132
  const { data: profile } = react$1.useProfile();
132
133
  const updateProfile = react$1.useUpdateProfile();
133
134
  const requestEmailChange = react$1.useRequestEmailChange();
134
135
  const confirmEmailChange = react$1.useConfirmEmailChange();
135
- const { user } = chunkBTDL4Q27_cjs.useConnection();
136
+ const { user } = chunkJCVZKCXC_cjs.useConnection();
136
137
  const name = react$1.useNameEditor({
137
138
  givenName: profile?.givenName,
138
139
  familyName: profile?.familyName,
139
140
  save: async (next) => {
140
141
  try {
141
142
  await updateProfile.mutateAsync(next);
142
- notify?.("Name updated", "success");
143
+ notify2?.("Name updated", "success");
143
144
  } catch (e) {
144
- notify?.("Failed to update name", "error");
145
+ notify2?.("Failed to update name", "error");
145
146
  throw e;
146
147
  }
147
148
  }
@@ -150,30 +151,30 @@ function ConnectedProfileCard({ notify, title = "Profile" }) {
150
151
  upload: async (picture) => {
151
152
  try {
152
153
  await updateProfile.mutateAsync({ picture });
153
- notify?.("Profile picture updated", "success");
154
+ notify2?.("Profile picture updated", "success");
154
155
  } catch (e) {
155
- notify?.("Failed to update picture", "error");
156
+ notify2?.("Failed to update picture", "error");
156
157
  throw e;
157
158
  }
158
159
  },
159
- onProblem: (problem) => notify?.(AVATAR_PROBLEMS[problem], "error")
160
+ onProblem: (problem) => notify2?.(AVATAR_PROBLEMS[problem], "error")
160
161
  });
161
162
  const email = react$1.useEmailChange({
162
163
  requestCode: async (address) => {
163
164
  try {
164
165
  await requestEmailChange.mutateAsync(address);
165
- notify?.("Verification code sent to your new email", "success");
166
+ notify2?.("Verification code sent to your new email", "success");
166
167
  } catch (e) {
167
- notify?.(errorText(e, "Failed to send verification code"), "error");
168
+ notify2?.(errorText(e, "Failed to send verification code"), "error");
168
169
  throw e;
169
170
  }
170
171
  },
171
172
  confirm: async (args) => {
172
173
  try {
173
174
  await confirmEmailChange.mutateAsync(args);
174
- notify?.("Email address updated", "success");
175
+ notify2?.("Email address updated", "success");
175
176
  } catch (e) {
176
- notify?.(errorText(e, "Invalid or expired verification code"), "error");
177
+ notify2?.(errorText(e, "Invalid or expired verification code"), "error");
177
178
  throw e;
178
179
  }
179
180
  }
@@ -224,7 +225,7 @@ function defaultUnmetPasswordRequirement(password) {
224
225
  return null;
225
226
  }
226
227
  function ConnectedSecuritySection({
227
- notify,
228
+ notify: notify2,
228
229
  getUnmetRequirement = defaultUnmetPasswordRequirement,
229
230
  renderRecoveryKey,
230
231
  children
@@ -237,7 +238,7 @@ function ConnectedSecuritySection({
237
238
  getUnmetRequirement,
238
239
  submit: async (vars) => {
239
240
  const result = await change.mutateAsync(vars);
240
- notify?.("Password changed successfully", "success");
241
+ notify2?.("Password changed successfully", "success");
241
242
  return result;
242
243
  },
243
244
  onClose: () => setOpen(false)
@@ -302,7 +303,7 @@ function ConnectedNotificationPreferences({
302
303
  ) }) });
303
304
  }
304
305
  function ConnectedSessionsRow({
305
- notify,
306
+ notify: notify2,
306
307
  confirm,
307
308
  renderSessionIcon
308
309
  }) {
@@ -356,7 +357,7 @@ function ConnectedSessionsRow({
356
357
  try {
357
358
  await terminate.mutateAsync(id);
358
359
  } catch {
359
- notify?.("Failed to end session. Please try again.", "error");
360
+ notify2?.("Failed to end session. Please try again.", "error");
360
361
  }
361
362
  })();
362
363
  }
@@ -370,7 +371,7 @@ function ConnectedLogoutDialog({
370
371
  isOnline = true,
371
372
  renderSessionIcon
372
373
  }) {
373
- const { logout } = chunkBTDL4Q27_cjs.useConnection();
374
+ const { logout } = chunkJCVZKCXC_cjs.useConnection();
374
375
  const sessions = react$1.useSessions({ enabled: open });
375
376
  const logoutAll = react$1.useLogoutAllSessions();
376
377
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -393,17 +394,17 @@ function ConnectedLogoutDialog({
393
394
  }
394
395
  );
395
396
  }
396
- function ConnectedDangerZone({ notify, renderSubscriptionLink }) {
397
+ function ConnectedDangerZone({ notify: notify2, renderSubscriptionLink }) {
397
398
  const [zoneOpen, setZoneOpen] = react.useState(false);
398
399
  const [dialogOpen, setDialogOpen] = react.useState(false);
399
- const { user, logout } = chunkBTDL4Q27_cjs.useConnection();
400
+ const { user, logout } = chunkJCVZKCXC_cjs.useConnection();
400
401
  const remove = react$1.useDeleteAccount();
401
402
  const flow = react$1.useDeleteAccountFlow({
402
403
  userEmail: user?.email ?? "",
403
404
  remove: () => remove.mutateAsync(),
404
405
  onClose: () => setDialogOpen(false),
405
406
  onDeleted: logout,
406
- onError: () => notify?.("Failed to delete account. Please try again.", "error")
407
+ onError: () => notify2?.("Failed to delete account. Please try again.", "error")
407
408
  });
408
409
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
409
410
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -444,54 +445,119 @@ function ConnectedDangerZone({ notify, renderSubscriptionLink }) {
444
445
  )
445
446
  ] });
446
447
  }
448
+ function useConnectedDocxNotifications(onOpen) {
449
+ const arbi = react$1.useArbi();
450
+ const { status, user, apiUrl } = chunkJCVZKCXC_cjs.useConnection();
451
+ const queries = reactQuery.useQueryClient();
452
+ const source = `docx-mentions:${apiUrl}:${user?.externalId || ""}`;
453
+ const queryKey = ["docx-mentions", apiUrl, user?.externalId];
454
+ const { data = [] } = reactQuery.useQuery({
455
+ queryKey,
456
+ queryFn: () => arbi.notifications.list("docx_mention"),
457
+ enabled: status === "authenticated",
458
+ refetchInterval: 3e4
459
+ });
460
+ react$1.useArbiWebSocket((message) => {
461
+ if (message.type === "docx_mention") void queries.invalidateQueries({ queryKey });
462
+ });
463
+ react.useEffect(() => {
464
+ const items = [];
465
+ if (status === "authenticated")
466
+ for (const note of data) {
467
+ if (note.recipient.external_id !== user?.externalId || !note.workspace_ext_id) continue;
468
+ try {
469
+ const target = JSON.parse(note.content || "{}");
470
+ if (!target.document_id?.startsWith("doc-") || !target.comment_id) continue;
471
+ const documentId = target.document_id, commentId = target.comment_id, workspaceId = note.workspace_ext_id;
472
+ items.push({
473
+ id: `docx:${note.external_id}`,
474
+ title: "Mentioned you in a document comment",
475
+ description: [note.sender.given_name, note.sender.family_name].filter(Boolean).join(" "),
476
+ variant: "info",
477
+ ts: Date.parse(note.created_at),
478
+ read: note.read,
479
+ source,
480
+ onSelect: () => {
481
+ void Promise.resolve(onOpen({ documentId, commentId, workspaceId })).catch(
482
+ (error) => react$1.notify.error(
483
+ error instanceof Error ? error.message : "Could not open the document."
484
+ )
485
+ );
486
+ }
487
+ });
488
+ } catch {
489
+ }
490
+ }
491
+ react$1.useNotify.getState().syncSource(source, items);
492
+ return () => react$1.useNotify.getState().syncSource(source, []);
493
+ }, [data, status, user?.externalId, source, onOpen]);
494
+ const markRead = async (ids) => {
495
+ try {
496
+ await arbi.notifications.markRead(ids);
497
+ await queries.invalidateQueries({ queryKey });
498
+ } catch {
499
+ react$1.notify.error("Could not mark document mentions read.");
500
+ }
501
+ };
502
+ return {
503
+ onMarkRead: (id) => {
504
+ if (id.startsWith("docx:")) void markRead([id.slice(5)]);
505
+ },
506
+ onMarkAllRead: () => {
507
+ void markRead(
508
+ data.filter((note) => !note.read && note.recipient.external_id === user?.externalId).map((note) => note.external_id)
509
+ );
510
+ }
511
+ };
512
+ }
447
513
 
448
514
  Object.defineProperty(exports, "ConnectedAssistantDock", {
449
515
  enumerable: true,
450
- get: function () { return chunkBTDL4Q27_cjs.ConnectedAssistantDock; }
516
+ get: function () { return chunkEUOGPUMJ_cjs.ConnectedAssistantDock; }
451
517
  });
452
- Object.defineProperty(exports, "ConnectionProvider", {
518
+ Object.defineProperty(exports, "redlineStats", {
453
519
  enumerable: true,
454
- get: function () { return chunkBTDL4Q27_cjs.ConnectionProvider; }
520
+ get: function () { return chunkEUOGPUMJ_cjs.redlineStats; }
455
521
  });
456
- Object.defineProperty(exports, "SESSION_EXPIRED_MESSAGE", {
522
+ Object.defineProperty(exports, "textToArtifact", {
457
523
  enumerable: true,
458
- get: function () { return chunkBTDL4Q27_cjs.SESSION_EXPIRED_MESSAGE; }
524
+ get: function () { return chunkEUOGPUMJ_cjs.textToArtifact; }
459
525
  });
460
- Object.defineProperty(exports, "isAuthenticated", {
526
+ Object.defineProperty(exports, "toRedlineMarkdown", {
461
527
  enumerable: true,
462
- get: function () { return chunkBTDL4Q27_cjs.isAuthenticated; }
528
+ get: function () { return chunkEUOGPUMJ_cjs.toRedlineMarkdown; }
463
529
  });
464
- Object.defineProperty(exports, "redlineStats", {
530
+ Object.defineProperty(exports, "useConnectedAiTask", {
465
531
  enumerable: true,
466
- get: function () { return chunkBTDL4Q27_cjs.redlineStats; }
532
+ get: function () { return chunkEUOGPUMJ_cjs.useConnectedAiTask; }
467
533
  });
468
- Object.defineProperty(exports, "textToArtifact", {
534
+ Object.defineProperty(exports, "useConnectedChat", {
469
535
  enumerable: true,
470
- get: function () { return chunkBTDL4Q27_cjs.textToArtifact; }
536
+ get: function () { return chunkEUOGPUMJ_cjs.useConnectedChat; }
471
537
  });
472
- Object.defineProperty(exports, "toRedlineMarkdown", {
538
+ Object.defineProperty(exports, "useSemanticSearch", {
473
539
  enumerable: true,
474
- get: function () { return chunkBTDL4Q27_cjs.toRedlineMarkdown; }
540
+ get: function () { return chunkEUOGPUMJ_cjs.useSemanticSearch; }
475
541
  });
476
- Object.defineProperty(exports, "useConnectedAiTask", {
542
+ Object.defineProperty(exports, "useWorkspaceDocs", {
477
543
  enumerable: true,
478
- get: function () { return chunkBTDL4Q27_cjs.useConnectedAiTask; }
544
+ get: function () { return chunkEUOGPUMJ_cjs.useWorkspaceDocs; }
479
545
  });
480
- Object.defineProperty(exports, "useConnectedChat", {
546
+ Object.defineProperty(exports, "ConnectionProvider", {
481
547
  enumerable: true,
482
- get: function () { return chunkBTDL4Q27_cjs.useConnectedChat; }
548
+ get: function () { return chunkJCVZKCXC_cjs.ConnectionProvider; }
483
549
  });
484
- Object.defineProperty(exports, "useConnection", {
550
+ Object.defineProperty(exports, "SESSION_EXPIRED_MESSAGE", {
485
551
  enumerable: true,
486
- get: function () { return chunkBTDL4Q27_cjs.useConnection; }
552
+ get: function () { return chunkJCVZKCXC_cjs.SESSION_EXPIRED_MESSAGE; }
487
553
  });
488
- Object.defineProperty(exports, "useSemanticSearch", {
554
+ Object.defineProperty(exports, "isAuthenticated", {
489
555
  enumerable: true,
490
- get: function () { return chunkBTDL4Q27_cjs.useSemanticSearch; }
556
+ get: function () { return chunkJCVZKCXC_cjs.isAuthenticated; }
491
557
  });
492
- Object.defineProperty(exports, "useWorkspaceDocs", {
558
+ Object.defineProperty(exports, "useConnection", {
493
559
  enumerable: true,
494
- get: function () { return chunkBTDL4Q27_cjs.useWorkspaceDocs; }
560
+ get: function () { return chunkJCVZKCXC_cjs.useConnection; }
495
561
  });
496
562
  exports.ArbiAppProvider = ArbiAppProvider;
497
563
  exports.ConnectedDangerZone = ConnectedDangerZone;
@@ -502,6 +568,7 @@ exports.ConnectedSecuritySection = ConnectedSecuritySection;
502
568
  exports.ConnectedSessionsRow = ConnectedSessionsRow;
503
569
  exports.StreamedArtifact = StreamedArtifact;
504
570
  exports.defaultUnmetPasswordRequirement = defaultUnmetPasswordRequirement;
571
+ exports.useConnectedDocxNotifications = useConnectedDocxNotifications;
505
572
  exports.useConnectedShellWorkspaces = useConnectedShellWorkspaces;
506
573
  //# sourceMappingURL=index.cjs.map
507
574
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/connection/ArbiAppProvider.tsx","../../src/connection/StreamedArtifact.tsx","../../src/connection/useConnectedShellWorkspaces.ts","../../src/connection/ConnectedSettings.tsx"],"names":["useConnection","jsx","ArbiWebSocketProvider","useState","QueryClient","QueryClientProvider","ArbiProvider","ConnectionProvider","lazy","artifacts","useStreamedArtifact","ArtifactCanvas","StreamedArtifactFrame","Suspense","useWorkspaces","useShellWorkspaces","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"],"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"]}
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"]}
@@ -9,3 +9,4 @@ export { useConnectedAiTask, useConnectedChat, ConnectedAssistantDock, useWorksp
9
9
  export { StreamedArtifact, type StreamedArtifactProps } from '../connection/StreamedArtifact';
10
10
  export { useConnectedShellWorkspaces, type UseConnectedShellWorkspacesOptions, } from '../connection/useConnectedShellWorkspaces';
11
11
  export { ConnectedProfileCard, ConnectedSecuritySection, ConnectedNotificationPreferences, ConnectedSessionsRow, ConnectedLogoutDialog, ConnectedDangerZone, defaultUnmetPasswordRequirement, type SettingsNotify, type ConnectedProfileCardProps, type ConnectedSecuritySectionProps, type ConnectedNotificationPreferencesProps, type ConnectedSessionsRowProps, type ConnectedLogoutDialogProps, type ConnectedDangerZoneProps, } from '../connection/ConnectedSettings';
12
+ export { useConnectedDocxNotifications } from '../connection/useConnectedDocxNotifications';