@arbidocs/blocks 0.5.33 → 0.5.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -501,3 +501,35 @@ Blocks hold no keys and do no crypto. Parts take the data of one workspace and n
501
501
  across workspaces. The few places that persist something locally (Studio local storage, the last
502
502
  selected workspace in `/connect`) are scoped per user (and workspace) and fail loudly instead of
503
503
  falling back to unscoped plaintext storage.
504
+
505
+ ## Navigation and action manifests
506
+
507
+ Import `defineNavigation`, `defineActions` and `ActionDefinition` from `@arbidocs/blocks`.
508
+ The host supplies labels, icons, destinations and handlers; the package supplies the projections
509
+ and dispatch. Destinations may be router paths or host page keys.
510
+
511
+ ```tsx
512
+ const navigation = defineNavigation([
513
+ { heading: 'Work', items: [{ id: 'files', to: '/files', label: 'Files', icon: File }] },
514
+ ])
515
+ // The same items satisfy CommandPaletteProvider's navItems contract, without a remap.
516
+ const paletteItems = navigation.items
517
+ const shellItems = navigation.resolve({
518
+ beforeNavigate: closeMainPanels,
519
+ onNavigate: ({ to }) => navigate(to),
520
+ onNavigated: closeDrawer,
521
+ itemProps: ({ to }) => ({ active: pathname === to }),
522
+ }) // ShellSidebar and MobileTabBar share these rows.
523
+
524
+ const actions = defineActions({
525
+ upload: { id: 'upload', label: 'Upload files', category: 'Files', icon: 'Upload', run: openUpload },
526
+ })
527
+ actions.options // picker values, labels and categories
528
+ actions.isActionId(incomingId) // validates registered or configured page-scoped ids
529
+ actions.run('upload') // invokes only a registered own action
530
+ ```
531
+
532
+ Page-scoped action ids can be passed as `scopedIds` in the second argument. They validate for tip
533
+ content but do not dispatch globally; `onUnknown` can report a mistaken global dispatch. Host-only
534
+ metadata (for example a guided demonstration id) stays on the action definition.
535
+ `ConnectedGridView` from `@arbidocs/blocks/connect` keeps `GridView` column layouts in the host session, keyed by `gridId` when `persistState` is enabled. The host persist adapter owns reload persistence.
@@ -6,7 +6,7 @@ import { testIdOr } from './chunk-7F6CBP3Z.js';
6
6
  import { Clock, UserMinus, Trash2, Gift, AtSign, MoreVertical, Plus, KeyRound, Loader2, BellOff, Bell, X, ChevronsUpDown, Paperclip, Mail, AlertCircle, CheckCircle2, Send, ArrowLeft, Reply, Sparkles, Forward, RotateCcw, Archive, FolderOpen, XCircle, CheckCircle, ChevronDown, ChevronRight } from 'lucide-react';
7
7
  import { cn, Tooltip, TooltipTrigger, Select, SelectTrigger, SelectContent, SelectItem, TooltipContent, SelectValue, Button, Textarea, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuSeparator, DropdownMenuItem, ScrollArea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, Popover, PopoverTrigger, PopoverContent, Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, Checkbox } from '@arbidocs/react/ui';
8
8
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
- import { useMemo, useState, useRef, useEffect } from 'react';
9
+ import { useMemo, useRef, useState, useEffect } from 'react';
10
10
  import DOMPurify from 'dompurify';
11
11
 
