@arbidocs/blocks 0.4.69 → 0.4.71

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 (129) hide show
  1. package/README.md +161 -1
  2. package/bin/arbidocs-copy-pdf-assets.mjs +112 -0
  3. package/dist/{StreamedArtifactEditor-OPL4KXOT.js → StreamedArtifactEditor-HTNPG4NB.js} +3 -2
  4. package/dist/StreamedArtifactEditor-HTNPG4NB.js.map +1 -0
  5. package/dist/{StreamedArtifactEditor-RIKG6CJQ.cjs → StreamedArtifactEditor-IZWYNFMM.cjs} +3 -2
  6. package/dist/StreamedArtifactEditor-IZWYNFMM.cjs.map +1 -0
  7. package/dist/agents/index.cjs +221 -220
  8. package/dist/agents/index.js +5 -4
  9. package/dist/artifacts/editor/index.cjs +1 -0
  10. package/dist/artifacts/editor/index.js +1 -0
  11. package/dist/artifacts/index.cjs +1 -0
  12. package/dist/artifacts/index.js +1 -0
  13. package/dist/auth/index.cjs +1 -0
  14. package/dist/auth/index.js +1 -0
  15. package/dist/chat/index.cjs +67 -66
  16. package/dist/chat/index.js +3 -2
  17. package/dist/{chunk-CW4WXGEN.js → chunk-3TVTG7FK.js} +3 -3
  18. package/dist/{chunk-CW4WXGEN.js.map → chunk-3TVTG7FK.js.map} +1 -1
  19. package/dist/chunk-4DVEGXZQ.cjs +72 -0
  20. package/dist/chunk-4DVEGXZQ.cjs.map +1 -0
  21. package/dist/{chunk-EHXSBH6U.js → chunk-5HOAOKZL.js} +4 -2
  22. package/dist/chunk-5HOAOKZL.js.map +1 -0
  23. package/dist/{chunk-ZYZMCNIS.cjs → chunk-7M22KND4.cjs} +5 -5
  24. package/dist/{chunk-ZYZMCNIS.cjs.map → chunk-7M22KND4.cjs.map} +1 -1
  25. package/dist/{chunk-ZQB7HNE6.js → chunk-BMWZTNZB.js} +3 -3
  26. package/dist/{chunk-ZQB7HNE6.js.map → chunk-BMWZTNZB.js.map} +1 -1
  27. package/dist/chunk-DES3K4SD.cjs +18 -0
  28. package/dist/chunk-DES3K4SD.cjs.map +1 -0
  29. package/dist/{chunk-4HZ46XP2.js → chunk-HLMFU7L2.js} +5 -5
  30. package/dist/{chunk-4HZ46XP2.js.map → chunk-HLMFU7L2.js.map} +1 -1
  31. package/dist/{chunk-BR2CPKFU.cjs → chunk-LTA2IAQB.cjs} +6 -6
  32. package/dist/{chunk-BR2CPKFU.cjs.map → chunk-LTA2IAQB.cjs.map} +1 -1
  33. package/dist/chunk-ODWCTAH7.js +66 -0
  34. package/dist/chunk-ODWCTAH7.js.map +1 -0
  35. package/dist/{chunk-TLQQV7WW.cjs → chunk-THO7DZNN.cjs} +4 -2
  36. package/dist/chunk-THO7DZNN.cjs.map +1 -0
  37. package/dist/chunk-VUNV25KB.js +15 -0
  38. package/dist/chunk-VUNV25KB.js.map +1 -0
  39. package/dist/{chunk-WKNAFILY.cjs → chunk-XNRGCQPZ.cjs} +3 -3
  40. package/dist/{chunk-WKNAFILY.cjs.map → chunk-XNRGCQPZ.cjs.map} +1 -1
  41. package/dist/citations/index.cjs +1 -0
  42. package/dist/citations/index.js +1 -0
  43. package/dist/collaboration/index.cjs +1 -0
  44. package/dist/collaboration/index.js +1 -0
  45. package/dist/connect/docx.cjs +3 -2
  46. package/dist/connect/docx.cjs.map +1 -1
  47. package/dist/connect/docx.js +2 -1
  48. package/dist/connect/docx.js.map +1 -1
  49. package/dist/connect/index.cjs +26 -25
  50. package/dist/connect/index.cjs.map +1 -1
  51. package/dist/connect/index.js +7 -6
  52. package/dist/connect/index.js.map +1 -1
  53. package/dist/connection/ConnectionProvider.d.ts +5 -0
  54. package/dist/connection/types.d.ts +6 -0
  55. package/dist/document-tools/DocumentToolButtons.d.ts +29 -0
  56. package/dist/document-tools/MarkupNotices.d.ts +12 -0
  57. package/dist/document-tools/MarkupViewNote.d.ts +11 -0
  58. package/dist/document-tools/SignDocumentDialog.d.ts +20 -0
  59. package/dist/document-tools/SignatureCertificate.d.ts +26 -0
  60. package/dist/document-tools/SignatureStatus.d.ts +24 -0
  61. package/dist/document-tools/VersionSnapshotBar.d.ts +27 -0
  62. package/dist/document-tools/index.cjs +637 -0
  63. package/dist/document-tools/index.cjs.map +1 -0
  64. package/dist/document-tools/index.d.ts +7 -0
  65. package/dist/document-tools/index.js +623 -0
  66. package/dist/document-tools/index.js.map +1 -0
  67. package/dist/document-tools/production/ProductionSetDialog.d.ts +23 -0
  68. package/dist/document-tools/production/index.cjs +102 -0
  69. package/dist/document-tools/production/index.cjs.map +1 -0
  70. package/dist/document-tools/production/index.d.ts +1 -0
  71. package/dist/document-tools/production/index.js +100 -0
  72. package/dist/document-tools/production/index.js.map +1 -0
  73. package/dist/document-tools/viewer/AnnotatedPdfViewer.d.ts +54 -0
  74. package/dist/document-tools/viewer/SignaturePlacementViewer.d.ts +20 -0
  75. package/dist/document-tools/viewer/index.cjs +273 -0
  76. package/dist/document-tools/viewer/index.cjs.map +1 -0
  77. package/dist/document-tools/viewer/index.d.ts +2 -0
  78. package/dist/document-tools/viewer/index.js +268 -0
  79. package/dist/document-tools/viewer/index.js.map +1 -0
  80. package/dist/docx/index.cjs +1 -0
  81. package/dist/docx/index.cjs.map +1 -1
  82. package/dist/docx/index.js +1 -0
  83. package/dist/docx/index.js.map +1 -1
  84. package/dist/facts/index.cjs +1 -0
  85. package/dist/facts/index.cjs.map +1 -1
  86. package/dist/facts/index.js +1 -0
  87. package/dist/facts/index.js.map +1 -1
  88. package/dist/files/cells/DocumentNameCell.d.ts +3 -1
  89. package/dist/files/index.cjs +39 -67
  90. package/dist/files/index.cjs.map +1 -1
  91. package/dist/files/index.js +20 -63
  92. package/dist/files/index.js.map +1 -1
  93. package/dist/home/index.cjs +1 -0
  94. package/dist/home/index.cjs.map +1 -1
  95. package/dist/home/index.js +1 -0
  96. package/dist/home/index.js.map +1 -1
  97. package/dist/index.cjs +481 -480
  98. package/dist/index.cjs.map +1 -1
  99. package/dist/index.js +8 -7
  100. package/dist/index.js.map +1 -1
  101. package/dist/lib-6QPUXAQS.cjs +9674 -0
  102. package/dist/lib-6QPUXAQS.cjs.map +1 -0
  103. package/dist/lib-NRGL2JGF.js +9672 -0
  104. package/dist/lib-NRGL2JGF.js.map +1 -0
  105. package/dist/retrieval/index.cjs +1 -0
  106. package/dist/retrieval/index.js +1 -0
  107. package/dist/settings/index.cjs +2 -1
  108. package/dist/settings/index.cjs.map +1 -1
  109. package/dist/settings/index.js +2 -1
  110. package/dist/settings/index.js.map +1 -1
  111. package/dist/shell/index.cjs +1 -0
  112. package/dist/shell/index.js +1 -0
  113. package/dist/site/index.cjs +1 -0
  114. package/dist/site/index.js +1 -0
  115. package/dist/studio/index.cjs +5 -4
  116. package/dist/studio/index.cjs.map +1 -1
  117. package/dist/studio/index.js +3 -2
  118. package/dist/studio/index.js.map +1 -1
  119. package/dist/timeline/index.cjs +1 -0
  120. package/dist/timeline/index.js +1 -0
  121. package/dist/workspaces/index.cjs +1 -0
  122. package/dist/workspaces/index.cjs.map +1 -1
  123. package/dist/workspaces/index.js +1 -0
  124. package/dist/workspaces/index.js.map +1 -1
  125. package/package.json +32 -4
  126. package/dist/StreamedArtifactEditor-OPL4KXOT.js.map +0 -1
  127. package/dist/StreamedArtifactEditor-RIKG6CJQ.cjs.map +0 -1
  128. package/dist/chunk-EHXSBH6U.js.map +0 -1
  129. package/dist/chunk-TLQQV7WW.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/workspaces/WorkspaceCard.tsx","../../src/workspaces/WorkspaceGallery.tsx","../../src/workspaces/WorkspaceGroup.tsx","../../src/workspaces/WorkspaceSettingsParts.tsx","../../src/workspaces/WorkspaceFormParts.tsx"],"names":["jsx","jsxs","cn","ChevronRight","Button","useState","FileText"],"mappings":"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","file":"index.js","sourcesContent":["import {\n createContext,\n useContext,\n type HTMLAttributes,\n useMemo,\n type KeyboardEvent,\n type ReactNode,\n} from 'react'\nimport { Check, ChevronRight, FileText, MessagesSquare, Users } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { fmtDate, fromNow } from '../lib/format'\nimport { ActionLink } from '../components/ActionLink'\nimport { MemberAvatarStack, type StackedMember } from '../components/MemberAvatarStack'\n\n/** Everything a workspace tile shows, source-agnostic (not the raw SDK shape). */\nexport interface WorkspaceSummary {\n id: string\n name: string\n description?: string | null\n /** Host-supplied line under the name (a reference, a client, a status...). Not interpreted. */\n subtitle?: ReactNode\n docCount: number\n /** Hidden when undefined, so a host without chats shows no empty counter. */\n chatCount?: number\n /** Number of visible members (agents excluded by the caller). */\n memberCount: number\n members: StackedMember[]\n /** The viewer may not see who is here (RLS): renders an em dash, not a `0`. */\n membersHidden?: boolean\n /** ISO timestamp: rendered as \"Updated {relative}\". */\n updatedAt?: string | null\n}\n\n/** Every fixed string of the workspace tile. Pass a partial `labels` to translate or reword. */\nexport interface WorkspaceCardLabels {\n /** The tile's accessible name. */\n openWorkspace: (name: string) => string\n currentWorkspace: string\n documents: string\n chats: string\n members: string\n /** `relative` is the formatted \"3 days ago\". */\n updated: (relative: string) => string\n}\n\nexport const DEFAULT_WORKSPACE_CARD_LABELS: WorkspaceCardLabels = {\n openWorkspace: (name) => `Open workspace ${name}`,\n currentWorkspace: 'Current workspace',\n documents: 'Documents',\n chats: 'Tasks',\n members: 'Members',\n updated: (relative) => `Updated ${relative}`,\n}\n\ninterface CardContextValue {\n current: boolean\n testId?: string\n labels: WorkspaceCardLabels\n}\n\nconst CardContext = createContext<CardContextValue>({\n current: false,\n labels: DEFAULT_WORKSPACE_CARD_LABELS,\n})\n\ntype DivProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'>\n\n/* ------------------------------------------------------------------ */\n/* Parts */\n/* ------------------------------------------------------------------ */\n\nexport interface WorkspaceCardRootProps extends DivProps {\n /** This is the workspace you are in: accented surface, \"Current workspace\" cue. */\n current?: boolean\n onSelect: () => void\n /**\n * Real link target. The tile then renders as an anchor (ctrl-click / new tab, in-SPA through\n * `BlocksProvider`'s `linkComponent`); `onSelect` still fires on a plain click.\n */\n href?: string\n /** Accessible name; defaults to `labels.openWorkspace(name)` when composed via `WorkspaceCard`. */\n label: string\n testId?: string\n labels?: Partial<WorkspaceCardLabels>\n children: ReactNode\n}\n\n/**\n * The tile surface: one button that opens the workspace. A raised white card\n * (hairline border, soft shadow, hover lift); the current workspace takes the selection tint.\n */\nfunction WorkspaceCardRoot({\n current = false,\n onSelect,\n href,\n label,\n testId,\n labels,\n className,\n children,\n ...rest\n}: WorkspaceCardRootProps) {\n const mergedLabels = useMemo(() => ({ ...DEFAULT_WORKSPACE_CARD_LABELS, ...labels }), [labels])\n const surfaceClass = cn(\n '@container/ws-card flex min-h-40 w-full cursor-pointer flex-col gap-3 rounded-lg p-4 text-left transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n current\n ? 'bg-accent text-accent-foreground'\n : 'border border-border bg-card shadow-xs transition-colors hover:border-ring/50 hover:bg-accent/40',\n className\n )\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.target !== event.currentTarget) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onSelect()\n }\n }\n return (\n <CardContext.Provider value={{ current, testId, labels: mergedLabels }}>\n {href ? (\n <ActionLink\n {...(rest as object)}\n href={href}\n onSelect={onSelect}\n aria-label={label}\n aria-current={current ? 'page' : undefined}\n data-slot=\"workspace-card\"\n data-testid={testId}\n data-active={current || undefined}\n className={surfaceClass}\n >\n {children}\n </ActionLink>\n ) : (\n <div\n {...rest}\n role=\"button\"\n tabIndex={0}\n aria-label={label}\n aria-current={current ? 'page' : undefined}\n data-slot=\"workspace-card\"\n data-testid={testId}\n data-active={current || undefined}\n onClick={onSelect}\n onKeyDown={handleKeyDown}\n className={surfaceClass}\n >\n {children}\n </div>\n )}\n </CardContext.Provider>\n )\n}\n\n/** Mark + name + open cue, on one row. Put the entity mark first. */\nfunction WorkspaceCardHeader({ className, children, ...rest }: DivProps & { children: ReactNode }) {\n return (\n <div\n {...rest}\n className={cn('flex flex-wrap items-center gap-x-3 gap-y-2', className)}\n data-slot=\"workspace-card-header\"\n >\n {children}\n </div>\n )\n}\n\nfunction WorkspaceCardTitle({ children, className }: { children: ReactNode; className?: string }) {\n const { testId } = useContext(CardContext)\n return (\n <h3\n className={cn(\n 'line-clamp-2 min-w-24 flex-1 break-words text-base font-semibold leading-tight text-foreground',\n className\n )}\n data-slot=\"workspace-card-title\"\n data-testid={testId && `${testId}-title`}\n >\n {children}\n </h3>\n )\n}\n\n/**\n * The open cue is always on screen (never hover-only): a chevron, or the words\n * \"Current workspace\" on the one you are in.\n */\nfunction WorkspaceCardOpenCue({\n testId,\n currentLabel,\n}: {\n /** Deliberately separate from the card id: suites count cards by prefix. */\n testId?: string\n /** Overrides `labels.currentWorkspace`. */\n currentLabel?: string\n}) {\n const { current, labels } = useContext(CardContext)\n return (\n <span\n className=\"inline-flex max-w-full min-w-0 shrink-0 items-center text-sm text-muted-foreground\"\n data-slot=\"workspace-card-open-cue\"\n data-testid={testId}\n >\n {current ? (\n // Never wider than the card: the words truncate, and in a card narrower than 20rem\n // the pill shrinks to a check (the words stay as the accessible name).\n <span className=\"inline-flex max-w-full min-w-0 items-center gap-1 rounded-full bg-background px-2 py-0.5 text-xs font-medium text-foreground\">\n <Check className=\"hidden size-3 shrink-0 @max-xs/ws-card:block\" aria-hidden=\"true\" />\n <span className=\"min-w-0 truncate @max-xs/ws-card:sr-only\">\n {currentLabel ?? labels.currentWorkspace}\n </span>\n </span>\n ) : (\n <ChevronRight className=\"size-4\" aria-hidden=\"true\" />\n )}\n </span>\n )\n}\n\nfunction WorkspaceCardDescription({\n children,\n className,\n}: {\n children: ReactNode\n className?: string\n}) {\n return (\n <p\n className={cn('line-clamp-2 text-sm text-muted-foreground', className)}\n title={typeof children === 'string' ? children : undefined}\n data-slot=\"workspace-card-description\"\n >\n {children}\n </p>\n )\n}\n\n/** Host-supplied line under the title. */\nfunction WorkspaceCardSubtitle({\n className,\n children,\n ...rest\n}: DivProps & { children: ReactNode }) {\n return (\n <div\n {...rest}\n className={cn('truncate text-xs text-muted-foreground', className)}\n data-slot=\"workspace-card-subtitle\"\n >\n {children}\n </div>\n )\n}\n\n/** Footer block: stats row and meta line, pinned to the bottom of the tile. */\nfunction WorkspaceCardFooter({ className, children, ...rest }: DivProps & { children: ReactNode }) {\n return (\n <div {...rest} className={cn('mt-auto flex flex-col gap-2', className)}>\n {children}\n </div>\n )\n}\n\nexport interface WorkspaceCardStatsProps {\n docCount: number\n /** Omit to hide the chats counter. */\n chatCount?: number\n memberCount: number\n members?: StackedMember[]\n membersHidden?: boolean\n /** Faces before the rest collapse into `+N`. */\n maxAvatars?: number\n className?: string\n}\n\n/** Documents / chats / members counts, with the member faces at the trailing edge. */\nfunction WorkspaceCardStats({\n docCount,\n chatCount,\n memberCount,\n members = [],\n membersHidden = false,\n maxAvatars = 3,\n className,\n}: WorkspaceCardStatsProps) {\n const { current, testId, labels } = useContext(CardContext)\n return (\n <div\n className={cn('flex w-full items-center gap-x-4 text-sm text-muted-foreground', className)}\n data-slot=\"workspace-card-stats\"\n >\n <span className=\"inline-flex items-center gap-1.5\" title={labels.documents}>\n <FileText className=\"size-4\" aria-hidden=\"true\" />\n <span className=\"tabular-nums\">{docCount.toLocaleString()}</span>\n </span>\n {chatCount !== undefined && (\n <span className=\"inline-flex items-center gap-1.5\" title={labels.chats}>\n <MessagesSquare className=\"size-4\" aria-hidden=\"true\" />\n <span className=\"tabular-nums\">{chatCount.toLocaleString()}</span>\n </span>\n )}\n <span className=\"inline-flex items-center gap-1.5\" title={labels.members}>\n <Users className=\"size-4\" aria-hidden=\"true\" />\n <span className=\"tabular-nums\" data-testid={testId && `${testId}-member-count`}>\n {membersHidden ? '—' : memberCount}\n </span>\n </span>\n <MemberAvatarStack\n members={members}\n total={memberCount}\n max={maxAvatars}\n hidden={membersHidden}\n ringClassName={current ? 'ring-accent' : 'ring-muted'}\n label={labels.members}\n className=\"ml-auto\"\n testId={testId && `${testId}-member-avatars`}\n />\n </div>\n )\n}\n\n/** \"Updated 3 days ago\", with the exact date on the title. */\nfunction WorkspaceCardMeta({ updatedAt }: { updatedAt: string }) {\n const { labels } = useContext(CardContext)\n return (\n <span\n className=\"min-w-0 max-w-full self-start truncate text-xs text-muted-foreground\"\n title={fmtDate(updatedAt)}\n data-slot=\"workspace-card-meta\"\n >\n {labels.updated(fromNow(updatedAt))}\n </span>\n )\n}\n\n/* ------------------------------------------------------------------ */\n/* Default composition */\n/* ------------------------------------------------------------------ */\n\nexport interface WorkspaceCardProps {\n workspace: WorkspaceSummary\n current?: boolean\n onSelect: () => void\n /** Real link target; see `WorkspaceCard.Root`. */\n href?: string\n /** The entity mark shown before the name (the host's own workspace glyph). */\n mark?: ReactNode\n /** Card id; derived ids: `-title`, `-member-count`, `-member-avatars`. */\n testId?: string\n /** Id for the open cue (kept apart from `testId`, see `WorkspaceCard.OpenCue`). */\n openCueTestId?: string\n maxAvatars?: number\n /**\n * The stats row: omit for the default counts + member faces, `false` to hide it, or any node to\n * replace it.\n */\n stats?: ReactNode | false\n /** Reword the tile's fixed strings. */\n labels?: Partial<WorkspaceCardLabels>\n className?: string\n}\n\n/**\n * The workspace tile: mark + name + open cue, description, stats and meta.\n * The whole tile opens the workspace; nothing on it is hover-only.\n *\n * Need a different layout? Compose the parts: `WorkspaceCard.Root`, `.Header`,\n * `.Title`, `.OpenCue`, `.Subtitle`, `.Description`, `.Footer`, `.Stats`, `.Meta`.\n */\nfunction WorkspaceCardBase({\n workspace,\n current = false,\n onSelect,\n href,\n mark,\n testId,\n openCueTestId,\n maxAvatars,\n stats,\n labels,\n className,\n}: WorkspaceCardProps) {\n const mergedLabels = { ...DEFAULT_WORKSPACE_CARD_LABELS, ...labels }\n return (\n <WorkspaceCardRoot\n current={current}\n onSelect={onSelect}\n href={href}\n label={mergedLabels.openWorkspace(workspace.name)}\n labels={labels}\n testId={testId}\n className={className}\n >\n <WorkspaceCardHeader>\n {mark}\n <WorkspaceCardTitle>{workspace.name}</WorkspaceCardTitle>\n <WorkspaceCardOpenCue testId={openCueTestId} />\n </WorkspaceCardHeader>\n {workspace.subtitle && <WorkspaceCardSubtitle>{workspace.subtitle}</WorkspaceCardSubtitle>}\n {workspace.description && (\n <WorkspaceCardDescription>{workspace.description}</WorkspaceCardDescription>\n )}\n <WorkspaceCardFooter>\n {stats === undefined ? (\n <WorkspaceCardStats\n docCount={workspace.docCount}\n chatCount={workspace.chatCount}\n memberCount={workspace.memberCount}\n members={workspace.members}\n membersHidden={workspace.membersHidden}\n maxAvatars={maxAvatars}\n />\n ) : (\n stats\n )}\n {workspace.updatedAt && <WorkspaceCardMeta updatedAt={workspace.updatedAt} />}\n </WorkspaceCardFooter>\n </WorkspaceCardRoot>\n )\n}\n\nexport const WorkspaceCard = Object.assign(WorkspaceCardBase, {\n Root: WorkspaceCardRoot,\n Header: WorkspaceCardHeader,\n Title: WorkspaceCardTitle,\n OpenCue: WorkspaceCardOpenCue,\n Subtitle: WorkspaceCardSubtitle,\n Description: WorkspaceCardDescription,\n Footer: WorkspaceCardFooter,\n Stats: WorkspaceCardStats,\n Meta: WorkspaceCardMeta,\n})\n","import { useCallback, useState, type ReactNode } from 'react'\nimport { FolderLock, Loader2 } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport {\n WorkspaceCard,\n type WorkspaceCardLabels,\n type WorkspaceCardProps,\n type WorkspaceSummary,\n} from './WorkspaceCard'\n\n/** What a host's `renderMark` is told about the card it decorates. */\nexport interface WorkspaceMarkState {\n current: boolean\n /** `onOpen` is in flight for this card: show progress instead of the glyph. */\n opening: boolean\n}\n\nexport interface WorkspaceGalleryProps {\n workspaces: readonly WorkspaceSummary[]\n /** The workspace the app is in; its card takes the \"Current workspace\" cue. */\n currentId?: string | null\n /**\n * Open a workspace. Called for EVERY card click or keypress, the current workspace included:\n * clicking \"where you already are\" still goes there. Return the promise of \"switch, then\n * navigate\" (`await select(w); navigate(...)`) and the card shows progress until it settles;\n * a rejection is the host's to report (toast it) and re-enables the card.\n */\n onOpen: (workspace: WorkspaceSummary) => Promise<unknown> | void\n /** Override the in-flight card (controlled), e.g. from a hook's `openingId`. */\n openingId?: string | null\n /** Per-card real link target, so ctrl-click / new tab work. */\n getHref?: (workspace: WorkspaceSummary) => string | undefined\n /** The entity mark before the name. Default: a folder glyph that becomes a spinner. */\n renderMark?: (workspace: WorkspaceSummary, state: WorkspaceMarkState) => ReactNode\n /** Per-card props passthrough (`stats`, `maxAvatars`, `className`...). */\n getCardProps?: (workspace: WorkspaceSummary) => Partial<WorkspaceCardProps>\n labels?: Partial<WorkspaceCardLabels>\n /** Id of the grid. Cards are `${cardTestIdPrefix}${id}`, cues `${openCueTestIdPrefix}${id}`. */\n testId?: string\n cardTestIdPrefix?: string\n openCueTestIdPrefix?: string\n /** After the cards, inside the grid: a `CreateTile`. */\n children?: ReactNode\n className?: string\n}\n\n/** The default entity mark: a quiet folder glyph, a spinner while opening. */\nfunction DefaultMark({ opening }: { opening: boolean }) {\n return (\n <div className=\"flex size-10 shrink-0 items-center justify-center rounded-md bg-background text-foreground\">\n {opening ? (\n <Loader2 className=\"size-5 animate-spin\" aria-hidden=\"true\" />\n ) : (\n <FolderLock className=\"size-5\" aria-hidden=\"true\" />\n )}\n </div>\n )\n}\n\n/**\n * The workspaces gallery: a responsive grid of `WorkspaceCard`s whose click ALWAYS opens the\n * workspace, the current one included, through one `onOpen`. Owns the per-card \"opening\" state\n * and ignores repeat clicks while one open is in flight.\n */\nexport function WorkspaceGallery({\n workspaces,\n currentId,\n onOpen,\n openingId,\n getHref,\n renderMark,\n getCardProps,\n labels,\n testId,\n cardTestIdPrefix = 'workspace-card-',\n openCueTestIdPrefix = 'workspace-open-',\n children,\n className,\n}: WorkspaceGalleryProps) {\n const [pendingId, setPendingId] = useState<string | null>(null)\n const activeOpeningId = openingId !== undefined ? openingId : pendingId\n\n const open = useCallback(\n async (workspace: WorkspaceSummary) => {\n if (activeOpeningId) return\n setPendingId(workspace.id)\n try {\n await onOpen(workspace)\n } catch {\n // The host reports failures (a toast); the gallery only has to become usable again.\n } finally {\n setPendingId(null)\n }\n },\n [onOpen, activeOpeningId]\n )\n\n return (\n <div\n className={cn('grid gap-4 sm:grid-cols-2 xl:grid-cols-3', className)}\n data-slot=\"workspace-gallery\"\n data-testid={testId}\n >\n {workspaces.map((workspace) => {\n const current = workspace.id === currentId\n const opening = workspace.id === activeOpeningId\n const state = { current, opening }\n return (\n <WorkspaceCard\n key={workspace.id}\n workspace={workspace}\n current={current}\n href={getHref?.(workspace)}\n onSelect={() => void open(workspace)}\n mark={renderMark ? renderMark(workspace, state) : <DefaultMark opening={opening} />}\n testId={`${cardTestIdPrefix}${workspace.id}`}\n openCueTestId={`${openCueTestIdPrefix}${workspace.id}`}\n labels={labels}\n {...getCardProps?.(workspace)}\n />\n )\n })}\n {children}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { ChevronRight } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { CollapsibleSection } from '../home/CollapsibleSection'\n\nexport interface WorkspaceListProps {\n children: ReactNode\n className?: string\n testId?: string\n}\n\n/** The column that stacks workspace groups (padding follows the page gutter). */\nexport function WorkspaceList({ children, className, testId }: WorkspaceListProps) {\n return (\n <div\n className={cn('flex w-full flex-col gap-2 px-4 py-4 sm:px-8', className)}\n data-slot=\"workspace-list\"\n data-testid={testId}\n >\n {children}\n </div>\n )\n}\n\nexport interface WorkspaceGroupProps {\n /** Group heading: name, count, badges. Plain text on the canvas, no band. */\n title: ReactNode\n isExpanded: boolean\n onToggle: () => void\n /**\n * Makes the whole header one target (e.g. open the project panel); the\n * chevron stays a separate toggle. Adds a trailing `openLabel` affordance.\n */\n onOpen?: () => void\n /** Words beside the trailing chevron when `onOpen` is set, e.g. \"Plans & Usage\". */\n openLabel?: string\n /** Muted words on the right of a collapsed group without `onOpen`, e.g. \"Show 11 shared workspaces\". */\n collapsedHint?: string\n /** The cards, laid out in a responsive grid (1 / 2 / 3 columns). */\n children: ReactNode\n className?: string\n}\n\n/**\n * One collapsible band of workspace tiles under a slim header. The open\n * affordance is always visible, so nothing is reachable by hover alone.\n */\nexport function WorkspaceGroup({\n title,\n isExpanded,\n onToggle,\n onOpen,\n openLabel,\n collapsedHint,\n children,\n className,\n}: WorkspaceGroupProps) {\n return (\n <CollapsibleSection\n title={title}\n isExpanded={isExpanded}\n onToggle={onToggle}\n onHeaderClick={onOpen}\n rightContent={\n onOpen && openLabel ? (\n <span className=\"flex shrink-0 items-center gap-1 text-sm font-medium text-muted-foreground\">\n {openLabel}\n <ChevronRight className=\"size-4 shrink-0\" aria-hidden=\"true\" />\n </span>\n ) : collapsedHint && !isExpanded ? (\n <span className=\"shrink-0 text-sm text-muted-foreground\">{collapsedHint}</span>\n ) : undefined\n }\n className={cn('group', className)}\n headerClassName=\"mb-3 flex-wrap gap-y-2 rounded-md px-1 py-1 pointer-coarse:min-h-11\"\n childrenClassName=\"mb-8 grid gap-3 @xl:grid-cols-2 @5xl:grid-cols-3\"\n >\n {children}\n </CollapsibleSection>\n )\n}\n","import type { ReactNode } from 'react'\nimport { LogOut, UserPlus } from 'lucide-react'\nimport { Button, cn, Popover, PopoverContent, PopoverTrigger } from '@arbidocs/react/ui'\n\n/**\n * Page frame of a workspace's home: a bounded column whose ONE scroll region spans the full\n * width (scrollbar on the outer edge), the inset living on the content inside it. A container,\n * so children can use `@2xl:` queries.\n */\nexport function WorkspacePageFrame({ testId, children }: { testId?: string; children: ReactNode }) {\n return (\n <div\n className=\"flex h-full flex-col @container\"\n data-slot=\"workspace-page\"\n data-testid={testId}\n >\n {/* scrollbar-gutter:stable keeps the content from jumping when a scrollbar appears. */}\n <div className=\"scrollbar-subtle min-h-0 flex-1 overflow-y-auto [scrollbar-gutter:stable]\">\n <div className=\"space-y-6 px-4 pb-6 sm:px-6 pt-4\">{children}</div>\n </div>\n </div>\n )\n}\n\n/** Tinted card holding the identity bar and the expandable member list. */\nexport function WorkspaceIdentityPanel({ children }: { children: ReactNode }) {\n return (\n <div\n data-slot=\"workspace-identity-panel\"\n className=\"group rounded-lg border border-border bg-card px-4 py-3 shadow-xs\"\n >\n {children}\n </div>\n )\n}\n\nexport interface WorkspaceProjectSlotProps {\n testId: string\n /** Screen-reader caption (\"Project:\"): the chip says what it is without a word in front. */\n caption: string\n children: ReactNode\n}\n\n/** The project control / chip pinned to the end of the name row. */\nexport function WorkspaceProjectSlot({ testId, caption, children }: WorkspaceProjectSlotProps) {\n return (\n <div className=\"flex min-w-0 items-center gap-3\">\n <div className=\"flex min-w-0 flex-1 items-center gap-2\" data-testid={testId}>\n <span className=\"sr-only\">{caption}</span>\n {children}\n </div>\n </div>\n )\n}\n\n/** Stated absence (\"None\") rather than a blank gap. */\nexport function ItalicNone({ children }: { children: ReactNode }) {\n return <span className=\"text-sm italic text-muted-foreground\">{children}</span>\n}\n\nexport interface WorkspaceAudienceLineProps {\n visibility: {\n testId: string\n caption: string\n /** The owner's visibility switch (developers only). */\n toggle?: ReactNode\n /** The state named in words, so the switch is never a puzzle. */\n stateText: string\n /** What the state means for who can see the workspace; opened by tapping the state words. */\n stateHelp: string\n }\n /** Member avatar stack. */\n members: ReactNode\n /** \"Share\" button (owners). */\n share?: { label: string; onClick: () => void; testId: string }\n}\n\n/** Visibility and members end the description line together: who can see and use the workspace. */\nexport function WorkspaceAudienceLine({ visibility, members, share }: WorkspaceAudienceLineProps) {\n return (\n <span className=\"flex flex-wrap items-center gap-x-4 gap-y-2\" data-slot=\"workspace-audience\">\n <span className=\"flex items-center gap-2\" data-testid={visibility.testId}>\n <span className=\"sr-only\">{visibility.caption}</span>\n {visibility.toggle}\n {/* Tap-to-explain, not hover-only: the words must answer a click on touch screens too. */}\n <Popover>\n <PopoverTrigger className=\"cursor-pointer rounded-sm text-sm text-muted-foreground underline decoration-dotted underline-offset-4 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\">\n {visibility.stateText}\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 text-sm\">\n {visibility.stateHelp}\n </PopoverContent>\n </Popover>\n </span>\n {/* Faces first, then Share: \"these people ... add more\". */}\n <span className=\"flex items-center gap-1\">\n {members}\n {share && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-8 gap-1.5 px-3 text-sm pointer-coarse:h-11\"\n onClick={share.onClick}\n data-testid={share.testId}\n >\n <UserPlus className=\"size-4\" />\n {share.label}\n </Button>\n )}\n </span>\n </span>\n )\n}\n\n/**\n * Collapsible block under the identity bar. Stays mounted and animates its height (grid-rows\n * 0fr to 1fr), so opening and closing glides instead of snapping.\n */\nexport function ExpandableSection({\n expanded,\n testId,\n children,\n}: {\n expanded: boolean\n testId?: string\n children: ReactNode\n}) {\n return (\n <div\n className={cn(\n 'grid transition-[grid-template-rows] duration-300 ease-in-out',\n expanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'\n )}\n data-slot=\"expandable-section\"\n data-expanded={expanded}\n data-testid={testId}\n >\n <div className=\"overflow-hidden\">\n <div className=\"mt-4 border-t border-border pt-4\">{children}</div>\n </div>\n </div>\n )\n}\n\n/** Centered loading placeholder of a page body. */\nexport function PageLoading({ children }: { children: ReactNode }) {\n return <div className=\"flex h-64 items-center justify-center\">{children}</div>\n}\n\nexport interface LeaveFooterProps {\n testId?: string\n leave: { label: string; disabled?: boolean; onClick: () => void; testId?: string }\n}\n\n/** Leaving ENDS your part in the workspace, so it sits last and alone at the foot of the page. */\nexport function LeaveFooter({ testId, leave }: LeaveFooterProps) {\n return (\n <div className=\"flex justify-end\" data-slot=\"leave-footer\" data-testid={testId}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={leave.onClick}\n disabled={leave.disabled}\n className=\"h-7 px-2 text-sm text-destructive hover:bg-destructive/10 hover:text-destructive pointer-coarse:h-11\"\n data-testid={leave.testId}\n >\n <LogOut className=\"mr-1 size-3.5\" />\n {leave.label}\n </Button>\n </div>\n )\n}\n","import { useState, type ReactNode, useId } from 'react'\nimport {\n AlertCircle,\n AlignLeft,\n ArrowUpRight,\n CreditCard,\n FileText,\n Globe,\n Plus,\n} from 'lucide-react'\nimport {\n Button,\n cn,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogTitle,\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n} from '@arbidocs/react/ui'\nimport { KeyValueRow } from '../home/KeyValueRow'\nimport { ModalHeader } from '../settings/ModalScaffold'\n\n/** Inline error strip of a form. */\nexport function FormErrorBanner({\n message,\n testId,\n className,\n id,\n}: {\n message: string\n testId?: string\n className?: string\n /** Lets a field point at this message with `aria-describedby`. */\n id?: string\n}) {\n return (\n <div\n id={id}\n role=\"alert\"\n data-slot=\"form-error\"\n data-testid={testId}\n className={cn(\n 'flex items-center gap-2 rounded-md border border-red-border bg-red-bg p-3 text-sm text-red-text',\n className\n )}\n >\n <AlertCircle className=\"size-4 shrink-0\" aria-hidden=\"true\" />\n {message}\n </div>\n )\n}\n\n/** Right-aligned footer row of a form (Cancel + submit). */\nexport function FormActions({ className, children }: { className?: string; children: ReactNode }) {\n return (\n <div\n data-slot=\"form-actions\"\n className={cn('sticky bottom-0 flex justify-end gap-2 bg-background pt-2', className)}\n >\n {children}\n </div>\n )\n}\n\n/** Footer row of a modal body, separated by a rule. */\nexport function ModalActionRow({ children }: { children: ReactNode }) {\n return (\n <div\n data-slot=\"modal-action-row\"\n className=\"sticky bottom-0 -mx-6 -mb-6 flex flex-col-reverse gap-2 border-t border-border bg-background px-6 pb-6 pt-3 sm:flex-row sm:items-center sm:justify-end\"\n >\n {children}\n </div>\n )\n}\n\nexport interface WorkspaceFormModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n title: ReactNode\n /** Icon before the title. */\n icon?: ReactNode\n /** Optional intro paragraph above the form (first-run welcome). */\n intro?: ReactNode\n testId?: string\n /** Visually hidden description. */\n description?: string\n children: ReactNode\n}\n\n/** Dialog frame of the create-workspace form: header, optional intro, scrolling body. */\nexport function WorkspaceFormModal({\n open,\n onOpenChange,\n title,\n icon,\n intro,\n testId,\n description = 'Create a new workspace',\n children,\n}: WorkspaceFormModalProps) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n presentation=\"sheet\"\n className=\"flex max-h-panel w-modal max-w-modal-vw flex-col overflow-hidden p-0\"\n data-testid={testId}\n >\n <ModalHeader>\n <ModalTitleRow icon={icon} title={title} description={description} />\n </ModalHeader>\n <div className=\"min-h-0 flex-1 overflow-auto px-6 pb-6\">\n {intro && <p className=\"pb-4 text-sm text-muted-foreground\">{intro}</p>}\n {children}\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction ModalTitleRow({\n icon,\n title,\n description,\n}: {\n icon?: ReactNode\n title: ReactNode\n description: string\n}) {\n return (\n <>\n <DialogTitle>\n <div className=\"flex items-center gap-2\">\n {icon}\n <span>{title}</span>\n </div>\n </DialogTitle>\n <DialogDescription className=\"sr-only\">{description}</DialogDescription>\n </>\n )\n}\n\n/** One entry of the project picker: identity on the left, optional quota summary on the right. */\nexport function ProjectOptionRow({ identity, meta }: { identity: ReactNode; meta?: string }) {\n return (\n <div className=\"flex w-full min-w-0 items-center gap-2\">\n {identity}\n {meta && <span className=\"ml-auto truncate text-sm text-muted-foreground\">{meta}</span>}\n </div>\n )\n}\n\nexport interface ProjectPickerOption {\n id: string\n content: ReactNode\n}\n\nexport interface ProjectPickerProps {\n value?: string\n options: ProjectPickerOption[]\n onChange: (id: string) => void\n /** Adds a \"Create new project...\" entry. */\n onCreate?: () => void\n disabled?: boolean\n readOnly?: boolean\n className?: string\n labels?: { placeholder: string; create: string }\n}\n\nconst CREATE_VALUE = '__create__'\n\n/** The workspace's owning project, as a picker (optionally with a create entry). */\nexport function ProjectPicker({\n value,\n options,\n onChange,\n onCreate,\n disabled,\n readOnly,\n className,\n labels = { placeholder: 'Select project', create: 'Create new project...' },\n}: ProjectPickerProps) {\n return (\n <Select\n value={value ?? options[0]?.id}\n onValueChange={(v) => (v === CREATE_VALUE ? onCreate?.() : onChange(v))}\n disabled={disabled || readOnly}\n >\n <SelectTrigger\n className={cn(className, readOnly && 'cursor-not-allowed')}\n data-testid=\"workspace-project-select\"\n >\n <SelectValue placeholder={labels.placeholder} />\n </SelectTrigger>\n <SelectContent>\n {options.map((o) => (\n <SelectItem key={o.id} value={o.id}>\n {o.content}\n </SelectItem>\n ))}\n {onCreate && (\n <>\n <SelectSeparator />\n <SelectItem value={CREATE_VALUE}>\n <div className=\"flex items-center gap-1.5 text-primary\">\n <Plus className=\"size-3.5\" />\n <span>{labels.create}</span>\n </div>\n </SelectItem>\n </>\n )}\n </SelectContent>\n </Select>\n )\n}\n\n/** Compact CTA on a project row (e.g. Upgrade / Change plan). */\nexport function ProjectActionButton({\n label,\n onClick,\n className,\n testId,\n}: {\n label: string\n onClick: () => void\n className?: string\n testId?: string\n}) {\n return (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={onClick}\n className={cn(\n 'h-7 gap-1.5 whitespace-nowrap px-2 py-0 text-sm font-medium pointer-coarse:h-11',\n className\n )}\n data-testid={testId}\n >\n <ArrowUpRight className=\"size-3.5\" />\n {label}\n </Button>\n )\n}\n\nexport interface WorkspaceFieldsViewProps {\n /** `modal` (create flow) or `settings` (editing an existing workspace). */\n variant?: 'modal' | 'settings'\n name: string\n description: string\n onNameChange: (value: string) => void\n onDescriptionChange: (value: string) => void\n onNameBlur?: () => void\n onNameFocus?: () => void\n onDescriptionBlur?: () => void\n disabled?: boolean\n readOnly?: boolean\n maxNameLength?: number\n /** Id of the form's error message (a `FormErrorBanner id`): the name input is then `aria-invalid`\n * and described by it. */\n errorId?: string\n /** Content of the Visibility row (settings only); omit to hide the row. */\n visibility?: ReactNode\n /** Content of the Project row; omit to hide the row. */\n project?: ReactNode\n labels?: Partial<WorkspaceFieldsLabels>\n}\n\nexport interface WorkspaceFieldsLabels {\n readOnlyNotice: string\n name: string\n description: string\n visibility: string\n project: string\n over: (n: number) => string\n charsLeft: (n: number) => string\n}\n\nconst DEFAULT_LABELS: WorkspaceFieldsLabels = {\n readOnlyNotice: 'Read-only workspace',\n name: 'Name *',\n description: 'Description',\n visibility: 'Visibility',\n project: 'Project',\n over: (n) => `${n} over`,\n charsLeft: (n) => `${n} chars left`,\n}\n\n/** Name / description / visibility / project rows shared by the create and settings forms. */\nexport function WorkspaceFieldsView({\n variant = 'modal',\n name,\n description,\n onNameChange,\n onDescriptionChange,\n onNameBlur,\n onNameFocus,\n onDescriptionBlur,\n disabled = false,\n readOnly = false,\n errorId,\n maxNameLength = 50,\n visibility,\n project,\n labels,\n}: WorkspaceFieldsViewProps) {\n const workspaceDescriptionId = useId()\n const workspaceNameId = useId()\n const l = { ...DEFAULT_LABELS, ...labels }\n const [nameFocused, setNameFocused] = useState(false)\n const isModal = variant === 'modal'\n const charsLeft = maxNameLength - name.length\n // The modal only surfaces the counter near the limit; settings shows it while focused.\n const counterVisible = !readOnly && nameFocused && (!isModal || charsLeft <= 10)\n const isDisabled = isModal ? disabled : disabled || readOnly\n\n return (\n <div className=\"space-y-1\" data-slot=\"workspace-fields\">\n {readOnly && (\n <div data-testid=\"workspace-form-readonly-notice\" className=\"sr-only\">\n {l.readOnlyNotice}\n </div>\n )}\n <KeyValueRow label={l.name} icon={<FileText size={14} />} htmlFor={workspaceNameId}>\n <div className=\"relative\">\n <Input\n id={workspaceNameId}\n type=\"text\"\n value={name}\n onChange={(e) => onNameChange(e.target.value)}\n onBlur={() => {\n setNameFocused(false)\n onNameBlur?.()\n }}\n onFocus={() => {\n setNameFocused(true)\n onNameFocus?.()\n }}\n maxLength={maxNameLength}\n readOnly={readOnly}\n disabled={isDisabled}\n className={cn(\n isModal ? 'bg-background' : 'capitalize',\n readOnly && 'cursor-not-allowed',\n 'pr-20'\n )}\n required\n aria-invalid={errorId ? true : undefined}\n aria-describedby={errorId}\n data-testid=\"workspace-form-name-input\"\n />\n {counterVisible && (\n <div\n className={cn(\n 'pointer-events-none absolute right-3 top-1/2 hidden -translate-y-1/2 text-sm lg:block',\n charsLeft < 0 ? 'text-red-text' : 'text-muted-foreground'\n )}\n >\n {charsLeft < 0 ? l.over(-charsLeft) : l.charsLeft(charsLeft)}\n </div>\n )}\n </div>\n </KeyValueRow>\n\n <KeyValueRow\n label={l.description}\n icon={<AlignLeft size={14} />}\n htmlFor={workspaceDescriptionId}\n >\n <Input\n id={workspaceDescriptionId}\n type=\"text\"\n dictate\n value={description}\n onChange={(e) => onDescriptionChange(e.target.value)}\n onBlur={onDescriptionBlur}\n readOnly={readOnly}\n disabled={isDisabled}\n className={cn(isModal && 'bg-background', readOnly && 'cursor-not-allowed')}\n data-testid=\"workspace-form-description-input\"\n />\n </KeyValueRow>\n\n {visibility && (\n <KeyValueRow label={l.visibility} icon={<Globe size={14} />}>\n {visibility}\n </KeyValueRow>\n )}\n {project && (\n <KeyValueRow label={l.project} icon={<CreditCard size={14} />}>\n {project}\n </KeyValueRow>\n )}\n </div>\n )\n}\n"]}
