@arbidocs/blocks 0.4.126 → 0.4.128

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 (64) hide show
  1. package/dist/calls/index.cjs +2 -2
  2. package/dist/calls/index.js +1 -1
  3. package/dist/chat/index.cjs +89 -72
  4. package/dist/chat/index.d.ts +1 -0
  5. package/dist/chat/index.js +2 -1
  6. package/dist/chat/open-document.d.ts +66 -0
  7. package/dist/{chunk-DZI7WOUD.cjs → chunk-3BJLNKOB.cjs} +6 -2
  8. package/dist/chunk-3BJLNKOB.cjs.map +1 -0
  9. package/dist/{chunk-IXTQYFIF.js → chunk-6HCJ3ZEU.js} +34 -6
  10. package/dist/chunk-6HCJ3ZEU.js.map +1 -0
  11. package/dist/{chunk-HQH35JWC.js → chunk-7BJRLP3U.js} +6 -3
  12. package/dist/chunk-7BJRLP3U.js.map +1 -0
  13. package/dist/{chunk-6Z72CXZR.js → chunk-CJBN5HIS.js} +6 -2
  14. package/dist/chunk-CJBN5HIS.js.map +1 -0
  15. package/dist/{chunk-JJLMCV3T.js → chunk-ECERC6TI.js} +32 -28
  16. package/dist/chunk-ECERC6TI.js.map +1 -0
  17. package/dist/{chunk-4VCKYR4D.cjs → chunk-FSBY2S4V.cjs} +6 -3
  18. package/dist/chunk-FSBY2S4V.cjs.map +1 -0
  19. package/dist/chunk-GYCQ3FNL.js +60 -0
  20. package/dist/chunk-GYCQ3FNL.js.map +1 -0
  21. package/dist/{chunk-VMZXFYHK.cjs → chunk-NZUQFF35.cjs} +2 -2
  22. package/dist/{chunk-VMZXFYHK.cjs.map → chunk-NZUQFF35.cjs.map} +1 -1
  23. package/dist/{chunk-U6MPHCEB.cjs → chunk-O6IEZDRC.cjs} +33 -5
  24. package/dist/chunk-O6IEZDRC.cjs.map +1 -0
  25. package/dist/chunk-SWQX6CTT.cjs +65 -0
  26. package/dist/chunk-SWQX6CTT.cjs.map +1 -0
  27. package/dist/{chunk-GICUGQNN.cjs → chunk-ZAVEMQ37.cjs} +31 -27
  28. package/dist/chunk-ZAVEMQ37.cjs.map +1 -0
  29. package/dist/{chunk-Y4X3RBFI.js → chunk-ZCHSJUCI.js} +2 -2
  30. package/dist/{chunk-Y4X3RBFI.js.map → chunk-ZCHSJUCI.js.map} +1 -1
  31. package/dist/collaboration/index.cjs +15 -15
  32. package/dist/collaboration/index.js +1 -1
  33. package/dist/collaboration/mail/MailMessageView.d.ts +5 -1
  34. package/dist/connect/docx.cjs +4 -3
  35. package/dist/connect/docx.cjs.map +1 -1
  36. package/dist/connect/docx.js +3 -2
  37. package/dist/connect/docx.js.map +1 -1
  38. package/dist/connect/index.cjs +93 -36
  39. package/dist/connect/index.cjs.map +1 -1
  40. package/dist/connect/index.js +66 -9
  41. package/dist/connect/index.js.map +1 -1
  42. package/dist/connection/mail/types.d.ts +2 -6
  43. package/dist/index.cjs +113 -96
  44. package/dist/index.cjs.map +1 -1
  45. package/dist/index.js +4 -3
  46. package/dist/index.js.map +1 -1
  47. package/dist/settings/ConfirmDialog.d.ts +4 -1
  48. package/dist/settings/index.cjs +3 -3
  49. package/dist/settings/index.js +1 -1
  50. package/dist/studio/index.cjs +3 -2
  51. package/dist/studio/index.cjs.map +1 -1
  52. package/dist/studio/index.js +2 -1
  53. package/dist/studio/index.js.map +1 -1
  54. package/node_modules/@arbidocs/coedit/package.json +1 -1
  55. package/package.json +5 -5
  56. package/src/docx/README.md +7 -3
  57. package/dist/chunk-4VCKYR4D.cjs.map +0 -1
  58. package/dist/chunk-6Z72CXZR.js.map +0 -1
  59. package/dist/chunk-DZI7WOUD.cjs.map +0 -1
  60. package/dist/chunk-GICUGQNN.cjs.map +0 -1
  61. package/dist/chunk-HQH35JWC.js.map +0 -1
  62. package/dist/chunk-IXTQYFIF.js.map +0 -1
  63. package/dist/chunk-JJLMCV3T.js.map +0 -1
  64. package/dist/chunk-U6MPHCEB.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arbidocs/coedit",
3
- "version": "0.4.126",
3
+ "version": "0.4.128",
4
4
  "description": "Real-time collaboration for the ARBI native DOCX editor: a Yjs mirror of the canonical OOXML package, session, and server runtime",
5
5
  "type": "module",
6
6
  "sideEffects": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arbidocs/blocks",
3
- "version": "0.4.126",
3
+ "version": "0.4.128",
4
4
  "description": "Composable, domain-neutral UI blocks for ARBI apps, organised by capability (retrieval, facts, agents, workspaces, citations, collaboration) plus shell, theme and site primitives, on top of @arbidocs/react.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -273,15 +273,15 @@
273
273
  "build": "rm -rf dist && tsup && tsc -p tsconfig.build.json",
274
274
  "test": "vitest run",
275
275
  "test:watch": "vitest",
276
- "typecheck": "tsc --noEmit",
276
+ "typecheck": "tsc -p tsconfig.typecheck.json",
277
277
  "example:dev": "vite --config examples/custom-ui/vite.config.ts",
278
278
  "example:build": "vite build --config examples/custom-ui/vite.config.ts",
279
279
  "example:preview": "vite preview --config examples/custom-ui/vite.config.ts",
280
280
  "example:test:e2e": "playwright test -c examples/custom-ui/playwright.config.ts"
281
281
  },
282
282
  "dependencies": {
283
- "@arbidocs/client": "0.4.126",
284
- "@arbidocs/coedit": "0.4.126",
283
+ "@arbidocs/client": "0.4.128",
284
+ "@arbidocs/coedit": "0.4.128",
285
285
  "@dnd-kit/core": "^6.3.1",
286
286
  "@dnd-kit/sortable": "^10.0.0",
287
287
  "@dnd-kit/utilities": "^3.2.2",
@@ -323,7 +323,7 @@
323
323
  "y-protocols": "^1.0.6"
324
324
  },