12
12
  function MemberMutedText({
@@ -704,6 +704,8 @@ function RecipientPicker({
704
704
  hasNoKnownUsers,
705
705
  labels
706
706
  }) {
707
+ const openRef = useRef(isOpen);
708
+ openRef.current = isOpen;
707
709
  const l = useMemo(() => ({ ...DEFAULT_RECIPIENT_PICKER_LABELS, ...labels }), [labels]);
708
710
  return /* @__PURE__ */ jsx("div", { className: "shrink-0 border-b px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
709
711
  /* @__PURE__ */ jsx(ModalSectionTitle, { className: "mb-0 shrink-0 py-1.5", children: l.to }),
@@ -773,6 +775,9 @@ function RecipientPicker({
773
775
  /* @__PURE__ */ jsx(
774
776
  PopoverContent,
775
777
  {
778
+ onCloseAutoFocus: (event) => {
779
+ if (openRef.current) event.preventDefault();
780
+ },
776
781
  className: "w-72 p-0",
777
782
  align: "start",
778
783
  onPointerDownOutside: (e) => e.preventDefault(),
@@ -1562,5 +1567,5 @@ function PlainMailBodyEditor({ text, disabled, onChange }) {
1562
1567
  }
1563
1568
 
1564
1569
  export { ActionMenu, AddContactsForm, AddContactsResults, DEFAULT_ADD_CONTACTS_LABELS, DEFAULT_CONTACT_INVITE_LABELS, DEFAULT_CONTACT_OUTCOME_LABELS, DEFAULT_DM_ACCESS_REQUEST_BANNER_LABELS, DEFAULT_DM_GRANT_ACCESS_DIALOG_LABELS, DEFAULT_DM_THREAD_FRAME_LABELS, DEFAULT_MAIL_FOLDER_TREE_LABELS, DEFAULT_RECIPIENT_PICKER_LABELS, DmAccessRequestBanner, DmGrantAccessDialogView, DmInviteAvatar, DmNewTabIcon, DmThreadFrame, EMPTY_CONTACT_FORM, MAX_INVITE_EMAILS, MailDeliveryBadge, MailDeliveryList, MailDocumentPicker, MailFolderTree, MailGrid, MailMessagePreview, MailMessageView, MemberBulkActions, MemberListLoading, MemberMutedText, MemberNameCell, MemberRoleCell, NEEDS_CONNECTION, PlainMailBodyEditor, RecipientPicker, RoleSelect, WorkspaceDeleteButton, applyContactInviteResults, buildMailFolderTree, contactName, contactOutcomeMessage, contactStatusLabel, contactToForm, descendantFolderIds, draftMailCompose, emailTokens, emptyMailCompose, failContactInvites, formToContactCard, hasCalendarPart, inviteEmail, isInboxFolder, isInvitableEmail, mailAddressLabel, matchesContact, normalizeVCardDate, parseEmails, parseMailRecipients, planContactInvites, primaryEmail, replyMailCompose, summarizeContactInvites, summarizeImport, summarizeUnsentInvites, toAddContactsRow, toAddContactsRows, toggleMailFolder, validateContactForm };
1565
- //# sourceMappingURL=chunk-H7L43DIE.js.map
1566
- //# sourceMappingURL=chunk-H7L43DIE.js.map
1570
+ //# sourceMappingURL=chunk-46WCQ4F3.js.map
1571
+ //# sourceMappingURL=chunk-46WCQ4F3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/collaboration/members/WorkspaceMembers.tsx","../src/collaboration/contacts/parseEmails.ts","../src/collaboration/contacts/AddContactsParts.tsx","../src/collaboration/contacts/invite-plan.ts","../src/collaboration/contacts/contact-form.ts","../src/collaboration/direct-messages/DmParts.tsx","../src/collaboration/mail/mailFolders.ts","../src/collaboration/mail/MailFolderTree.tsx","../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":["jsxs","Fragment","jsx","Button","EMAIL","AtSign","useMemo","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Tooltip","TooltipTrigger","TooltipContent","useRef","cn","deliveryProblem","Clock","AlertCircle","Trash2","Paperclip","useState","Popover","PopoverTrigger","PopoverContent","Command","CommandInput","CommandList","CommandEmpty","CommandGroup","CommandItem"],"mappings":"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","file":"chunk-46WCQ4F3.js","sourcesContent":["import type { ReactNode } from 'react'\nimport { Clock, Trash2, UserMinus } from 'lucide-react'\nimport {\n Button,\n cn,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@arbidocs/react/ui'\nimport { RoleBadge } from '../../workspaces/WorkspaceBadges'\n\n/** One assignable role. `badgeClass` is the host's palette for the role. */\nexport interface MemberRoleOption {\n value: string\n label: string\n badgeClass: string\n}\n\n/** Tooltip + grid-cell text of the members table, kept in one place. */\nexport function MemberMutedText({\n children,\n title,\n className,\n}: {\n children: ReactNode\n title?: string\n className?: string\n}) {\n return (\n <span className={cn('text-sm text-muted-foreground', className)} title={title}>\n {children}\n </span>\n )\n}\n\n/** Layout of the Name cell: identity chip followed by optional contact toggle. */\nexport function MemberNameCell({ children }: { children: ReactNode }) {\n return <div className=\"flex h-full items-center gap-2\">{children}</div>\n}\n\nexport interface MemberRoleCellProps {\n role: string\n roles: MemberRoleOption[]\n /** Tooltip: why the role is locked, or what the role means. */\n tooltip: string\n canChange: boolean\n isPending: boolean\n onChange: (role: string) => void\n /** Session-scoped (temporary) grant: adds a clock with its explanation. */\n temporaryHint?: string\n}\n\n/** Inline role dropdown of a member row (always rendered so chevrons align). */\nexport function MemberRoleCell({\n role,\n roles,\n tooltip,\n canChange,\n isPending,\n onChange,\n temporaryHint,\n}: MemberRoleCellProps) {\n const current = roles.find((r) => r.value === role)\n return (\n <div className=\"flex h-full items-center gap-1\">\n <Tooltip>\n <TooltipTrigger asChild>\n <span>\n <Select value={role} onValueChange={onChange} disabled={!canChange || isPending}>\n <SelectTrigger\n className={cn(\n 'h-6 w-[130px] border-0 bg-transparent text-sm focus:ring-0 focus:ring-offset-0 disabled:opacity-100',\n canChange ? 'hover:bg-muted/50' : 'cursor-not-allowed [&>svg]:opacity-30'\n )}\n >\n <RoleBadge label={current?.label ?? role} badgeClass={current?.badgeClass ?? ''} />\n </SelectTrigger>\n <SelectContent>\n {roles.map((r) => (\n <SelectItem key={r.value} value={r.value}>\n <RoleBadge label={r.label} badgeClass={r.badgeClass} />\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </span>\n </TooltipTrigger>\n <TooltipContent side=\"right\" className=\"max-w-[300px]\">\n <p>{tooltip}</p>\n </TooltipContent>\n </Tooltip>\n {temporaryHint && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Clock\n className=\"size-3.5 shrink-0 cursor-default text-muted-foreground\"\n aria-label={temporaryHint}\n />\n </TooltipTrigger>\n <TooltipContent side=\"right\" className=\"max-w-[300px]\">\n <p>{temporaryHint}</p>\n </TooltipContent>\n </Tooltip>\n )}\n </div>\n )\n}\n\n/** Loading strip of the members list. */\nexport function MemberListLoading({ label = 'Loading users...' }: { label?: string }) {\n return (\n <div\n className=\"rounded-md bg-blue-bg p-3 text-center text-sm\"\n data-testid=\"workspace-users-loading\"\n >\n <div className=\"mr-2 inline-block size-4 animate-spin rounded-full border-2 border-primary/30 border-t-primary\" />\n {label}\n </div>\n )\n}\n\nexport interface MemberBulkActionsProps {\n /** Roles a bulk change may assign. */\n roles: { value: string; label: string }[]\n onChangeRole: (role: string) => void\n isRoleDisabled: boolean\n roleTooltip: string\n /** Only the workspace owner can use either control (also styles them muted). */\n isOwner: boolean\n onRemove: () => void\n isRemoveDisabled: boolean\n removeTooltip: string\n changeRolePlaceholder?: string\n}\n\n/** Role change dropdown + remove button inside the selection bar of the members table. */\nexport function MemberBulkActions({\n roles,\n onChangeRole,\n isRoleDisabled,\n roleTooltip,\n isOwner,\n onRemove,\n isRemoveDisabled,\n removeTooltip,\n changeRolePlaceholder = 'Change role',\n}: MemberBulkActionsProps) {\n return (\n <>\n <Tooltip>\n <TooltipTrigger asChild onFocusCapture={(e) => e.stopPropagation()}>\n <span tabIndex={!isOwner ? 0 : undefined}>\n <Select value=\"\" onValueChange={onChangeRole} disabled={isRoleDisabled}>\n <SelectTrigger\n className={cn(\n 'h-7 w-[120px] text-sm pointer-coarse:h-11',\n isRoleDisabled ? 'border-border text-muted-foreground' : 'border-input'\n )}\n >\n <SelectValue placeholder={changeRolePlaceholder} />\n </SelectTrigger>\n <SelectContent>\n {roles.map((r) => (\n <SelectItem key={r.value} value={r.value}>\n {r.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </span>\n </TooltipTrigger>\n <TooltipContent>\n <p>{roleTooltip}</p>\n </TooltipContent>\n </Tooltip>\n\n <Tooltip>\n <TooltipTrigger asChild>\n <span tabIndex={!isOwner ? 0 : undefined}>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={onRemove}\n disabled={isRemoveDisabled}\n aria-label={removeTooltip}\n className={cn(\n 'size-7 pointer-coarse:size-11',\n isOwner\n ? 'border-destructive/30 text-destructive hover:bg-destructive hover:text-destructive-foreground'\n : 'border-border text-muted-foreground'\n )}\n >\n <UserMinus className=\"size-4\" />\n </Button>\n </span>\n </TooltipTrigger>\n <TooltipContent>\n <p>{removeTooltip}</p>\n </TooltipContent>\n </Tooltip>\n </>\n )\n}\n\nexport interface WorkspaceDeleteButtonProps {\n canDelete: boolean\n /** Why deletion is not allowed (tooltip on the disabled button). */\n disabledReason?: string\n isDeleting?: boolean\n onDelete: () => void\n labels?: { delete: string; deleting: string }\n}\n\n/** Destructive \"Delete\" of a workspace; disabled with an explanation when not allowed. */\nexport function WorkspaceDeleteButton({\n canDelete,\n disabledReason = '',\n isDeleting = false,\n onDelete,\n labels = { delete: 'Delete', deleting: 'Deleting...' },\n}: WorkspaceDeleteButtonProps) {\n const button = (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={canDelete ? onDelete : undefined}\n disabled={!canDelete || isDeleting}\n className=\"h-7 px-2 text-sm text-destructive hover:bg-destructive/10 hover:text-destructive pointer-coarse:h-11\"\n data-testid=\"workspace-delete-button\"\n >\n <Trash2 className=\"mr-1 size-3.5\" />\n <span>{isDeleting ? labels.deleting : labels.delete}</span>\n </Button>\n )\n\n if (canDelete || !disabledReason) return button\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <span tabIndex={0}>{button}</span>\n </TooltipTrigger>\n <TooltipContent>\n <p>{disabledReason}</p>\n </TooltipContent>\n </Tooltip>\n )\n}\n\nexport interface RoleSelectProps {\n value: string\n roles: MemberRoleOption[]\n onChange: (role: string) => void\n /** Tooltip: what the selected role allows. */\n description: string\n}\n\n/** Role picker shown beside a user selector (e.g. when sharing a workspace). */\nexport function RoleSelect({ value, roles, onChange, description }: RoleSelectProps) {\n const current = roles.find((r) => r.value === value)\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <span>\n <Select value={value} onValueChange={onChange}>\n <SelectTrigger className=\"h-8 w-[140px] pointer-coarse:h-11\">\n <SelectValue>\n <RoleBadge label={current?.label ?? value} badgeClass={current?.badgeClass ?? ''} />\n </SelectValue>\n </SelectTrigger>\n <SelectContent>\n {roles.map((r) => (\n <SelectItem key={r.value} value={r.value}>\n <RoleBadge label={r.label} badgeClass={r.badgeClass} />\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </span>\n </TooltipTrigger>\n <TooltipContent side=\"left\" className=\"max-w-[300px]\">\n <p>{description}</p>\n </TooltipContent>\n </Tooltip>\n )\n}\n","import type { components } from '@arbidocs/client'\nimport type { AddContactsResultRow } from './AddContactsParts'\n\n/** The most addresses one add-contacts request may carry (the API's own limit). */\nexport const MAX_INVITE_EMAILS = 100\n\nconst EMAIL = /^[^\\s@,;]+@[^\\s@,;]+\\.[^\\s@,;]+$/\n\n/**\n * Distinct, lower-cased, well-formed addresses typed or pasted into the invite box. Commas,\n * semicolons, spaces and new lines all separate; anything that is not an address is dropped.\n */\nexport function parseEmails(text: string): string[] {\n const parts = text.split(/[\\s,;]+/).map((e) => e.trim().toLowerCase())\n return [...new Set(parts.filter((e) => EMAIL.test(e)))]\n}\n\ntype ContactRow = Pick<\n components['schemas']['ContactResponse'],\n 'email' | 'status' | 'outcome' | 'outcome_detail'\n>\n\n/** One plain sentence per outcome the backend reports. */\nexport interface ContactOutcomeLabels {\n contact_added: string\n already_contact: string\n invited: string\n reinvited: string\n not_resent_still_pending: string\n /** Fallback when the backend gives no detail for a failure. */\n failed: string\n /** A row the backend reported without an outcome. */\n added: string\n}\n\nexport const DEFAULT_CONTACT_OUTCOME_LABELS: ContactOutcomeLabels = {\n contact_added: 'Added to contacts (existing user)',\n already_contact: 'Already in your contacts',\n invited: 'Invitation sent',\n reinvited: 'Previous invitation expired, new one sent',\n not_resent_still_pending: 'Invitation already pending, not resent',\n failed: 'Could not be invited',\n added: 'Added successfully',\n}\n\n/**\n * What the backend did with one address, as a sentence. `outcome_detail` carries what only the server\n * knows (which rate limit refused, how long a live invitation has left), so it is always added.\n */\nexport function contactOutcomeMessage(\n row: ContactRow,\n labels: Partial<ContactOutcomeLabels> = {}\n): string {\n const l = { ...DEFAULT_CONTACT_OUTCOME_LABELS, ...labels }\n const base = row.outcome\n ? l[row.outcome]\n : row.status === 'registered'\n ? l.contact_added\n : l.added\n return row.outcome_detail ? `${base} — ${row.outcome_detail}` : base\n}\n\n/** A backend add-contact row as an {@link AddContactsResultRow} for `AddContactsResults`. */\nexport function toAddContactsRow(\n row: ContactRow,\n labels: Partial<ContactOutcomeLabels> = {}\n): AddContactsResultRow {\n return {\n email: row.email ?? '',\n status: row.outcome === 'failed' ? 'failed' : 'success',\n message: contactOutcomeMessage(row, labels),\n }\n}\n\n/** Map every row of an add-contacts response. */\nexport const toAddContactsRows = (\n rows: ContactRow[],\n labels?: Partial<ContactOutcomeLabels>\n): AddContactsResultRow[] => rows.map((r) => toAddContactsRow(r, labels))\n","import { useMemo, type ReactNode } from 'react'\nimport { AlertCircle, AtSign, CheckCircle, Gift, XCircle } from 'lucide-react'\nimport { Button, Textarea } from '@arbidocs/react/ui'\nimport { ModalSection, ModalSectionTitle } from '../../settings/ModalScaffold'\nimport { MAX_INVITE_EMAILS, parseEmails } from './parseEmails'\n\n/** Every fixed string of the add-contacts flow. */\nexport interface AddContactsLabels {\n placeholder: string\n hint: string\n add: (count: number) => string\n addOverMax: (count: number, max: number) => string\n adding: string\n cancel: string\n results: string\n email: string\n status: string\n done: string\n addMore: string\n /** The invite-reward banner text for a formatted amount. */\n reward: (amount: string) => ReactNode\n}\n\nexport const DEFAULT_ADD_CONTACTS_LABELS: AddContactsLabels = {\n placeholder: 'name@example.com',\n hint: 'Paste one or multiple emails — separated by commas, spaces, or new lines.',\n add: (count) => `Add${count > 0 ? ` (${count})` : ''}`,\n addOverMax: (count, max) => `Add (${count}) - Max ${max}`,\n adding: 'Adding...',\n cancel: 'Cancel',\n results: 'Results',\n email: 'Email',\n status: 'Status',\n done: 'Done',\n addMore: 'Add More',\n reward: (amount) => (\n <>\n Get <span className=\"font-semibold text-foreground\">{amount} off your next invoice</span> for\n every invited contact who goes Pro. They get {amount} off theirs.\n </>\n ),\n}\n\nexport interface AddContactsFormProps {\n value: string\n onChange: (value: string) => void\n /**\n * How many addresses `value` holds. Omit it: the form parses `value` itself with\n * {@link parseEmails} (commas, semicolons, spaces and new lines; distinct, valid, lower-cased).\n */\n emailCount?: number\n /** The most addresses one submit may carry. Default {@link MAX_INVITE_EMAILS} (the API's own limit). */\n maxEmails?: number\n isPending: boolean\n /** Receives the parsed addresses, ready to send. */\n onSubmit: (emails: string[]) => void\n onCancel?: () => void\n /** Formatted referral reward (\"$10\"); omit to hide the banner. */\n rewardAmount?: string\n labels?: Partial<AddContactsLabels>\n}\n\n/** Email invite form: a textarea for one or many addresses, and Add / Cancel. */\nexport function AddContactsForm({\n value,\n onChange,\n emailCount: emailCountProp,\n maxEmails = MAX_INVITE_EMAILS,\n isPending,\n onSubmit,\n onCancel,\n rewardAmount,\n labels,\n}: AddContactsFormProps) {\n const l = useMemo(() => ({ ...DEFAULT_ADD_CONTACTS_LABELS, ...labels }), [labels])\n const emails = useMemo(() => parseEmails(value), [value])\n const emailCount = emailCountProp ?? emails.length\n const overMax = emailCount > maxEmails\n return (\n <div className=\"space-y-4\" data-slot=\"add-contacts-form\">\n {rewardAmount && (\n <div\n className=\"flex items-start gap-2 rounded-md bg-green-bg p-3 text-sm\"\n data-testid=\"invite-reward-banner\"\n >\n <Gift className=\"mt-0.5 size-4 shrink-0 text-green-text\" />\n <p className=\"text-muted-foreground\">{l.reward(rewardAmount)}</p>\n </div>\n )}\n <div>\n <Textarea\n id=\"invite-emails\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n disabled={isPending}\n placeholder={l.placeholder}\n rows={2}\n autoFocus\n data-testid=\"invite-emails-input\"\n />\n <p className=\"mt-1.5 text-sm text-muted-foreground\">{l.hint}</p>\n </div>\n\n <div className=\"flex flex-col gap-2 pt-2\">\n <Button\n onClick={() => onSubmit(emails)}\n disabled={emailCount === 0 || overMax || isPending}\n className=\"w-full\"\n data-testid=\"invite-send-button\"\n >\n {isPending ? (\n l.adding\n ) : (\n <>\n <AtSign className=\"mr-2 size-4\" />\n {overMax ? l.addOverMax(emailCount, maxEmails) : l.add(emailCount)}\n </>\n )}\n </Button>\n <Button variant=\"outline\" onClick={onCancel} disabled={isPending} className=\"w-full\">\n {l.cancel}\n </Button>\n </div>\n </div>\n )\n}\n\nexport interface AddContactsResultRow {\n email: string\n status: 'success' | 'failed' | 'pending'\n message: string\n}\n\nexport interface AddContactsResultsProps {\n rows: AddContactsResultRow[]\n onDone?: () => void\n onAddMore: () => void\n labels?: Partial<AddContactsLabels>\n}\n\nconst STATUS_ICON = {\n success: <CheckCircle className=\"size-4 shrink-0 text-green-text\" />,\n failed: <XCircle className=\"size-4 shrink-0 text-red-text\" />,\n pending: <AlertCircle className=\"size-4 shrink-0 text-yellow-text\" />,\n} as const\n\n/** Per-address outcome table with Done / Add More. */\nexport function AddContactsResults({ rows, onDone, onAddMore, labels }: AddContactsResultsProps) {\n const l = useMemo(() => ({ ...DEFAULT_ADD_CONTACTS_LABELS, ...labels }), [labels])\n return (\n <ModalSection>\n <ModalSectionTitle>{l.results}</ModalSectionTitle>\n <div className=\"max-h-80 overflow-y-auto rounded-md border\">\n <table className=\"w-full\">\n <thead className=\"sticky top-0 bg-muted/50\">\n <tr>\n <th className=\"p-2 text-left font-medium\">{l.email}</th>\n <th className=\"p-2 text-left font-medium\">{l.status}</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((row, index) => (\n <tr\n key={index}\n className=\"border-t hover:bg-muted/30\"\n data-testid={`email-status-row-${index}`}\n >\n <td className=\"p-2\">{row.email}</td>\n <td className=\"p-2\">\n <div className=\"flex items-center gap-2\">\n {STATUS_ICON[row.status]}\n <span className=\"text-muted-foreground\">{row.message}</span>\n </div>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n <div className=\"flex flex-col gap-2 pt-4\">\n <Button onClick={onDone} className=\"w-full\" data-testid=\"close-results-button\">\n {l.done}\n </Button>\n <Button\n variant=\"outline\"\n onClick={onAddMore}\n className=\"w-full\"\n data-testid=\"start-over-button\"\n >\n {l.addMore}\n </Button>\n </div>\n </ModalSection>\n )\n}\n","/**\n * The \"add contacts by e-mail\" flow as pure steps: what was typed → which addresses to send (and a row for\n * every one left out, with the reason) → the rows once the server answered → one summary sentence.\n */\nimport type { components } from '@arbidocs/client'\nimport type { AddContactsResultRow } from './AddContactsParts'\nimport { toAddContactsRow, type ContactOutcomeLabels } from './parseEmails'\n\ntype Contact = components['schemas']['ContactResponse']\n\n/** Every typed token, lower-cased and distinct (commas, semicolons, spaces and new lines separate). */\nexport function emailTokens(text: string): string[] {\n return [\n ...new Set(\n text\n .split(/[,;\\s]+/)\n .map((e) => e.trim().toLowerCase())\n .filter(Boolean)\n ),\n ]\n}\n\nconst EMAIL = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/\n\n/** A deliverable address: local@domain.tld, a TLD of 2+ letters, no doubled dots. */\nexport const isInvitableEmail = (email: string): boolean =>\n EMAIL.test(email) && !email.includes('..')\n\n/** Every fixed sentence of the planned rows and the summary. */\nexport interface ContactInviteLabels {\n invalid: string\n self: string\n resending: string\n sending: string\n alreadyInvited: string\n alreadyRegistered: string\n notProcessed: string\n}\n\nexport const DEFAULT_CONTACT_INVITE_LABELS: ContactInviteLabels = {\n invalid: 'Invalid email format (excluded)',\n self: \"Can't add yourself as a contact\",\n resending: 'Resending invitation...',\n sending: 'Sending...',\n alreadyInvited: 'User already in contacts (invitation pending)',\n alreadyRegistered: 'User already in contacts (registered)',\n notProcessed: 'Not processed by server (may be rate limited or invalid)',\n}\n\nexport interface ContactInvitePlan {\n /** One row per typed address, in the order shown. */\n rows: AddContactsResultRow[]\n /** The addresses to send (new ones, and expired invitations to resend). */\n send: string[]\n}\n\n/**\n * Plan an invite: bad addresses and your own are left out, people already in your contacts are not sent\n * again (an expired invitation is), the rest are sent.\n */\nexport function planContactInvites(\n text: string,\n contacts: Pick<Contact, 'email' | 'status'>[],\n selfEmail?: string | null,\n labels: Partial<ContactInviteLabels> = {}\n): ContactInvitePlan {\n const l = { ...DEFAULT_CONTACT_INVITE_LABELS, ...labels }\n const me = selfEmail?.toLowerCase()\n const tokens = emailTokens(text)\n const invalid = tokens.filter((e) => !isInvitableEmail(e))\n const valid = tokens.filter((e) => isInvitableEmail(e))\n const rows: AddContactsResultRow[] = invalid.map((email) => ({\n email,\n status: 'failed',\n message: l.invalid,\n }))\n const self = valid.filter((e) => me && e === me)\n rows.push(...self.map((email) => ({ email, status: 'failed' as const, message: l.self })))\n const send: string[] = []\n for (const email of valid) {\n if (me && email === me) continue\n const existing = contacts.find((c) => c.email?.toLowerCase() === email)\n if (!existing) {\n send.push(email)\n rows.push({ email, status: 'pending', message: l.sending })\n } else if (existing.status === 'expired') {\n send.push(email)\n rows.push({ email, status: 'pending', message: l.resending })\n } else\n rows.push({\n email,\n status: 'success',\n message: existing.status === 'invited' ? l.alreadyInvited : l.alreadyRegistered,\n })\n }\n return { rows, send }\n}\n\n/** The planned rows once the server answered for the sent addresses. */\nexport function applyContactInviteResults(\n plan: ContactInvitePlan,\n response: Pick<Contact, 'email' | 'status' | 'outcome' | 'outcome_detail'>[],\n labels: Partial<ContactInviteLabels & ContactOutcomeLabels> = {}\n): AddContactsResultRow[] {\n const l = { ...DEFAULT_CONTACT_INVITE_LABELS, ...labels }\n return plan.rows.map((row) => {\n if (!plan.send.includes(row.email)) return row\n const answer = response.find((c) => c.email?.toLowerCase() === row.email)\n return answer\n ? { ...toAddContactsRow(answer, labels), email: row.email }\n : { email: row.email, status: 'failed', message: l.notProcessed }\n })\n}\n\n/** The planned rows when the request itself failed: every sent address carries `message`. */\nexport function failContactInvites(\n plan: ContactInvitePlan,\n message: string\n): AddContactsResultRow[] {\n return plan.rows.map((row) =>\n plan.send.includes(row.email) ? { ...row, status: 'failed', message } : row\n )\n}\n\n/** \"2 contacts added, 1 invitation email sent, 1 failed\" for what the server did. */\nexport function summarizeContactInvites(response: Pick<Contact, 'outcome'>[]): {\n message: string\n failed: boolean\n} {\n const count = (...outcomes: Contact['outcome'][]) =>\n response.filter((c) => outcomes.includes(c.outcome)).length\n const added = count('contact_added')\n const sent = count('invited', 'reinvited')\n const failed = count('failed')\n const notResent = count('not_resent_still_pending')\n const parts: string[] = []\n if (added) parts.push(`${added} contact${added !== 1 ? 's' : ''} added`)\n if (sent) parts.push(`${sent} invitation email${sent !== 1 ? 's' : ''} sent`)\n if (notResent) parts.push(`${notResent} already pending`)\n if (failed) parts.push(`${failed} failed`)\n return { message: parts.length ? parts.join(', ') : 'No changes', failed: failed > 0 }\n}\n\n/** The sentence when nothing needed sending (everyone already a contact, or left out). */\nexport function summarizeUnsentInvites(\n rows: AddContactsResultRow[],\n labels: Partial<ContactInviteLabels> = {}\n): string {\n const l = { ...DEFAULT_CONTACT_INVITE_LABELS, ...labels }\n const already = rows.filter(\n (r) => r.message === l.alreadyInvited || r.message === l.alreadyRegistered\n ).length\n const excluded = rows.filter((r) => r.message === l.invalid).length\n if (already && excluded) return `${already} already in contacts, ${excluded} excluded`\n if (already) return `All ${already} email${already !== 1 ? 's are' : ' is'} already in contacts`\n return 'All emails excluded (invalid or duplicate)'\n}\n","/** Contact form state ↔ API (`ContactCardWrite` / `ContactCard`) mapping, validation and list helpers. Pure. */\nimport type { components } from '@arbidocs/client'\n\ntype Contact = components['schemas']['ContactResponse']\ntype ContactCard = components['schemas']['ContactCard']\ntype ContactCardWrite = components['schemas']['ContactCardWrite']\ntype ContactImportResult = components['schemas']['ContactImportResult']\n\nexport interface LabeledValue {\n value: string\n type: string\n}\n\nexport interface ContactFormState {\n name: string\n emails: LabeledValue[]\n phones: LabeledValue[]\n addresses: LabeledValue[]\n organization: string\n title: string\n /** YYYY-MM-DD, --MM-DD, or MM-DD (normalised to --MM-DD) */\n birthday: string\n anniversary: string\n note: string\n /** Not edited in the form; carried so an edit does not drop them. */\n nickname: string\n urls: string[]\n}\n\nexport const EMPTY_CONTACT_FORM: ContactFormState = {\n name: '',\n emails: [{ value: '', type: '' }],\n phones: [{ value: '', type: '' }],\n addresses: [],\n organization: '',\n title: '',\n birthday: '',\n anniversary: '',\n note: '',\n nickname: '',\n urls: [],\n}\n\nfunction str(v: unknown): string {\n return typeof v === 'string' ? v : ''\n}\n\nexport function contactToForm(c: ContactCard): ContactFormState {\n const pick = (rows: object[] | undefined, key: string) =>\n (rows ?? []).map((row) => {\n const r = row as Record<string, unknown>\n return { value: str(r[key]), type: str(r.type) }\n })\n const emails = pick(c.emails, 'email')\n const phones = pick(c.phones, 'number')\n return {\n name: c.name ?? '',\n emails: emails.length ? emails : [{ value: '', type: '' }],\n phones: phones.length ? phones : [{ value: '', type: '' }],\n addresses: pick(c.addresses, 'value'),\n organization: c.organization ?? '',\n title: c.title ?? '',\n birthday: c.birthday ?? '',\n anniversary: c.anniversary ?? '',\n note: c.note ?? '',\n nickname: c.nickname ?? '',\n urls: c.urls ?? [],\n }\n}\n\nconst FULL_DATE = /^\\d{4}-\\d{2}-\\d{2}$/\nconst NO_YEAR = /^--\\d{2}-\\d{2}$/\nconst MONTH_DAY = /^\\d{2}-\\d{2}$/\n\n/**\n * A vCard date: `YYYY-MM-DD`, or `--MM-DD` when the year is unknown (`MM-DD` is accepted and normalised).\n * Returns null for empty input and `undefined` when invalid.\n */\nexport function normalizeVCardDate(input: string): string | null | undefined {\n const v = input.trim()\n if (!v) return null\n const candidate = MONTH_DAY.test(v) ? `--${v}` : v\n if (!FULL_DATE.test(candidate) && !NO_YEAR.test(candidate)) return undefined\n const [m, d] = candidate.slice(-5).split('-').map(Number)\n if (m < 1 || m > 12 || d < 1 || d > 31) return undefined\n if (FULL_DATE.test(candidate)) {\n const y = Number(candidate.slice(0, 4))\n const t = new Date(Date.UTC(y, m - 1, d))\n if (t.getUTCMonth() !== m - 1) return undefined\n } else {\n // Feb 29 is fine without a year; reject impossible days.\n const max = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m - 1]\n if (d > max) return undefined\n }\n return candidate\n}\n\nconst EMAIL = /^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/\n\nexport function validateContactForm(f: ContactFormState): Record<string, string> {\n const errors: Record<string, string> = {}\n if (!f.name.trim()) errors.name = 'Enter a name'\n if (f.emails.some((e) => e.value.trim() && !EMAIL.test(e.value.trim())))\n errors.emails = 'Check the e-mail address'\n if (normalizeVCardDate(f.birthday) === undefined)\n errors.birthday = 'Use YYYY-MM-DD, or --MM-DD without a year'\n if (normalizeVCardDate(f.anniversary) === undefined)\n errors.anniversary = 'Use YYYY-MM-DD, or --MM-DD without a year'\n return errors\n}\n\n/** Build the API body: trims, drops blank rows, nulls empty optional text, normalises dates. */\nexport function formToContactCard(f: ContactFormState): ContactCardWrite {\n const rows = (list: LabeledValue[]) =>\n list.map((r) => ({ value: r.value.trim(), type: r.type.trim() || null })).filter((r) => r.value)\n const opt = (v: string) => v.trim() || null\n return {\n name: f.name.trim(),\n emails: rows(f.emails).map((r) => ({ email: r.value, type: r.type })),\n phones: rows(f.phones).map((r) => ({ number: r.value, type: r.type })),\n addresses: rows(f.addresses).map((r) => ({ value: r.value, type: r.type })),\n organization: opt(f.organization),\n title: opt(f.title),\n birthday: normalizeVCardDate(f.birthday) ?? null,\n anniversary: normalizeVCardDate(f.anniversary) ?? null,\n note: opt(f.note),\n nickname: opt(f.nickname),\n urls: f.urls.map((u) => u.trim()).filter(Boolean),\n }\n}\n\n/** The first well-formed e-mail address on the form: the one \"Invite to ARBI\" links. */\nexport function inviteEmail(f: ContactFormState): string | null {\n const first = f.emails.map((e) => e.value.trim()).find((e) => EMAIL.test(e))\n return first ? first.toLowerCase() : null\n}\n\n/** The name a contact is listed under: its card, else the ARBI account, else the address. */\nexport function contactName(c: Contact): string {\n const user = c.user ? [c.user.given_name, c.user.family_name].filter(Boolean).join(' ') : ''\n return c.card?.name || user || c.email || ''\n}\n\n/** Primary e-mail of a contact for list display: the linked address, else the card's first. */\nexport function primaryEmail(c: Contact): string | null {\n return c.email || c.card?.emails?.[0]?.email || null\n}\n\nexport function matchesContact(c: Contact, q: string): boolean {\n const term = q.trim().toLowerCase()\n if (!term) return true\n const card = c.card\n const hay = [\n contactName(c),\n c.email,\n card?.organization,\n card?.title,\n card?.nickname,\n ...(card?.emails ?? []).map((e) => e.email),\n ...(card?.phones ?? []).map((p) => p.number),\n ]\n return hay.some((h) => h && h.toLowerCase().includes(term))\n}\n\n/** The short status a contact row shows; a plain card shows none. */\nexport function contactStatusLabel(status: Contact['status']): string | null {\n switch (status) {\n case 'registered':\n return 'On ARBI'\n case 'invited':\n return 'Invited'\n case 'expired':\n return 'Invite expired'\n case 'failed':\n return 'Invite failed'\n default:\n return null\n }\n}\n\n/** \"12 added, 3 matched existing contacts, 1 skipped\" for a .vcf import. */\nexport function summarizeImport(r: ContactImportResult): string {\n const parts = [`${r.added} added`]\n if (r.matched) parts.push(`${r.matched} matched existing contact${r.matched === 1 ? '' : 's'}`)\n if (r.skipped.length) parts.push(`${r.skipped.length} skipped`)\n return parts.join(', ')\n}\n","import { useMemo, useRef, type ReactNode, type Ref } from 'react'\nimport {\n AtSign,\n ChevronsUpDown,\n KeyRound,\n Loader2,\n MoreVertical,\n Plus,\n Bell,\n BellOff,\n X,\n} from 'lucide-react'\nimport {\n Button,\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Popover,\n PopoverContent,\n PopoverTrigger,\n ScrollArea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@arbidocs/react/ui'\nimport { ModalSectionTitle } from '../../settings/ModalScaffold'\n\n/** Every fixed string of the access-request banner. */\nexport interface DmAccessRequestBannerLabels {\n /** Text after the bold peer name (keep the leading space). */\n requestedAccess: string\n review: string\n}\n\nexport const DEFAULT_DM_ACCESS_REQUEST_BANNER_LABELS: DmAccessRequestBannerLabels = {\n requestedAccess: ' requested workspace access',\n review: 'Review',\n}\n\n/** Every fixed string of the thread frame. */\nexport interface DmThreadFrameLabels {\n noMessages: string\n}\n\nexport const DEFAULT_DM_THREAD_FRAME_LABELS: DmThreadFrameLabels = {\n noMessages: 'No messages yet — say hi 👋',\n}\n\n/** Every fixed string of the grant-access dialog. */\nexport interface DmGrantAccessDialogLabels {\n title: string\n description: (peerName: string) => string\n noWorkspace: string\n workspace: string\n role: string\n cancel: string\n grantAccess: string\n}\n\nexport const DEFAULT_DM_GRANT_ACCESS_DIALOG_LABELS: DmGrantAccessDialogLabels = {\n title: 'Grant workspace access',\n description: (peerName) =>\n `Give ${peerName} access to one of your workspaces. Access is permanent until you remove it.`,\n noWorkspace:\n 'Open the workspace you want to share, as its owner, and you can grant access to it from here.',\n workspace: 'Workspace',\n role: 'Role',\n cancel: 'Cancel',\n grantAccess: 'Grant access',\n}\n\n/** Every fixed string of the recipient picker. */\nexport interface RecipientPickerLabels {\n to: string\n unmuteNotifications: string\n muteNotifications: string\n removeRecipient: string\n selectRecipient: string\n addRecipient: string\n searchUsers: string\n noKnownUsers: string\n noMatchingUsers: string\n addContactsHint: string\n}\n\nexport const DEFAULT_RECIPIENT_PICKER_LABELS: RecipientPickerLabels = {\n to: 'To',\n unmuteNotifications: 'Unmute notifications',\n muteNotifications: 'Mute notifications',\n removeRecipient: 'Remove recipient',\n selectRecipient: 'Select recipient...',\n addRecipient: 'Add recipient',\n searchUsers: 'Search users...',\n noKnownUsers: 'No known users',\n noMatchingUsers: 'No matching users',\n addContactsHint: 'Add contacts or join workspaces to send private messages',\n}\n\nexport type ActionMenuEntry =\n | {\n id: string\n label: ReactNode\n icon?: ReactNode\n onSelect: () => void\n testId?: string\n destructive?: boolean\n }\n | { id: string; separator: true }\n\nexport interface ActionMenuProps {\n /** Accessible name of the trigger. */\n label: string\n testId?: string\n entries: ActionMenuEntry[]\n /** Width class of the menu. */\n contentClassName?: string\n}\n\n/** A single ⋮ overflow menu: the occasional actions on a row or header. */\nexport function ActionMenu({ label, testId, entries, contentClassName = 'w-56' }: ActionMenuProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-7 shrink-0 text-muted-foreground hover:text-foreground pointer-coarse:size-11\"\n aria-label={label}\n data-testid={testId}\n onClick={(e) => e.stopPropagation()}\n >\n <MoreVertical className=\"size-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className={contentClassName}>\n {entries.map((entry) =>\n 'separator' in entry ? (\n <DropdownMenuSeparator key={entry.id} />\n ) : (\n <DropdownMenuItem\n key={entry.id}\n onClick={entry.onSelect}\n className={entry.destructive ? 'text-destructive focus:text-destructive' : undefined}\n data-testid={entry.testId}\n >\n {entry.icon && (\n <span className=\"mr-2 inline-flex size-4 items-center\">{entry.icon}</span>\n )}\n {entry.label}\n </DropdownMenuItem>\n )\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\n/** Round \"@\" mark standing in for the face of a pending invitation. */\nexport function DmInviteAvatar() {\n return (\n <span className=\"flex size-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground\">\n <AtSign className=\"size-4\" />\n </span>\n )\n}\n\n/** Round \"+\" tab icon of a new (compose) conversation. */\nexport function DmNewTabIcon() {\n return (\n <div className=\"flex h-5 w-5 items-center justify-center rounded-full bg-primary/10\">\n <Plus className=\"h-3 w-3 text-primary\" />\n </div>\n )\n}\n\n/** Banner at the top of a thread: the peer asked for workspace access; Review opens the grant flow. */\nexport function DmAccessRequestBanner({\n name,\n onReview,\n labels,\n}: {\n name: string\n onReview: () => void\n labels?: Partial<DmAccessRequestBannerLabels>\n}) {\n const l = useMemo(() => ({ ...DEFAULT_DM_ACCESS_REQUEST_BANNER_LABELS, ...labels }), [labels])\n return (\n <div className=\"mx-4 mt-3 flex items-center gap-3 rounded-lg bg-muted px-3 py-2.5\">\n <KeyRound className=\"h-4 w-4 shrink-0 text-primary\" />\n <span className=\"min-w-0 flex-1 text-sm text-foreground\">\n <span className=\"font-medium\">{name}</span>\n {l.requestedAccess}\n </span>\n <Button size=\"sm\" onClick={onReview} data-testid=\"dm-review-access-button\">\n {l.review}\n </Button>\n </div>\n )\n}\n\nexport interface DmThreadFrameProps {\n /** Recipient picker, shown above everything in compose mode. */\n recipientPicker?: ReactNode\n accessBanner?: ReactNode\n /** A recipient is chosen: the history area shows. */\n hasRecipient: boolean\n /** The history is still decrypting. */\n isLoading: boolean\n /** Messages (and the typing indicator), rendered inside the scroll area. */\n history: ReactNode\n /** No messages yet. */\n isEmpty: boolean\n /** Prompt shown when there is no recipient and users exist to pick from. */\n noRecipientPrompt?: ReactNode\n /** Ref to the history wrapper (the host scrolls its viewport). */\n historyRef?: Ref<HTMLDivElement>\n composer: ReactNode\n labels?: Partial<DmThreadFrameLabels>\n}\n\n/** Layout of one direct-message thread: picker, banner, scrolling history, composer. */\nexport function DmThreadFrame({\n recipientPicker,\n accessBanner,\n hasRecipient,\n isLoading,\n history,\n isEmpty,\n noRecipientPrompt,\n historyRef,\n composer,\n labels,\n}: DmThreadFrameProps) {\n const l = useMemo(() => ({ ...DEFAULT_DM_THREAD_FRAME_LABELS, ...labels }), [labels])\n return (\n <div className=\"flex h-full flex-col bg-background\">\n {recipientPicker}\n {accessBanner}\n\n {/* Clean page surface: the peer bubble is `bg-card` and the own bubble a soft tint. */}\n {hasRecipient && (\n <div className=\"min-h-0 flex-1 overflow-hidden bg-background\" ref={historyRef}>\n <ScrollArea className=\"h-full\">\n <div className=\"px-4 py-3\">\n {isLoading ? (\n <div className=\"flex h-32 items-center justify-center\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n </div>\n ) : !isEmpty ? (\n history\n ) : (\n <div className=\"flex h-32 items-center justify-center text-sm text-muted-foreground\">\n {l.noMessages}\n </div>\n )}\n </div>\n </ScrollArea>\n </div>\n )}\n\n {!hasRecipient && noRecipientPrompt && (\n <div className=\"flex min-h-0 flex-1 items-center justify-center bg-background p-4\">\n <p className=\"text-center text-sm text-muted-foreground\">{noRecipientPrompt}</p>\n </div>\n )}\n\n <div className=\"shrink-0\">{composer}</div>\n </div>\n )\n}\n\nexport interface DmGrantAccessDialogViewProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n peerName: string\n /** The one workspace that can be shared; `null` when none is eligible. */\n workspaceName: string | null\n role: string\n onRoleChange: (role: string) => void\n roles: { value: string; label: string; hint: string }[]\n isGranting: boolean\n onGrant: () => void\n labels?: Partial<DmGrantAccessDialogLabels>\n}\n\n/** Offer a person access to the open workspace: the workspace, a role, a grant button. */\nexport function DmGrantAccessDialogView({\n open,\n onOpenChange,\n peerName,\n workspaceName,\n role,\n onRoleChange,\n roles,\n isGranting,\n onGrant,\n labels,\n}: DmGrantAccessDialogViewProps) {\n const l = useMemo(() => ({ ...DEFAULT_DM_GRANT_ACCESS_DIALOG_LABELS, ...labels }), [labels])\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent presentation=\"sheet\" data-testid=\"dm-grant-access-modal\">\n <DialogHeader>\n <DialogTitle>{l.title}</DialogTitle>\n <DialogDescription>{l.description(peerName)}</DialogDescription>\n </DialogHeader>\n\n {workspaceName === null ? (\n <p className=\"text-sm text-muted-foreground\" data-testid=\"dm-grant-none\">\n {l.noWorkspace}\n </p>\n ) : (\n <div className=\"space-y-4\">\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">{l.workspace}</label>\n <p className=\"rounded-lg bg-muted px-3 py-2 text-sm\" data-testid=\"dm-grant-workspace\">\n {workspaceName}\n </p>\n </div>\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">{l.role}</label>\n <Select value={role} onValueChange={onRoleChange}>\n <SelectTrigger data-testid=\"dm-grant-role\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {roles.map((r) => (\n <SelectItem key={r.value} value={r.value}>\n {r.label} — {r.hint}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n )}\n\n <DialogFooter>\n <Button variant=\"ghost\" onClick={() => onOpenChange(false)} disabled={isGranting}>\n {l.cancel}\n </Button>\n <Button\n onClick={onGrant}\n disabled={isGranting || workspaceName === null}\n data-testid=\"dm-grant-submit\"\n >\n {isGranting && <Loader2 className=\"mr-2 size-4 animate-spin\" />}\n {l.grantAccess}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nexport interface RecipientView {\n id: string\n /** Avatar + name pill. */\n identity: ReactNode\n isMuted: boolean\n muteTooltip: string\n onToggleMute: () => void\n isMuteBusy?: boolean\n}\n\nexport interface RecipientCandidate {\n id: string\n identity: ReactNode\n}\n\nexport interface RecipientPickerProps {\n selected: RecipientView[]\n onRemove: (id: string) => void\n candidates: RecipientCandidate[]\n onPick: (id: string) => void\n /** Hide the add control (the maximum is reached). */\n canAdd: boolean\n isOpen: boolean\n onOpenChange: (open: boolean) => void\n search: string\n onSearchChange: (value: string) => void\n /** There is nobody at all to pick from (vs. no search match). */\n hasNoKnownUsers: boolean\n labels?: Partial<RecipientPickerLabels>\n}\n\n/** \"To:\" row of the compose view: chosen recipients (mutable) and a searchable add control. */\nexport function RecipientPicker({\n selected,\n onRemove,\n candidates,\n onPick,\n canAdd,\n isOpen,\n onOpenChange,\n search,\n onSearchChange,\n hasNoKnownUsers,\n labels,\n}: RecipientPickerProps) {\n const openRef = useRef(isOpen)\n openRef.current = isOpen\n const l = useMemo(() => ({ ...DEFAULT_RECIPIENT_PICKER_LABELS, ...labels }), [labels])\n return (\n <div className=\"shrink-0 border-b px-6 py-4\">\n <div className=\"flex items-start gap-3\">\n <ModalSectionTitle className=\"mb-0 shrink-0 py-1.5\">{l.to}</ModalSectionTitle>\n\n <div className=\"flex flex-1 flex-col gap-1.5\">\n {selected.map((recipient) => (\n <div\n key={recipient.id}\n className=\"flex items-center justify-between gap-2 rounded-md bg-muted/50 px-3 py-1.5\"\n >\n <div className=\"flex items-center gap-2\">\n {recipient.identity}\n <Tooltip>\n <TooltipTrigger\n onClick={recipient.onToggleMute}\n aria-label={recipient.isMuted ? l.unmuteNotifications : l.muteNotifications}\n aria-pressed={recipient.isMuted}\n className={`rounded p-1 transition-colors hover:bg-muted pointer-coarse:p-3 ${\n recipient.isMuted\n ? 'text-muted-foreground'\n : 'text-muted-foreground/40 hover:text-muted-foreground'\n }`}\n disabled={recipient.isMuteBusy}\n >\n {recipient.isMuted ? (\n <BellOff size={14} fill=\"currentColor\" />\n ) : (\n <Bell size={14} />\n )}\n </TooltipTrigger>\n <TooltipContent className=\"max-w-[250px]\">{recipient.muteTooltip}</TooltipContent>\n </Tooltip>\n </div>\n <button\n type=\"button\"\n onClick={() => onRemove(recipient.id)}\n className=\"p-1 text-muted-foreground hover:text-destructive pointer-coarse:p-3\"\n title={l.removeRecipient}\n aria-label={l.removeRecipient}\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n ))}\n\n {canAdd && (\n <Popover open={isOpen} onOpenChange={onOpenChange}>\n <PopoverTrigger asChild>\n {selected.length === 0 ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={hasNoKnownUsers}\n className=\"w-full justify-start text-muted-foreground\"\n >\n <ChevronsUpDown className=\"mr-2 h-4 w-4\" />\n {l.selectRecipient}\n </Button>\n ) : (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n disabled={hasNoKnownUsers}\n className=\"h-7 w-7 rounded-full\"\n title={l.addRecipient}\n aria-label={l.addRecipient}\n >\n <Plus className=\"h-4 w-4\" />\n </Button>\n )}\n </PopoverTrigger>\n <PopoverContent\n // A previous close can restore focus after this picker reopened. Keep the new\n // input focused; the ordinary close still returns focus to the trigger.\n onCloseAutoFocus={(event) => {\n if (openRef.current) event.preventDefault()\n }}\n className=\"w-72 p-0\"\n align=\"start\"\n onPointerDownOutside={(e) => e.preventDefault()}\n >\n <Command shouldFilter={false}>\n <CommandInput\n placeholder={l.searchUsers}\n value={search}\n onValueChange={onSearchChange}\n />\n <CommandList>\n {candidates.length === 0 ? (\n <CommandEmpty>\n {hasNoKnownUsers ? l.noKnownUsers : l.noMatchingUsers}\n </CommandEmpty>\n ) : (\n <CommandGroup>\n {candidates.map((candidate) => (\n <CommandItem\n key={candidate.id}\n onSelect={() => onPick(candidate.id)}\n className=\"cursor-pointer justify-start\"\n >\n {candidate.identity}\n </CommandItem>\n ))}\n </CommandGroup>\n )}\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n )}\n\n {hasNoKnownUsers && <p className=\"text-sm text-muted-foreground\">{l.addContactsHint}</p>}\n </div>\n </div>\n </div>\n )\n}\n","/** A selectable mail folder (Outlook) or label (Gmail). */\nexport interface MailFolder {\n id: string\n /** Full path, e.g. \"Inbox/Clients/Acme\". */\n name: string\n /** Total messages (null/undefined when unavailable). */\n count?: number | null\n}\n\nexport interface MailFolderNode {\n key: string\n label: string\n /** null for a path segment with no folder of its own (a grouping row). */\n folder: MailFolder | null\n children: MailFolderNode[]\n}\n\nexport const isInboxFolder = (f: MailFolder) => f.id === 'INBOX' || /^inbox$/i.test(f.name)\n\n/** Build the folder tree from full-path names; Inbox first, then alphabetical. */\nexport function buildMailFolderTree(folders: MailFolder[]): MailFolderNode[] {\n const root: MailFolderNode = { key: '', label: '', folder: null, children: [] }\n const byPath = new Map<string, MailFolderNode>([['', root]])\n // Parents before children so a real folder claims its node before descendants.\n const sorted = [...folders].sort((a, b) => a.name.split('/').length - b.name.split('/').length)\n for (const f of sorted) {\n const parts = f.name.split('/')\n let path = ''\n let parent = root\n parts.forEach((part, i) => {\n path = path ? `${path}/${part}` : part\n let node = byPath.get(path)\n if (!node) {\n node = { key: path, label: part, folder: null, children: [] }\n byPath.set(path, node)\n parent.children.push(node)\n }\n if (i === parts.length - 1 && !node.folder) node.folder = f\n parent = node\n })\n }\n const order = (nodes: MailFolderNode[]) => {\n nodes.sort((a, b) => {\n const ai = a.folder ? isInboxFolder(a.folder) : false\n const bi = b.folder ? isInboxFolder(b.folder) : false\n if (ai !== bi) return ai ? -1 : 1\n return a.label.localeCompare(b.label)\n })\n nodes.forEach((n) => order(n.children))\n }\n order(root.children)\n return root.children\n}\n\n/** Ids of every real folder beneath `node`. */\nexport function descendantFolderIds(node: MailFolderNode): string[] {\n return node.children.flatMap((c) => [\n ...(c.folder ? [c.folder.id] : []),\n ...descendantFolderIds(c),\n ])\n}\n\n/**\n * Selection after toggling `node`: untick removes it; tick adds it and, when `cascade`, drops any\n * selected descendants (the parent already covers its subtree, so only the top-most is kept).\n */\nexport function toggleMailFolder(\n selected: string[],\n node: MailFolderNode,\n cascade: boolean\n): string[] {\n const id = node.folder?.id\n if (!id) return selected\n if (selected.includes(id)) return selected.filter((s) => s !== id)\n const covered = cascade ? new Set(descendantFolderIds(node)) : new Set<string>()\n return [...selected.filter((s) => !covered.has(s)), id]\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { ChevronDown, ChevronRight } from 'lucide-react'\nimport { Checkbox, cn } from '@arbidocs/react/ui'\nimport { testIdOr } from '../../chat/test-id'\nimport { isInboxFolder, toggleMailFolder, type MailFolderNode } from './mailFolders'\n\nfunction hasSelectedDescendant(node: MailFolderNode, selected: string[]): boolean {\n return node.children.some(\n (c) => (c.folder && selected.includes(c.folder.id)) || hasSelectedDescendant(c, selected)\n )\n}\n\nexport interface MailFolderTreeLabels {\n collapse: string\n expand: string\n recommended: string\n}\n\nexport const DEFAULT_MAIL_FOLDER_TREE_LABELS: MailFolderTreeLabels = {\n collapse: 'Collapse folder',\n expand: 'Expand folder',\n recommended: 'Recommended',\n}\n\nexport interface MailFolderTreeTestIds {\n /** Builds the id of a node's expand toggle from its key. */\n toggle: (nodeKey: string) => string\n /** Builds the id of a folder checkbox from its folder id. */\n checkbox: (folderId: string) => string\n}\n\ninterface RowProps {\n labels: MailFolderTreeLabels\n testIds?: Partial<MailFolderTreeTestIds>\n node: MailFolderNode\n depth: number\n selected: string[]\n onToggle: (node: MailFolderNode) => void\n ancestorSelected: boolean\n cascade: boolean\n expandAllNonce: number\n collapseAllNonce: number\n}\n\nfunction MailFolderRow({\n labels,\n testIds,\n node,\n depth,\n selected,\n onToggle,\n ancestorSelected,\n cascade,\n expandAllNonce,\n collapseAllNonce,\n}: RowProps) {\n const f = node.folder\n // Open a selected folder (so its checked subfolders show) or a branch holding a selection;\n // later ticks never force a node open.\n const [expanded, setExpanded] = useState(\n () =>\n (!!f && selected.includes(f.id)) ||\n hasSelectedDescendant(node, selected) ||\n expandAllNonce > collapseAllNonce\n )\n // \"Expand all\" / \"Collapse all\": each bump of a nonce opens / closes this node.\n const applied = useRef({ expand: expandAllNonce, collapse: collapseAllNonce })\n useEffect(() => {\n if (expandAllNonce > applied.current.expand) setExpanded(true)\n if (collapseAllNonce > applied.current.collapse) setExpanded(false)\n applied.current = { expand: expandAllNonce, collapse: collapseAllNonce }\n }, [expandAllNonce, collapseAllNonce])\n const isSelected = ancestorSelected || (!!f && selected.includes(f.id))\n return (\n <div>\n <div\n className=\"flex items-center gap-1.5 rounded px-1 py-1 text-sm hover:bg-muted/50 pointer-coarse:min-h-11\"\n style={{ paddingLeft: depth * 18 + 4 }}\n >\n {node.children.length > 0 ? (\n <button\n type=\"button\"\n className=\"flex size-4 shrink-0 items-center justify-center text-muted-foreground pointer-coarse:size-8\"\n onClick={() => setExpanded((e) => !e)}\n aria-label={expanded ? labels.collapse : labels.expand}\n aria-expanded={expanded}\n data-testid={testIdOr(testIds?.toggle?.(node.key), {\n testId: `mail-folder-toggle-${node.key}`,\n })}\n >\n {expanded ? (\n <ChevronDown className=\"size-3.5\" />\n ) : (\n <ChevronRight className=\"size-3.5\" />\n )}\n </button>\n ) : (\n <span className=\"size-4 shrink-0\" />\n )}\n {f ? (\n <label className=\"flex min-w-0 flex-1 cursor-pointer items-center gap-2\">\n <Checkbox\n checked={isSelected}\n disabled={ancestorSelected}\n onCheckedChange={() => onToggle(node)}\n data-testid={testIdOr(testIds?.checkbox?.(f.id), {\n testId: `mail-folder-checkbox-${f.id}`,\n })}\n />\n <span className=\"truncate\" title={f.name}>\n {node.label}\n </span>\n {typeof f.count === 'number' && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">\n ({f.count.toLocaleString()})\n </span>\n )}\n {isInboxFolder(f) && (\n <span className=\"ml-auto shrink-0 rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground\">\n {labels.recommended}\n </span>\n )}\n </label>\n ) : (\n <span className=\"truncate font-medium text-muted-foreground\">{node.label}</span>\n )}\n </div>\n {expanded &&\n node.children.map((c) => (\n <MailFolderRow\n labels={labels}\n testIds={testIds}\n key={c.key}\n node={c}\n depth={depth + 1}\n selected={selected}\n onToggle={onToggle}\n ancestorSelected={cascade && isSelected}\n cascade={cascade}\n expandAllNonce={expandAllNonce}\n collapseAllNonce={collapseAllNonce}\n />\n ))}\n </div>\n )\n}\n\nexport interface MailFolderTreeProps {\n nodes: MailFolderNode[]\n /** Selected folder ids. */\n selected: string[]\n onChange: (selected: string[]) => void\n /** Selecting a folder includes its subfolders (default). Descendants show checked + locked. */\n cascade?: boolean\n /** Bump to open every node. */\n expandAllNonce?: number\n /** Bump to close every node. */\n collapseAllNonce?: number\n labels?: Partial<MailFolderTreeLabels>\n testIds?: Partial<MailFolderTreeTestIds>\n className?: string\n}\n\n/**\n * A mailbox's folders / labels as an expandable checkbox tree. Build `nodes` with\n * `buildMailFolderTree`. With `cascade` only the top-most selected folder is stored; the server\n * expands it at sync time so new subfolders are picked up too.\n */\nexport function MailFolderTree({\n nodes,\n selected,\n onChange,\n cascade = true,\n expandAllNonce = 0,\n collapseAllNonce = 0,\n labels,\n testIds,\n className,\n}: MailFolderTreeProps) {\n const l = { ...DEFAULT_MAIL_FOLDER_TREE_LABELS, ...labels }\n return (\n <div className={cn('space-y-0.5', className)} data-slot=\"mail-folder-tree\">\n {nodes.map((n) => (\n <MailFolderRow\n labels={l}\n testIds={testIds}\n key={n.key}\n node={n}\n depth={0}\n selected={selected}\n onToggle={(node) => onChange(toggleMailFolder(selected, node, cascade))}\n ancestorSelected={false}\n cascade={cascade}\n expandAllNonce={expandAllNonce}\n collapseAllNonce={collapseAllNonce}\n />\n ))}\n </div>\n )\n}\n","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 {\n Archive,\n ArrowLeft,\n Forward,\n Paperclip,\n Reply,\n RotateCcw,\n Sparkles,\n Trash2,\n} 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 /** In the Trash (ARBI mail): put it back in the folder it was trashed from. Absent: \"Move to Inbox\". */\n onRestore?: () => void\n /** In the Trash (ARBI mail): delete it for good (the host confirms). Absent: not offered. */\n onDeleteForever?: () => void\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 onRestore,\n onDeleteForever,\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 === 'trash' && onRestore ? (\n <Button\n variant=\"ghost\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={onRestore}\n data-testid=\"mail-restore-button\"\n >\n <RotateCcw className=\"mr-2 size-4\" />\n Restore\n </Button>\n ) : (\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 )}\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 {folderRole === 'trash' && onDeleteForever ? (\n <Button\n variant=\"ghost\"\n disabled={!isOnline}\n title={offlineTitle}\n onClick={onDeleteForever}\n data-testid=\"mail-delete-forever-button\"\n >\n <Trash2 className=\"mr-2 size-4\" />\n Delete forever\n </Button>\n ) : (\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 )}\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"]}
@@ -710,6 +710,8 @@ function RecipientPicker({
710
710
  hasNoKnownUsers,
711
711
  labels
712
712
  }) {
713
+ const openRef = react.useRef(isOpen);
714
+ openRef.current = isOpen;
713
715
  const l = react.useMemo(() => ({ ...DEFAULT_RECIPIENT_PICKER_LABELS, ...labels }), [labels]);
714
716
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 border-b px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
715
717
  /* @__PURE__ */ jsxRuntime.jsx(chunkULWRNGGE_cjs.ModalSectionTitle, { className: "mb-0 shrink-0 py-1.5", children: l.to }),
@@ -779,6 +781,9 @@ function RecipientPicker({
779
781
  /* @__PURE__ */ jsxRuntime.jsx(
780
782
  ui.PopoverContent,
781
783
  {
784
+ onCloseAutoFocus: (event) => {
785
+ if (openRef.current) event.preventDefault();
786
+ },
782
787
  className: "w-72 p-0",
783
788
  align: "start",
784
789
  onPointerDownOutside: (e) => e.preventDefault(),
@@ -1633,5 +1638,5 @@ exports.toAddContactsRow = toAddContactsRow;
1633
1638
  exports.toAddContactsRows = toAddContactsRows;
1634
1639
  exports.toggleMailFolder = toggleMailFolder;
1635
1640
  exports.validateContactForm = validateContactForm;
1636
- //# sourceMappingURL=chunk-WUG24K7P.cjs.map
1637
- //# sourceMappingURL=chunk-WUG24K7P.cjs.map
1641
+ //# sourceMappingURL=chunk-5V4HH7EH.cjs.map
1642
+ //# sourceMappingURL=chunk-5V4HH7EH.cjs.map