1
+ {"version":3,"sources":["../../src/workspaces/WorkspaceCard.tsx","../../src/workspaces/WorkspaceGallery.tsx","../../src/workspaces/WorkspaceGroup.tsx","../../src/workspaces/WorkspaceSettingsParts.tsx","../../src/workspaces/WorkspaceFormParts.tsx"],"names":["jsx","jsxs","cn","ChevronRight","Button","useState","FileText"],"mappings":"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","file":"index.js","sourcesContent":["import {\n createContext,\n useContext,\n type HTMLAttributes,\n useMemo,\n type KeyboardEvent,\n type ReactNode,\n} from 'react'\nimport { Check, ChevronRight, FileText, MessagesSquare, Users } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { fmtDate, fromNow } from '../lib/format'\nimport { ActionLink } from '../components/ActionLink'\nimport { MemberAvatarStack, type StackedMember } from '../components/MemberAvatarStack'\n\n/** Everything a workspace tile shows, source-agnostic (not the raw SDK shape). */\nexport interface WorkspaceSummary {\n id: string\n name: string\n description?: string | null\n /** Host-supplied line under the name (a reference, a client, a status...). Not interpreted. */\n subtitle?: ReactNode\n docCount: number\n /** Hidden when undefined, so a host without chats shows no empty counter. */\n chatCount?: number\n /** Number of visible members (agents excluded by the caller). */\n memberCount: number\n members: StackedMember[]\n /** The viewer may not see who is here (RLS): renders an em dash, not a `0`. */\n membersHidden?: boolean\n /** ISO timestamp: rendered as \"Updated {relative}\". */\n updatedAt?: string | null\n}\n\n/** Every fixed string of the workspace tile. Pass a partial `labels` to translate or reword. */\nexport interface WorkspaceCardLabels {\n /** The tile's accessible name. */\n openWorkspace: (name: string) => string\n currentWorkspace: string\n documents: string\n chats: string\n members: string\n /** `relative` is the formatted \"3 days ago\". */\n updated: (relative: string) => string\n}\n\nexport const DEFAULT_WORKSPACE_CARD_LABELS: WorkspaceCardLabels = {\n openWorkspace: (name) => `Open workspace ${name}`,\n currentWorkspace: 'Current workspace',\n documents: 'Documents',\n chats: 'Tasks',\n members: 'Members',\n updated: (relative) => `Updated ${relative}`,\n}\n\ninterface CardContextValue {\n current: boolean\n testId?: string\n labels: WorkspaceCardLabels\n}\n\nconst CardContext = createContext<CardContextValue>({\n current: false,\n labels: DEFAULT_WORKSPACE_CARD_LABELS,\n})\n\ntype DivProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'>\n\n/* ------------------------------------------------------------------ */\n/* Parts */\n/* ------------------------------------------------------------------ */\n\nexport interface WorkspaceCardRootProps extends DivProps {\n /** This is the workspace you are in: accented surface, \"Current workspace\" cue. */\n current?: boolean\n onSelect: () => void\n /**\n * Real link target. The tile then renders as an anchor (ctrl-click / new tab, in-SPA through\n * `BlocksProvider`'s `linkComponent`); `onSelect` still fires on a plain click.\n */\n href?: string\n /** Accessible name; defaults to `labels.openWorkspace(name)` when composed via `WorkspaceCard`. */\n label: string\n testId?: string\n labels?: Partial<WorkspaceCardLabels>\n children: ReactNode\n}\n\n/**\n * The tile surface: one button that opens the workspace. A raised white card\n * (hairline border, soft shadow, hover lift); the current workspace takes the selection tint.\n */\nfunction WorkspaceCardRoot({\n current = false,\n onSelect,\n href,\n label,\n testId,\n labels,\n className,\n children,\n ...rest\n}: WorkspaceCardRootProps) {\n const mergedLabels = useMemo(() => ({ ...DEFAULT_WORKSPACE_CARD_LABELS, ...labels }), [labels])\n const surfaceClass = cn(\n '@container/ws-card flex min-h-40 w-full cursor-pointer flex-col gap-3 rounded-lg p-4 text-left transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n current\n ? 'bg-accent text-accent-foreground'\n : 'border border-border bg-card shadow-xs transition-colors hover:border-ring/50 hover:bg-accent/40',\n className\n )\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.target !== event.currentTarget) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onSelect()\n }\n }\n return (\n <CardContext.Provider value={{ current, testId, labels: mergedLabels }}>\n {href ? (\n <ActionLink\n {...(rest as object)}\n href={href}\n onSelect={onSelect}\n aria-label={label}\n aria-current={current ? 'page' : undefined}\n data-slot=\"workspace-card\"\n data-testid={testId}\n data-active={current || undefined}\n className={surfaceClass}\n >\n {children}\n </ActionLink>\n ) : (\n <div\n {...rest}\n role=\"button\"\n tabIndex={0}\n aria-label={label}\n aria-current={current ? 'page' : undefined}\n data-slot=\"workspace-card\"\n data-testid={testId}\n data-active={current || undefined}\n onClick={onSelect}\n onKeyDown={handleKeyDown}\n className={surfaceClass}\n >\n {children}\n </div>\n )}\n </CardContext.Provider>\n )\n}\n\n/** Mark + name + open cue, on one row. Put the entity mark first. */\nfunction WorkspaceCardHeader({ className, children, ...rest }: DivProps & { children: ReactNode }) {\n return (\n <div\n {...rest}\n className={cn('flex flex-wrap items-center gap-x-3 gap-y-2', className)}\n data-slot=\"workspace-card-header\"\n >\n {children}\n </div>\n )\n}\n\nfunction WorkspaceCardTitle({ children, className }: { children: ReactNode; className?: string }) {\n const { testId } = useContext(CardContext)\n return (\n <h3\n className={cn(\n 'line-clamp-2 min-w-24 flex-1 break-words text-base font-semibold leading-tight text-foreground',\n className\n )}\n data-slot=\"workspace-card-title\"\n data-testid={testId && `${testId}-title`}\n >\n {children}\n </h3>\n )\n}\n\n/**\n * The open cue is always on screen (never hover-only): a chevron, or the words\n * \"Current workspace\" on the one you are in.\n */\nfunction WorkspaceCardOpenCue({\n testId,\n currentLabel,\n}: {\n /** Deliberately separate from the card id: suites count cards by prefix. */\n testId?: string\n /** Overrides `labels.currentWorkspace`. */\n currentLabel?: string\n}) {\n const { current, labels } = useContext(CardContext)\n return (\n <span\n className=\"inline-flex max-w-full min-w-0 shrink-0 items-center text-sm text-muted-foreground\"\n data-slot=\"workspace-card-open-cue\"\n data-testid={testId}\n >\n {current ? (\n // Never wider than the card: the words truncate, and in a card narrower than 20rem\n // the pill shrinks to a check (the words stay as the accessible name).\n <span className=\"inline-flex max-w-full min-w-0 items-center gap-1 rounded-full bg-background px-2 py-0.5 text-xs font-medium text-foreground\">\n <Check className=\"hidden size-3 shrink-0 @max-xs/ws-card:block\" aria-hidden=\"true\" />\n <span className=\"min-w-0 truncate @max-xs/ws-card:sr-only\">\n {currentLabel ?? labels.currentWorkspace}\n </span>\n </span>\n ) : (\n <ChevronRight className=\"size-4\" aria-hidden=\"true\" />\n )}\n </span>\n )\n}\n\nfunction WorkspaceCardDescription({\n children,\n className,\n}: {\n children: ReactNode\n className?: string\n}) {\n return (\n <p\n className={cn('line-clamp-2 text-sm text-muted-foreground', className)}\n title={typeof children === 'string' ? children : undefined}\n data-slot=\"workspace-card-description\"\n >\n {children}\n </p>\n )\n}\n\n/** Host-supplied line under the title. */\nfunction WorkspaceCardSubtitle({\n className,\n children,\n ...rest\n}: DivProps & { children: ReactNode }) {\n return (\n <div\n {...rest}\n className={cn('truncate text-xs text-muted-foreground', className)}\n data-slot=\"workspace-card-subtitle\"\n >\n {children}\n </div>\n )\n}\n\n/** Footer block: stats row and meta line, pinned to the bottom of the tile. */\nfunction WorkspaceCardFooter({ className, children, ...rest }: DivProps & { children: ReactNode }) {\n return (\n <div {...rest} className={cn('mt-auto flex flex-col gap-2', className)}>\n {children}\n </div>\n )\n}\n\nexport interface WorkspaceCardStatsProps {\n docCount: number\n /** Omit to hide the chats counter. */\n chatCount?: number\n memberCount: number\n members?: StackedMember[]\n membersHidden?: boolean\n /** Faces before the rest collapse into `+N`. */\n maxAvatars?: number\n className?: string\n}\n\n/** Documents / chats / members counts, with the member faces at the trailing edge. */\nfunction WorkspaceCardStats({\n docCount,\n chatCount,\n memberCount,\n members = [],\n membersHidden = false,\n maxAvatars = 3,\n className,\n}: WorkspaceCardStatsProps) {\n const { current, testId, labels } = useContext(CardContext)\n return (\n <div\n className={cn('flex w-full items-center gap-x-4 text-sm text-muted-foreground', className)}\n data-slot=\"workspace-card-stats\"\n >\n <span className=\"inline-flex items-center gap-1.5\" title={labels.documents}>\n <FileText className=\"size-4\" aria-hidden=\"true\" />\n <span className=\"tabular-nums\">{docCount.toLocaleString()}</span>\n </span>\n {chatCount !== undefined && (\n <span className=\"inline-flex items-center gap-1.5\" title={labels.chats}>\n <MessagesSquare className=\"size-4\" aria-hidden=\"true\" />\n <span className=\"tabular-nums\">{chatCount.toLocaleString()}</span>\n </span>\n )}\n <span className=\"inline-flex items-center gap-1.5\" title={labels.members}>\n <Users className=\"size-4\" aria-hidden=\"true\" />\n <span className=\"tabular-nums\" data-testid={testId && `${testId}-member-count`}>\n {membersHidden ? '—' : memberCount}\n </span>\n </span>\n <MemberAvatarStack\n members={members}\n total={memberCount}\n max={maxAvatars}\n hidden={membersHidden}\n ringClassName={current ? 'ring-accent' : 'ring-muted'}\n label={labels.members}\n className=\"ml-auto\"\n testId={testId && `${testId}-member-avatars`}\n />\n </div>\n )\n}\n\n/** \"Updated 3 days ago\", with the exact date on the title. */\nfunction WorkspaceCardMeta({ updatedAt }: { updatedAt: string }) {\n const { labels } = useContext(CardContext)\n return (\n <span\n className=\"min-w-0 max-w-full self-start truncate text-xs text-muted-foreground\"\n title={fmtDate(updatedAt)}\n data-slot=\"workspace-card-meta\"\n >\n {labels.updated(fromNow(updatedAt))}\n </span>\n )\n}\n\n/* ------------------------------------------------------------------ */\n/* Default composition */\n/* ------------------------------------------------------------------ */\n\nexport interface WorkspaceCardProps {\n workspace: WorkspaceSummary\n current?: boolean\n onSelect: () => void\n /** Real link target; see `WorkspaceCard.Root`. */\n href?: string\n /** The entity mark shown before the name (the host's own workspace glyph). */\n mark?: ReactNode\n /** Card id; derived ids: `-title`, `-member-count`, `-member-avatars`. */\n testId?: string\n /** Id for the open cue (kept apart from `testId`, see `WorkspaceCard.OpenCue`). */\n openCueTestId?: string\n maxAvatars?: number\n /**\n * The stats row: omit for the default counts + member faces, `false` to hide it, or any node to\n * replace it.\n */\n stats?: ReactNode | false\n /** Reword the tile's fixed strings. */\n labels?: Partial<WorkspaceCardLabels>\n className?: string\n}\n\n/**\n * The workspace tile: mark + name + open cue, description, stats and meta.\n * The whole tile opens the workspace; nothing on it is hover-only.\n *\n * Need a different layout? Compose the parts: `WorkspaceCard.Root`, `.Header`,\n * `.Title`, `.OpenCue`, `.Subtitle`, `.Description`, `.Footer`, `.Stats`, `.Meta`.\n */\nfunction WorkspaceCardBase({\n workspace,\n current = false,\n onSelect,\n href,\n mark,\n testId,\n openCueTestId,\n maxAvatars,\n stats,\n labels,\n className,\n}: WorkspaceCardProps) {\n const mergedLabels = { ...DEFAULT_WORKSPACE_CARD_LABELS, ...labels }\n return (\n <WorkspaceCardRoot\n current={current}\n onSelect={onSelect}\n href={href}\n label={mergedLabels.openWorkspace(workspace.name)}\n labels={labels}\n testId={testId}\n className={className}\n >\n <WorkspaceCardHeader>\n {mark}\n <WorkspaceCardTitle>{workspace.name}</WorkspaceCardTitle>\n <WorkspaceCardOpenCue testId={openCueTestId} />\n </WorkspaceCardHeader>\n {workspace.subtitle && <WorkspaceCardSubtitle>{workspace.subtitle}</WorkspaceCardSubtitle>}\n {workspace.description && (\n <WorkspaceCardDescription>{workspace.description}</WorkspaceCardDescription>\n )}\n <WorkspaceCardFooter>\n {stats === undefined ? (\n <WorkspaceCardStats\n docCount={workspace.docCount}\n chatCount={workspace.chatCount}\n memberCount={workspace.memberCount}\n members={workspace.members}\n membersHidden={workspace.membersHidden}\n maxAvatars={maxAvatars}\n />\n ) : (\n stats\n )}\n {workspace.updatedAt && <WorkspaceCardMeta updatedAt={workspace.updatedAt} />}\n </WorkspaceCardFooter>\n </WorkspaceCardRoot>\n )\n}\n\nexport const WorkspaceCard = Object.assign(WorkspaceCardBase, {\n Root: WorkspaceCardRoot,\n Header: WorkspaceCardHeader,\n Title: WorkspaceCardTitle,\n OpenCue: WorkspaceCardOpenCue,\n Subtitle: WorkspaceCardSubtitle,\n Description: WorkspaceCardDescription,\n Footer: WorkspaceCardFooter,\n Stats: WorkspaceCardStats,\n Meta: WorkspaceCardMeta,\n})\n","import { useCallback, useState, type ReactNode } from 'react'\nimport { FolderLock, Loader2 } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport {\n WorkspaceCard,\n type WorkspaceCardLabels,\n type WorkspaceCardProps,\n type WorkspaceSummary,\n} from './WorkspaceCard'\n\n/** What a host's `renderMark` is told about the card it decorates. */\nexport interface WorkspaceMarkState {\n current: boolean\n /** `onOpen` is in flight for this card: show progress instead of the glyph. */\n opening: boolean\n}\n\nexport interface WorkspaceGalleryProps {\n workspaces: readonly WorkspaceSummary[]\n /** The workspace the app is in; its card takes the \"Current workspace\" cue. */\n currentId?: string | null\n /**\n * Open a workspace. Called for EVERY card click or keypress, the current workspace included:\n * clicking \"where you already are\" still goes there. Return the promise of \"switch, then\n * navigate\" (`await select(w); navigate(...)`) and the card shows progress until it settles;\n * a rejection is the host's to report (toast it) and re-enables the card.\n */\n onOpen: (workspace: WorkspaceSummary) => Promise<unknown> | void\n /** Override the in-flight card (controlled), e.g. from a hook's `openingId`. */\n openingId?: string | null\n /** Per-card real link target, so ctrl-click / new tab work. */\n getHref?: (workspace: WorkspaceSummary) => string | undefined\n /** The entity mark before the name. Default: a folder glyph that becomes a spinner. */\n renderMark?: (workspace: WorkspaceSummary, state: WorkspaceMarkState) => ReactNode\n /** Per-card props passthrough (`stats`, `maxAvatars`, `className`...). */\n getCardProps?: (workspace: WorkspaceSummary) => Partial<WorkspaceCardProps>\n labels?: Partial<WorkspaceCardLabels>\n /** Id of the grid. Cards are `${cardTestIdPrefix}${id}`, cues `${openCueTestIdPrefix}${id}`. */\n testId?: string\n cardTestIdPrefix?: string\n openCueTestIdPrefix?: string\n /** After the cards, inside the grid: a `CreateTile`. */\n children?: ReactNode\n className?: string\n}\n\n/** The default entity mark: a quiet folder glyph, a spinner while opening. */\nfunction DefaultMark({ opening }: { opening: boolean }) {\n return (\n <div className=\"flex size-10 shrink-0 items-center justify-center rounded-md bg-background text-foreground\">\n {opening ? (\n <Loader2 className=\"size-5 animate-spin\" aria-hidden=\"true\" />\n ) : (\n <FolderLock className=\"size-5\" aria-hidden=\"true\" />\n )}\n </div>\n )\n}\n\n/**\n * The workspaces gallery: a responsive grid of `WorkspaceCard`s whose click ALWAYS opens the\n * workspace, the current one included, through one `onOpen`. Owns the per-card \"opening\" state\n * and ignores repeat clicks while one open is in flight.\n */\nexport function WorkspaceGallery({\n workspaces,\n currentId,\n onOpen,\n openingId,\n getHref,\n renderMark,\n getCardProps,\n labels,\n testId,\n cardTestIdPrefix = 'workspace-card-',\n openCueTestIdPrefix = 'workspace-open-',\n children,\n className,\n}: WorkspaceGalleryProps) {\n const [pendingId, setPendingId] = useState<string | null>(null)\n const activeOpeningId = openingId !== undefined ? openingId : pendingId\n\n const open = useCallback(\n async (workspace: WorkspaceSummary) => {\n if (activeOpeningId) return\n setPendingId(workspace.id)\n try {\n await onOpen(workspace)\n } catch {\n // The host reports failures (a toast); the gallery only has to become usable again.\n } finally {\n setPendingId(null)\n }\n },\n [onOpen, activeOpeningId]\n )\n\n return (\n <div\n className={cn('grid gap-4 sm:grid-cols-2 xl:grid-cols-3', className)}\n data-slot=\"workspace-gallery\"\n data-testid={testId}\n >\n {workspaces.map((workspace) => {\n const current = workspace.id === currentId\n const opening = workspace.id === activeOpeningId\n const state = { current, opening }\n return (\n <WorkspaceCard\n key={workspace.id}\n workspace={workspace}\n current={current}\n href={getHref?.(workspace)}\n onSelect={() => void open(workspace)}\n mark={renderMark ? renderMark(workspace, state) : <DefaultMark opening={opening} />}\n testId={`${cardTestIdPrefix}${workspace.id}`}\n openCueTestId={`${openCueTestIdPrefix}${workspace.id}`}\n labels={labels}\n {...getCardProps?.(workspace)}\n />\n )\n })}\n {children}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { ChevronRight } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { CollapsibleSection } from '../home/CollapsibleSection'\n\nexport interface WorkspaceListProps {\n children: ReactNode\n className?: string\n testId?: string\n}\n\n/** The column that stacks workspace groups (padding follows the page gutter). */\nexport function WorkspaceList({ children, className, testId }: WorkspaceListProps) {\n return (\n <div\n className={cn('flex w-full flex-col gap-2 px-4 py-4 sm:px-8', className)}\n data-slot=\"workspace-list\"\n data-testid={testId}\n >\n {children}\n </div>\n )\n}\n\nexport interface WorkspaceGroupProps {\n /** Group heading: name, count, badges. Plain text on the canvas, no band. */\n title: ReactNode\n isExpanded: boolean\n onToggle: () => void\n /**\n * Makes the whole header one target (e.g. open the project panel); the\n * chevron stays a separate toggle. Adds a trailing `openLabel` affordance.\n */\n onOpen?: () => void\n /** Words beside the trailing chevron when `onOpen` is set, e.g. \"Plans & Usage\". */\n openLabel?: string\n /** Muted words on the right of a collapsed group without `onOpen`, e.g. \"Show 11 shared workspaces\". */\n collapsedHint?: string\n /** The cards, laid out in a responsive grid (1 / 2 / 3 columns). */\n children: ReactNode\n className?: string\n}\n\n/**\n * One collapsible band of workspace tiles under a slim header. The open\n * affordance is always visible, so nothing is reachable by hover alone.\n */\nexport function WorkspaceGroup({\n title,\n isExpanded,\n onToggle,\n onOpen,\n openLabel,\n collapsedHint,\n children,\n className,\n}: WorkspaceGroupProps) {\n return (\n <CollapsibleSection\n title={title}\n isExpanded={isExpanded}\n onToggle={onToggle}\n onHeaderClick={onOpen}\n rightContent={\n onOpen && openLabel ? (\n <span className=\"flex shrink-0 items-center gap-1 text-sm font-medium text-muted-foreground\">\n {openLabel}\n <ChevronRight className=\"size-4 shrink-0\" aria-hidden=\"true\" />\n </span>\n ) : collapsedHint && !isExpanded ? (\n <span className=\"shrink-0 text-sm text-muted-foreground\">{collapsedHint}</span>\n ) : undefined\n }\n className={cn('group', className)}\n headerClassName=\"mb-3 flex-wrap gap-y-2 rounded-md px-1 py-1 pointer-coarse:min-h-11\"\n childrenClassName=\"mb-8 grid gap-3 @xl:grid-cols-2 @5xl:grid-cols-3\"\n >\n {children}\n </CollapsibleSection>\n )\n}\n","import type { ReactNode } from 'react'\nimport { LogOut, UserPlus } from 'lucide-react'\nimport { Button, cn, Popover, PopoverContent, PopoverTrigger } from '@arbidocs/react/ui'\n\n/**\n * Page frame of a workspace's home: a bounded column whose ONE scroll region spans the full\n * width (scrollbar on the outer edge), the inset living on the content inside it. A container,\n * so children can use `@2xl:` queries.\n */\nexport function WorkspacePageFrame({ testId, children }: { testId?: string; children: ReactNode }) {\n return (\n <div\n className=\"flex h-full flex-col @container\"\n data-slot=\"workspace-page\"\n data-testid={testId}\n >\n {/* scrollbar-gutter:stable keeps the content from jumping when a scrollbar appears. */}\n <div className=\"scrollbar-subtle min-h-0 flex-1 overflow-y-auto [scrollbar-gutter:stable]\">\n <div className=\"space-y-6 px-4 pb-6 sm:px-6 pt-4\">{children}</div>\n </div>\n </div>\n )\n}\n\n/** Tinted card holding the identity bar and the expandable member list. */\nexport function WorkspaceIdentityPanel({ children }: { children: ReactNode }) {\n return (\n <div\n data-slot=\"workspace-identity-panel\"\n className=\"group rounded-lg border border-border bg-card px-4 py-3 shadow-xs\"\n >\n {children}\n </div>\n )\n}\n\nexport interface WorkspaceProjectSlotProps {\n testId: string\n /** Screen-reader caption (\"Project:\"): the chip says what it is without a word in front. */\n caption: string\n children: ReactNode\n}\n\n/** The project control / chip pinned to the end of the name row. */\nexport function WorkspaceProjectSlot({ testId, caption, children }: WorkspaceProjectSlotProps) {\n return (\n <div className=\"flex min-w-0 items-center gap-3\">\n <div className=\"flex min-w-0 flex-1 items-center gap-2\" data-testid={testId}>\n <span className=\"sr-only\">{caption}</span>\n {children}\n </div>\n </div>\n )\n}\n\n/** Stated absence (\"None\") rather than a blank gap. */\nexport function ItalicNone({ children }: { children: ReactNode }) {\n return <span className=\"text-sm italic text-muted-foreground\">{children}</span>\n}\n\nexport interface WorkspaceAudienceLineProps {\n visibility: {\n testId: string\n caption: string\n /** The owner's visibility switch (developers only). */\n toggle?: ReactNode\n /** The state named in words, so the switch is never a puzzle. */\n stateText: string\n /** What the state means for who can see the workspace; opened by tapping the state words. */\n stateHelp: string\n }\n /** Member avatar stack. */\n members: ReactNode\n /** \"Share\" button (owners). */\n share?: { label: string; onClick: () => void; testId: string }\n}\n\n/** Visibility and members end the description line together: who can see and use the workspace. */\nexport function WorkspaceAudienceLine({ visibility, members, share }: WorkspaceAudienceLineProps) {\n return (\n <span className=\"flex flex-wrap items-center gap-x-4 gap-y-2\" data-slot=\"workspace-audience\">\n <span className=\"flex items-center gap-2\" data-testid={visibility.testId}>\n <span className=\"sr-only\">{visibility.caption}</span>\n {visibility.toggle}\n {/* Tap-to-explain, not hover-only: the words must answer a click on touch screens too. */}\n <Popover>\n <PopoverTrigger className=\"cursor-pointer rounded-sm text-sm text-muted-foreground underline decoration-dotted underline-offset-4 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\">\n {visibility.stateText}\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 text-sm\">\n {visibility.stateHelp}\n </PopoverContent>\n </Popover>\n </span>\n {/* Faces first, then Share: \"these people ... add more\". */}\n <span className=\"flex items-center gap-1\">\n {members}\n {share && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-8 gap-1.5 px-3 text-sm pointer-coarse:h-11\"\n onClick={share.onClick}\n data-testid={share.testId}\n >\n <UserPlus className=\"size-4\" />\n {share.label}\n </Button>\n )}\n </span>\n </span>\n )\n}\n\n/**\n * Collapsible block under the identity bar. Stays mounted and animates its height (grid-rows\n * 0fr to 1fr), so opening and closing glides instead of snapping.\n */\nexport function ExpandableSection({\n expanded,\n testId,\n children,\n}: {\n expanded: boolean\n testId?: string\n children: ReactNode\n}) {\n return (\n <div\n className={cn(\n 'grid transition-[grid-template-rows] duration-300 ease-in-out',\n expanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'\n )}\n data-slot=\"expandable-section\"\n data-expanded={expanded}\n data-testid={testId}\n >\n <div className=\"overflow-hidden\">\n <div className=\"mt-4 border-t border-border pt-4\">{children}</div>\n </div>\n </div>\n )\n}\n\n/** Centered loading placeholder of a page body. */\nexport function PageLoading({ children }: { children: ReactNode }) {\n return <div className=\"flex h-64 items-center justify-center\">{children}</div>\n}\n\nexport interface LeaveFooterProps {\n testId?: string\n leave: { label: string; disabled?: boolean; onClick: () => void; testId?: string }\n}\n\n/** Leaving ENDS your part in the workspace, so it sits last and alone at the foot of the page. */\nexport function LeaveFooter({ testId, leave }: LeaveFooterProps) {\n return (\n <div className=\"flex justify-end\" data-slot=\"leave-footer\" data-testid={testId}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={leave.onClick}\n disabled={leave.disabled}\n className=\"h-7 px-2 text-sm text-destructive hover:bg-destructive/10 hover:text-destructive pointer-coarse:h-11\"\n data-testid={leave.testId}\n >\n <LogOut className=\"mr-1 size-3.5\" />\n {leave.label}\n </Button>\n </div>\n )\n}\n","import { useState, type ReactNode, useId } from 'react'\nimport {\n AlertCircle,\n AlignLeft,\n ArrowUpRight,\n CreditCard,\n FileText,\n Globe,\n Plus,\n} from 'lucide-react'\nimport {\n Button,\n cn,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogTitle,\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n} from '@arbidocs/react/ui'\nimport { KeyValueRow } from '../home/KeyValueRow'\nimport { ModalHeader } from '../settings/ModalScaffold'\n\n/** Inline error strip of a form. */\nexport function FormErrorBanner({\n message,\n testId,\n className,\n id,\n}: {\n message: string\n testId?: string\n className?: string\n /** Lets a field point at this message with `aria-describedby`. */\n id?: string\n}) {\n return (\n <div\n id={id}\n role=\"alert\"\n data-slot=\"form-error\"\n data-testid={testId}\n className={cn(\n 'flex items-center gap-2 rounded-md border border-red-border bg-red-bg p-3 text-sm text-red-text',\n className\n )}\n >\n <AlertCircle className=\"size-4 shrink-0\" aria-hidden=\"true\" />\n {message}\n </div>\n )\n}\n\n/** Right-aligned footer row of a form (Cancel + submit). */\nexport function FormActions({ className, children }: { className?: string; children: ReactNode }) {\n return (\n <div\n data-slot=\"form-actions\"\n className={cn('sticky bottom-0 flex justify-end gap-2 bg-background pt-2', className)}\n >\n {children}\n </div>\n )\n}\n\n/** Footer row of a modal body, separated by a rule. */\nexport function ModalActionRow({ children }: { children: ReactNode }) {\n return (\n <div\n data-slot=\"modal-action-row\"\n className=\"sticky bottom-0 -mx-6 -mb-6 flex flex-col-reverse gap-2 border-t border-border bg-background px-6 pb-6 pt-3 sm:flex-row sm:items-center sm:justify-end\"\n >\n {children}\n </div>\n )\n}\n\nexport interface WorkspaceFormModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n title: ReactNode\n /** Icon before the title. */\n icon?: ReactNode\n /** Optional intro paragraph above the form (first-run welcome). */\n intro?: ReactNode\n testId?: string\n /** Visually hidden description. */\n description?: string\n children: ReactNode\n}\n\n/** Dialog frame of the create-workspace form: header, optional intro, scrolling body. */\nexport function WorkspaceFormModal({\n open,\n onOpenChange,\n title,\n icon,\n intro,\n testId,\n description = 'Create a new workspace',\n children,\n}: WorkspaceFormModalProps) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n presentation=\"sheet\"\n className=\"flex max-h-panel w-modal max-w-modal-vw flex-col overflow-hidden p-0\"\n data-testid={testId}\n >\n <ModalHeader>\n <ModalTitleRow icon={icon} title={title} description={description} />\n </ModalHeader>\n <div className=\"min-h-0 flex-1 overflow-auto px-6 pb-6\">\n {intro && <p className=\"pb-4 text-sm text-muted-foreground\">{intro}</p>}\n {children}\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction ModalTitleRow({\n icon,\n title,\n description,\n}: {\n icon?: ReactNode\n title: ReactNode\n description: string\n}) {\n return (\n <>\n <DialogTitle>\n <div className=\"flex items-center gap-2\">\n {icon}\n <span>{title}</span>\n </div>\n </DialogTitle>\n <DialogDescription className=\"sr-only\">{description}</DialogDescription>\n </>\n )\n}\n\n/** One entry of the project picker: identity on the left, optional quota summary on the right. */\nexport function ProjectOptionRow({ identity, meta }: { identity: ReactNode; meta?: string }) {\n return (\n <div className=\"flex w-full min-w-0 items-center gap-2\">\n {identity}\n {meta && <span className=\"ml-auto truncate text-sm text-muted-foreground\">{meta}</span>}\n </div>\n )\n}\n\nexport interface ProjectPickerOption {\n id: string\n content: ReactNode\n}\n\nexport interface ProjectPickerProps {\n value?: string\n options: ProjectPickerOption[]\n onChange: (id: string) => void\n /** Adds a \"Create new project...\" entry. */\n onCreate?: () => void\n disabled?: boolean\n readOnly?: boolean\n className?: string\n labels?: { placeholder: string; create: string }\n}\n\nconst CREATE_VALUE = '__create__'\n\n/** The workspace's owning project, as a picker (optionally with a create entry). */\nexport function ProjectPicker({\n value,\n options,\n onChange,\n onCreate,\n disabled,\n readOnly,\n className,\n labels = { placeholder: 'Select project', create: 'Create new project...' },\n}: ProjectPickerProps) {\n return (\n <Select\n value={value ?? options[0]?.id}\n onValueChange={(v) => (v === CREATE_VALUE ? onCreate?.() : onChange(v))}\n disabled={disabled || readOnly}\n >\n <SelectTrigger\n className={cn(className, readOnly && 'cursor-not-allowed')}\n data-testid=\"workspace-project-select\"\n >\n <SelectValue placeholder={labels.placeholder} />\n </SelectTrigger>\n <SelectContent>\n {options.map((o) => (\n <SelectItem key={o.id} value={o.id}>\n {o.content}\n </SelectItem>\n ))}\n {onCreate && (\n <>\n <SelectSeparator />\n <SelectItem value={CREATE_VALUE}>\n <div className=\"flex items-center gap-1.5 text-primary\">\n <Plus className=\"size-3.5\" />\n <span>{labels.create}</span>\n </div>\n </SelectItem>\n </>\n )}\n </SelectContent>\n </Select>\n )\n}\n\n/** Compact CTA on a project row (e.g. Upgrade / Change plan). */\nexport function ProjectActionButton({\n label,\n onClick,\n className,\n testId,\n}: {\n label: string\n onClick: () => void\n className?: string\n testId?: string\n}) {\n return (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={onClick}\n className={cn(\n 'h-7 gap-1.5 whitespace-nowrap px-2 py-0 text-sm font-medium pointer-coarse:h-11',\n className\n )}\n data-testid={testId}\n >\n <ArrowUpRight className=\"size-3.5\" />\n {label}\n </Button>\n )\n}\n\nexport interface WorkspaceFieldsViewProps {\n /** `modal` (create flow) or `settings` (editing an existing workspace). */\n variant?: 'modal' | 'settings'\n name: string\n description: string\n onNameChange: (value: string) => void\n onDescriptionChange: (value: string) => void\n onNameBlur?: () => void\n onNameFocus?: () => void\n onDescriptionBlur?: () => void\n disabled?: boolean\n readOnly?: boolean\n maxNameLength?: number\n /** Id of the form's error message (a `FormErrorBanner id`): the name input is then `aria-invalid`\n * and described by it. */\n errorId?: string\n /** Content of the Visibility row (settings only); omit to hide the row. */\n visibility?: ReactNode\n /** Content of the Project row; omit to hide the row. */\n project?: ReactNode\n labels?: Partial<WorkspaceFieldsLabels>\n}\n\nexport interface WorkspaceFieldsLabels {\n readOnlyNotice: string\n name: string\n description: string\n visibility: string\n project: string\n over: (n: number) => string\n charsLeft: (n: number) => string\n}\n\nconst DEFAULT_LABELS: WorkspaceFieldsLabels = {\n readOnlyNotice: 'Read-only workspace',\n name: 'Name *',\n description: 'Description',\n visibility: 'Visibility',\n project: 'Project',\n over: (n) => `${n} over`,\n charsLeft: (n) => `${n} chars left`,\n}\n\n/** Name / description / visibility / project rows shared by the create and settings forms. */\nexport function WorkspaceFieldsView({\n variant = 'modal',\n name,\n description,\n onNameChange,\n onDescriptionChange,\n onNameBlur,\n onNameFocus,\n onDescriptionBlur,\n disabled = false,\n readOnly = false,\n errorId,\n maxNameLength = 50,\n visibility,\n project,\n labels,\n}: WorkspaceFieldsViewProps) {\n const workspaceDescriptionId = useId()\n const workspaceNameId = useId()\n const l = { ...DEFAULT_LABELS, ...labels }\n const [nameFocused, setNameFocused] = useState(false)\n const isModal = variant === 'modal'\n const charsLeft = maxNameLength - name.length\n // The modal only surfaces the counter near the limit; settings shows it while focused.\n const counterVisible = !readOnly && nameFocused && (!isModal || charsLeft <= 10)\n const isDisabled = isModal ? disabled : disabled || readOnly\n\n return (\n <div className=\"space-y-1\" data-slot=\"workspace-fields\">\n {readOnly && (\n <div data-testid=\"workspace-form-readonly-notice\" className=\"sr-only\">\n {l.readOnlyNotice}\n </div>\n )}\n <KeyValueRow label={l.name} icon={<FileText size={14} />} htmlFor={workspaceNameId}>\n <div className=\"relative\">\n <Input\n id={workspaceNameId}\n type=\"text\"\n value={name}\n onChange={(e) => onNameChange(e.target.value)}\n onBlur={() => {\n setNameFocused(false)\n onNameBlur?.()\n }}\n onFocus={() => {\n setNameFocused(true)\n onNameFocus?.()\n }}\n maxLength={maxNameLength}\n readOnly={readOnly}\n disabled={isDisabled}\n className={cn(\n isModal ? 'bg-background' : 'capitalize',\n readOnly && 'cursor-not-allowed',\n 'pr-20'\n )}\n required\n aria-invalid={errorId ? true : undefined}\n aria-describedby={errorId}\n data-testid=\"workspace-form-name-input\"\n />\n {counterVisible && (\n <div\n className={cn(\n 'pointer-events-none absolute right-3 top-1/2 hidden -translate-y-1/2 text-sm lg:block',\n charsLeft < 0 ? 'text-red-text' : 'text-muted-foreground'\n )}\n >\n {charsLeft < 0 ? l.over(-charsLeft) : l.charsLeft(charsLeft)}\n </div>\n )}\n </div>\n </KeyValueRow>\n\n <KeyValueRow\n label={l.description}\n icon={<AlignLeft size={14} />}\n htmlFor={workspaceDescriptionId}\n >\n <Input\n id={workspaceDescriptionId}\n type=\"text\"\n dictate\n value={description}\n onChange={(e) => onDescriptionChange(e.target.value)}\n onBlur={onDescriptionBlur}\n readOnly={readOnly}\n disabled={isDisabled}\n className={cn(isModal && 'bg-background', readOnly && 'cursor-not-allowed')}\n data-testid=\"workspace-form-description-input\"\n />\n </KeyValueRow>\n\n {visibility && (\n <KeyValueRow label={l.visibility} icon={<Globe size={14} />}>\n {visibility}\n </KeyValueRow>\n )}\n {project && (\n <KeyValueRow label={l.project} icon={<CreditCard size={14} />}>\n {project}\n </KeyValueRow>\n )}\n </div>\n )\n}\n"]}
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@arbidocs/blocks",
3
- "version": "0.4.69",
3
+ "version": "0.4.71",
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",
7
7
  "module": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "arbidocs-copy-pdf-assets": "./bin/arbidocs-copy-pdf-assets.mjs"