325
325
  "peerDependencies": {
326
- "@arbidocs/react": "0.4.126",
326
+ "@arbidocs/react": "0.4.128",
327
327
  "@lexical/html": "0.35.0",
328
328
  "@lexical/link": "0.35.0",
329
329
  "@lexical/list": "0.35.0",
@@ -59,9 +59,13 @@ Workspace people and agents are available through the adapter's `mentions` and
59
59
  the originating comment thread. `ConnectedNativeDocxEditor` from `@arbidocs/blocks/connect/docx` supplies these
60
60
  callbacks using the blocks connection and authenticated SDK, including normal
61
61
  session recovery. Import the same two stylesheets and serve the document fonts.
62
- For a prompt panel, pass `activeArtifactExtId: documentId` to
63
- `useConnectedAiTask().run(prompt, [], options)`; the backend edits the live DOCX
64
- with tracked operations and refuses stale targets.
62
+ While a `ConnectedNativeDocxEditor` is open (not a snapshot, stream or draft) it is the chat's
63
+ open document: every `useConnectedChat` / `ConnectedAgentChatPanel` turn names it
64
+ (`active_artifact_ext_id`), and the backend edits the live DOCX with tracked operations and refuses
65
+ stale targets. A host viewer registers its own document with `useRegisterOpenDocument` (with
66
+ `shownId`/`showLive` when it can show an earlier version, which a sent turn returns to the live
67
+ document); a host chat reads it with `takeOpenDocumentForTurn`. For a prompt panel, pass
68
+ `activeArtifactExtId: documentId` to `useConnectedAiTask().run(prompt, [], options)`.
65
69
 
66
70
  `NativeDocxComparison` uses the same adapter and native editor for the LibreOffice
67
71
  Word redline. Pass `baseId`, `revisedId`, `title` and optionally `onCompared` to
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connection/ai.tsx"],"names":["useConnection","useKitAiTask","useCallback","useKitWorkspaceDocs","useKitSemanticSearch","useWorkspaceUsers","useArbiChat","jsx","AssistantDock"],"mappings":"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","file":"chunk-4VCKYR4D.cjs","sourcesContent":["/**\n * The connected agent hooks — thin adapters over the reusable AI kit in\n * `@arbidocs/react`. The streaming/accumulation/search plumbing lives once in\n * the SDK; these hooks only bind the *workspace source* (from the connection\n * context, falling back to the configured workspace) and inject the host's\n * default assistant *configuration* so call sites needn't know the config\n * ext_id. An explicit `opts.model` still wins.\n */\nimport { useCallback } from 'react'\nimport {\n useAiTask as useKitAiTask,\n useWorkspaceDocs as useKitWorkspaceDocs,\n useSemanticSearch as useKitSemanticSearch,\n useArbiChat,\n useWorkspaceUsers,\n type ArbiChat,\n type UseArbiChatOptions,\n type AiRunOptions,\n} from '@arbidocs/react'\nimport { useConnection } from './ConnectionProvider'\nimport { AssistantDock, type AssistantDockProps } from '../chat/AssistantDock'\nimport type { MentionCandidate } from '../chat/mentions'\n\nexport type { AiTaskStatus, AiRunOptions, SearchChunk, ArtifactEvent } from '@arbidocs/react'\n\n/** Client-side redlining, re-exported so a host app has one import surface. */\nexport { toRedlineMarkdown, redlineStats, textToArtifact } from '@arbidocs/react'\n\n/**\n * The kit's `useAiTask` with the host's default assistant configuration\n * injected, so call sites needn't know the config ext_id.\n */\nexport function useConnectedAiTask() {\n const { assistantConfig } = useConnection()\n const task = useKitAiTask()\n const kitRun = task.run\n const run = useCallback(\n (question: string, docIds: string[], opts?: AiRunOptions) =>\n kitRun(question, docIds, { ...opts, model: opts?.model ?? assistantConfig }),\n [kitRun, assistantConfig]\n )\n return { ...task, run }\n}\n\n/** Resolve the active workspace + its document ids (what we ground the agent on). */\nexport function useWorkspaceDocs() {\n const { workspaceId, fallbackWorkspaceId } = useConnection()\n return useKitWorkspaceDocs(workspaceId ?? fallbackWorkspaceId)\n}\n\n/** Search the active workspace's documents and return the top matching passages. */\nexport function useSemanticSearch() {\n const { docIds } = useWorkspaceDocs()\n return useKitSemanticSearch(docIds)\n}\n\n/**\n * The chat controller for `ChatPage` bound to the connection: the active workspace and the host's\n * default assistant configuration are injected, so a host writes\n * `<ChatPage chat={useConnectedChat()} />`.\n */\nexport function useConnectedChat(\n options?: Omit<UseArbiChatOptions, 'workspaceId'>\n): ArbiChat & { mentionCandidates: MentionCandidate[] } {\n const { workspaceId, fallbackWorkspaceId, assistantConfig, user, status, ensureWorkspaceOpen } =\n useConnection()\n const wsId = workspaceId ?? fallbackWorkspaceId\n const { data: members = [] } = useWorkspaceUsers(wsId, {\n enabled: status === 'authenticated' && !!wsId,\n beforeFetch: ensureWorkspaceOpen,\n })\n const mentionCandidates: MentionCandidate[] = [\n { id: 'assistant', kind: 'assistant', label: 'Assistant' },\n ...(status === 'authenticated' ? members : [])\n .filter(\n (member) =>\n !member.agent_ext_id &&\n member.user.external_id !== user?.externalId &&\n !member.user.external_id.startsWith('agt-')\n )\n .map((member) => ({\n id: member.user.external_id,\n kind: 'user' as const,\n label:\n [member.user.given_name, member.user.family_name].filter(Boolean).join(' ') ||\n member.user.email,\n description: member.user.email,\n }))\n .sort((a, b) => a.label.localeCompare(b.label)),\n ]\n const chat = useArbiChat({\n ...options,\n workspaceId: workspaceId ?? fallbackWorkspaceId,\n model: options?.model ?? assistantConfig,\n })\n return {\n ...chat,\n mentionCandidates,\n messages: chat.messages.map((message) => ({\n ...message,\n ...(message.authorId\n ? {\n senderName:\n message.authorId === user?.externalId\n ? user?.name || user?.email\n : mentionCandidates.find((candidate) => candidate.id === message.authorId)?.label,\n }\n : {}),\n })),\n }\n}\n\n/**\n * The assistant dock bound to the connection: mount it once in the layout (`Shell.Root`'s `aside`)\n * and put `AssistantDockToggle` in the topbar. Chat state lives here, so it survives closing the dock.\n */\nexport function ConnectedAssistantDock(props: Omit<AssistantDockProps, 'chat'>) {\n const chat = useConnectedChat()\n return <AssistantDock {...props} chat={chat} />\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connection/ConnectedNativeDocxEditor.tsx"],"names":[],"mappings":"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","file":"chunk-6Z72CXZR.js","sourcesContent":["import { useMemo } from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useArbi, notify, arbiQueryKeys } from '@arbidocs/react'\nimport { useConnection } from './ConnectionProvider'\nimport {\n NativeDocxEditor,\n type NativeDocxAdapter,\n type NativeDocxEditorProps,\n} from '../docx/NativeDocxEditor'\nimport { loadDocxFonts } from '../docx/fonts'\n\n/** Native Word widget bound to the standard blocks connection and SDK session. */\nexport function ConnectedNativeDocxEditor({\n fontBaseUrl = '/native-docx/fonts',\n ...props\n}: Omit<NativeDocxEditorProps, 'adapter'> & { fontBaseUrl?: string }) {\n const adapter = useConnectedNativeDocxAdapter(fontBaseUrl)\n return <NativeDocxEditor {...props} adapter={adapter} />\n}\n\nexport function useConnectedNativeDocxAdapter(fontBaseUrl = '/native-docx/fonts') {\n const arbi = useArbi()\n const { workspaceId, apiUrl, user, ensureWorkspaceOpen } = useConnection()\n const queries = useQueryClient()\n const { data: members } = useQuery({\n queryKey: ['native-docx-members', apiUrl, user?.externalId, workspaceId],\n enabled: arbi.isLoggedIn && !!workspaceId,\n queryFn: async () => {\n await ensureWorkspaceOpen()\n return arbi.workspaces.listUsers()\n },\n })\n const adapter = useMemo<NativeDocxAdapter>(\n () => ({\n request: async (path, options) => {\n await ensureWorkspaceOpen()\n return arbi.editor.request(path, options)\n },\n open: async (id) => {\n await ensureWorkspaceOpen()\n return (\n await arbi.editor.request(`/${encodeURIComponent(id)}/session`, { method: 'POST' })\n ).json()\n },\n save: async (id, state) =>\n (\n await arbi.editor.request(`/${encodeURIComponent(id)}/save`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ state }),\n })\n ).json(),\n loadFonts: () => loadDocxFonts(fontBaseUrl),\n baseUrl: apiUrl,\n author: user?.name || 'You',\n onVersionSaved: async (id) => {\n if (!workspaceId) return\n const key = arbiQueryKeys.documents(workspaceId)\n try {\n const documents = await arbi.documents.get([id])\n if (!documents.length) throw new Error('The saved version is not available yet.')\n queries.setQueryData<Awaited<ReturnType<typeof arbi.documents.list>>>(key, (previous) => [\n ...documents,\n ...(previous || []).filter(\n (doc) => !documents.some((saved) => saved.external_id === doc.external_id)\n ),\n ])\n } catch {\n await queries.invalidateQueries({ queryKey: key })\n }\n },\n notify: (message, kind) => notify[kind](message),\n mentions: members?.map(({ user: member }) => ({\n id: member.external_id,\n name: [member.given_name, member.family_name].filter(Boolean).join(' '),\n kind: member.external_id.startsWith('agt-') ? 'agent' : 'human',\n })),\n requestAgent: async (id, request) => {\n const response = await arbi.editor.request(`/${encodeURIComponent(id)}/mentions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n comment_id: request.commentId,\n instruction: request.instruction,\n request_id: request.requestId,\n recipient_ids: request.recipientIds,\n }),\n })\n const delivery = (await response.json()) as { response_ids: string[] }\n notify.success('Mention delivered.')\n return { responseIds: delivery.response_ids || [] }\n },\n getAgentStatus: async (responseId) => (await arbi.assistant.getResponse(responseId)).status,\n }),\n [arbi, apiUrl, user?.name, members, ensureWorkspaceOpen, fontBaseUrl, queries, workspaceId]\n )\n return adapter\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connection/ConnectedNativeDocxEditor.tsx"],"names":["jsx","NativeDocxEditor","useArbi","useConnection","useQueryClient","useQuery","useMemo","loadDocxFonts","arbiQueryKeys","notify"],"mappings":"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","file":"chunk-DZI7WOUD.cjs","sourcesContent":["import { useMemo } from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useArbi, notify, arbiQueryKeys } from '@arbidocs/react'\nimport { useConnection } from './ConnectionProvider'\nimport {\n NativeDocxEditor,\n type NativeDocxAdapter,\n type NativeDocxEditorProps,\n} from '../docx/NativeDocxEditor'\nimport { loadDocxFonts } from '../docx/fonts'\n\n/** Native Word widget bound to the standard blocks connection and SDK session. */\nexport function ConnectedNativeDocxEditor({\n fontBaseUrl = '/native-docx/fonts',\n ...props\n}: Omit<NativeDocxEditorProps, 'adapter'> & { fontBaseUrl?: string }) {\n const adapter = useConnectedNativeDocxAdapter(fontBaseUrl)\n return <NativeDocxEditor {...props} adapter={adapter} />\n}\n\nexport function useConnectedNativeDocxAdapter(fontBaseUrl = '/native-docx/fonts') {\n const arbi = useArbi()\n const { workspaceId, apiUrl, user, ensureWorkspaceOpen } = useConnection()\n const queries = useQueryClient()\n const { data: members } = useQuery({\n queryKey: ['native-docx-members', apiUrl, user?.externalId, workspaceId],\n enabled: arbi.isLoggedIn && !!workspaceId,\n queryFn: async () => {\n await ensureWorkspaceOpen()\n return arbi.workspaces.listUsers()\n },\n })\n const adapter = useMemo<NativeDocxAdapter>(\n () => ({\n request: async (path, options) => {\n await ensureWorkspaceOpen()\n return arbi.editor.request(path, options)\n },\n open: async (id) => {\n await ensureWorkspaceOpen()\n return (\n await arbi.editor.request(`/${encodeURIComponent(id)}/session`, { method: 'POST' })\n ).json()\n },\n save: async (id, state) =>\n (\n await arbi.editor.request(`/${encodeURIComponent(id)}/save`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ state }),\n })\n ).json(),\n loadFonts: () => loadDocxFonts(fontBaseUrl),\n baseUrl: apiUrl,\n author: user?.name || 'You',\n onVersionSaved: async (id) => {\n if (!workspaceId) return\n const key = arbiQueryKeys.documents(workspaceId)\n try {\n const documents = await arbi.documents.get([id])\n if (!documents.length) throw new Error('The saved version is not available yet.')\n queries.setQueryData<Awaited<ReturnType<typeof arbi.documents.list>>>(key, (previous) => [\n ...documents,\n ...(previous || []).filter(\n (doc) => !documents.some((saved) => saved.external_id === doc.external_id)\n ),\n ])\n } catch {\n await queries.invalidateQueries({ queryKey: key })\n }\n },\n notify: (message, kind) => notify[kind](message),\n mentions: members?.map(({ user: member }) => ({\n id: member.external_id,\n name: [member.given_name, member.family_name].filter(Boolean).join(' '),\n kind: member.external_id.startsWith('agt-') ? 'agent' : 'human',\n })),\n requestAgent: async (id, request) => {\n const response = await arbi.editor.request(`/${encodeURIComponent(id)}/mentions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n comment_id: request.commentId,\n instruction: request.instruction,\n request_id: request.requestId,\n recipient_ids: request.recipientIds,\n }),\n })\n const delivery = (await response.json()) as { response_ids: string[] }\n notify.success('Mention delivered.')\n return { responseIds: delivery.response_ids || [] }\n },\n getAgentStatus: async (responseId) => (await arbi.assistant.getResponse(responseId)).status,\n }),\n [arbi, apiUrl, user?.name, members, ensureWorkspaceOpen, fontBaseUrl, queries, workspaceId]\n )\n return adapter\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/settings/ConfirmDialog.tsx"],"names":["useMemo","useRef","jsx","ModalScaffold","AlertTriangle","testIdOr","jsxs","Button"],"mappings":";;;;;;;;;AAaO,IAAM,6BAAA,GAAqD;AAAA,EAChE,OAAA,EAAS,SAAA;AAAA,EACT,MAAA,EAAQ,QAAA;AAAA,EACR,UAAA,EAAY;AACd;AAuBO,SAAS,aAAA,CAAc;AAAA,EAC5B,MAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA,GAAU,aAAA;AAAA,EACV,SAAA,GAAY,KAAA;AAAA,EACZ,MAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAuB;AACrB,EAAA,MAAM,CAAA,GAAIA,aAAA,CAAQ,OAAO,EAAE,GAAG,6BAAA,EAA+B,GAAG,MAAA,EAAO,CAAA,EAAI,CAAC,MAAM,CAAC,CAAA;AACnF,EAAA,MAAM,SAAA,GAAYC,aAA0B,IAAI,CAAA;AAChD,EAAA,uBACEC,cAAA;AAAA,IAACC,+BAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,MAAA;AAAA,MACN,YAAA,EAAc,CAAC,IAAA,KAAS;AACtB,QAAA,IAAI,CAAC,MAAM,OAAA,EAAQ;AAAA,MACrB,CAAA;AAAA,MACA,IAAA,EAAK,aAAA;AAAA,MACL,eAAA,EAAiB,SAAA;AAAA,MACjB,KAAA;AAAA,MACA,WAAA;AAAA,MACA,eAAA,EAAe,IAAA;AAAA,MACf,IAAA,EACE,YAAY,aAAA,mBACVD,cAAA,CAACE,6BAAc,SAAA,EAAU,uBAAA,EAAwB,aAAA,EAAY,MAAA,EAAO,CAAA,GAClE,IAAA;AAAA,MAEN,QAAQC,0BAAA,CAAS,MAAA,EAAQ,EAAE,MAAA,EAAQ,sBAAsB,CAAA;AAAA,MAEzD,QAAA,kBAAAC,eAAA,CAACH,+BAAA,CAAc,MAAA,EAAd,EACC,QAAA,EAAA;AAAA,wBAAAD,cAAA;AAAA,UAACK,SAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,SAAA;AAAA,YACL,OAAA,EAAQ,SAAA;AAAA,YACR,OAAA,EAAS,MAAM,OAAA,EAAQ;AAAA,YACvB,QAAA,EAAU,SAAA;AAAA,YACV,eAAaF,0BAAA,CAAS,OAAA,EAAS,QAAQ,EAAE,MAAA,EAAQ,oCAAoC,CAAA;AAAA,YAEpF,wBAAc,CAAA,CAAE;AAAA;AAAA,SACnB;AAAA,wBACAH,cAAA;AAAA,UAACK,SAAA;AAAA,UAAA;AAAA,YACC,OAAA;AAAA,YACA,OAAA,EAAS,SAAA;AAAA,YACT,QAAA,EAAU,SAAA;AAAA,YACV,eAAaF,0BAAA,CAAS,OAAA,EAAS,SAAS,EAAE,MAAA,EAAQ,qCAAqC,CAAA;AAAA,YAEtF,QAAA,EAAA,SAAA,GAAY,CAAA,CAAE,UAAA,GAAc,WAAA,IAAe,CAAA,CAAE;AAAA;AAAA;AAChD,OAAA,EACF;AAAA;AAAA,GACF;AAEJ","file":"chunk-GICUGQNN.cjs","sourcesContent":["import { useMemo, useRef } from 'react'\nimport { AlertTriangle } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\nimport { ModalScaffold } from './ModalScaffold'\n\n/** Every fixed string of the confirm dialog. `confirmText` / `cancelText` props win. */\nexport interface ConfirmDialogLabels {\n confirm: string\n cancel: string\n pleaseWait: string\n}\n\nexport const DEFAULT_CONFIRM_DIALOG_LABELS: ConfirmDialogLabels = {\n confirm: 'Confirm',\n cancel: 'Cancel',\n pleaseWait: 'Please wait...',\n}\n\nexport interface ConfirmDialogProps {\n labels?: Partial<ConfirmDialogLabels>\n isOpen: boolean\n onClose: () => void\n onConfirm: () => void\n title: string\n description: string\n confirmText?: string\n cancelText?: string\n variant?: 'destructive' | 'default'\n isLoading?: boolean\n /** Dialog test id (default `confirmation-modal`). */\n testId?: string\n /** Button ids; defaults are the current ids. */\n testIds?: Partial<Record<'cancel' | 'confirm', string>>\n}\n\n/**\n * Declarative yes/no confirmation with a loading state. An `alertdialog`: initial focus is on\n * Cancel (the safe action) and clicking outside does not dismiss it; Escape and Cancel do.\n */\nexport function ConfirmDialog({\n isOpen,\n onClose,\n onConfirm,\n title,\n description,\n confirmText,\n cancelText,\n variant = 'destructive',\n isLoading = false,\n labels,\n testId,\n testIds,\n}: ConfirmDialogProps) {\n const l = useMemo(() => ({ ...DEFAULT_CONFIRM_DIALOG_LABELS, ...labels }), [labels])\n const cancelRef = useRef<HTMLButtonElement>(null)\n return (\n <ModalScaffold\n open={isOpen}\n onOpenChange={(next) => {\n if (!next) onClose()\n }}\n role=\"alertdialog\"\n initialFocusRef={cancelRef}\n title={title}\n description={description}\n showDescription\n icon={\n variant === 'destructive' ? (\n <AlertTriangle className=\"h-5 w-5 text-red-text\" aria-hidden=\"true\" />\n ) : null\n }\n testId={testIdOr(testId, { testId: 'confirmation-modal' })}\n >\n <ModalScaffold.Footer>\n <Button\n ref={cancelRef}\n variant=\"outline\"\n onClick={() => onClose()}\n disabled={isLoading}\n data-testid={testIdOr(testIds?.cancel, { testId: 'confirmation-modal-cancel-button' })}\n >\n {cancelText ?? l.cancel}\n </Button>\n <Button\n variant={variant}\n onClick={onConfirm}\n disabled={isLoading}\n data-testid={testIdOr(testIds?.confirm, { testId: 'confirmation-modal-confirm-button' })}\n >\n {isLoading ? l.pleaseWait : (confirmText ?? l.confirm)}\n </Button>\n </ModalScaffold.Footer>\n </ModalScaffold>\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connection/ai.tsx"],"names":["useKitAiTask","useKitWorkspaceDocs","useKitSemanticSearch"],"mappings":"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","file":"chunk-HQH35JWC.js","sourcesContent":["/**\n * The connected agent hooks — thin adapters over the reusable AI kit in\n * `@arbidocs/react`. The streaming/accumulation/search plumbing lives once in\n * the SDK; these hooks only bind the *workspace source* (from the connection\n * context, falling back to the configured workspace) and inject the host's\n * default assistant *configuration* so call sites needn't know the config\n * ext_id. An explicit `opts.model` still wins.\n */\nimport { useCallback } from 'react'\nimport {\n useAiTask as useKitAiTask,\n useWorkspaceDocs as useKitWorkspaceDocs,\n useSemanticSearch as useKitSemanticSearch,\n useArbiChat,\n useWorkspaceUsers,\n type ArbiChat,\n type UseArbiChatOptions,\n type AiRunOptions,\n} from '@arbidocs/react'\nimport { useConnection } from './ConnectionProvider'\nimport { AssistantDock, type AssistantDockProps } from '../chat/AssistantDock'\nimport type { MentionCandidate } from '../chat/mentions'\n\nexport type { AiTaskStatus, AiRunOptions, SearchChunk, ArtifactEvent } from '@arbidocs/react'\n\n/** Client-side redlining, re-exported so a host app has one import surface. */\nexport { toRedlineMarkdown, redlineStats, textToArtifact } from '@arbidocs/react'\n\n/**\n * The kit's `useAiTask` with the host's default assistant configuration\n * injected, so call sites needn't know the config ext_id.\n */\nexport function useConnectedAiTask() {\n const { assistantConfig } = useConnection()\n const task = useKitAiTask()\n const kitRun = task.run\n const run = useCallback(\n (question: string, docIds: string[], opts?: AiRunOptions) =>\n kitRun(question, docIds, { ...opts, model: opts?.model ?? assistantConfig }),\n [kitRun, assistantConfig]\n )\n return { ...task, run }\n}\n\n/** Resolve the active workspace + its document ids (what we ground the agent on). */\nexport function useWorkspaceDocs() {\n const { workspaceId, fallbackWorkspaceId } = useConnection()\n return useKitWorkspaceDocs(workspaceId ?? fallbackWorkspaceId)\n}\n\n/** Search the active workspace's documents and return the top matching passages. */\nexport function useSemanticSearch() {\n const { docIds } = useWorkspaceDocs()\n return useKitSemanticSearch(docIds)\n}\n\n/**\n * The chat controller for `ChatPage` bound to the connection: the active workspace and the host's\n * default assistant configuration are injected, so a host writes\n * `<ChatPage chat={useConnectedChat()} />`.\n */\nexport function useConnectedChat(\n options?: Omit<UseArbiChatOptions, 'workspaceId'>\n): ArbiChat & { mentionCandidates: MentionCandidate[] } {\n const { workspaceId, fallbackWorkspaceId, assistantConfig, user, status, ensureWorkspaceOpen } =\n useConnection()\n const wsId = workspaceId ?? fallbackWorkspaceId\n const { data: members = [] } = useWorkspaceUsers(wsId, {\n enabled: status === 'authenticated' && !!wsId,\n beforeFetch: ensureWorkspaceOpen,\n })\n const mentionCandidates: MentionCandidate[] = [\n { id: 'assistant', kind: 'assistant', label: 'Assistant' },\n ...(status === 'authenticated' ? members : [])\n .filter(\n (member) =>\n !member.agent_ext_id &&\n member.user.external_id !== user?.externalId &&\n !member.user.external_id.startsWith('agt-')\n )\n .map((member) => ({\n id: member.user.external_id,\n kind: 'user' as const,\n label:\n [member.user.given_name, member.user.family_name].filter(Boolean).join(' ') ||\n member.user.email,\n description: member.user.email,\n }))\n .sort((a, b) => a.label.localeCompare(b.label)),\n ]\n const chat = useArbiChat({\n ...options,\n workspaceId: workspaceId ?? fallbackWorkspaceId,\n model: options?.model ?? assistantConfig,\n })\n return {\n ...chat,\n mentionCandidates,\n messages: chat.messages.map((message) => ({\n ...message,\n ...(message.authorId\n ? {\n senderName:\n message.authorId === user?.externalId\n ? user?.name || user?.email\n : mentionCandidates.find((candidate) => candidate.id === message.authorId)?.label,\n }\n : {}),\n })),\n }\n}\n\n/**\n * The assistant dock bound to the connection: mount it once in the layout (`Shell.Root`'s `aside`)\n * and put `AssistantDockToggle` in the topbar. Chat state lives here, so it survives closing the dock.\n */\nexport function ConnectedAssistantDock(props: Omit<AssistantDockProps, 'chat'>) {\n const chat = useConnectedChat()\n return <AssistantDock {...props} chat={chat} />\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/collaboration/mail/MailMessagePreview.tsx","../src/collaboration/mail/mailCompose.ts","../src/collaboration/mail/MailGrid.tsx","../src/collaboration/mail/MailDeliveryList.tsx","../src/collaboration/mail/MailMessageView.tsx","../src/collaboration/mail/MailDocumentPicker.tsx","../src/collaboration/mail/PlainMailBodyEditor.tsx"],"names":["deliveryProblem","jsx","jsxs","cn","Paperclip","useMemo","Button"],"mappings":"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","file":"chunk-IXTQYFIF.js","sourcesContent":["import { Paperclip } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\n\nexport interface MailMessagePreviewProps {\n participants: string\n subject: string\n preview?: string\n date: string\n dateTime?: string\n unread?: boolean\n hasAttachments?: boolean\n /** A sent message's delivery problem; sent and delivered mail shows nothing, as in other clients. */\n deliveryProblem?: MailDeliveryProblem\n}\n\nexport type MailDeliveryProblem = 'bounced' | 'partially_bounced' | 'delayed'\n\nconst DELIVERY_BADGE: Record<MailDeliveryProblem, { label: string; title: string; tone: string }> =\n {\n bounced: {\n label: 'Bounced',\n title: \"Not delivered: the recipient's mail server sent this message back.\",\n tone: 'bg-destructive/10 text-destructive',\n },\n partially_bounced: {\n label: 'Partly bounced',\n title: 'Some recipients did not get this message. Open it to see who.',\n tone: 'bg-destructive/10 text-destructive',\n },\n delayed: {\n label: 'Delayed',\n title: \"Delivery is delayed; the recipient's server will keep retrying.\",\n tone: 'bg-muted text-muted-foreground',\n },\n }\n\n/** A pill for a sent message that bounced, partly bounced, or is delayed. */\nexport function MailDeliveryBadge({\n problem,\n className,\n}: {\n problem: MailDeliveryProblem\n className?: string\n}) {\n const badge = DELIVERY_BADGE[problem]\n return (\n <span\n className={cn('shrink-0 rounded-full px-2 py-0.5 text-xs font-medium', badge.tone, className)}\n title={badge.title}\n data-testid=\"mail-delivery-badge\"\n >\n {badge.label}\n </span>\n )\n}\n\n/** Compact inbox identity: sender/date, subject, then a body preview. */\nexport function MailMessagePreview({\n participants,\n subject,\n preview,\n date,\n dateTime,\n unread,\n hasAttachments,\n deliveryProblem,\n}: MailMessagePreviewProps) {\n return (\n <div className=\"flex h-full w-full min-w-0 flex-col justify-center gap-0.5 text-sm leading-5\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className={cn('min-w-0 flex-1 truncate', unread && 'font-semibold')}>\n {participants}\n </span>\n {hasAttachments && (\n <Paperclip\n className=\"size-3.5 shrink-0 text-muted-foreground\"\n aria-label=\"Has attachments\"\n />\n )}\n {deliveryProblem && <MailDeliveryBadge problem={deliveryProblem} />}\n <time dateTime={dateTime} className=\"shrink-0 text-xs font-normal text-muted-foreground\">\n {date}\n </time>\n </div>\n <div className={cn('truncate', unread && 'font-semibold')}>{subject || '(No subject)'}</div>\n <div className=\"truncate font-normal text-muted-foreground\">{preview || '\\u00a0'}</div>\n </div>\n )\n}\n","/** Pure helpers for writing mail: an empty message, recipient parsing, replies and forwards. */\n\nimport type {\n MailAccount,\n MailAddress,\n MailAttachment,\n MailCompose,\n MailMessage,\n} from '@arbidocs/react'\n\nexport const emptyMailCompose = (): MailCompose => ({\n to: [],\n cc: [],\n bcc: [],\n subject: '',\n text: '',\n attachments: [],\n})\n\n/** A person as shown: the name on the message, else the address. */\nexport const mailAddressLabel = (person: MailAddress): string => person.name || person.email\n\n/**\n * Typed or pasted recipients (`a@x.org; Pat <pat@y.org>`), separated by commas, semicolons or\n * lines, deduplicated by address.\n */\nexport function parseMailRecipients(value: string): MailAddress[] {\n const addresses = (value.match(/(?:[^,;\"\\n]|\"[^\"]*\")+/g) ?? [])\n .map((entry) => entry.trim())\n .filter(Boolean)\n .map((entry) => {\n const named = entry.match(/^(.*?)\\s*<([^<>]+)>$/)\n return named\n ? { email: named[2].trim(), name: named[1].trim().replace(/^\"|\"$/g, '') }\n : { email: entry }\n })\n return addresses.filter(\n (address, index) =>\n addresses.findIndex((item) => item.email.toLowerCase() === address.email.toLowerCase()) ===\n index\n )\n}\n\n/** A reply (to the sender, or everyone with `all`) or a forward of `message`. */\nexport function replyMailCompose(\n message: MailMessage,\n {\n account,\n folderRole,\n forward = false,\n all = false,\n attachments = [],\n }: {\n account: MailAccount\n /** The folder the message is in: replying from Sent goes to its recipients. */\n folderRole: string\n forward?: boolean\n all?: boolean\n /** A forward's attachments, with their content. */\n attachments?: MailAttachment[]\n }\n): MailCompose {\n return {\n ...emptyMailCompose(),\n to: forward ? [] : folderRole === 'sent' ? message.to : message.sender,\n cc: all\n ? [...message.to, ...message.cc]\n .filter(\n (r) =>\n r.email.toLowerCase() !== account.email.toLowerCase() &&\n !message.sender.some((s) => s.email.toLowerCase() === r.email.toLowerCase())\n )\n .filter(\n (r, i, values) =>\n values.findIndex((v) => v.email.toLowerCase() === r.email.toLowerCase()) === i\n )\n : [],\n subject: `${forward ? 'Fwd' : 'Re'}: ${message.subject.replace(/^(Re|Fwd):\\s*/i, '')}`,\n text: `\\n\\n${message.sender.map((s) => s.email).join(', ')} wrote:\\n${message.text}`,\n in_reply_to: forward ? undefined : message.message_id,\n references: [...message.references, ...(message.message_id ? [message.message_id] : [])],\n attachments,\n secure_delivery: message.secure_delivery,\n }\n}\n\n/** A saved draft, reopened for editing (`attachments` with their content). */\nexport function draftMailCompose(message: MailMessage, attachments: MailAttachment[]): MailCompose {\n return {\n to: message.to,\n cc: message.cc,\n bcc: message.bcc,\n subject: message.subject,\n text: message.text,\n html: message.html,\n attachments,\n draft_id: message.id,\n secure_delivery: message.secure_delivery,\n }\n}\n\n/** Whether a message carries a calendar invite (an .ics part). */\nexport const hasCalendarPart = (attachments: MailAttachment[]): boolean =>\n attachments.some(\n (a) => /^text\\/calendar\\b|^application\\/ics\\b/i.test(a.content_type) || /\\.ics$/i.test(a.name)\n )\n","import { useMemo } from 'react'\nimport type { ColDef, GridState } from 'ag-grid-community'\nimport { Mail } from 'lucide-react'\nimport type { MailAddress, MailMessage } from '@arbidocs/react'\nimport { GridView } from '../../files/GridView'\nimport { MailMessagePreview, type MailDeliveryProblem } from './MailMessagePreview'\nimport { mailAddressLabel } from './mailCompose'\n\n/** The list shows only delivery problems; sent and delivered mail stays quiet. */\nfunction deliveryProblem(status: MailMessage['delivery_status']): MailDeliveryProblem | undefined {\n return status === 'bounced' || status === 'partially_bounced' || status === 'delayed'\n ? status\n : undefined\n}\n\nexport interface MailGridProps {\n messages: MailMessage[]\n loading: boolean\n selected: string | null\n /** Sent, Drafts or Outbox: rows show recipients instead of the sender. */\n outgoing?: boolean\n onSelect: (id: string) => void\n /** How a person is named (default: the name on the message, else the address). */\n personLabel?: (person: MailAddress) => string\n /** Column state to restore at mount, and where to persist changes (both optional). */\n gridState?: GridState\n onGridStateChange?: (state: GridState) => void\n}\n\n/** A folder's messages: one row per message, unread dot, participants, subject and preview. */\nexport function MailGrid({\n messages,\n loading,\n selected,\n onSelect,\n outgoing = false,\n personLabel = mailAddressLabel,\n gridState,\n onGridStateChange,\n}: MailGridProps) {\n const columns = useMemo<ColDef<MailMessage>[]>(\n () => [\n {\n colId: 'unread',\n cellStyle: { padding: 0, justifyContent: 'center' },\n headerName: '',\n width: 34,\n minWidth: 34,\n maxWidth: 34,\n sortable: false,\n resizable: false,\n cellRenderer: ({ data }: { data?: MailMessage }) =>\n data?.unread ? (\n <span className=\"inline-block size-2 rounded-full bg-primary\" aria-label=\"Unread\" />\n ) : null,\n },\n {\n colId: 'message',\n cellClass:\n '[&_.ag-cell-value]:h-full [&_.ag-cell-value]:w-full [&_.ag-cell-wrapper]:h-full [&_.ag-cell-wrapper]:w-full',\n headerName: 'Message',\n flex: 1,\n minWidth: 240,\n sortable: false,\n valueGetter: (p) => p.data?.subject ?? '',\n cellRenderer: ({ data }: { data?: MailMessage }) =>\n data ? (\n <MailMessagePreview\n participants={(outgoing ? data.to : data.sender).map(personLabel).join(', ')}\n subject={data.subject}\n preview={data.preview}\n unread={data.unread}\n hasAttachments={Boolean(data.attachments.length)}\n deliveryProblem={deliveryProblem(data.delivery_status)}\n dateTime={data.received_at}\n date={\n data.received_at\n ? new Date(data.received_at).toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })\n : ''\n }\n />\n ) : null,\n },\n ],\n [outgoing, personLabel]\n )\n return (\n <GridView<MailMessage>\n items={messages}\n columnDefs={columns}\n getItemId={(m) => m.id}\n onRowClick={(m) => onSelect(m.id)}\n height=\"100%\"\n rowHeight={84}\n persistState={Boolean(onGridStateChange)}\n gridId=\"personal-mail-grid-v2\"\n gridState={gridState}\n onGridStateChange={onGridStateChange}\n testId=\"mail-grid\"\n isLoading={loading}\n getRowTestId={(m) => `mail-row-${m.id}`}\n emptyState={{\n icon: <Mail className=\"size-10 text-muted-foreground/50\" />,\n title: 'No messages',\n message: 'Messages in this folder will appear here.',\n }}\n gridOptions={{\n headerHeight: 0,\n suppressCellFocus: false,\n onCellKeyDown: (event) => {\n if ((event.event as KeyboardEvent)?.key === 'Enter' && event.data) onSelect(event.data.id)\n },\n defaultColDef: {\n sortable: true,\n resizable: true,\n filter: false,\n },\n rowClassRules: { 'bg-muted/60': (p) => p.data?.id === selected },\n }}\n />\n )\n}\n","import { AlertCircle, CheckCircle2, Clock, Send } from 'lucide-react'\nimport type { MailDeliveryRecipient } from '@arbidocs/react'\nimport { cn } from '@arbidocs/react/ui'\n\nconst ICONS: Record<MailDeliveryRecipient['status'], typeof Send> = {\n accepted: Send,\n relayed: Send,\n expanded: Send,\n delivered: CheckCircle2,\n delayed: Clock,\n rejected: AlertCircle,\n failed: AlertCircle,\n}\n\nconst LABELS: Record<MailDeliveryRecipient['status'], string> = {\n accepted: 'Sent',\n relayed: 'Sent',\n expanded: 'Sent',\n delivered: 'Delivered',\n delayed: 'Delayed',\n rejected: 'Not delivered',\n failed: 'Not delivered',\n}\n\n/**\n * Where a sent message got to, per recipient: the relay's answer and any delivery reports that came\n * back, in plain words. Shown on sent native mail only.\n */\nexport function MailDeliveryList({\n recipients,\n}: {\n recipients: MailDeliveryRecipient[]\n}): React.ReactElement | null {\n if (recipients.length === 0) return null\n return (\n <section\n aria-label=\"Delivery\"\n className=\"mb-5 rounded-md border border-border/60 px-3 py-2\"\n data-testid=\"mail-delivery-list\"\n >\n <h3 className=\"mb-1 text-xs font-medium text-muted-foreground\">Delivery</h3>\n <ul className=\"space-y-1\">\n {recipients.map((recipient) => {\n const Icon = ICONS[recipient.status]\n const failed = recipient.status === 'failed' || recipient.status === 'rejected'\n return (\n <li\n key={recipient.email}\n className=\"flex flex-wrap items-baseline gap-x-2 text-sm\"\n data-testid={`mail-delivery-${recipient.email}`}\n >\n <Icon\n aria-hidden=\"true\"\n className={cn(\n 'size-3.5 shrink-0 self-center',\n failed ? 'text-destructive' : 'text-muted-foreground'\n )}\n />\n <span className=\"font-medium\">{recipient.email}</span>\n <span className={cn(failed ? 'text-destructive' : 'text-muted-foreground')}>\n {LABELS[recipient.status]}: {recipient.description}\n </span>\n </li>\n )\n })}\n </ul>\n </section>\n )\n}\n","import type { ReactNode } from 'react'\nimport DOMPurify from 'dompurify'\nimport { Archive, ArrowLeft, Forward, Paperclip, Reply, Sparkles, Trash2 } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport type {\n MailAccount,\n MailAddress,\n MailAttachment,\n MailFolder,\n MailMessage,\n MailMessageUpdate,\n} from '@arbidocs/react'\nimport { MailDeliveryBadge } from './MailMessagePreview'\nimport { MailDeliveryList } from './MailDeliveryList'\nimport { hasCalendarPart, mailAddressLabel } from './mailCompose'\n\n/** Why an action that changes the mailbox on the server can't run right now. */\nexport const NEEDS_CONNECTION = 'Available when you are back online'\n\nexport interface MailMessageViewProps {\n account: MailAccount\n message: MailMessage\n folderRole: string\n folders: MailFolder[] | undefined\n isOnline: boolean\n loading: boolean\n uploadPending?: boolean\n onBack: () => void\n onEditDraft: () => void\n onReply: (forward?: boolean, all?: boolean) => void\n /** Ask ARBI to draft the reply (in a chat beside it). Absent: not offered. */\n onReplyWithArbi?: () => void\n onUpdate: (body: MailMessageUpdate) => void\n onDownloadAttachment: (attachment: MailAttachment) => void\n onDownloadOriginal: () => void\n /** Native mail: save the email to a workspace. Absent: not offered. */\n onSaveToWorkspace?: () => void\n /** How a person is named (default: the name on the message, else the address). */\n personLabel?: (person: MailAddress) => string\n /** A calendar invite card, for a message that carries an .ics part. */\n renderInvite?: () => ReactNode\n}\n\nconst SANITIZE = {\n ALLOWED_TAGS: [\n 'p',\n 'br',\n 'strong',\n 'b',\n 'em',\n 'i',\n 'u',\n 's',\n 'ul',\n 'ol',\n 'li',\n 'a',\n 'span',\n 'blockquote',\n ],\n ALLOWED_ATTR: ['href'],\n ALLOW_DATA_ATTR: false,\n}\n\n/** An opened message: its actions, sender, recipients, delivery, attachments and body. */\nexport function MailMessageView({\n account,\n message,\n folderRole,\n folders,\n isOnline,\n loading,\n uploadPending,\n onBack,\n onEditDraft,\n onReply,\n onReplyWithArbi,\n onUpdate,\n onDownloadAttachment,\n onDownloadOriginal,\n onSaveToWorkspace,\n personLabel = mailAddressLabel,\n renderInvite,\n}: MailMessageViewProps) {\n // Moving, marking and saving change the server's mailbox; offline they are unavailable, with why.\n const offlineTitle = isOnline ? undefined : NEEDS_CONNECTION\n return (\n <article className=\"min-w-0 flex-1 overflow-auto p-4 sm:p-5\">\n <Button className=\"mb-3\" variant=\"ghost\" onClick={onBack}>\n <ArrowLeft className=\"mr-2 size-4\" />\n Back\n </Button>\n {loading && <p className=\"text-muted-foreground\">Loading message…</p>}\n <div className=\"-mx-4 mb-5 flex flex-wrap items-center gap-1 border-b bg-muted/20 px-3 py-1.5 sm:-mx-5 [&_button]:h-8 [&_button]:px-2 [&_button]:text-xs\">\n {folderRole === 'drafts' ? (\n <Button onClick={onEditDraft}>Edit draft</Button>\n ) : (\n <>\n <Button variant=\"ghost\" onClick={() => onReply()}>\n <Reply className=\"mr-2 size-4\" />\n Reply\n </Button>\n {onReplyWithArbi && (\n <Button variant=\"ghost\" onClick={onReplyWithArbi}>\n <Sparkles className=\"mr-2 size-4\" />\n Reply with ARBI\n </Button>\n )}\n {message.to.length + message.cc.length > 1 && (\n <Button variant=\"ghost\" onClick={() => onReply(false, true)}>\n Reply all\n </Button>\n )}\n <Button variant=\"ghost\" onClick={() => onReply(true)}>\n <Forward className=\"mr-2 size-4\" />\n Forward\n </Button>\n </>\n )}\n <Button\n variant=\"ghost\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={() => onUpdate({ unread: !message.unread })}\n >\n {message.unread ? 'Mark read' : 'Mark unread'}\n </Button>\n {(folderRole === 'archive' || folderRole === 'trash') && (\n <Button\n variant=\"ghost\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={() =>\n onUpdate({ folder_id: folders?.find((f) => f.role === 'inbox')?.id ?? 'inbox' })\n }\n >\n Move to Inbox\n </Button>\n )}\n <Button\n variant=\"ghost\"\n aria-label=\"Archive message\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={() =>\n onUpdate({ folder_id: folders?.find((f) => f.role === 'archive')?.id ?? 'archive' })\n }\n >\n <Archive className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n aria-label=\"Trash message\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={() => onUpdate({ action: 'trash' })}\n >\n <Trash2 className=\"size-4\" />\n </Button>\n </div>\n <div className=\"mb-4 flex flex-wrap items-center gap-2\">\n <h2 className=\"text-xl font-semibold leading-snug tracking-tight\">\n {message.subject || '(No subject)'}\n </h2>\n {(message.delivery_status === 'bounced' ||\n message.delivery_status === 'partially_bounced' ||\n message.delivery_status === 'delayed') && (\n <MailDeliveryBadge problem={message.delivery_status} />\n )}\n </div>\n <div className=\"mb-5 flex gap-3 border-b border-border/60 pb-4\">\n <span\n aria-hidden=\"true\"\n className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-primary/10 text-sm font-semibold text-primary\"\n >\n {(message.sender[0]?.name || message.sender[0]?.email || '?')\n .split(/\\s+/)\n .slice(0, 2)\n .map((part) => part[0])\n .join('')\n .toUpperCase()}\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-baseline justify-between gap-1\">\n <p className=\"text-sm font-semibold\">\n {message.sender.map((person) => person.name || person.email).join(', ')}\n </p>\n <time className=\"text-[11px] text-muted-foreground\">\n {message.received_at ? new Date(message.received_at).toLocaleString() : ''}\n </time>\n </div>\n <p className=\"break-all text-xs text-muted-foreground\">\n {message.sender.map((person) => person.email).join(', ')}\n </p>\n <p className=\"mt-2 break-all text-xs text-muted-foreground\">\n To: {message.to.map(personLabel).join(', ')}\n {message.cc.length > 0 && ` · Cc: ${message.cc.map(personLabel).join(', ')}`}\n </p>\n </div>\n </div>\n <MailDeliveryList recipients={message.delivery ?? []} />\n {renderInvite && hasCalendarPart(message.attachments) && renderInvite()}\n <div className=\"mb-4 flex flex-wrap gap-2\">\n {message.attachments.map((a) => (\n <Button\n key={a.id}\n className=\"h-auto min-h-12 justify-start rounded-md border-border/70 bg-muted/20 px-3 py-2 text-left shadow-none hover:bg-muted/60\"\n variant=\"outline\"\n onClick={() => onDownloadAttachment(a)}\n >\n <Paperclip className=\"mr-2 size-4\" />\n <span className=\"min-w-0\">\n <span className=\"block truncate text-xs font-medium\">{a.name}</span>\n <span\n aria-hidden=\"true\"\n className=\"block text-[11px] font-normal text-muted-foreground\"\n >\n {a.size < 1024 ? `${a.size} B` : `${Math.ceil(a.size / 1024)} KB`}\n </span>\n </span>\n </Button>\n ))}\n </div>\n {message.html && message.text ? (\n <div\n data-testid=\"mail-message-body\"\n className=\"text-sm leading-7 [&_p]:mb-3 [&_ul]:list-disc [&_ul]:pl-6 [&_ol]:list-decimal [&_ol]:pl-6 [&_a]:text-primary [&_a]:underline\"\n dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(message.html, SANITIZE) }}\n />\n ) : message.text ? (\n <pre\n data-testid=\"mail-message-body\"\n className=\"whitespace-pre-wrap break-words font-sans text-sm leading-7 text-foreground/90\"\n >\n {message.text.split(/(https?:\\/\\/[^\\s]+)/g).map((part, index) =>\n /^https?:\\/\\//.test(part) ? (\n <a\n key={index}\n href={part}\n className=\"text-primary underline underline-offset-2\"\n rel=\"noreferrer\"\n >\n {part}\n </a>\n ) : (\n part\n )\n )}\n </pre>\n ) : message.html ? (\n <iframe\n title=\"Email body\"\n sandbox=\"\"\n referrerPolicy=\"no-referrer\"\n className=\"min-h-96 w-full border-0 bg-white\"\n srcDoc={`<meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'none'; img-src data:; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'\">${message.html}`}\n />\n ) : (\n <p className=\"text-muted-foreground\">Empty message</p>\n )}\n {account.provider === 'native' && (\n <div className=\"flex flex-wrap gap-2\">\n <Button\n className=\"mt-5\"\n variant=\"outline\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={onDownloadOriginal}\n >\n Download original email\n </Button>\n {onSaveToWorkspace && (\n <Button\n className=\"mt-5\"\n variant=\"outline\"\n disabled={uploadPending || !isOnline}\n title={offlineTitle}\n onClick={onSaveToWorkspace}\n >\n Save to workspace\n </Button>\n )}\n </div>\n )}\n </article>\n )\n}\n","import { useMemo, useState, type ReactNode } from 'react'\nimport { FolderOpen } from 'lucide-react'\nimport {\n Button,\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@arbidocs/react/ui'\n\n/** A workspace document that can be attached to an email. */\nexport interface MailAttachableDocument {\n id: string\n title: string\n /** Its file-type icon. */\n icon?: ReactNode\n}\n\nexport interface MailDocumentPickerProps {\n documents: MailAttachableDocument[]\n onAttach: (document: MailAttachableDocument) => void\n disabled?: boolean\n}\n\n/** \"From workspace\": a searchable list of the workspace's documents, attached as their files. */\nexport function MailDocumentPicker({\n documents,\n onAttach,\n disabled = false,\n}: MailDocumentPickerProps): React.ReactElement {\n const [open, setOpen] = useState(false)\n const [query, setQuery] = useState('')\n const filtered = useMemo(() => {\n const q = query.trim().toLowerCase()\n return q ? documents.filter((d) => d.title.toLowerCase().includes(q)) : documents\n }, [documents, query])\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={disabled}\n data-testid=\"mail-attach-workspace-document\"\n >\n <FolderOpen className=\"mr-2 size-4\" />\n From workspace\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-80 p-0\" align=\"start\" sideOffset={4}>\n <Command shouldFilter={false}>\n <CommandInput placeholder=\"Search documents...\" value={query} onValueChange={setQuery} />\n <CommandList className=\"max-h-72\">\n <CommandEmpty>No documents in this workspace</CommandEmpty>\n <CommandGroup>\n {filtered.map((doc) => (\n <CommandItem\n key={doc.id}\n value={doc.id}\n onSelect={() => {\n setOpen(false)\n setQuery('')\n onAttach(doc)\n }}\n data-testid={`document-search-item-${doc.id}`}\n >\n {doc.icon && <span className=\"shrink-0 text-muted-foreground\">{doc.icon}</span>}\n <span className=\"ml-1.5 flex-1 truncate text-sm\">{doc.title}</span>\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n )\n}\n","export interface MailBodyEditorProps {\n text: string\n html?: string\n disabled: boolean\n /** Every edit: the plain text and, from the rich editor, its HTML (`''` from this one). */\n onChange: (text: string, html: string) => void\n}\n\n/**\n * The message body as plain text: used when the rich editor (an optional peer, `lexical`) is not\n * installed or could not be loaded.\n */\nexport function PlainMailBodyEditor({ text, disabled, onChange }: MailBodyEditorProps) {\n return (\n <textarea\n aria-label=\"Message\"\n className=\"my-3 min-h-48 w-full resize-y bg-transparent text-sm outline-none\"\n value={text}\n disabled={disabled}\n onChange={(event) => onChange(event.target.value, '')}\n />\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/settings/ConfirmDialog.tsx"],"names":[],"mappings":";;;;;;;AAaO,IAAM,6BAAA,GAAqD;AAAA,EAChE,OAAA,EAAS,SAAA;AAAA,EACT,MAAA,EAAQ,QAAA;AAAA,EACR,UAAA,EAAY;AACd;AAuBO,SAAS,aAAA,CAAc;AAAA,EAC5B,MAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA,GAAU,aAAA;AAAA,EACV,SAAA,GAAY,KAAA;AAAA,EACZ,MAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAuB;AACrB,EAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,OAAO,EAAE,GAAG,6BAAA,EAA+B,GAAG,MAAA,EAAO,CAAA,EAAI,CAAC,MAAM,CAAC,CAAA;AACnF,EAAA,MAAM,SAAA,GAAY,OAA0B,IAAI,CAAA;AAChD,EAAA,uBACE,GAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,MAAA;AAAA,MACN,YAAA,EAAc,CAAC,IAAA,KAAS;AACtB,QAAA,IAAI,CAAC,MAAM,OAAA,EAAQ;AAAA,MACrB,CAAA;AAAA,MACA,IAAA,EAAK,aAAA;AAAA,MACL,eAAA,EAAiB,SAAA;AAAA,MACjB,KAAA;AAAA,MACA,WAAA;AAAA,MACA,eAAA,EAAe,IAAA;AAAA,MACf,IAAA,EACE,YAAY,aAAA,mBACV,GAAA,CAAC,iBAAc,SAAA,EAAU,uBAAA,EAAwB,aAAA,EAAY,MAAA,EAAO,CAAA,GAClE,IAAA;AAAA,MAEN,QAAQ,QAAA,CAAS,MAAA,EAAQ,EAAE,MAAA,EAAQ,sBAAsB,CAAA;AAAA,MAEzD,QAAA,kBAAA,IAAA,CAAC,aAAA,CAAc,MAAA,EAAd,EACC,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,SAAA;AAAA,YACL,OAAA,EAAQ,SAAA;AAAA,YACR,OAAA,EAAS,MAAM,OAAA,EAAQ;AAAA,YACvB,QAAA,EAAU,SAAA;AAAA,YACV,eAAa,QAAA,CAAS,OAAA,EAAS,QAAQ,EAAE,MAAA,EAAQ,oCAAoC,CAAA;AAAA,YAEpF,wBAAc,CAAA,CAAE;AAAA;AAAA,SACnB;AAAA,wBACA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,OAAA;AAAA,YACA,OAAA,EAAS,SAAA;AAAA,YACT,QAAA,EAAU,SAAA;AAAA,YACV,eAAa,QAAA,CAAS,OAAA,EAAS,SAAS,EAAE,MAAA,EAAQ,qCAAqC,CAAA;AAAA,YAEtF,QAAA,EAAA,SAAA,GAAY,CAAA,CAAE,UAAA,GAAc,WAAA,IAAe,CAAA,CAAE;AAAA;AAAA;AAChD,OAAA,EACF;AAAA;AAAA,GACF;AAEJ","file":"chunk-JJLMCV3T.js","sourcesContent":["import { useMemo, useRef } from 'react'\nimport { AlertTriangle } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\nimport { ModalScaffold } from './ModalScaffold'\n\n/** Every fixed string of the confirm dialog. `confirmText` / `cancelText` props win. */\nexport interface ConfirmDialogLabels {\n confirm: string\n cancel: string\n pleaseWait: string\n}\n\nexport const DEFAULT_CONFIRM_DIALOG_LABELS: ConfirmDialogLabels = {\n confirm: 'Confirm',\n cancel: 'Cancel',\n pleaseWait: 'Please wait...',\n}\n\nexport interface ConfirmDialogProps {\n labels?: Partial<ConfirmDialogLabels>\n isOpen: boolean\n onClose: () => void\n onConfirm: () => void\n title: string\n description: string\n confirmText?: string\n cancelText?: string\n variant?: 'destructive' | 'default'\n isLoading?: boolean\n /** Dialog test id (default `confirmation-modal`). */\n testId?: string\n /** Button ids; defaults are the current ids. */\n testIds?: Partial<Record<'cancel' | 'confirm', string>>\n}\n\n/**\n * Declarative yes/no confirmation with a loading state. An `alertdialog`: initial focus is on\n * Cancel (the safe action) and clicking outside does not dismiss it; Escape and Cancel do.\n */\nexport function ConfirmDialog({\n isOpen,\n onClose,\n onConfirm,\n title,\n description,\n confirmText,\n cancelText,\n variant = 'destructive',\n isLoading = false,\n labels,\n testId,\n testIds,\n}: ConfirmDialogProps) {\n const l = useMemo(() => ({ ...DEFAULT_CONFIRM_DIALOG_LABELS, ...labels }), [labels])\n const cancelRef = useRef<HTMLButtonElement>(null)\n return (\n <ModalScaffold\n open={isOpen}\n onOpenChange={(next) => {\n if (!next) onClose()\n }}\n role=\"alertdialog\"\n initialFocusRef={cancelRef}\n title={title}\n description={description}\n showDescription\n icon={\n variant === 'destructive' ? (\n <AlertTriangle className=\"h-5 w-5 text-red-text\" aria-hidden=\"true\" />\n ) : null\n }\n testId={testIdOr(testId, { testId: 'confirmation-modal' })}\n >\n <ModalScaffold.Footer>\n <Button\n ref={cancelRef}\n variant=\"outline\"\n onClick={() => onClose()}\n disabled={isLoading}\n data-testid={testIdOr(testIds?.cancel, { testId: 'confirmation-modal-cancel-button' })}\n >\n {cancelText ?? l.cancel}\n </Button>\n <Button\n variant={variant}\n onClick={onConfirm}\n disabled={isLoading}\n data-testid={testIdOr(testIds?.confirm, { testId: 'confirmation-modal-confirm-button' })}\n >\n {isLoading ? l.pleaseWait : (confirmText ?? l.confirm)}\n </Button>\n </ModalScaffold.Footer>\n </ModalScaffold>\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/collaboration/mail/MailMessagePreview.tsx","../src/collaboration/mail/mailCompose.ts","../src/collaboration/mail/MailGrid.tsx","../src/collaboration/mail/MailDeliveryList.tsx","../src/collaboration/mail/MailMessageView.tsx","../src/collaboration/mail/MailDocumentPicker.tsx","../src/collaboration/mail/PlainMailBodyEditor.tsx"],"names":["jsx","cn","deliveryProblem","jsxs","Paperclip","useMemo","GridView","Mail","Send","CheckCircle2","Clock","AlertCircle","Button","ArrowLeft","Fragment","Reply","Sparkles","Forward","Archive","Trash2","DOMPurify","useState","Popover","PopoverTrigger","FolderOpen","PopoverContent","Command","CommandInput","CommandList","CommandEmpty","CommandGroup","CommandItem"],"mappings":"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","file":"chunk-U6MPHCEB.cjs","sourcesContent":["import { Paperclip } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\n\nexport interface MailMessagePreviewProps {\n participants: string\n subject: string\n preview?: string\n date: string\n dateTime?: string\n unread?: boolean\n hasAttachments?: boolean\n /** A sent message's delivery problem; sent and delivered mail shows nothing, as in other clients. */\n deliveryProblem?: MailDeliveryProblem\n}\n\nexport type MailDeliveryProblem = 'bounced' | 'partially_bounced' | 'delayed'\n\nconst DELIVERY_BADGE: Record<MailDeliveryProblem, { label: string; title: string; tone: string }> =\n {\n bounced: {\n label: 'Bounced',\n title: \"Not delivered: the recipient's mail server sent this message back.\",\n tone: 'bg-destructive/10 text-destructive',\n },\n partially_bounced: {\n label: 'Partly bounced',\n title: 'Some recipients did not get this message. Open it to see who.',\n tone: 'bg-destructive/10 text-destructive',\n },\n delayed: {\n label: 'Delayed',\n title: \"Delivery is delayed; the recipient's server will keep retrying.\",\n tone: 'bg-muted text-muted-foreground',\n },\n }\n\n/** A pill for a sent message that bounced, partly bounced, or is delayed. */\nexport function MailDeliveryBadge({\n problem,\n className,\n}: {\n problem: MailDeliveryProblem\n className?: string\n}) {\n const badge = DELIVERY_BADGE[problem]\n return (\n <span\n className={cn('shrink-0 rounded-full px-2 py-0.5 text-xs font-medium', badge.tone, className)}\n title={badge.title}\n data-testid=\"mail-delivery-badge\"\n >\n {badge.label}\n </span>\n )\n}\n\n/** Compact inbox identity: sender/date, subject, then a body preview. */\nexport function MailMessagePreview({\n participants,\n subject,\n preview,\n date,\n dateTime,\n unread,\n hasAttachments,\n deliveryProblem,\n}: MailMessagePreviewProps) {\n return (\n <div className=\"flex h-full w-full min-w-0 flex-col justify-center gap-0.5 text-sm leading-5\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className={cn('min-w-0 flex-1 truncate', unread && 'font-semibold')}>\n {participants}\n </span>\n {hasAttachments && (\n <Paperclip\n className=\"size-3.5 shrink-0 text-muted-foreground\"\n aria-label=\"Has attachments\"\n />\n )}\n {deliveryProblem && <MailDeliveryBadge problem={deliveryProblem} />}\n <time dateTime={dateTime} className=\"shrink-0 text-xs font-normal text-muted-foreground\">\n {date}\n </time>\n </div>\n <div className={cn('truncate', unread && 'font-semibold')}>{subject || '(No subject)'}</div>\n <div className=\"truncate font-normal text-muted-foreground\">{preview || '\\u00a0'}</div>\n </div>\n )\n}\n","/** Pure helpers for writing mail: an empty message, recipient parsing, replies and forwards. */\n\nimport type {\n MailAccount,\n MailAddress,\n MailAttachment,\n MailCompose,\n MailMessage,\n} from '@arbidocs/react'\n\nexport const emptyMailCompose = (): MailCompose => ({\n to: [],\n cc: [],\n bcc: [],\n subject: '',\n text: '',\n attachments: [],\n})\n\n/** A person as shown: the name on the message, else the address. */\nexport const mailAddressLabel = (person: MailAddress): string => person.name || person.email\n\n/**\n * Typed or pasted recipients (`a@x.org; Pat <pat@y.org>`), separated by commas, semicolons or\n * lines, deduplicated by address.\n */\nexport function parseMailRecipients(value: string): MailAddress[] {\n const addresses = (value.match(/(?:[^,;\"\\n]|\"[^\"]*\")+/g) ?? [])\n .map((entry) => entry.trim())\n .filter(Boolean)\n .map((entry) => {\n const named = entry.match(/^(.*?)\\s*<([^<>]+)>$/)\n return named\n ? { email: named[2].trim(), name: named[1].trim().replace(/^\"|\"$/g, '') }\n : { email: entry }\n })\n return addresses.filter(\n (address, index) =>\n addresses.findIndex((item) => item.email.toLowerCase() === address.email.toLowerCase()) ===\n index\n )\n}\n\n/** A reply (to the sender, or everyone with `all`) or a forward of `message`. */\nexport function replyMailCompose(\n message: MailMessage,\n {\n account,\n folderRole,\n forward = false,\n all = false,\n attachments = [],\n }: {\n account: MailAccount\n /** The folder the message is in: replying from Sent goes to its recipients. */\n folderRole: string\n forward?: boolean\n all?: boolean\n /** A forward's attachments, with their content. */\n attachments?: MailAttachment[]\n }\n): MailCompose {\n return {\n ...emptyMailCompose(),\n to: forward ? [] : folderRole === 'sent' ? message.to : message.sender,\n cc: all\n ? [...message.to, ...message.cc]\n .filter(\n (r) =>\n r.email.toLowerCase() !== account.email.toLowerCase() &&\n !message.sender.some((s) => s.email.toLowerCase() === r.email.toLowerCase())\n )\n .filter(\n (r, i, values) =>\n values.findIndex((v) => v.email.toLowerCase() === r.email.toLowerCase()) === i\n )\n : [],\n subject: `${forward ? 'Fwd' : 'Re'}: ${message.subject.replace(/^(Re|Fwd):\\s*/i, '')}`,\n text: `\\n\\n${message.sender.map((s) => s.email).join(', ')} wrote:\\n${message.text}`,\n in_reply_to: forward ? undefined : message.message_id,\n references: [...message.references, ...(message.message_id ? [message.message_id] : [])],\n attachments,\n secure_delivery: message.secure_delivery,\n }\n}\n\n/** A saved draft, reopened for editing (`attachments` with their content). */\nexport function draftMailCompose(message: MailMessage, attachments: MailAttachment[]): MailCompose {\n return {\n to: message.to,\n cc: message.cc,\n bcc: message.bcc,\n subject: message.subject,\n text: message.text,\n html: message.html,\n attachments,\n draft_id: message.id,\n secure_delivery: message.secure_delivery,\n }\n}\n\n/** Whether a message carries a calendar invite (an .ics part). */\nexport const hasCalendarPart = (attachments: MailAttachment[]): boolean =>\n attachments.some(\n (a) => /^text\\/calendar\\b|^application\\/ics\\b/i.test(a.content_type) || /\\.ics$/i.test(a.name)\n )\n","import { useMemo } from 'react'\nimport type { ColDef, GridState } from 'ag-grid-community'\nimport { Mail } from 'lucide-react'\nimport type { MailAddress, MailMessage } from '@arbidocs/react'\nimport { GridView } from '../../files/GridView'\nimport { MailMessagePreview, type MailDeliveryProblem } from './MailMessagePreview'\nimport { mailAddressLabel } from './mailCompose'\n\n/** The list shows only delivery problems; sent and delivered mail stays quiet. */\nfunction deliveryProblem(status: MailMessage['delivery_status']): MailDeliveryProblem | undefined {\n return status === 'bounced' || status === 'partially_bounced' || status === 'delayed'\n ? status\n : undefined\n}\n\nexport interface MailGridProps {\n messages: MailMessage[]\n loading: boolean\n selected: string | null\n /** Sent, Drafts or Outbox: rows show recipients instead of the sender. */\n outgoing?: boolean\n onSelect: (id: string) => void\n /** How a person is named (default: the name on the message, else the address). */\n personLabel?: (person: MailAddress) => string\n /** Column state to restore at mount, and where to persist changes (both optional). */\n gridState?: GridState\n onGridStateChange?: (state: GridState) => void\n}\n\n/** A folder's messages: one row per message, unread dot, participants, subject and preview. */\nexport function MailGrid({\n messages,\n loading,\n selected,\n onSelect,\n outgoing = false,\n personLabel = mailAddressLabel,\n gridState,\n onGridStateChange,\n}: MailGridProps) {\n const columns = useMemo<ColDef<MailMessage>[]>(\n () => [\n {\n colId: 'unread',\n cellStyle: { padding: 0, justifyContent: 'center' },\n headerName: '',\n width: 34,\n minWidth: 34,\n maxWidth: 34,\n sortable: false,\n resizable: false,\n cellRenderer: ({ data }: { data?: MailMessage }) =>\n data?.unread ? (\n <span className=\"inline-block size-2 rounded-full bg-primary\" aria-label=\"Unread\" />\n ) : null,\n },\n {\n colId: 'message',\n cellClass:\n '[&_.ag-cell-value]:h-full [&_.ag-cell-value]:w-full [&_.ag-cell-wrapper]:h-full [&_.ag-cell-wrapper]:w-full',\n headerName: 'Message',\n flex: 1,\n minWidth: 240,\n sortable: false,\n valueGetter: (p) => p.data?.subject ?? '',\n cellRenderer: ({ data }: { data?: MailMessage }) =>\n data ? (\n <MailMessagePreview\n participants={(outgoing ? data.to : data.sender).map(personLabel).join(', ')}\n subject={data.subject}\n preview={data.preview}\n unread={data.unread}\n hasAttachments={Boolean(data.attachments.length)}\n deliveryProblem={deliveryProblem(data.delivery_status)}\n dateTime={data.received_at}\n date={\n data.received_at\n ? new Date(data.received_at).toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })\n : ''\n }\n />\n ) : null,\n },\n ],\n [outgoing, personLabel]\n )\n return (\n <GridView<MailMessage>\n items={messages}\n columnDefs={columns}\n getItemId={(m) => m.id}\n onRowClick={(m) => onSelect(m.id)}\n height=\"100%\"\n rowHeight={84}\n persistState={Boolean(onGridStateChange)}\n gridId=\"personal-mail-grid-v2\"\n gridState={gridState}\n onGridStateChange={onGridStateChange}\n testId=\"mail-grid\"\n isLoading={loading}\n getRowTestId={(m) => `mail-row-${m.id}`}\n emptyState={{\n icon: <Mail className=\"size-10 text-muted-foreground/50\" />,\n title: 'No messages',\n message: 'Messages in this folder will appear here.',\n }}\n gridOptions={{\n headerHeight: 0,\n suppressCellFocus: false,\n onCellKeyDown: (event) => {\n if ((event.event as KeyboardEvent)?.key === 'Enter' && event.data) onSelect(event.data.id)\n },\n defaultColDef: {\n sortable: true,\n resizable: true,\n filter: false,\n },\n rowClassRules: { 'bg-muted/60': (p) => p.data?.id === selected },\n }}\n />\n )\n}\n","import { AlertCircle, CheckCircle2, Clock, Send } from 'lucide-react'\nimport type { MailDeliveryRecipient } from '@arbidocs/react'\nimport { cn } from '@arbidocs/react/ui'\n\nconst ICONS: Record<MailDeliveryRecipient['status'], typeof Send> = {\n accepted: Send,\n relayed: Send,\n expanded: Send,\n delivered: CheckCircle2,\n delayed: Clock,\n rejected: AlertCircle,\n failed: AlertCircle,\n}\n\nconst LABELS: Record<MailDeliveryRecipient['status'], string> = {\n accepted: 'Sent',\n relayed: 'Sent',\n expanded: 'Sent',\n delivered: 'Delivered',\n delayed: 'Delayed',\n rejected: 'Not delivered',\n failed: 'Not delivered',\n}\n\n/**\n * Where a sent message got to, per recipient: the relay's answer and any delivery reports that came\n * back, in plain words. Shown on sent native mail only.\n */\nexport function MailDeliveryList({\n recipients,\n}: {\n recipients: MailDeliveryRecipient[]\n}): React.ReactElement | null {\n if (recipients.length === 0) return null\n return (\n <section\n aria-label=\"Delivery\"\n className=\"mb-5 rounded-md border border-border/60 px-3 py-2\"\n data-testid=\"mail-delivery-list\"\n >\n <h3 className=\"mb-1 text-xs font-medium text-muted-foreground\">Delivery</h3>\n <ul className=\"space-y-1\">\n {recipients.map((recipient) => {\n const Icon = ICONS[recipient.status]\n const failed = recipient.status === 'failed' || recipient.status === 'rejected'\n return (\n <li\n key={recipient.email}\n className=\"flex flex-wrap items-baseline gap-x-2 text-sm\"\n data-testid={`mail-delivery-${recipient.email}`}\n >\n <Icon\n aria-hidden=\"true\"\n className={cn(\n 'size-3.5 shrink-0 self-center',\n failed ? 'text-destructive' : 'text-muted-foreground'\n )}\n />\n <span className=\"font-medium\">{recipient.email}</span>\n <span className={cn(failed ? 'text-destructive' : 'text-muted-foreground')}>\n {LABELS[recipient.status]}: {recipient.description}\n </span>\n </li>\n )\n })}\n </ul>\n </section>\n )\n}\n","import type { ReactNode } from 'react'\nimport DOMPurify from 'dompurify'\nimport { Archive, ArrowLeft, Forward, Paperclip, Reply, Sparkles, Trash2 } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport type {\n MailAccount,\n MailAddress,\n MailAttachment,\n MailFolder,\n MailMessage,\n MailMessageUpdate,\n} from '@arbidocs/react'\nimport { MailDeliveryBadge } from './MailMessagePreview'\nimport { MailDeliveryList } from './MailDeliveryList'\nimport { hasCalendarPart, mailAddressLabel } from './mailCompose'\n\n/** Why an action that changes the mailbox on the server can't run right now. */\nexport const NEEDS_CONNECTION = 'Available when you are back online'\n\nexport interface MailMessageViewProps {\n account: MailAccount\n message: MailMessage\n folderRole: string\n folders: MailFolder[] | undefined\n isOnline: boolean\n loading: boolean\n uploadPending?: boolean\n onBack: () => void\n onEditDraft: () => void\n onReply: (forward?: boolean, all?: boolean) => void\n /** Ask ARBI to draft the reply (in a chat beside it). Absent: not offered. */\n onReplyWithArbi?: () => void\n onUpdate: (body: MailMessageUpdate) => void\n onDownloadAttachment: (attachment: MailAttachment) => void\n onDownloadOriginal: () => void\n /** Native mail: save the email to a workspace. Absent: not offered. */\n onSaveToWorkspace?: () => void\n /** How a person is named (default: the name on the message, else the address). */\n personLabel?: (person: MailAddress) => string\n /** A calendar invite card, for a message that carries an .ics part. */\n renderInvite?: () => ReactNode\n}\n\nconst SANITIZE = {\n ALLOWED_TAGS: [\n 'p',\n 'br',\n 'strong',\n 'b',\n 'em',\n 'i',\n 'u',\n 's',\n 'ul',\n 'ol',\n 'li',\n 'a',\n 'span',\n 'blockquote',\n ],\n ALLOWED_ATTR: ['href'],\n ALLOW_DATA_ATTR: false,\n}\n\n/** An opened message: its actions, sender, recipients, delivery, attachments and body. */\nexport function MailMessageView({\n account,\n message,\n folderRole,\n folders,\n isOnline,\n loading,\n uploadPending,\n onBack,\n onEditDraft,\n onReply,\n onReplyWithArbi,\n onUpdate,\n onDownloadAttachment,\n onDownloadOriginal,\n onSaveToWorkspace,\n personLabel = mailAddressLabel,\n renderInvite,\n}: MailMessageViewProps) {\n // Moving, marking and saving change the server's mailbox; offline they are unavailable, with why.\n const offlineTitle = isOnline ? undefined : NEEDS_CONNECTION\n return (\n <article className=\"min-w-0 flex-1 overflow-auto p-4 sm:p-5\">\n <Button className=\"mb-3\" variant=\"ghost\" onClick={onBack}>\n <ArrowLeft className=\"mr-2 size-4\" />\n Back\n </Button>\n {loading && <p className=\"text-muted-foreground\">Loading message…</p>}\n <div className=\"-mx-4 mb-5 flex flex-wrap items-center gap-1 border-b bg-muted/20 px-3 py-1.5 sm:-mx-5 [&_button]:h-8 [&_button]:px-2 [&_button]:text-xs\">\n {folderRole === 'drafts' ? (\n <Button onClick={onEditDraft}>Edit draft</Button>\n ) : (\n <>\n <Button variant=\"ghost\" onClick={() => onReply()}>\n <Reply className=\"mr-2 size-4\" />\n Reply\n </Button>\n {onReplyWithArbi && (\n <Button variant=\"ghost\" onClick={onReplyWithArbi}>\n <Sparkles className=\"mr-2 size-4\" />\n Reply with ARBI\n </Button>\n )}\n {message.to.length + message.cc.length > 1 && (\n <Button variant=\"ghost\" onClick={() => onReply(false, true)}>\n Reply all\n </Button>\n )}\n <Button variant=\"ghost\" onClick={() => onReply(true)}>\n <Forward className=\"mr-2 size-4\" />\n Forward\n </Button>\n </>\n )}\n <Button\n variant=\"ghost\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={() => onUpdate({ unread: !message.unread })}\n >\n {message.unread ? 'Mark read' : 'Mark unread'}\n </Button>\n {(folderRole === 'archive' || folderRole === 'trash') && (\n <Button\n variant=\"ghost\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={() =>\n onUpdate({ folder_id: folders?.find((f) => f.role === 'inbox')?.id ?? 'inbox' })\n }\n >\n Move to Inbox\n </Button>\n )}\n <Button\n variant=\"ghost\"\n aria-label=\"Archive message\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={() =>\n onUpdate({ folder_id: folders?.find((f) => f.role === 'archive')?.id ?? 'archive' })\n }\n >\n <Archive className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n aria-label=\"Trash message\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={() => onUpdate({ action: 'trash' })}\n >\n <Trash2 className=\"size-4\" />\n </Button>\n </div>\n <div className=\"mb-4 flex flex-wrap items-center gap-2\">\n <h2 className=\"text-xl font-semibold leading-snug tracking-tight\">\n {message.subject || '(No subject)'}\n </h2>\n {(message.delivery_status === 'bounced' ||\n message.delivery_status === 'partially_bounced' ||\n message.delivery_status === 'delayed') && (\n <MailDeliveryBadge problem={message.delivery_status} />\n )}\n </div>\n <div className=\"mb-5 flex gap-3 border-b border-border/60 pb-4\">\n <span\n aria-hidden=\"true\"\n className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-primary/10 text-sm font-semibold text-primary\"\n >\n {(message.sender[0]?.name || message.sender[0]?.email || '?')\n .split(/\\s+/)\n .slice(0, 2)\n .map((part) => part[0])\n .join('')\n .toUpperCase()}\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-baseline justify-between gap-1\">\n <p className=\"text-sm font-semibold\">\n {message.sender.map((person) => person.name || person.email).join(', ')}\n </p>\n <time className=\"text-[11px] text-muted-foreground\">\n {message.received_at ? new Date(message.received_at).toLocaleString() : ''}\n </time>\n </div>\n <p className=\"break-all text-xs text-muted-foreground\">\n {message.sender.map((person) => person.email).join(', ')}\n </p>\n <p className=\"mt-2 break-all text-xs text-muted-foreground\">\n To: {message.to.map(personLabel).join(', ')}\n {message.cc.length > 0 && ` · Cc: ${message.cc.map(personLabel).join(', ')}`}\n </p>\n </div>\n </div>\n <MailDeliveryList recipients={message.delivery ?? []} />\n {renderInvite && hasCalendarPart(message.attachments) && renderInvite()}\n <div className=\"mb-4 flex flex-wrap gap-2\">\n {message.attachments.map((a) => (\n <Button\n key={a.id}\n className=\"h-auto min-h-12 justify-start rounded-md border-border/70 bg-muted/20 px-3 py-2 text-left shadow-none hover:bg-muted/60\"\n variant=\"outline\"\n onClick={() => onDownloadAttachment(a)}\n >\n <Paperclip className=\"mr-2 size-4\" />\n <span className=\"min-w-0\">\n <span className=\"block truncate text-xs font-medium\">{a.name}</span>\n <span\n aria-hidden=\"true\"\n className=\"block text-[11px] font-normal text-muted-foreground\"\n >\n {a.size < 1024 ? `${a.size} B` : `${Math.ceil(a.size / 1024)} KB`}\n </span>\n </span>\n </Button>\n ))}\n </div>\n {message.html && message.text ? (\n <div\n data-testid=\"mail-message-body\"\n className=\"text-sm leading-7 [&_p]:mb-3 [&_ul]:list-disc [&_ul]:pl-6 [&_ol]:list-decimal [&_ol]:pl-6 [&_a]:text-primary [&_a]:underline\"\n dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(message.html, SANITIZE) }}\n />\n ) : message.text ? (\n <pre\n data-testid=\"mail-message-body\"\n className=\"whitespace-pre-wrap break-words font-sans text-sm leading-7 text-foreground/90\"\n >\n {message.text.split(/(https?:\\/\\/[^\\s]+)/g).map((part, index) =>\n /^https?:\\/\\//.test(part) ? (\n <a\n key={index}\n href={part}\n className=\"text-primary underline underline-offset-2\"\n rel=\"noreferrer\"\n >\n {part}\n </a>\n ) : (\n part\n )\n )}\n </pre>\n ) : message.html ? (\n <iframe\n title=\"Email body\"\n sandbox=\"\"\n referrerPolicy=\"no-referrer\"\n className=\"min-h-96 w-full border-0 bg-white\"\n srcDoc={`<meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'none'; img-src data:; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'\">${message.html}`}\n />\n ) : (\n <p className=\"text-muted-foreground\">Empty message</p>\n )}\n {account.provider === 'native' && (\n <div className=\"flex flex-wrap gap-2\">\n <Button\n className=\"mt-5\"\n variant=\"outline\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={onDownloadOriginal}\n >\n Download original email\n </Button>\n {onSaveToWorkspace && (\n <Button\n className=\"mt-5\"\n variant=\"outline\"\n disabled={uploadPending || !isOnline}\n title={offlineTitle}\n onClick={onSaveToWorkspace}\n >\n Save to workspace\n </Button>\n )}\n </div>\n )}\n </article>\n )\n}\n","import { useMemo, useState, type ReactNode } from 'react'\nimport { FolderOpen } from 'lucide-react'\nimport {\n Button,\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@arbidocs/react/ui'\n\n/** A workspace document that can be attached to an email. */\nexport interface MailAttachableDocument {\n id: string\n title: string\n /** Its file-type icon. */\n icon?: ReactNode\n}\n\nexport interface MailDocumentPickerProps {\n documents: MailAttachableDocument[]\n onAttach: (document: MailAttachableDocument) => void\n disabled?: boolean\n}\n\n/** \"From workspace\": a searchable list of the workspace's documents, attached as their files. */\nexport function MailDocumentPicker({\n documents,\n onAttach,\n disabled = false,\n}: MailDocumentPickerProps): React.ReactElement {\n const [open, setOpen] = useState(false)\n const [query, setQuery] = useState('')\n const filtered = useMemo(() => {\n const q = query.trim().toLowerCase()\n return q ? documents.filter((d) => d.title.toLowerCase().includes(q)) : documents\n }, [documents, query])\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={disabled}\n data-testid=\"mail-attach-workspace-document\"\n >\n <FolderOpen className=\"mr-2 size-4\" />\n From workspace\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-80 p-0\" align=\"start\" sideOffset={4}>\n <Command shouldFilter={false}>\n <CommandInput placeholder=\"Search documents...\" value={query} onValueChange={setQuery} />\n <CommandList className=\"max-h-72\">\n <CommandEmpty>No documents in this workspace</CommandEmpty>\n <CommandGroup>\n {filtered.map((doc) => (\n <CommandItem\n key={doc.id}\n value={doc.id}\n onSelect={() => {\n setOpen(false)\n setQuery('')\n onAttach(doc)\n }}\n data-testid={`document-search-item-${doc.id}`}\n >\n {doc.icon && <span className=\"shrink-0 text-muted-foreground\">{doc.icon}</span>}\n <span className=\"ml-1.5 flex-1 truncate text-sm\">{doc.title}</span>\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n )\n}\n","export interface MailBodyEditorProps {\n text: string\n html?: string\n disabled: boolean\n /** Every edit: the plain text and, from the rich editor, its HTML (`''` from this one). */\n onChange: (text: string, html: string) => void\n}\n\n/**\n * The message body as plain text: used when the rich editor (an optional peer, `lexical`) is not\n * installed or could not be loaded.\n */\nexport function PlainMailBodyEditor({ text, disabled, onChange }: MailBodyEditorProps) {\n return (\n <textarea\n aria-label=\"Message\"\n className=\"my-3 min-h-48 w-full resize-y bg-transparent text-sm outline-none\"\n value={text}\n disabled={disabled}\n onChange={(event) => onChange(event.target.value, '')}\n />\n )\n}\n"]}