11
+ },
9
12
  "exports": {
10
13
  ".": {
11
14
  "types": "./dist/index.d.ts",
@@ -123,6 +126,21 @@
123
126
  "types": "./dist/connect/docx.d.ts",
124
127
  "import": "./dist/connect/docx.js",
125
128
  "require": "./dist/connect/docx.cjs"
129
+ },
130
+ "./document-tools": {
131
+ "types": "./dist/document-tools/index.d.ts",
132
+ "import": "./dist/document-tools/index.js",
133
+ "require": "./dist/document-tools/index.cjs"
134
+ },
135
+ "./document-tools/viewer": {
136
+ "types": "./dist/document-tools/viewer/index.d.ts",
137
+ "import": "./dist/document-tools/viewer/index.js",
138
+ "require": "./dist/document-tools/viewer/index.cjs"
139
+ },
140
+ "./document-tools/production": {
141
+ "types": "./dist/document-tools/production/index.d.ts",
142
+ "import": "./dist/document-tools/production/index.js",
143
+ "require": "./dist/document-tools/production/index.cjs"
126
144
  }
127
145
  },
128
146
  "typesVersions": {
@@ -189,10 +207,20 @@
189
207
  ],
190
208
  "connect/docx": [
191
209
  "./dist/connect/docx.d.ts"
210
+ ],
211
+ "document-tools": [
212
+ "./dist/document-tools/index.d.ts"
213
+ ],
214
+ "document-tools/viewer": [
215
+ "./dist/document-tools/viewer/index.d.ts"
216
+ ],
217
+ "document-tools/production": [
218
+ "./dist/document-tools/production/index.d.ts"
192
219
  ]
193
220
  }
194
221
  },
195
222
  "files": [
223
+ "bin",
196
224
  "dist",
197
225
  "src/tokens.css",
198
226
  "src/blocks.css",
@@ -213,7 +241,7 @@
213
241
  "example:test:e2e": "playwright test -c examples/custom-ui/playwright.config.ts"
214
242
  },
215
243
  "dependencies": {
216
- "@arbidocs/client": "0.4.69",
244
+ "@arbidocs/client": "0.4.71",
217
245
  "@dnd-kit/core": "^6.3.1",
218
246
  "@dnd-kit/sortable": "^10.0.0",
219
247
  "@dnd-kit/utilities": "^3.2.2",
@@ -228,10 +256,10 @@
228
256
  "zustand": "^5.0.14",
229
257
  "fflate": "^0.8.2",
230
258
  "@hocuspocus/provider": "4.6.0",
231
- "@arbidocs/coedit": "0.4.69"
259
+ "@arbidocs/coedit": "0.4.71"
232
260
  },
233
261
  "peerDependencies": {
234
- "@arbidocs/react": "0.4.69",
262
+ "@arbidocs/react": "0.4.71",
235
263
  "@mdxeditor/editor": "^4.0.4",
236
264
  "@measured/puck": ">=0.20",
237
265
  "@playwright/test": ">=1.40",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connection/StreamedArtifactEditor.tsx"],"names":[],"mappings":"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","file":"StreamedArtifactEditor-OPL4KXOT.js","sourcesContent":["import { useState, type ReactNode } from 'react'\nimport { Copy, Download } from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { renderArtifactMarkdown, useArtifactSession } from '@arbidocs/react/artifacts'\nimport { ArtifactEditor, ArtifactRedlineView, type ArtifactEditorLabels } from '../artifacts'\nimport {\n ArtifactMarkdownEditor,\n type ArtifactMarkdownEditorProps,\n} from '../artifacts/editor/ArtifactMarkdownEditor'\n\nexport interface StreamedArtifactEditorProps {\n workspaceId: string | undefined\n /** The stored first version (the lineage's root as far as this panel goes). */\n docId: string\n /** File name for the versions saved from here. */\n title: string\n testId: string\n className?: string\n /** Extra props of the rich-text editor (`dictation`, labels). */\n editorProps?: Partial<Omit<ArtifactMarkdownEditorProps, 'markdown' | 'onChange' | 'onNormalized'>>\n /** Called after a version is saved. */\n onSaved?: (docId: string | undefined) => void\n onSaveError?: (error: unknown) => void\n /** Extra header actions next to the toolbar. */\n actions?: (ctx: { content: string; title: string }) => ReactNode\n /** Hide the default Copy and Download buttons. */\n hideDefaultActions?: boolean\n labels?: Partial<ArtifactEditorLabels>\n}\n\n/**\n * The editing stage of `StreamedArtifact`: `ArtifactEditor` bound to `useArtifactSession`. It is\n * a separate module because it pulls the rich-text editor (Lexical), which must stay behind a\n * `lazy()` boundary.\n */\nexport default function StreamedArtifactEditor({\n workspaceId,\n docId,\n title,\n testId,\n className,\n editorProps,\n onSaved,\n onSaveError,\n actions,\n hideDefaultActions,\n labels,\n}: StreamedArtifactEditorProps) {\n const [openId, setOpenId] = useState(docId)\n const s = useArtifactSession({\n workspaceId,\n docId: openId,\n title,\n onSaved: ({ docId: next }) => {\n if (next) setOpenId(next)\n onSaved?.(next)\n },\n onSaveError,\n })\n\n const copy = () => void navigator.clipboard.writeText(s.content)\n const download = () => {\n const url = URL.createObjectURL(new Blob([s.content], { type: 'text/markdown' }))\n const a = document.createElement('a')\n a.href = url\n a.download = `${title.replace(/\\.md$/i, '')}.md`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div\n className={cn(\n 'flex min-h-[560px] flex-col rounded-xl border border-border bg-card',\n className\n )}\n data-testid={testId}\n >\n <ArtifactEditor\n {...s.view}\n className=\"min-h-[560px] flex-1\"\n labels={labels}\n onOpenVersion={setOpenId}\n renderMarkdown={renderArtifactMarkdown}\n editor={<ArtifactMarkdownEditor {...editorProps} {...s.editorProps} />}\n redline={\n <ArtifactRedlineView {...s.redlineProps} renderMarkdown={renderArtifactMarkdown} />\n }\n actions={\n <>\n {!hideDefaultActions && (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={copy}\n data-testid={`${testId}-copy`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Copy className=\"size-4\" aria-hidden /> Copy\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={download}\n data-testid={`${testId}-download`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Download className=\"size-4\" aria-hidden /> Download\n </Button>\n </>\n )}\n {actions?.({ content: s.content, title })}\n </>\n }\n />\n </div>\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connection/StreamedArtifactEditor.tsx"],"names":["useState","useArtifactSession","jsx","cn","ArtifactEditor","renderArtifactMarkdown","ArtifactMarkdownEditor","ArtifactRedlineView","jsxs","Fragment","Button","Copy","Download"],"mappings":"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","file":"StreamedArtifactEditor-RIKG6CJQ.cjs","sourcesContent":["import { useState, type ReactNode } from 'react'\nimport { Copy, Download } from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { renderArtifactMarkdown, useArtifactSession } from '@arbidocs/react/artifacts'\nimport { ArtifactEditor, ArtifactRedlineView, type ArtifactEditorLabels } from '../artifacts'\nimport {\n ArtifactMarkdownEditor,\n type ArtifactMarkdownEditorProps,\n} from '../artifacts/editor/ArtifactMarkdownEditor'\n\nexport interface StreamedArtifactEditorProps {\n workspaceId: string | undefined\n /** The stored first version (the lineage's root as far as this panel goes). */\n docId: string\n /** File name for the versions saved from here. */\n title: string\n testId: string\n className?: string\n /** Extra props of the rich-text editor (`dictation`, labels). */\n editorProps?: Partial<Omit<ArtifactMarkdownEditorProps, 'markdown' | 'onChange' | 'onNormalized'>>\n /** Called after a version is saved. */\n onSaved?: (docId: string | undefined) => void\n onSaveError?: (error: unknown) => void\n /** Extra header actions next to the toolbar. */\n actions?: (ctx: { content: string; title: string }) => ReactNode\n /** Hide the default Copy and Download buttons. */\n hideDefaultActions?: boolean\n labels?: Partial<ArtifactEditorLabels>\n}\n\n/**\n * The editing stage of `StreamedArtifact`: `ArtifactEditor` bound to `useArtifactSession`. It is\n * a separate module because it pulls the rich-text editor (Lexical), which must stay behind a\n * `lazy()` boundary.\n */\nexport default function StreamedArtifactEditor({\n workspaceId,\n docId,\n title,\n testId,\n className,\n editorProps,\n onSaved,\n onSaveError,\n actions,\n hideDefaultActions,\n labels,\n}: StreamedArtifactEditorProps) {\n const [openId, setOpenId] = useState(docId)\n const s = useArtifactSession({\n workspaceId,\n docId: openId,\n title,\n onSaved: ({ docId: next }) => {\n if (next) setOpenId(next)\n onSaved?.(next)\n },\n onSaveError,\n })\n\n const copy = () => void navigator.clipboard.writeText(s.content)\n const download = () => {\n const url = URL.createObjectURL(new Blob([s.content], { type: 'text/markdown' }))\n const a = document.createElement('a')\n a.href = url\n a.download = `${title.replace(/\\.md$/i, '')}.md`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div\n className={cn(\n 'flex min-h-[560px] flex-col rounded-xl border border-border bg-card',\n className\n )}\n data-testid={testId}\n >\n <ArtifactEditor\n {...s.view}\n className=\"min-h-[560px] flex-1\"\n labels={labels}\n onOpenVersion={setOpenId}\n renderMarkdown={renderArtifactMarkdown}\n editor={<ArtifactMarkdownEditor {...editorProps} {...s.editorProps} />}\n redline={\n <ArtifactRedlineView {...s.redlineProps} renderMarkdown={renderArtifactMarkdown} />\n }\n actions={\n <>\n {!hideDefaultActions && (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={copy}\n data-testid={`${testId}-copy`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Copy className=\"size-4\" aria-hidden /> Copy\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={download}\n data-testid={`${testId}-download`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Download className=\"size-4\" aria-hidden /> Download\n </Button>\n </>\n )}\n {actions?.({ content: s.content, title })}\n </>\n }\n />\n </div>\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connection/ConnectionProvider.tsx"],"names":[],"mappings":"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","file":"chunk-EHXSBH6U.js","sourcesContent":["/**\n * The demo/live connection layer for a host app. Holds auth + workspace\n * selection state and exposes it via {@link useConnection}, so every surface\n * works identically whether it's talking to a live ARBI backend or the seeded\n * demo workspace. Host-specific values (backend URL, demo identity, default\n * workspace/assistant ids) arrive once through {@link ArbiConnectionConfig}.\n */\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport { useArbi, type LoginProfile } from '@arbidocs/react'\nimport type { ArbiMode, ArbiUser, ConnectionStatus, ArbiConnectionConfig } from './types'\n\ninterface ConnectionValue {\n mode: ArbiMode\n status: ConnectionStatus\n user: ArbiUser | null\n workspaceId: string | null\n apiConfigured: boolean\n apiUrl: string\n error: string | null\n /** Default assistant config ext_id (for the AI hooks). */\n assistantConfig?: string\n /** Fallback workspace ext_id when none is actively selected. */\n fallbackWorkspaceId?: string\n /** Authenticate. Live login when a backend is configured, otherwise the demo workspace. */\n login: (email: string, password: string) => Promise<void>\n /** One-click demo entry (no backend required). */\n enterDemo: () => void\n logout: () => void\n /**\n * Affirmatively select a workspace: opens it on the server (via the SDK),\n * updates the app-wide state, and persists the choice so it survives future\n * logins. This is the single entry point for \"the user is now in workspace X\".\n */\n setWorkspace: (id: string) => Promise<void>\n /**\n * Re-assert the selected workspace on the server session (idempotent `/open`).\n * Call before a workspace-scoped write when the session may have lost its open\n * workspace (token re-login, backend restart, session expiry) — the server\n * resolves the workspace from the session, so a dropped `/open` yields\n * \"No active workspace\" until it's re-opened.\n */\n ensureWorkspaceOpen: () => Promise<void>\n}\n\nconst ConnectionContext = createContext<ConnectionValue | null>(null)\n\n/**\n * Persist the affirmatively-selected workspace per backend AND per signed-in user, so a returning\n * user lands back in the workspace they last chose, while the next person on a shared browser\n * never starts from someone else's workspace id. Namespaced by apiUrl so distinct deployments\n * (and the demo workspace) don't clobber each other. Cleared on logout.\n */\nconst WORKSPACE_STORAGE_PREFIX = 'arbi:selectedWorkspace'\nconst sessionUserKey = (apiUrl: string) => `arbi:sessionUser:${apiUrl}`\nfunction rememberSessionUser(apiUrl: string, email: string | null) {\n try {\n if (email) window.localStorage.setItem(sessionUserKey(apiUrl), normalizeUserKey(email))\n else window.localStorage.removeItem(sessionUserKey(apiUrl))\n } catch {\n /* Storage may be unavailable. */\n }\n}\nconst normalizeUserKey = (email: string) => email.trim().toLowerCase()\n\n/** Exported for tests. */\nexport const workspaceStorageKey = (apiUrl: string, userKey: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}:${normalizeUserKey(userKey)}`\n\n/** The pre-isolation key (apiUrl only). Never read: removed so it cannot leak across users. */\nconst legacyWorkspaceStorageKey = (apiUrl: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}`\n\nfunction readPersistedWorkspace(apiUrl: string, userKey: string | null): string | null {\n if (!userKey) return null\n try {\n return window.localStorage.getItem(workspaceStorageKey(apiUrl, userKey))\n } catch {\n return null\n }\n}\n\nfunction persistWorkspace(apiUrl: string, userKey: string | null, id: string | null): void {\n if (!userKey) return\n try {\n if (id) window.localStorage.setItem(workspaceStorageKey(apiUrl, userKey), id)\n else window.localStorage.removeItem(workspaceStorageKey(apiUrl, userKey))\n window.localStorage.removeItem(legacyWorkspaceStorageKey(apiUrl))\n } catch {\n // Storage unavailable (private mode, SSR) — selection stays in-memory only.\n }\n}\n\n/** Shown on the sign-in screen after the session could not be recovered. */\nexport const SESSION_EXPIRED_MESSAGE = 'Your session expired. Sign in again.'\n\n/** The connection user for a profile: its full name, falling back to the email local part. */\nfunction userFromProfile(profile: LoginProfile, externalId?: string): ArbiUser {\n const fullName = [profile.givenName, profile.familyName]\n .map((part) => part?.trim())\n .filter(Boolean)\n .join(' ')\n return {\n name: fullName || profile.email.split('@')[0],\n email: profile.email,\n externalId,\n picture: profile.picture,\n }\n}\n\nexport function ConnectionProvider({\n config,\n children,\n}: {\n config: ArbiConnectionConfig\n children: ReactNode\n}) {\n const arbi = useArbi()\n const isLiveConfigured = config.apiUrl.length > 0\n const demoWorkspaceId = config.demoWorkspaceId ?? 'demo-workspace'\n\n const [status, setStatus] = useState<ConnectionStatus>(\n isLiveConfigured ? 'connecting' : 'disconnected'\n )\n const [user, setUser] = useState<ArbiUser | null>(null)\n const [workspaceId, setWorkspaceId] = useState<string | null>(null)\n const [mode, setMode] = useState<ArbiMode>('demo')\n const [error, setError] = useState<string | null>(null)\n // Who the persisted workspace belongs to; set at sign-in, cleared at logout.\n const storageUserRef = useRef<string | null>(null)\n\n // The SDK could not recover the session (token refused, workspace not re-openable): drop to\n // 'disconnected' with a plain message, so the host's gate sends the user to sign in instead of\n // every call failing with a raw backend error. The remembered workspace is kept for next login.\n useEffect(\n () =>\n arbi.onSessionExpired?.(() => {\n rememberSessionUser(config.apiUrl, null)\n storageUserRef.current = null\n setUser(null)\n setWorkspaceId(null)\n setStatus('disconnected')\n setError(SESSION_EXPIRED_MESSAGE)\n }),\n [arbi, config.apiUrl]\n )\n\n // A saved name, picture or email reaches every surface reading `useConnection().user`.\n useEffect(\n () =>\n arbi.user.onProfileChange?.((profile) =>\n setUser((current) => (current ? userFromProfile(profile, current.externalId) : current))\n ),\n [arbi]\n )\n\n const enterDemo = useCallback(() => {\n setMode('demo')\n setStatus('demo')\n setError(null)\n setUser({ name: config.demoUser.name, email: config.demoUser.email })\n setWorkspaceId(demoWorkspaceId)\n }, [config.demoUser.name, config.demoUser.email, demoWorkspaceId])\n\n const login = useCallback(\n async (email: string, password: string, restoring = false) => {\n setError(null)\n // No backend configured → run the seeded demo workspace.\n if (!isLiveConfigured) {\n enterDemo()\n return\n }\n setStatus('connecting')\n setMode('live')\n try {\n if (restoring) {\n if (!(await arbi.restoreSession(email))) {\n rememberSessionUser(config.apiUrl, null)\n setStatus('disconnected')\n return\n }\n } else await arbi.login(email, password)\n storageUserRef.current = normalizeUserKey(email)\n const workspaces = await arbi.workspaces.list()\n if (workspaces?.length) {\n // Prefer the workspace the user last affirmatively selected (persisted),\n // then the configured workspace (there may be several — e.g. a\n // marketing/KM workspace), then whichever happens to be first. Ternary\n // (not `&&`) so an empty value can't leak `\"\"` into `target`.\n const persisted = readPersistedWorkspace(config.apiUrl, storageUserRef.current)\n const preferred = persisted ?? config.workspaceId\n const target =\n (preferred ? workspaces.find((w) => w.external_id === preferred) : undefined) ??\n workspaces[0]\n await arbi.selectWorkspace(target.external_id)\n setWorkspaceId(target.external_id)\n persistWorkspace(config.apiUrl, storageUserRef.current, target.external_id)\n }\n // The profile (name + avatar) comes with the login response. A session restored without\n // a login has none, so fall back to finding ourselves in the workspace roster; the email\n // local part is only the last resort, never the answer when a profile name exists.\n let resolved: ArbiUser = { name: email.split('@')[0], email }\n const me = arbi.user.identity()\n const profile = arbi.user.profile?.()\n if (profile) {\n resolved = userFromProfile(profile, me?.externalId)\n } else {\n try {\n const members = await arbi.workspaces.listUsers()\n const self = members.find((m) => m.user.external_id === me?.externalId)?.user\n if (self) {\n const fullName = [self.given_name, self.family_name].filter(Boolean).join(' ').trim()\n resolved = {\n name: fullName || email.split('@')[0],\n email: self.email || email,\n externalId: self.external_id,\n picture: self.picture ?? null,\n }\n } else if (me?.externalId) {\n resolved.externalId = me.externalId\n }\n } catch {\n // Roster not available (e.g. no workspace) — keep the fallback identity.\n }\n }\n setUser(resolved)\n rememberSessionUser(config.apiUrl, email)\n setStatus('authenticated')\n } catch (e) {\n // Surface the real error — no silent fallback to a fake session.\n setError(e instanceof Error ? e.message : 'Sign-in failed. Check your credentials.')\n setStatus('error')\n }\n },\n [arbi, enterDemo, isLiveConfigured, config.workspaceId, config.apiUrl]\n )\n\n // Run once even under StrictMode; passwords and signing keys are never stored here.\n const recoveryStarted = useRef(false)\n useEffect(() => {\n if (recoveryStarted.current || !isLiveConfigured) return\n recoveryStarted.current = true\n let email: string | null = null\n try {\n email = window.localStorage.getItem(sessionUserKey(config.apiUrl))\n } catch {\n /* unavailable */\n }\n if (email) void login(email, '', true)\n else setStatus('disconnected')\n }, [isLiveConfigured, config.apiUrl, login])\n\n const logout = useCallback(() => {\n rememberSessionUser(config.apiUrl, null)\n if (mode === 'live') {\n void arbi.logout?.()\n }\n setUser(null)\n setWorkspaceId(null)\n persistWorkspace(config.apiUrl, storageUserRef.current, null)\n storageUserRef.current = null\n setStatus('disconnected')\n setError(null)\n }, [arbi, mode, config.apiUrl])\n\n // Affirmative selection: open the workspace on the server (live), then remember\n // it in state + storage so every surface — and the next login — is in sync.\n const setWorkspace = useCallback(\n async (id: string) => {\n if (mode === 'live' && arbi.isLoggedIn) {\n await arbi.selectWorkspace(id)\n }\n setWorkspaceId(id)\n persistWorkspace(config.apiUrl, storageUserRef.current, id)\n },\n [arbi, mode, config.apiUrl]\n )\n\n // Re-open the selected workspace on the session if the server may have dropped\n // it. Idempotent: re-running `/open` for the already-selected workspace is safe.\n const ensureWorkspaceOpen = useCallback(async () => {\n if (mode !== 'live' || !arbi.isLoggedIn) return\n const id =\n workspaceId ??\n readPersistedWorkspace(config.apiUrl, storageUserRef.current) ??\n config.workspaceId\n if (id) await arbi.selectWorkspace(id)\n }, [arbi, mode, workspaceId, config.apiUrl, config.workspaceId])\n\n const value = useMemo<ConnectionValue>(\n () => ({\n mode,\n status,\n user,\n workspaceId,\n apiConfigured: isLiveConfigured,\n apiUrl: config.apiUrl,\n error,\n assistantConfig: config.assistantConfig,\n fallbackWorkspaceId: config.workspaceId,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n }),\n [\n mode,\n status,\n user,\n workspaceId,\n isLiveConfigured,\n config.apiUrl,\n config.assistantConfig,\n config.workspaceId,\n error,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n ]\n )\n\n return <ConnectionContext.Provider value={value}>{children}</ConnectionContext.Provider>\n}\n\nexport function useConnection(): ConnectionValue {\n const ctx = useContext(ConnectionContext)\n if (!ctx) throw new Error('useConnection must be used within ConnectionProvider')\n return ctx\n}\n\nexport const isAuthenticated = (s: ConnectionStatus) => s === 'demo' || s === 'authenticated'\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connection/ConnectionProvider.tsx"],"names":["createContext","useArbi","useState","useRef","useEffect","useCallback","useMemo","jsx","useContext"],"mappings":"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","file":"chunk-TLQQV7WW.cjs","sourcesContent":["/**\n * The demo/live connection layer for a host app. Holds auth + workspace\n * selection state and exposes it via {@link useConnection}, so every surface\n * works identically whether it's talking to a live ARBI backend or the seeded\n * demo workspace. Host-specific values (backend URL, demo identity, default\n * workspace/assistant ids) arrive once through {@link ArbiConnectionConfig}.\n */\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport { useArbi, type LoginProfile } from '@arbidocs/react'\nimport type { ArbiMode, ArbiUser, ConnectionStatus, ArbiConnectionConfig } from './types'\n\ninterface ConnectionValue {\n mode: ArbiMode\n status: ConnectionStatus\n user: ArbiUser | null\n workspaceId: string | null\n apiConfigured: boolean\n apiUrl: string\n error: string | null\n /** Default assistant config ext_id (for the AI hooks). */\n assistantConfig?: string\n /** Fallback workspace ext_id when none is actively selected. */\n fallbackWorkspaceId?: string\n /** Authenticate. Live login when a backend is configured, otherwise the demo workspace. */\n login: (email: string, password: string) => Promise<void>\n /** One-click demo entry (no backend required). */\n enterDemo: () => void\n logout: () => void\n /**\n * Affirmatively select a workspace: opens it on the server (via the SDK),\n * updates the app-wide state, and persists the choice so it survives future\n * logins. This is the single entry point for \"the user is now in workspace X\".\n */\n setWorkspace: (id: string) => Promise<void>\n /**\n * Re-assert the selected workspace on the server session (idempotent `/open`).\n * Call before a workspace-scoped write when the session may have lost its open\n * workspace (token re-login, backend restart, session expiry) — the server\n * resolves the workspace from the session, so a dropped `/open` yields\n * \"No active workspace\" until it's re-opened.\n */\n ensureWorkspaceOpen: () => Promise<void>\n}\n\nconst ConnectionContext = createContext<ConnectionValue | null>(null)\n\n/**\n * Persist the affirmatively-selected workspace per backend AND per signed-in user, so a returning\n * user lands back in the workspace they last chose, while the next person on a shared browser\n * never starts from someone else's workspace id. Namespaced by apiUrl so distinct deployments\n * (and the demo workspace) don't clobber each other. Cleared on logout.\n */\nconst WORKSPACE_STORAGE_PREFIX = 'arbi:selectedWorkspace'\nconst sessionUserKey = (apiUrl: string) => `arbi:sessionUser:${apiUrl}`\nfunction rememberSessionUser(apiUrl: string, email: string | null) {\n try {\n if (email) window.localStorage.setItem(sessionUserKey(apiUrl), normalizeUserKey(email))\n else window.localStorage.removeItem(sessionUserKey(apiUrl))\n } catch {\n /* Storage may be unavailable. */\n }\n}\nconst normalizeUserKey = (email: string) => email.trim().toLowerCase()\n\n/** Exported for tests. */\nexport const workspaceStorageKey = (apiUrl: string, userKey: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}:${normalizeUserKey(userKey)}`\n\n/** The pre-isolation key (apiUrl only). Never read: removed so it cannot leak across users. */\nconst legacyWorkspaceStorageKey = (apiUrl: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}`\n\nfunction readPersistedWorkspace(apiUrl: string, userKey: string | null): string | null {\n if (!userKey) return null\n try {\n return window.localStorage.getItem(workspaceStorageKey(apiUrl, userKey))\n } catch {\n return null\n }\n}\n\nfunction persistWorkspace(apiUrl: string, userKey: string | null, id: string | null): void {\n if (!userKey) return\n try {\n if (id) window.localStorage.setItem(workspaceStorageKey(apiUrl, userKey), id)\n else window.localStorage.removeItem(workspaceStorageKey(apiUrl, userKey))\n window.localStorage.removeItem(legacyWorkspaceStorageKey(apiUrl))\n } catch {\n // Storage unavailable (private mode, SSR) — selection stays in-memory only.\n }\n}\n\n/** Shown on the sign-in screen after the session could not be recovered. */\nexport const SESSION_EXPIRED_MESSAGE = 'Your session expired. Sign in again.'\n\n/** The connection user for a profile: its full name, falling back to the email local part. */\nfunction userFromProfile(profile: LoginProfile, externalId?: string): ArbiUser {\n const fullName = [profile.givenName, profile.familyName]\n .map((part) => part?.trim())\n .filter(Boolean)\n .join(' ')\n return {\n name: fullName || profile.email.split('@')[0],\n email: profile.email,\n externalId,\n picture: profile.picture,\n }\n}\n\nexport function ConnectionProvider({\n config,\n children,\n}: {\n config: ArbiConnectionConfig\n children: ReactNode\n}) {\n const arbi = useArbi()\n const isLiveConfigured = config.apiUrl.length > 0\n const demoWorkspaceId = config.demoWorkspaceId ?? 'demo-workspace'\n\n const [status, setStatus] = useState<ConnectionStatus>(\n isLiveConfigured ? 'connecting' : 'disconnected'\n )\n const [user, setUser] = useState<ArbiUser | null>(null)\n const [workspaceId, setWorkspaceId] = useState<string | null>(null)\n const [mode, setMode] = useState<ArbiMode>('demo')\n const [error, setError] = useState<string | null>(null)\n // Who the persisted workspace belongs to; set at sign-in, cleared at logout.\n const storageUserRef = useRef<string | null>(null)\n\n // The SDK could not recover the session (token refused, workspace not re-openable): drop to\n // 'disconnected' with a plain message, so the host's gate sends the user to sign in instead of\n // every call failing with a raw backend error. The remembered workspace is kept for next login.\n useEffect(\n () =>\n arbi.onSessionExpired?.(() => {\n rememberSessionUser(config.apiUrl, null)\n storageUserRef.current = null\n setUser(null)\n setWorkspaceId(null)\n setStatus('disconnected')\n setError(SESSION_EXPIRED_MESSAGE)\n }),\n [arbi, config.apiUrl]\n )\n\n // A saved name, picture or email reaches every surface reading `useConnection().user`.\n useEffect(\n () =>\n arbi.user.onProfileChange?.((profile) =>\n setUser((current) => (current ? userFromProfile(profile, current.externalId) : current))\n ),\n [arbi]\n )\n\n const enterDemo = useCallback(() => {\n setMode('demo')\n setStatus('demo')\n setError(null)\n setUser({ name: config.demoUser.name, email: config.demoUser.email })\n setWorkspaceId(demoWorkspaceId)\n }, [config.demoUser.name, config.demoUser.email, demoWorkspaceId])\n\n const login = useCallback(\n async (email: string, password: string, restoring = false) => {\n setError(null)\n // No backend configured → run the seeded demo workspace.\n if (!isLiveConfigured) {\n enterDemo()\n return\n }\n setStatus('connecting')\n setMode('live')\n try {\n if (restoring) {\n if (!(await arbi.restoreSession(email))) {\n rememberSessionUser(config.apiUrl, null)\n setStatus('disconnected')\n return\n }\n } else await arbi.login(email, password)\n storageUserRef.current = normalizeUserKey(email)\n const workspaces = await arbi.workspaces.list()\n if (workspaces?.length) {\n // Prefer the workspace the user last affirmatively selected (persisted),\n // then the configured workspace (there may be several — e.g. a\n // marketing/KM workspace), then whichever happens to be first. Ternary\n // (not `&&`) so an empty value can't leak `\"\"` into `target`.\n const persisted = readPersistedWorkspace(config.apiUrl, storageUserRef.current)\n const preferred = persisted ?? config.workspaceId\n const target =\n (preferred ? workspaces.find((w) => w.external_id === preferred) : undefined) ??\n workspaces[0]\n await arbi.selectWorkspace(target.external_id)\n setWorkspaceId(target.external_id)\n persistWorkspace(config.apiUrl, storageUserRef.current, target.external_id)\n }\n // The profile (name + avatar) comes with the login response. A session restored without\n // a login has none, so fall back to finding ourselves in the workspace roster; the email\n // local part is only the last resort, never the answer when a profile name exists.\n let resolved: ArbiUser = { name: email.split('@')[0], email }\n const me = arbi.user.identity()\n const profile = arbi.user.profile?.()\n if (profile) {\n resolved = userFromProfile(profile, me?.externalId)\n } else {\n try {\n const members = await arbi.workspaces.listUsers()\n const self = members.find((m) => m.user.external_id === me?.externalId)?.user\n if (self) {\n const fullName = [self.given_name, self.family_name].filter(Boolean).join(' ').trim()\n resolved = {\n name: fullName || email.split('@')[0],\n email: self.email || email,\n externalId: self.external_id,\n picture: self.picture ?? null,\n }\n } else if (me?.externalId) {\n resolved.externalId = me.externalId\n }\n } catch {\n // Roster not available (e.g. no workspace) — keep the fallback identity.\n }\n }\n setUser(resolved)\n rememberSessionUser(config.apiUrl, email)\n setStatus('authenticated')\n } catch (e) {\n // Surface the real error — no silent fallback to a fake session.\n setError(e instanceof Error ? e.message : 'Sign-in failed. Check your credentials.')\n setStatus('error')\n }\n },\n [arbi, enterDemo, isLiveConfigured, config.workspaceId, config.apiUrl]\n )\n\n // Run once even under StrictMode; passwords and signing keys are never stored here.\n const recoveryStarted = useRef(false)\n useEffect(() => {\n if (recoveryStarted.current || !isLiveConfigured) return\n recoveryStarted.current = true\n let email: string | null = null\n try {\n email = window.localStorage.getItem(sessionUserKey(config.apiUrl))\n } catch {\n /* unavailable */\n }\n if (email) void login(email, '', true)\n else setStatus('disconnected')\n }, [isLiveConfigured, config.apiUrl, login])\n\n const logout = useCallback(() => {\n rememberSessionUser(config.apiUrl, null)\n if (mode === 'live') {\n void arbi.logout?.()\n }\n setUser(null)\n setWorkspaceId(null)\n persistWorkspace(config.apiUrl, storageUserRef.current, null)\n storageUserRef.current = null\n setStatus('disconnected')\n setError(null)\n }, [arbi, mode, config.apiUrl])\n\n // Affirmative selection: open the workspace on the server (live), then remember\n // it in state + storage so every surface — and the next login — is in sync.\n const setWorkspace = useCallback(\n async (id: string) => {\n if (mode === 'live' && arbi.isLoggedIn) {\n await arbi.selectWorkspace(id)\n }\n setWorkspaceId(id)\n persistWorkspace(config.apiUrl, storageUserRef.current, id)\n },\n [arbi, mode, config.apiUrl]\n )\n\n // Re-open the selected workspace on the session if the server may have dropped\n // it. Idempotent: re-running `/open` for the already-selected workspace is safe.\n const ensureWorkspaceOpen = useCallback(async () => {\n if (mode !== 'live' || !arbi.isLoggedIn) return\n const id =\n workspaceId ??\n readPersistedWorkspace(config.apiUrl, storageUserRef.current) ??\n config.workspaceId\n if (id) await arbi.selectWorkspace(id)\n }, [arbi, mode, workspaceId, config.apiUrl, config.workspaceId])\n\n const value = useMemo<ConnectionValue>(\n () => ({\n mode,\n status,\n user,\n workspaceId,\n apiConfigured: isLiveConfigured,\n apiUrl: config.apiUrl,\n error,\n assistantConfig: config.assistantConfig,\n fallbackWorkspaceId: config.workspaceId,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n }),\n [\n mode,\n status,\n user,\n workspaceId,\n isLiveConfigured,\n config.apiUrl,\n config.assistantConfig,\n config.workspaceId,\n error,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n ]\n )\n\n return <ConnectionContext.Provider value={value}>{children}</ConnectionContext.Provider>\n}\n\nexport function useConnection(): ConnectionValue {\n const ctx = useContext(ConnectionContext)\n if (!ctx) throw new Error('useConnection must be used within ConnectionProvider')\n return ctx\n}\n\nexport const isAuthenticated = (s: ConnectionStatus) => s === 'demo' || s === 'authenticated'\n"]}