@arbidocs/blocks 0.5.119 → 0.5.120

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 (115) hide show
  1. package/dist/{ConnectedNativeDocxComparison-546ILGLW.cjs → ConnectedNativeDocxComparison-SGE4R3M4.cjs} +6 -6
  2. package/dist/{ConnectedNativeDocxComparison-546ILGLW.cjs.map → ConnectedNativeDocxComparison-SGE4R3M4.cjs.map} +1 -1
  3. package/dist/{ConnectedStreamedWordArtifact-S2ZFZLZQ.cjs → ConnectedStreamedWordArtifact-6MCLJRIT.cjs} +6 -6
  4. package/dist/{ConnectedStreamedWordArtifact-S2ZFZLZQ.cjs.map → ConnectedStreamedWordArtifact-6MCLJRIT.cjs.map} +1 -1
  5. package/dist/{DocumentReviewCard-ZSBZBGFK.cjs → DocumentReviewCard-BPIAJJED.cjs} +14 -14
  6. package/dist/{DocumentReviewCard-ZSBZBGFK.cjs.map → DocumentReviewCard-BPIAJJED.cjs.map} +1 -1
  7. package/dist/{FilesViewerDialog-6UKR5WEF.cjs → FilesViewerDialog-67WK3TZC.cjs} +11 -11
  8. package/dist/{FilesViewerDialog-6UKR5WEF.cjs.map → FilesViewerDialog-67WK3TZC.cjs.map} +1 -1
  9. package/dist/agents/index.cjs +185 -185
  10. package/dist/agents/tasks/ConversationListView.js +10 -2
  11. package/dist/agents/tasks/ConversationListView.js.map +2 -2
  12. package/dist/agents/tasks/TaskTable.js +5 -4
  13. package/dist/agents/tasks/TaskTable.js.map +2 -2
  14. package/dist/agents/tasks/WorkflowsTable.js +4 -5
  15. package/dist/agents/tasks/WorkflowsTable.js.map +2 -2
  16. package/dist/agents/tasks/taskColumns.js +1 -1
  17. package/dist/agents/tasks/taskColumns.js.map +1 -1
  18. package/dist/agents/tasks/taskTableLabels.js +1 -1
  19. package/dist/agents/tasks/taskTableLabels.js.map +1 -1
  20. package/dist/agents/tasks/workflowTableLabels.js +1 -1
  21. package/dist/agents/tasks/workflowTableLabels.js.map +1 -1
  22. package/dist/{chunk-P77YTTJ3.cjs → chunk-3GWWOYGS.cjs} +4 -4
  23. package/dist/{chunk-P77YTTJ3.cjs.map → chunk-3GWWOYGS.cjs.map} +1 -1
  24. package/dist/{chunk-HB2O4THB.cjs → chunk-5IZFSAEZ.cjs} +4 -4
  25. package/dist/{chunk-HB2O4THB.cjs.map → chunk-5IZFSAEZ.cjs.map} +1 -1
  26. package/dist/{chunk-DDIW4HLU.cjs → chunk-775S43W7.cjs} +19 -10
  27. package/dist/chunk-775S43W7.cjs.map +1 -0
  28. package/dist/{chunk-Y24V6HPR.cjs → chunk-BP3IJ34D.cjs} +4 -4
  29. package/dist/{chunk-Y24V6HPR.cjs.map → chunk-BP3IJ34D.cjs.map} +1 -1
  30. package/dist/{chunk-TT4IF52H.cjs → chunk-BUVIBHFU.cjs} +37 -38
  31. package/dist/chunk-BUVIBHFU.cjs.map +1 -0
  32. package/dist/{chunk-OEREKAAP.cjs → chunk-CKCG4NDB.cjs} +8 -8
  33. package/dist/{chunk-OEREKAAP.cjs.map → chunk-CKCG4NDB.cjs.map} +1 -1
  34. package/dist/{chunk-YGXOKB5Z.cjs → chunk-DFBDQKGE.cjs} +4 -4
  35. package/dist/{chunk-YGXOKB5Z.cjs.map → chunk-DFBDQKGE.cjs.map} +1 -1
  36. package/dist/{chunk-VGCTYTEW.cjs → chunk-ECLUFKYR.cjs} +4 -4
  37. package/dist/{chunk-VGCTYTEW.cjs.map → chunk-ECLUFKYR.cjs.map} +1 -1
  38. package/dist/{chunk-CPG7II4E.cjs → chunk-HA66DHW6.cjs} +28 -28
  39. package/dist/{chunk-CPG7II4E.cjs.map → chunk-HA66DHW6.cjs.map} +1 -1
  40. package/dist/{chunk-57NHXEU2.cjs → chunk-MXBXZXXQ.cjs} +5 -5
  41. package/dist/{chunk-57NHXEU2.cjs.map → chunk-MXBXZXXQ.cjs.map} +1 -1
  42. package/dist/{chunk-NNUK5ZM7.cjs → chunk-NLSWDP42.cjs} +9 -17
  43. package/dist/chunk-NLSWDP42.cjs.map +1 -0
  44. package/dist/{chunk-B2HNNG25.cjs → chunk-Q6CLWOP2.cjs} +29 -29
  45. package/dist/{chunk-B2HNNG25.cjs.map → chunk-Q6CLWOP2.cjs.map} +1 -1
  46. package/dist/{chunk-R7CJEIA5.cjs → chunk-QQWHG3KF.cjs} +5 -6
  47. package/dist/chunk-QQWHG3KF.cjs.map +1 -0
  48. package/dist/{chunk-VLCY46K6.cjs → chunk-TG2GM7WJ.cjs} +4 -3
  49. package/dist/chunk-TG2GM7WJ.cjs.map +1 -0
  50. package/dist/{chunk-QHOHDNBU.cjs → chunk-VZCPMXWC.cjs} +4 -4
  51. package/dist/{chunk-QHOHDNBU.cjs.map → chunk-VZCPMXWC.cjs.map} +1 -1
  52. package/dist/{chunk-NIE3N6OM.cjs → chunk-W6INT5GS.cjs} +5 -5
  53. package/dist/{chunk-NIE3N6OM.cjs.map → chunk-W6INT5GS.cjs.map} +1 -1
  54. package/dist/{chunk-ZPPMAL5P.cjs → chunk-WQMR3O2D.cjs} +6 -10
  55. package/dist/chunk-WQMR3O2D.cjs.map +1 -0
  56. package/dist/{chunk-SB4M3ITT.cjs → chunk-X36UR4A7.cjs} +173 -56
  57. package/dist/chunk-X36UR4A7.cjs.map +1 -0
  58. package/dist/{chunk-XKVPSOKP.cjs → chunk-YYSBWMDJ.cjs} +4 -4
  59. package/dist/{chunk-XKVPSOKP.cjs.map → chunk-YYSBWMDJ.cjs.map} +1 -1
  60. package/dist/collaboration/index.cjs +3 -3
  61. package/dist/collaboration/sharing/ShareControl.js +10 -2
  62. package/dist/collaboration/sharing/ShareControl.js.map +2 -2
  63. package/dist/components/SharedCell.d.ts +2 -4
  64. package/dist/components/SharedCell.js +4 -8
  65. package/dist/components/SharedCell.js.map +2 -2
  66. package/dist/connect/docx.cjs +9 -9
  67. package/dist/connect/index.cjs +595 -567
  68. package/dist/connect/index.cjs.map +1 -1
  69. package/dist/connect/viewer.cjs +9 -9
  70. package/dist/connection/facts/factPageColumns.js +3 -9
  71. package/dist/connection/facts/factPageColumns.js.map +2 -2
  72. package/dist/connection/files/grid/cells.js +1 -3
  73. package/dist/connection/files/grid/cells.js.map +2 -2
  74. package/dist/connection/files/grid/documentColumns.js +3 -2
  75. package/dist/connection/files/grid/documentColumns.js.map +2 -2
  76. package/dist/connection/sharing/WorkspaceMembersList.d.ts +4 -0
  77. package/dist/connection/sharing/WorkspaceMembersList.js +34 -0
  78. package/dist/connection/sharing/WorkspaceMembersList.js.map +7 -0
  79. package/dist/connection/shell/ConnectedAppShell.js +4 -0
  80. package/dist/connection/shell/ConnectedAppShell.js.map +2 -2
  81. package/dist/connection/viewer/ConnectedDocumentViewer.js +3 -2
  82. package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
  83. package/dist/connection/viewer/ViewerPdfPane.js +20 -2
  84. package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
  85. package/dist/connection/viewer/pdf/PdfPassageHighlights.d.ts +12 -0
  86. package/dist/connection/viewer/pdf/PdfPassageHighlights.js +36 -0
  87. package/dist/connection/viewer/pdf/PdfPassageHighlights.js.map +7 -0
  88. package/dist/connection/viewer/pdf/passageHighlights.d.ts +26 -0
  89. package/dist/connection/viewer/pdf/passageHighlights.js +40 -0
  90. package/dist/connection/viewer/pdf/passageHighlights.js.map +7 -0
  91. package/dist/connection/viewer/pdf/usePdfPassageHighlights.d.ts +9 -0
  92. package/dist/connection/viewer/pdf/usePdfPassageHighlights.js +47 -0
  93. package/dist/connection/viewer/pdf/usePdfPassageHighlights.js.map +7 -0
  94. package/dist/connection/workflows/workflowsPageLabels.js +1 -1
  95. package/dist/connection/workflows/workflowsPageLabels.js.map +1 -1
  96. package/dist/embed/index.cjs +13 -13
  97. package/dist/facts/factColumns.js +3 -3
  98. package/dist/facts/factColumns.js.map +1 -1
  99. package/dist/facts/index.cjs +42 -42
  100. package/dist/files/HtmlViewerParts.js +7 -15
  101. package/dist/files/HtmlViewerParts.js.map +2 -2
  102. package/dist/files/index.cjs +223 -223
  103. package/dist/index.cjs +238 -238
  104. package/dist/styles.css +1 -1
  105. package/dist/workflow-canvas/index.cjs +24 -24
  106. package/dist/workflow-canvas/index.cjs.map +1 -1
  107. package/node_modules/@arbidocs/coedit/package.json +1 -1
  108. package/package.json +5 -5
  109. package/dist/chunk-DDIW4HLU.cjs.map +0 -1
  110. package/dist/chunk-NNUK5ZM7.cjs.map +0 -1
  111. package/dist/chunk-R7CJEIA5.cjs.map +0 -1
  112. package/dist/chunk-SB4M3ITT.cjs.map +0 -1
  113. package/dist/chunk-TT4IF52H.cjs.map +0 -1
  114. package/dist/chunk-VLCY46K6.cjs.map +0 -1
  115. package/dist/chunk-ZPPMAL5P.cjs.map +0 -1
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { SharingEntity } from "@arbidocs/react/ui";
3
4
  import { useAssistantCopy } from "@arbidocs/react/shell";
4
5
  import { useMemo, useRef, useState } from "react";
5
6
  import { MessageSquare } from "lucide-react";
6
- import { ThreadVisibilityIcon } from "@arbidocs/react/ui";
7
7
  import { ThreadStatusLine } from "./ThreadStatusLine.js";
8
8
  import { EntityChip } from "../../components/EntityChip.js";
9
9
  import { CellHoverIcon } from "../../files/cells/HoverIconCell.js";
@@ -55,10 +55,18 @@ function ConversationListView(p) {
55
55
  minWidth: 200,
56
56
  valueGetter: ({ data }) => data?.title?.trim() || "Untitled thread",
57
57
  cellRenderer: ({ data }) => data && /* @__PURE__ */ jsxs("div", { className: "group flex h-full min-w-0 items-center gap-2", children: [
58
+ /* @__PURE__ */ jsx(
59
+ SharingEntity,
60
+ {
61
+ shared: data.is_shared ?? false,
62
+ variant: "icon",
63
+ "data-testid": `thread-sharing-${data.external_id}`
64
+ }
65
+ ),
58
66
  /* @__PURE__ */ jsx("div", { className: "min-w-0", children: liveProps.current.renderThread ? liveProps.current.renderThread(data) : /* @__PURE__ */ jsx(
59
67
  EntityChip,
60
68
  {
61
- icon: /* @__PURE__ */ jsx(ThreadVisibilityIcon, { shared: data.is_shared ?? false, className: "size-4" }),
69
+ icon: /* @__PURE__ */ jsx(MessageSquare, { className: "size-4", "aria-hidden": true }),
62
70
  label: data.title?.trim() || "Untitled thread",
63
71
  pillTooltip: "Open conversation",
64
72
  labelMaxWidth: "max-w-full",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/agents/tasks/ConversationListView.tsx"],
4
- "sourcesContent": ["import { useAssistantCopy } from '@arbidocs/react/shell'\nimport { useMemo, useRef, useState, type ReactNode } from 'react'\nimport { MessageSquare } from 'lucide-react'\nimport { ThreadVisibilityIcon } from '@arbidocs/react/ui'\nimport { ThreadStatusLine } from './ThreadStatusLine'\nimport { EntityChip } from '../../components/EntityChip'\nimport { CellHoverIcon } from '../../files/cells/HoverIconCell'\nimport type { ColDef, ICellRendererParams, ValueGetterParams } from 'ag-grid-community'\nimport { GridView } from '../../files/GridView'\nimport { SelectionBar } from '../../files/SelectionBar'\nimport { TabHeader } from '../../shell/TabHeader'\nimport { FilterInput } from '../../shell/FilterInput'\nimport { useIsPhone } from '../../lib/use-media-query'\n\n/** Only fields on the conversation object: no message or participant fetches. */\nexport interface ConversationListRow {\n external_id: string\n title?: string | null\n created_at?: string | null\n updated_at?: string | null\n created_by_ext_id?: string | null\n assistant_mode?: string | null\n message_count?: number | null\n is_shared?: boolean | null\n is_owner?: boolean | null\n status?: string | null\n in_progress?: boolean | null\n last_message_role?: string | null\n last_message_updated_at?: string | null\n last_message_actor?: {\n external_id: string\n given_name: string\n family_name?: string | null\n picture?: string | null\n parent_ext_id?: string | null\n } | null\n last_message_status?: string | null\n /** Set when the thread is a call's meeting chat. */\n meeting_call_ext_id?: string | null\n}\n\nexport interface ConversationListViewProps<T extends ConversationListRow> {\n conversations: T[]\n isLoading?: boolean\n visibilityFilters?: { me: 'include' | 'exclude' | null; workspace: 'include' | 'exclude' | null }\n doneFilter?: 'include' | 'exclude' | null\n /** \"Meetings\": only (include) or no (exclude) meeting threads. */\n meetingFilter?: 'include' | 'exclude' | null\n filterText?: string\n /** Below the list: the launcher that starts a new thread from here. */\n footer?: ReactNode\n showHeader?: boolean\n formatDate: (iso: string) => string\n renderThread?: (conversation: T) => ReactNode\n renderBy?: (conversation: T) => ReactNode\n renderStatus?: (conversation: T) => ReactNode\n renderLabels?: (conversation: T) => ReactNode\n labelText?: (conversation: T) => string\n onOpen: (conversation: T) => void\n onRename: (conversation: T) => void\n onDelete: (conversation: T) => void\n canEditShared?: boolean\n isWorkspaceOwner?: boolean\n selectionActions?: (selected: T[], compact: boolean, clear: () => void) => ReactNode\n}\n\n/** Shared title/label filtering and latest-activity ordering for the header and grid. */\nexport function filterConversationRows<T extends ConversationListRow>(\n conversations: T[],\n query: string,\n labelText?: (row: T) => string,\n doneFilter: 'include' | 'exclude' | null = 'exclude',\n visibilityFilters?: { me: 'include' | 'exclude' | null; workspace: 'include' | 'exclude' | null },\n meetingFilter: 'include' | 'exclude' | null = null\n): T[] {\n const q = query.trim().toLowerCase()\n return [...conversations]\n .sort(\n (a, b) =>\n (Date.parse(b.last_message_updated_at || b.updated_at || b.created_at || '') || 0) -\n (Date.parse(a.last_message_updated_at || a.updated_at || a.created_at || '') || 0)\n )\n .filter((row) =>\n doneFilter === 'exclude'\n ? row.status !== 'done'\n : doneFilter === 'include'\n ? row.status === 'done'\n : true\n )\n .filter((row) => {\n const state = row.is_shared ? visibilityFilters?.workspace : visibilityFilters?.me\n const hasIncluded =\n visibilityFilters?.me === 'include' || visibilityFilters?.workspace === 'include'\n return state !== 'exclude' && (!hasIncluded || state === 'include')\n })\n .filter((row) =>\n meetingFilter === 'include'\n ? !!row.meeting_call_ext_id\n : meetingFilter === 'exclude'\n ? !row.meeting_call_ext_id\n : true\n )\n .filter((row) => !q || `${row.title ?? ''} ${labelText?.(row) ?? ''}`.toLowerCase().includes(q))\n}\n\n/** Conversation history ordered by activity, including conversations attached to work. */\nexport function ConversationListView<T extends ConversationListRow>(\n p: ConversationListViewProps<T>\n) {\n const liveProps = useRef(p)\n liveProps.current = p\n const [query, setQuery] = useState('')\n const [selected, setSelected] = useState<Set<string>>(new Set())\n const q = `${query} ${p.filterText ?? ''}`.trim().toLowerCase()\n // On a phone the thread name and labels stay; the other columns are hidden. Labels get a fixed\n // width there so the grid overflows and scrolls sideways instead of squeezing them into the edge.\n const isPhone = useIsPhone()\n const rows = useMemo(\n () =>\n filterConversationRows(\n p.conversations,\n q,\n p.labelText,\n p.doneFilter,\n p.visibilityFilters,\n p.meetingFilter\n ),\n [p.conversations, q, p.labelText, p.doneFilter, p.visibilityFilters, p.meetingFilter]\n )\n const selectedRows = p.conversations.filter((c) => selected.has(c.external_id))\n const hasLabels = p.conversations.some((c) => !!p.labelText?.(c))\n const columns = useMemo<ColDef<T>[]>(\n () => [\n {\n colId: 'name',\n headerName: 'Thread',\n flex: 2,\n minWidth: 200,\n valueGetter: ({ data }) => data?.title?.trim() || 'Untitled thread',\n cellRenderer: ({ data }: ICellRendererParams<T>) =>\n data && (\n <div className=\"group flex h-full min-w-0 items-center gap-2\">\n <div className=\"min-w-0\">\n {liveProps.current.renderThread ? (\n liveProps.current.renderThread(data)\n ) : (\n <EntityChip\n icon={\n <ThreadVisibilityIcon shared={data.is_shared ?? false} className=\"size-4\" />\n }\n label={data.title?.trim() || 'Untitled thread'}\n pillTooltip=\"Open conversation\"\n labelMaxWidth=\"max-w-full\"\n onClick={() => liveProps.current.onOpen(data)}\n testId={`thread-open-${data.external_id}`}\n />\n )}\n </div>\n {/* How long it is, beside its name (not a column of its own). */}\n {(data.message_count ?? 0) > 0 && (\n <span\n className=\"inline-flex h-5 shrink-0 items-center gap-0.5 self-center rounded-full bg-muted px-1.5 text-[10px] font-medium leading-none tabular-nums text-muted-foreground\"\n title={`${data.message_count} ${data.message_count === 1 ? 'message' : 'messages'}`}\n data-testid={`thread-messages-${data.external_id}`}\n >\n <MessageSquare className=\"size-3\" aria-hidden />\n {data.message_count}\n </span>\n )}\n {(data.is_owner !== false || liveProps.current.canEditShared) && (\n <button\n type=\"button\"\n aria-label={`Rename ${data.title?.trim() || 'Untitled thread'}`}\n onClick={() => liveProps.current.onRename(data)}\n data-testid={`thread-rename-${data.external_id}`}\n className=\"shrink-0 pointer-coarse:flex pointer-coarse:size-11 pointer-coarse:items-center pointer-coarse:justify-center\"\n >\n <CellHoverIcon />\n </button>\n )}\n </div>\n ),\n },\n // Labels only when a thread has some (an empty column only takes the names' room), and never\n // on a phone, where the status is what a row must say.\n ...(liveProps.current.renderLabels && hasLabels && !isPhone\n ? [\n {\n colId: 'labels',\n headerName: 'Labels',\n flex: 0.5,\n minWidth: 100,\n valueGetter: ({ data }: ValueGetterParams<T>) =>\n data ? (liveProps.current.labelText?.(data) ?? '') : '',\n cellRenderer: ({ data }: ICellRendererParams<T>) =>\n data && liveProps.current.renderLabels?.(data),\n },\n ]\n : []),\n {\n colId: 'status',\n headerName: 'Status',\n width: isPhone ? 170 : 240,\n valueGetter: ({ data }) => data?.status,\n cellRenderer: ({ data }: ICellRendererParams<T>) =>\n data &&\n (liveProps.current.renderStatus ? (\n liveProps.current.renderStatus(data)\n ) : (\n <ThreadStatusLine\n state={data.status === 'done' ? 'done' : data.status === 'todo' ? 'todo' : 'ready'}\n />\n )),\n },\n // Who spoke last (their face) and when: the two read together, at the row's end.\n ...(liveProps.current.renderBy\n ? [\n {\n colId: 'by',\n headerName: 'By',\n width: 64,\n hide: isPhone,\n sortable: false,\n resizable: false,\n cellRenderer: ({ data }: ICellRendererParams<T>) =>\n data && liveProps.current.renderBy?.(data),\n },\n ]\n : []),\n {\n colId: 'activity',\n initialSort: 'desc',\n headerName: 'Updated',\n width: 128,\n hide: isPhone,\n valueGetter: ({ data }) =>\n data?.last_message_updated_at || data?.updated_at || data?.created_at || '',\n valueFormatter: ({ value }) => (value ? liveProps.current.formatDate(value) : '\u2014'),\n cellClass: 'flex items-center text-xs text-muted-foreground/80',\n },\n ],\n [\n Boolean(p.renderThread),\n Boolean(p.renderLabels),\n Boolean(p.renderBy),\n Boolean(p.renderStatus),\n isPhone,\n hasLabels,\n ]\n )\n // Every cell's content sits in the middle of its row (a two-line title makes rows taller).\n const assistant = useAssistantCopy()\n const centred = useMemo(\n () => columns.map((c) => ({ cellClass: 'flex items-center', ...c })),\n [columns]\n )\n return (\n <div className=\"flex min-h-0 flex-1 flex-col\" data-testid=\"conversation-list-view\">\n {p.showHeader !== false && (\n <TabHeader\n testId=\"threads-tab-header\"\n tabs={[\n {\n id: 'threads',\n label: '',\n count: rows.length,\n countIcon: <MessageSquare className=\"size-3.5\" />,\n countPlacement: 'leading',\n presentation: 'count',\n hasActiveFilters: !!q,\n },\n ]}\n activeTabId=\"threads\"\n onTabChange={() => {}}\n firstTabContent={\n <FilterInput\n value={query}\n hideFieldPicker\n ariaLabel=\"Search threads\"\n onChange={setQuery}\n fields={['text']}\n onFieldsChange={() => {}}\n labels={{\n placeholder: 'Find a thread\u2026',\n fieldNames: { text: 'Thread' },\n }}\n className=\"w-44 max-w-[40vw]\"\n />\n }\n />\n )}\n <div className=\"min-h-0 flex-1\">\n <GridView<T>\n testId=\"threads-grid\"\n items={rows}\n columnDefs={centred}\n getItemId={(row) => row.external_id}\n getRowTestId={(row) => `thread-row-${row.external_id}`}\n onRowClick={p.onOpen}\n height=\"100%\"\n isLoading={p.isLoading}\n loadingMessage=\"Loading threads\u2026\"\n emptyState={{\n title: q ? 'No threads match' : 'No conversations yet',\n message: p.footer ? assistant.emptyThreadsComposer : assistant.emptyThreadsNewTask,\n }}\n selection={\n p.selectionActions\n ? {\n mode: 'multiple',\n controlled: true,\n selected: selectedRows,\n onSelectionChange: (items) =>\n setSelected(new Set(items.map((item) => item.external_id))),\n }\n : undefined\n }\n gridOptions={{\n suppressClickEdit: true,\n onCellKeyDown: (event) => {\n if (\n (event.event as KeyboardEvent | undefined)?.key === 'Enter' &&\n 'column' in event &&\n event.column.getColId() === 'name' &&\n event.data\n )\n p.onOpen(event.data)\n },\n }}\n />\n </div>\n {p.footer}\n {/* Above the footer's composer dock (z-40), which sits in the same place. */}\n {p.selectionActions && (\n <SelectionBar\n className=\"z-50\"\n count={selectedRows.length}\n onClear={() => setSelected(new Set())}\n >\n {(compact) => p.selectionActions?.(selectedRows, compact, () => setSelected(new Set()))}\n </SelectionBar>\n )}\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { SharingEntity } from '@arbidocs/react/ui'\nimport { useAssistantCopy } from '@arbidocs/react/shell'\nimport { useMemo, useRef, useState, type ReactNode } from 'react'\nimport { MessageSquare } from 'lucide-react'\nimport { ThreadStatusLine } from './ThreadStatusLine'\nimport { EntityChip } from '../../components/EntityChip'\nimport { CellHoverIcon } from '../../files/cells/HoverIconCell'\nimport type { ColDef, ICellRendererParams, ValueGetterParams } from 'ag-grid-community'\nimport { GridView } from '../../files/GridView'\nimport { SelectionBar } from '../../files/SelectionBar'\nimport { TabHeader } from '../../shell/TabHeader'\nimport { FilterInput } from '../../shell/FilterInput'\nimport { useIsPhone } from '../../lib/use-media-query'\n\n/** Only fields on the conversation object: no message or participant fetches. */\nexport interface ConversationListRow {\n external_id: string\n title?: string | null\n created_at?: string | null\n updated_at?: string | null\n created_by_ext_id?: string | null\n assistant_mode?: string | null\n message_count?: number | null\n is_shared?: boolean | null\n is_owner?: boolean | null\n status?: string | null\n in_progress?: boolean | null\n last_message_role?: string | null\n last_message_updated_at?: string | null\n last_message_actor?: {\n external_id: string\n given_name: string\n family_name?: string | null\n picture?: string | null\n parent_ext_id?: string | null\n } | null\n last_message_status?: string | null\n /** Set when the thread is a call's meeting chat. */\n meeting_call_ext_id?: string | null\n}\n\nexport interface ConversationListViewProps<T extends ConversationListRow> {\n conversations: T[]\n isLoading?: boolean\n visibilityFilters?: { me: 'include' | 'exclude' | null; workspace: 'include' | 'exclude' | null }\n doneFilter?: 'include' | 'exclude' | null\n /** \"Meetings\": only (include) or no (exclude) meeting threads. */\n meetingFilter?: 'include' | 'exclude' | null\n filterText?: string\n /** Below the list: the launcher that starts a new thread from here. */\n footer?: ReactNode\n showHeader?: boolean\n formatDate: (iso: string) => string\n renderThread?: (conversation: T) => ReactNode\n renderBy?: (conversation: T) => ReactNode\n renderStatus?: (conversation: T) => ReactNode\n renderLabels?: (conversation: T) => ReactNode\n labelText?: (conversation: T) => string\n onOpen: (conversation: T) => void\n onRename: (conversation: T) => void\n onDelete: (conversation: T) => void\n canEditShared?: boolean\n isWorkspaceOwner?: boolean\n selectionActions?: (selected: T[], compact: boolean, clear: () => void) => ReactNode\n}\n\n/** Shared title/label filtering and latest-activity ordering for the header and grid. */\nexport function filterConversationRows<T extends ConversationListRow>(\n conversations: T[],\n query: string,\n labelText?: (row: T) => string,\n doneFilter: 'include' | 'exclude' | null = 'exclude',\n visibilityFilters?: { me: 'include' | 'exclude' | null; workspace: 'include' | 'exclude' | null },\n meetingFilter: 'include' | 'exclude' | null = null\n): T[] {\n const q = query.trim().toLowerCase()\n return [...conversations]\n .sort(\n (a, b) =>\n (Date.parse(b.last_message_updated_at || b.updated_at || b.created_at || '') || 0) -\n (Date.parse(a.last_message_updated_at || a.updated_at || a.created_at || '') || 0)\n )\n .filter((row) =>\n doneFilter === 'exclude'\n ? row.status !== 'done'\n : doneFilter === 'include'\n ? row.status === 'done'\n : true\n )\n .filter((row) => {\n const state = row.is_shared ? visibilityFilters?.workspace : visibilityFilters?.me\n const hasIncluded =\n visibilityFilters?.me === 'include' || visibilityFilters?.workspace === 'include'\n return state !== 'exclude' && (!hasIncluded || state === 'include')\n })\n .filter((row) =>\n meetingFilter === 'include'\n ? !!row.meeting_call_ext_id\n : meetingFilter === 'exclude'\n ? !row.meeting_call_ext_id\n : true\n )\n .filter((row) => !q || `${row.title ?? ''} ${labelText?.(row) ?? ''}`.toLowerCase().includes(q))\n}\n\n/** Conversation history ordered by activity, including conversations attached to work. */\nexport function ConversationListView<T extends ConversationListRow>(\n p: ConversationListViewProps<T>\n) {\n const liveProps = useRef(p)\n liveProps.current = p\n const [query, setQuery] = useState('')\n const [selected, setSelected] = useState<Set<string>>(new Set())\n const q = `${query} ${p.filterText ?? ''}`.trim().toLowerCase()\n // On a phone the thread name and labels stay; the other columns are hidden. Labels get a fixed\n // width there so the grid overflows and scrolls sideways instead of squeezing them into the edge.\n const isPhone = useIsPhone()\n const rows = useMemo(\n () =>\n filterConversationRows(\n p.conversations,\n q,\n p.labelText,\n p.doneFilter,\n p.visibilityFilters,\n p.meetingFilter\n ),\n [p.conversations, q, p.labelText, p.doneFilter, p.visibilityFilters, p.meetingFilter]\n )\n const selectedRows = p.conversations.filter((c) => selected.has(c.external_id))\n const hasLabels = p.conversations.some((c) => !!p.labelText?.(c))\n const columns = useMemo<ColDef<T>[]>(\n () => [\n {\n colId: 'name',\n headerName: 'Thread',\n flex: 2,\n minWidth: 200,\n valueGetter: ({ data }) => data?.title?.trim() || 'Untitled thread',\n cellRenderer: ({ data }: ICellRendererParams<T>) =>\n data && (\n <div className=\"group flex h-full min-w-0 items-center gap-2\">\n <SharingEntity\n shared={data.is_shared ?? false}\n variant=\"icon\"\n data-testid={`thread-sharing-${data.external_id}`}\n />\n <div className=\"min-w-0\">\n {liveProps.current.renderThread ? (\n liveProps.current.renderThread(data)\n ) : (\n <EntityChip\n icon={<MessageSquare className=\"size-4\" aria-hidden />}\n label={data.title?.trim() || 'Untitled thread'}\n pillTooltip=\"Open conversation\"\n labelMaxWidth=\"max-w-full\"\n onClick={() => liveProps.current.onOpen(data)}\n testId={`thread-open-${data.external_id}`}\n />\n )}\n </div>\n {/* How long it is, beside its name (not a column of its own). */}\n {(data.message_count ?? 0) > 0 && (\n <span\n className=\"inline-flex h-5 shrink-0 items-center gap-0.5 self-center rounded-full bg-muted px-1.5 text-[10px] font-medium leading-none tabular-nums text-muted-foreground\"\n title={`${data.message_count} ${data.message_count === 1 ? 'message' : 'messages'}`}\n data-testid={`thread-messages-${data.external_id}`}\n >\n <MessageSquare className=\"size-3\" aria-hidden />\n {data.message_count}\n </span>\n )}\n {(data.is_owner !== false || liveProps.current.canEditShared) && (\n <button\n type=\"button\"\n aria-label={`Rename ${data.title?.trim() || 'Untitled thread'}`}\n onClick={() => liveProps.current.onRename(data)}\n data-testid={`thread-rename-${data.external_id}`}\n className=\"shrink-0 pointer-coarse:flex pointer-coarse:size-11 pointer-coarse:items-center pointer-coarse:justify-center\"\n >\n <CellHoverIcon />\n </button>\n )}\n </div>\n ),\n },\n // Labels only when a thread has some (an empty column only takes the names' room), and never\n // on a phone, where the status is what a row must say.\n ...(liveProps.current.renderLabels && hasLabels && !isPhone\n ? [\n {\n colId: 'labels',\n headerName: 'Labels',\n flex: 0.5,\n minWidth: 100,\n valueGetter: ({ data }: ValueGetterParams<T>) =>\n data ? (liveProps.current.labelText?.(data) ?? '') : '',\n cellRenderer: ({ data }: ICellRendererParams<T>) =>\n data && liveProps.current.renderLabels?.(data),\n },\n ]\n : []),\n {\n colId: 'status',\n headerName: 'Status',\n width: isPhone ? 170 : 240,\n valueGetter: ({ data }) => data?.status,\n cellRenderer: ({ data }: ICellRendererParams<T>) =>\n data &&\n (liveProps.current.renderStatus ? (\n liveProps.current.renderStatus(data)\n ) : (\n <ThreadStatusLine\n state={data.status === 'done' ? 'done' : data.status === 'todo' ? 'todo' : 'ready'}\n />\n )),\n },\n // Who spoke last (their face) and when: the two read together, at the row's end.\n ...(liveProps.current.renderBy\n ? [\n {\n colId: 'by',\n headerName: 'By',\n width: 64,\n hide: isPhone,\n sortable: false,\n resizable: false,\n cellRenderer: ({ data }: ICellRendererParams<T>) =>\n data && liveProps.current.renderBy?.(data),\n },\n ]\n : []),\n {\n colId: 'activity',\n initialSort: 'desc',\n headerName: 'Updated',\n width: 128,\n hide: isPhone,\n valueGetter: ({ data }) =>\n data?.last_message_updated_at || data?.updated_at || data?.created_at || '',\n valueFormatter: ({ value }) => (value ? liveProps.current.formatDate(value) : '\u2014'),\n cellClass: 'flex items-center text-xs text-muted-foreground/80',\n },\n ],\n [\n Boolean(p.renderThread),\n Boolean(p.renderLabels),\n Boolean(p.renderBy),\n Boolean(p.renderStatus),\n isPhone,\n hasLabels,\n ]\n )\n // Every cell's content sits in the middle of its row (a two-line title makes rows taller).\n const assistant = useAssistantCopy()\n const centred = useMemo(\n () => columns.map((c) => ({ cellClass: 'flex items-center', ...c })),\n [columns]\n )\n return (\n <div className=\"flex min-h-0 flex-1 flex-col\" data-testid=\"conversation-list-view\">\n {p.showHeader !== false && (\n <TabHeader\n testId=\"threads-tab-header\"\n tabs={[\n {\n id: 'threads',\n label: '',\n count: rows.length,\n countIcon: <MessageSquare className=\"size-3.5\" />,\n countPlacement: 'leading',\n presentation: 'count',\n hasActiveFilters: !!q,\n },\n ]}\n activeTabId=\"threads\"\n onTabChange={() => {}}\n firstTabContent={\n <FilterInput\n value={query}\n hideFieldPicker\n ariaLabel=\"Search threads\"\n onChange={setQuery}\n fields={['text']}\n onFieldsChange={() => {}}\n labels={{\n placeholder: 'Find a thread\u2026',\n fieldNames: { text: 'Thread' },\n }}\n className=\"w-44 max-w-[40vw]\"\n />\n }\n />\n )}\n <div className=\"min-h-0 flex-1\">\n <GridView<T>\n testId=\"threads-grid\"\n items={rows}\n columnDefs={centred}\n getItemId={(row) => row.external_id}\n getRowTestId={(row) => `thread-row-${row.external_id}`}\n onRowClick={p.onOpen}\n height=\"100%\"\n isLoading={p.isLoading}\n loadingMessage=\"Loading threads\u2026\"\n emptyState={{\n title: q ? 'No threads match' : 'No conversations yet',\n message: p.footer ? assistant.emptyThreadsComposer : assistant.emptyThreadsNewTask,\n }}\n selection={\n p.selectionActions\n ? {\n mode: 'multiple',\n controlled: true,\n selected: selectedRows,\n onSelectionChange: (items) =>\n setSelected(new Set(items.map((item) => item.external_id))),\n }\n : undefined\n }\n gridOptions={{\n suppressClickEdit: true,\n onCellKeyDown: (event) => {\n if (\n (event.event as KeyboardEvent | undefined)?.key === 'Enter' &&\n 'column' in event &&\n event.column.getColId() === 'name' &&\n event.data\n )\n p.onOpen(event.data)\n },\n }}\n />\n </div>\n {p.footer}\n {/* Above the footer's composer dock (z-40), which sits in the same place. */}\n {p.selectionActions && (\n <SelectionBar\n className=\"z-50\"\n count={selectedRows.length}\n onClear={() => setSelected(new Set())}\n >\n {(compact) => p.selectionActions?.(selectedRows, compact, () => setSelected(new Set()))}\n </SelectionBar>\n )}\n </div>\n )\n}\n"],
5
+ "mappings": ";AA8Ic,cAqBE,YArBF;AA9Id,SAAS,qBAAqB;AAC9B,SAAS,wBAAwB;AACjC,SAAS,SAAS,QAAQ,gBAAgC;AAC1D,SAAS,qBAAqB;AAC9B,SAAS,wBAAwB;AACjC,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AAE9B,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAuDpB,SAAS,uBACd,eACA,OACA,WACA,aAA2C,WAC3C,mBACA,gBAA8C,MACzC;AACL,QAAM,IAAI,MAAM,KAAK,EAAE,YAAY;AACnC,SAAO,CAAC,GAAG,aAAa,EACrB;AAAA,IACC,CAAC,GAAG,OACD,KAAK,MAAM,EAAE,2BAA2B,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,MAC/E,KAAK,MAAM,EAAE,2BAA2B,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK;AAAA,EACpF,EACC;AAAA,IAAO,CAAC,QACP,eAAe,YACX,IAAI,WAAW,SACf,eAAe,YACb,IAAI,WAAW,SACf;AAAA,EACR,EACC,OAAO,CAAC,QAAQ;AACf,UAAM,QAAQ,IAAI,YAAY,mBAAmB,YAAY,mBAAmB;AAChF,UAAM,cACJ,mBAAmB,OAAO,aAAa,mBAAmB,cAAc;AAC1E,WAAO,UAAU,cAAc,CAAC,eAAe,UAAU;AAAA,EAC3D,CAAC,EACA;AAAA,IAAO,CAAC,QACP,kBAAkB,YACd,CAAC,CAAC,IAAI,sBACN,kBAAkB,YAChB,CAAC,IAAI,sBACL;AAAA,EACR,EACC,OAAO,CAAC,QAAQ,CAAC,KAAK,GAAG,IAAI,SAAS,EAAE,IAAI,YAAY,GAAG,KAAK,EAAE,GAAG,YAAY,EAAE,SAAS,CAAC,CAAC;AACnG;AAGO,SAAS,qBACd,GACA;AACA,QAAM,YAAY,OAAO,CAAC;AAC1B,YAAU,UAAU;AACpB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,UAAU,WAAW,IAAI,SAAsB,oBAAI,IAAI,CAAC;AAC/D,QAAM,IAAI,GAAG,KAAK,IAAI,EAAE,cAAc,EAAE,GAAG,KAAK,EAAE,YAAY;AAG9D,QAAM,UAAU,WAAW;AAC3B,QAAM,OAAO;AAAA,IACX,MACE;AAAA,MACE,EAAE;AAAA,MACF;AAAA,MACA,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,IACJ;AAAA,IACF,CAAC,EAAE,eAAe,GAAG,EAAE,WAAW,EAAE,YAAY,EAAE,mBAAmB,EAAE,aAAa;AAAA,EACtF;AACA,QAAM,eAAe,EAAE,cAAc,OAAO,CAAC,MAAM,SAAS,IAAI,EAAE,WAAW,CAAC;AAC9E,QAAM,YAAY,EAAE,cAAc,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;AAChE,QAAM,UAAU;AAAA,IACd,MAAM;AAAA,MACJ;AAAA,QACE,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,aAAa,CAAC,EAAE,KAAK,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA,QAClD,cAAc,CAAC,EAAE,KAAK,MACpB,QACE,qBAAC,SAAI,WAAU,gDACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,QAAQ,KAAK,aAAa;AAAA,cAC1B,SAAQ;AAAA,cACR,eAAa,kBAAkB,KAAK,WAAW;AAAA;AAAA,UACjD;AAAA,UACA,oBAAC,SAAI,WAAU,WACZ,oBAAU,QAAQ,eACjB,UAAU,QAAQ,aAAa,IAAI,IAEnC;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,oBAAC,iBAAc,WAAU,UAAS,eAAW,MAAC;AAAA,cACpD,OAAO,KAAK,OAAO,KAAK,KAAK;AAAA,cAC7B,aAAY;AAAA,cACZ,eAAc;AAAA,cACd,SAAS,MAAM,UAAU,QAAQ,OAAO,IAAI;AAAA,cAC5C,QAAQ,eAAe,KAAK,WAAW;AAAA;AAAA,UACzC,GAEJ;AAAA,WAEE,KAAK,iBAAiB,KAAK,KAC3B;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO,GAAG,KAAK,aAAa,IAAI,KAAK,kBAAkB,IAAI,YAAY,UAAU;AAAA,cACjF,eAAa,mBAAmB,KAAK,WAAW;AAAA,cAEhD;AAAA,oCAAC,iBAAc,WAAU,UAAS,eAAW,MAAC;AAAA,gBAC7C,KAAK;AAAA;AAAA;AAAA,UACR;AAAA,WAEA,KAAK,aAAa,SAAS,UAAU,QAAQ,kBAC7C;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY,UAAU,KAAK,OAAO,KAAK,KAAK,iBAAiB;AAAA,cAC7D,SAAS,MAAM,UAAU,QAAQ,SAAS,IAAI;AAAA,cAC9C,eAAa,iBAAiB,KAAK,WAAW;AAAA,cAC9C,WAAU;AAAA,cAEV,8BAAC,iBAAc;AAAA;AAAA,UACjB;AAAA,WAEJ;AAAA,MAEN;AAAA;AAAA;AAAA,MAGA,GAAI,UAAU,QAAQ,gBAAgB,aAAa,CAAC,UAChD;AAAA,QACE;AAAA,UACE,OAAO;AAAA,UACP,YAAY;AAAA,UACZ,MAAM;AAAA,UACN,UAAU;AAAA,UACV,aAAa,CAAC,EAAE,KAAK,MACnB,OAAQ,UAAU,QAAQ,YAAY,IAAI,KAAK,KAAM;AAAA,UACvD,cAAc,CAAC,EAAE,KAAK,MACpB,QAAQ,UAAU,QAAQ,eAAe,IAAI;AAAA,QACjD;AAAA,MACF,IACA,CAAC;AAAA,MACL;AAAA,QACE,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,OAAO,UAAU,MAAM;AAAA,QACvB,aAAa,CAAC,EAAE,KAAK,MAAM,MAAM;AAAA,QACjC,cAAc,CAAC,EAAE,KAAK,MACpB,SACC,UAAU,QAAQ,eACjB,UAAU,QAAQ,aAAa,IAAI,IAEnC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,KAAK,WAAW,SAAS,SAAS,KAAK,WAAW,SAAS,SAAS;AAAA;AAAA,QAC7E;AAAA,MAEN;AAAA;AAAA,MAEA,GAAI,UAAU,QAAQ,WAClB;AAAA,QACE;AAAA,UACE,OAAO;AAAA,UACP,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAW;AAAA,UACX,cAAc,CAAC,EAAE,KAAK,MACpB,QAAQ,UAAU,QAAQ,WAAW,IAAI;AAAA,QAC7C;AAAA,MACF,IACA,CAAC;AAAA,MACL;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,aAAa,CAAC,EAAE,KAAK,MACnB,MAAM,2BAA2B,MAAM,cAAc,MAAM,cAAc;AAAA,QAC3E,gBAAgB,CAAC,EAAE,MAAM,MAAO,QAAQ,UAAU,QAAQ,WAAW,KAAK,IAAI;AAAA,QAC9E,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA;AAAA,MACE,QAAQ,EAAE,YAAY;AAAA,MACtB,QAAQ,EAAE,YAAY;AAAA,MACtB,QAAQ,EAAE,QAAQ;AAAA,MAClB,QAAQ,EAAE,YAAY;AAAA,MACtB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,iBAAiB;AACnC,QAAM,UAAU;AAAA,IACd,MAAM,QAAQ,IAAI,CAAC,OAAO,EAAE,WAAW,qBAAqB,GAAG,EAAE,EAAE;AAAA,IACnE,CAAC,OAAO;AAAA,EACV;AACA,SACE,qBAAC,SAAI,WAAU,gCAA+B,eAAY,0BACvD;AAAA,MAAE,eAAe,SAChB;AAAA,MAAC;AAAA;AAAA,QACC,QAAO;AAAA,QACP,MAAM;AAAA,UACJ;AAAA,YACE,IAAI;AAAA,YACJ,OAAO;AAAA,YACP,OAAO,KAAK;AAAA,YACZ,WAAW,oBAAC,iBAAc,WAAU,YAAW;AAAA,YAC/C,gBAAgB;AAAA,YAChB,cAAc;AAAA,YACd,kBAAkB,CAAC,CAAC;AAAA,UACtB;AAAA,QACF;AAAA,QACA,aAAY;AAAA,QACZ,aAAa,MAAM;AAAA,QAAC;AAAA,QACpB,iBACE;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP,iBAAe;AAAA,YACf,WAAU;AAAA,YACV,UAAU;AAAA,YACV,QAAQ,CAAC,MAAM;AAAA,YACf,gBAAgB,MAAM;AAAA,YAAC;AAAA,YACvB,QAAQ;AAAA,cACN,aAAa;AAAA,cACb,YAAY,EAAE,MAAM,SAAS;AAAA,YAC/B;AAAA,YACA,WAAU;AAAA;AAAA,QACZ;AAAA;AAAA,IAEJ;AAAA,IAEF,oBAAC,SAAI,WAAU,kBACb;AAAA,MAAC;AAAA;AAAA,QACC,QAAO;AAAA,QACP,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,WAAW,CAAC,QAAQ,IAAI;AAAA,QACxB,cAAc,CAAC,QAAQ,cAAc,IAAI,WAAW;AAAA,QACpD,YAAY,EAAE;AAAA,QACd,QAAO;AAAA,QACP,WAAW,EAAE;AAAA,QACb,gBAAe;AAAA,QACf,YAAY;AAAA,UACV,OAAO,IAAI,qBAAqB;AAAA,UAChC,SAAS,EAAE,SAAS,UAAU,uBAAuB,UAAU;AAAA,QACjE;AAAA,QACA,WACE,EAAE,mBACE;AAAA,UACE,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,mBAAmB,CAAC,UAClB,YAAY,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,WAAW,CAAC,CAAC;AAAA,QAC9D,IACA;AAAA,QAEN,aAAa;AAAA,UACX,mBAAmB;AAAA,UACnB,eAAe,CAAC,UAAU;AACxB,gBACG,MAAM,OAAqC,QAAQ,WACpD,YAAY,SACZ,MAAM,OAAO,SAAS,MAAM,UAC5B,MAAM;AAEN,gBAAE,OAAO,MAAM,IAAI;AAAA,UACvB;AAAA,QACF;AAAA;AAAA,IACF,GACF;AAAA,IACC,EAAE;AAAA,IAEF,EAAE,oBACD;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO,aAAa;AAAA,QACpB,SAAS,MAAM,YAAY,oBAAI,IAAI,CAAC;AAAA,QAEnC,WAAC,YAAY,EAAE,mBAAmB,cAAc,SAAS,MAAM,YAAY,oBAAI,IAAI,CAAC,CAAC;AAAA;AAAA,IACxF;AAAA,KAEJ;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -12,7 +12,7 @@ import {
12
12
  Trash2,
13
13
  Workflow
14
14
  } from "lucide-react";
15
- import { Button, Input, VisibilityToggle, cn } from "@arbidocs/react/ui";
15
+ import { Button, Input, cn, SharingEntity } from "@arbidocs/react/ui";
16
16
  import { EmptyState } from "../../components/EmptyState.js";
17
17
  import { ToneBadge } from "../../components/ToneBadge.js";
18
18
  import { GridView } from "../../files/GridView.js";
@@ -350,13 +350,14 @@ function TaskTable(props) {
350
350
  const { task } = row;
351
351
  if (!p.onToggleShared) return null;
352
352
  return /* @__PURE__ */ jsx(
353
- VisibilityToggle,
353
+ SharingEntity,
354
354
  {
355
- items: { shared: task.is_shared ?? false },
355
+ shared: task.is_shared ?? false,
356
356
  onToggle: (shouldShare) => latest.current.props.onToggleShared?.(task, shouldShare),
357
357
  disabled: task.is_owner === false,
358
358
  disabledTooltip: lb.sharedOwnerOnly,
359
- showLabel: false,
359
+ tooltipActive: "Shared with this workspace \u2014 click to make private",
360
+ tooltipInactive: "Only you can see this \u2014 click to share with this workspace",
360
361
  "data-testid": `task-shared-${task.external_id}`
361
362
  }
362
363
  );
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/agents/tasks/TaskTable.tsx"],
4
- "sourcesContent": ["import { useEffect, useMemo, useRef, useState } from 'react'\nimport type { CellKeyDownEvent, GridApi, GridOptions } from 'ag-grid-community'\nimport {\n ChevronDown,\n ChevronRight,\n ChevronsDownUp,\n ChevronsUpDown,\n CheckCheck,\n KeyRound,\n ListTodo,\n Trash2,\n Workflow,\n} from 'lucide-react'\nimport { Button, Input, VisibilityToggle, cn } from '@arbidocs/react/ui'\nimport { EmptyState } from '../../components/EmptyState'\nimport { ToneBadge } from '../../components/ToneBadge'\nimport { GridView } from '../../files/GridView'\nimport { SelectionBar, SelectionBarAction } from '../../files/SelectionBar'\nimport { testIdOr } from '../../chat/test-id'\nimport { PersonPill, type TaskPerson } from './PersonPill'\nimport { TaskOutputsCell, type TaskOutput, type TaskOutputsCellLabels } from './TaskOutputsCell'\nimport { TaskMoveDialog } from './TaskMoveDialog'\nimport { TaskRowMenu } from './TaskRowMenu'\nimport {\n DEFAULT_TASK_STATUS_PILL_LABELS,\n TaskStatusPill,\n type TaskStatusPillLabels,\n} from './TaskStatusPill'\nimport { createTaskColumns, type SortableTaskColumn } from './taskColumns'\nimport { applyColumnWidthRules, type ColumnWidthRule } from './gridWidth'\nimport { STATUS_LABELS, STATUS_ORDER, asTaskStatus, goalProgress } from './taskLabels'\nimport {\n buildTaskRows,\n ownerExtId,\n descendantIds,\n indexTasks,\n isPlainTodo,\n moveTargets,\n type TaskFilter,\n type TaskGridRow,\n type TaskListRow,\n} from './taskRows'\nimport { DEFAULT_TASK_LIST_LABELS, type TaskListLabels } from './taskTableLabels'\n\nexport interface TaskTableProps<T extends TaskListRow> {\n /** The workspace's tasks: the conversations that have a status (the host drops plain chats). */\n tasks: T[]\n isLoading?: boolean\n /** Friendly display of an ISO timestamp. */\n formatDate: (iso: string) => string\n /** Open the task's thread (its conversation). */\n onOpenThread: (conversationId: string, task: T) => void\n /** A person marks a task done / reopens a finished one. */\n onMarkDone: (task: T) => void\n onReopen: (task: T) => void\n /** People in the workspace, by id: names the Owner column. */\n people?: { id: string; label: string }[]\n /** Agent names by id, for the Assigned to column (falls back to \"Agent\"). */\n agentNames?: Record<string, string>\n /** Workflow names by id: names a task whose title the run has not generated yet, and its origin chip. */\n workflowNames?: Record<string, string>\n /** Share a task with the workspace or make it private (the shared/private toggle appears with it). */\n onToggleShared?: (task: T, shouldShare: boolean) => void\n onEdit: (task: T) => void\n onDelete: (task: T) => void\n /** Start a new task that is a child of this one. */\n onAddSubtask?: (task: T) => void\n /** Re-parent a task (`null` = top level). With it, the row menu offers \"Move to\u2026\". */\n onMove?: (task: T, parentId: string | null) => void\n /** Bulk actions on the selected rows (the selection bar shows only the ones provided). */\n onMarkDoneMany?: (tasks: T[]) => void\n onDeleteMany?: (tasks: T[]) => void\n /** When set, a run waiting for access shows a one-click \"allow access\" action. */\n onGrantAccess?: (task: T) => void\n /** Task id with a request in flight: its row disables its actions. */\n busyId?: string | null\n /** Text from outside the table (a topbar filter) that narrows the rows like the search box does. */\n filterText?: string\n /**\n * The viewer edits the workspace (owner or collaborator): a row they do not own is always shared, and\n * they may then edit, run, move, mark done and add sub-tasks to it. The share toggle, Delete and Allow\n * access stay with the row's owner. A guest leaves this off and only reads.\n */\n canEditShared?: boolean\n /** The viewer owns the workspace: with a row's creator, the only one who deletes it. Who can see it stays the creator's alone. */\n isWorkspaceOwner?: boolean\n /** Saved column state key (AG Grid persists by it). */\n gridId?: string\n labels?: Partial<TaskListLabels>\n testId?: string\n statusPillLabels?: Partial<TaskStatusPillLabels>\n /** Generated documents per task id (latest versions only); a task with none shows a dash. */\n outputsByTask?: Record<string, readonly TaskOutput[]>\n /** Open one generated document (Tasks view's Outputs column). */\n onOpenOutput?: (documentId: string, task: T) => void\n outputsLabels?: Partial<TaskOutputsCellLabels>\n /** Open a task's activity timeline (row menu: \"Activity\"). */\n onOpenActivity?: (task: T) => void\n /** \"2 min ago\" for the status tooltip; without it the tooltip is left out. */\n formatRelative?: (iso: string) => string\n}\n\nconst ROW_HEIGHT = 56\n/** Taller on a phone, where the status sits under the title. */\nconst NARROW_ROW_HEIGHT = 76\n/** Sub-tasks stop indenting after this depth (the table stays readable at any nesting). */\nconst MAX_INDENT_DEPTH = 4\n/** Above this many rows the grid stops animating row changes. */\nconst ANIMATE_ROWS_UP_TO = 500\n\n/** Below this grid width the table is one column and a menu. */\nconst NARROW_GRID = 640\n\n/** What goes first as the grid narrows (the grid is the page minus the sidebar). */\nconst WIDTH_RULES: readonly ColumnWidthRule[] = [\n { colId: 'shared', minWidth: 1050 },\n { colId: 'due', minWidth: 850 },\n { colId: 'outputs', minWidth: 930 },\n { colId: 'owner', minWidth: 730 },\n { colId: 'status', minWidth: NARROW_GRID },\n]\n\ntype Row<T extends TaskListRow> = TaskGridRow<T>\n\n/** The tooltip on the status pill: the latest step and how long ago. */\nfunction statusHint<T extends TaskListRow>(\n task: T,\n ctx: {\n props: TaskTableProps<T>\n l: TaskListLabels\n }\n): string | undefined {\n const { props: p, l } = ctx\n if (!p.formatRelative || !task.updated_at) return undefined\n const key = asTaskStatus(task.status)\n const pill = { ...DEFAULT_TASK_STATUS_PILL_LABELS, ...p.statusPillLabels }\n const label = task.pending_auth_request_id ? pill.waitingForAccess : STATUS_LABELS[key]\n return l.statusHint(label, p.formatRelative(task.updated_at))\n}\n\n/**\n * The tasks of a workspace as a person's work list, in the same grid as every other list in the app:\n * what an agent is generating first, then to-dos and, last, what is done.\n * Sub-tasks sit indented under their parent. Rows are selected with the grid's checkboxes (shift-click\n * for a range; ticking a parent ticks its sub-tasks) and acted on from the selection bar. Agents prepare\n * work; only a person closes it.\n */\nexport function TaskTable<T extends TaskListRow>(props: TaskTableProps<T>) {\n const { tasks: allTasks, isLoading, busyId, testId } = props\n const l: TaskListLabels = {\n ...DEFAULT_TASK_LIST_LABELS,\n ...props.labels,\n status: { ...STATUS_LABELS, ...props.labels?.status },\n }\n const [filter, setFilter] = useState<TaskFilter>('all')\n const [query, setQuery] = useState('')\n const [collapsed, setCollapsed] = useState<Set<string>>(new Set())\n const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())\n const [sort, setSort] = useState<{ colId: SortableTaskColumn; dir: 'asc' | 'desc' } | null>(null)\n const [moving, setMoving] = useState<T | null>(null)\n const tasks = allTasks\n const apiRef = useRef<GridApi<Row<T>> | null>(null)\n // A phone-width grid: one column and a menu, the status under the title (see onGridSizeChanged).\n const [narrow, setNarrow] = useState(false)\n const rowCache = useRef(new Map<string, Row<T>>())\n\n const tree = useMemo(() => indexTasks(tasks), [tasks])\n const peopleNames = useMemo(\n () => new Map((props.people ?? []).map((p) => [p.id, p.label])),\n [props.people]\n )\n /** What a task is called: its title, else the workflow that made it, else \"Untitled\". */\n const nameOf = (task: T): string =>\n task.title?.trim() ||\n (task.workflow_ext_id && props.workflowNames?.[task.workflow_ext_id]) ||\n l.untitled\n /** Who owns the task: its creator. */\n const owner = (task: T): TaskPerson => {\n const id = ownerExtId(task)\n const mine = task.is_owner !== false\n return {\n id,\n label: mine ? l.me : ((id && peopleNames.get(id)) ?? l.someone),\n isMe: mine,\n }\n }\n /** Who started a thread. */\n const starter = (task: T): TaskPerson => {\n const id = task.created_by_ext_id ?? task.owner_ext_id\n const mine = task.is_owner !== false\n return {\n id,\n label: mine ? l.me : ((id && peopleNames.get(id)) ?? l.someone),\n isMe: mine,\n }\n }\n const renderPerson = (person: TaskPerson) => <PersonPill person={person} />\n\n const q = (query.trim() || (props.filterText ?? '').trim()).toLowerCase()\n const counts = useMemo(() => {\n const map = new Map<string, number>(STATUS_ORDER.map((s) => [s, 0]))\n let all = 0\n for (const task of tasks) {\n const text = `${nameOf(task)} ${task.description ?? ''}`.toLowerCase()\n if (q && !text.includes(q)) continue\n all += 1\n const s = asTaskStatus(task.status)\n map.set(s, (map.get(s) ?? 0) + 1)\n }\n map.set('all', all)\n return map\n // nameOf reads the labels and workflow names the table was given.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tasks, q, props.workflowNames, l.untitled])\n\n const compare = useMemo(() => {\n if (!sort) return undefined\n // A sort key is computed once per task, not once per comparison.\n const keys = new Map<T, string | number>()\n const compute = (t: T): string | number => {\n switch (sort.colId) {\n case 'name':\n return nameOf(t).toLowerCase()\n case 'owner':\n return owner(t).label.toLowerCase()\n case 'updated':\n return t.updated_at ? Date.parse(t.updated_at) : 0\n case 'messages':\n return t.message_count ?? 0\n case 'due':\n return t.due_at ? Date.parse(t.due_at) : Number.POSITIVE_INFINITY\n default:\n return STATUS_ORDER.indexOf(asTaskStatus(t.status))\n }\n }\n const key = (t: T): string | number => {\n let k = keys.get(t)\n if (k === undefined) {\n k = compute(t)\n keys.set(t, k)\n }\n return k\n }\n const sign = sort.dir === 'asc' ? 1 : -1\n return (a: T, b: T) => {\n const [x, y] = [key(a), key(b)]\n if (typeof x === 'number' && typeof y === 'number') return (x - y) * sign\n return String(x).localeCompare(String(y)) * sign\n }\n // The name lookups close over the people, agents and workflows the table was given.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n sort,\n peopleNames,\n props.agentNames,\n props.workflowNames,\n l.me,\n l.agent,\n l.someone,\n l.untitled,\n ])\n\n const rows = useMemo(\n () =>\n buildTaskRows(tasks, filter, collapsed, compare, {\n query: query.trim() || props.filterText,\n titleOf: nameOf,\n cache: rowCache.current,\n }),\n // nameOf reads the labels and workflow names the table was given.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [tasks, filter, collapsed, compare, query, props.filterText, props.workflowNames, l.untitled]\n )\n\n // Selection lives here (the grid mirrors it), so a parent can carry its sub-tasks with it, even\n // the collapsed or filtered-out ones the grid does not show.\n const selectedRows = useMemo(\n () => rows.filter((r) => selectedIds.has(r.external_id)),\n [rows, selectedIds]\n )\n const selectedTasks = useMemo(\n () => tasks.filter((t) => selectedIds.has(t.external_id)),\n [tasks, selectedIds]\n )\n const subtasksIncluded = useMemo(\n () =>\n selectedTasks.filter((t) => {\n const parent = tree.parentOf.get(t.external_id)\n return parent !== undefined && selectedIds.has(parent)\n }).length,\n [selectedTasks, selectedIds, tree]\n )\n // Only a task is marked done: a plain chat has no status to finish.\n const markable = selectedTasks.filter(\n (t) =>\n t.status != null &&\n (t.is_owner !== false || props.canEditShared) &&\n isPlainTodo(t) &&\n asTaskStatus(t.status) !== 'done'\n )\n const deletable = selectedTasks.filter((t) => t.is_owner !== false || props.isWorkspaceOwner)\n\n const rowsRef = useRef(rows)\n rowsRef.current = rows\n const handleSelectionChange = (picked: Row<T>[]) => {\n const visible = new Set(rowsRef.current.map((r) => r.external_id))\n const pickedIds = new Set(picked.map((r) => r.external_id))\n setSelectedIds((prev) => {\n const added = [...pickedIds].filter((id) => !prev.has(id))\n const removed = [...prev].filter((id) => visible.has(id) && !pickedIds.has(id))\n if (added.length === 0 && removed.length === 0) return prev\n const next = new Set(prev)\n const nested = true\n for (const id of added) {\n next.add(id)\n if (nested) for (const d of descendantIds(tree, id)) next.add(d)\n }\n for (const id of removed) {\n next.delete(id)\n if (!nested) continue\n for (const d of descendantIds(tree, id)) next.delete(d)\n // A parent is no longer fully selected once one of its sub-tasks is not.\n for (let at = tree.parentOf.get(id); at; at = tree.parentOf.get(at)) next.delete(at)\n }\n return next\n })\n }\n\n const setExpanded = (id: string, expanded: boolean) =>\n setCollapsed((prev) => {\n if (prev.has(id) === !expanded) return prev\n const next = new Set(prev)\n if (expanded) next.delete(id)\n else next.add(id)\n return next\n })\n const expandAll = () => setCollapsed(new Set())\n const collapseAll = () => setCollapsed(new Set(tree.kids.keys()))\n\n // The column definitions are built once. Their cells read the latest props and lookups through\n // this ref, so a selection, a filter or an expand never makes the grid rebuild its columns.\n const latest = useRef({ props, l, owner, starter, renderPerson, nameOf, setExpanded, narrow })\n latest.current = { props, l, owner, starter, renderPerson, nameOf, setExpanded, narrow }\n\n // The Outputs column earns its room once some task has produced something.\n const showOutputs = Object.values(props.outputsByTask ?? {}).some((o) => o.length > 0)\n const columnDefs = useMemo(\n () =>\n createTaskColumns<T>({\n narrow,\n labels: l,\n getOwnerName: (row) => latest.current.owner(row.task).label,\n renderName: (row) => {\n const { l: lb, props: p, nameOf: name } = latest.current\n const { task, depth, childStats, expanded } = row\n const id = task.external_id\n const status = asTaskStatus(task.status)\n const goal = goalProgress(task)\n const workflowName = task.workflow_ext_id ? p.workflowNames?.[task.workflow_ext_id] : null\n return (\n <div\n className=\"flex min-w-0 flex-1 items-center gap-1.5\"\n style={\n depth > 0\n ? { paddingLeft: `${Math.min(depth, MAX_INDENT_DEPTH) * 1.5}rem` }\n : undefined\n }\n data-depth={depth}\n aria-level={depth + 1}\n aria-setsize={row.setSize}\n aria-posinset={row.posInSet}\n data-context={row.context || undefined}\n >\n {childStats ? (\n <button\n type=\"button\"\n onClick={() => latest.current.setExpanded(id, !expanded)}\n aria-expanded={expanded}\n aria-label={expanded ? lb.collapseSubtasks : lb.expandSubtasks}\n className=\"flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-muted hover:text-foreground\"\n data-testid={`task-expand-${id}`}\n >\n {expanded ? (\n <ChevronDown className=\"size-4\" aria-hidden />\n ) : (\n <ChevronRight className=\"size-4\" aria-hidden />\n )}\n </button>\n ) : depth > 0 ? (\n <span className=\"size-5 shrink-0\" aria-hidden />\n ) : null}\n <div className=\"min-w-0 flex-1 leading-tight\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => latest.current.props.onOpenThread(id, task)}\n // The agent that prepared the work is not a column: it is named here, on hover.\n title={\n task.agent_ext_id\n ? lb.preparedBy(p.agentNames?.[task.agent_ext_id] || lb.agent)\n : undefined\n }\n className={cn(\n // The title has priority: it keeps at least 12 characters before it ellipsises.\n 'min-w-[12ch] truncate text-left text-sm font-medium hover:underline focus-visible:underline focus-visible:outline-none',\n status === 'done' && 'text-muted-foreground line-through'\n )}\n data-testid={`task-name-${id}`}\n >\n {name(task)}\n </button>\n {goal && (\n <ToneBadge\n tone={goal.done ? 'success' : 'neutral'}\n data-testid={`task-goal-progress-${id}`}\n >\n {goal.done ? '\u2713 ' : ''}\n {lb.goalMet(goal.met, goal.total)}\n </ToneBadge>\n )}\n </div>\n {/* A phone has no Status column: the status sits under the title. */}\n {latest.current.narrow && (\n <div className=\"pt-0.5\">\n <TaskStatusPill\n id={id}\n status={status}\n runStartedAt={task.run_started_at}\n lastError={task.last_error}\n awaitingAccess={Boolean(task.pending_auth_request_id)}\n labels={p.statusPillLabels}\n />\n </div>\n )}\n {/* Second line: what it is (or where it came from) and the sub-task count, which never\n squeezes the title above it. */}\n {(task.description || workflowName || childStats) && (\n <div className=\"flex min-w-0 items-center gap-2 text-xs text-muted-foreground\">\n {task.description ? (\n <p className=\"min-w-0 truncate\">{task.description}</p>\n ) : workflowName ? (\n <span\n className=\"inline-flex min-w-0 items-center gap-1.5\"\n data-testid={`task-workflow-${id}`}\n >\n <Workflow className=\"size-3.5 shrink-0\" aria-hidden />\n <span className=\"truncate\">{lb.fromWorkflow(workflowName)}</span>\n </span>\n ) : null}\n {childStats && (\n <span\n className=\"shrink-0 tabular-nums\"\n data-testid={`task-subtask-progress-${id}`}\n >\n {lb.subtasksDone(childStats.done, childStats.total)}\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n )\n },\n // Who has the next step: the person pill, with the \"Me\" treatment. A plain chat is its starter's.\n renderOwner: (row) => (\n <span data-testid={`task-owner-${row.external_id}`} className=\"flex min-w-0\">\n {latest.current.renderPerson(\n row.task.status ? latest.current.owner(row.task) : latest.current.starter(row.task)\n )}\n </span>\n ),\n renderDue: (row) => {\n const { l: lb, props: p } = latest.current\n const { task } = row\n const dueMs = task.due_at ? Date.parse(task.due_at) : NaN\n const overdue =\n asTaskStatus(task.status) !== 'done' && !Number.isNaN(dueMs) && dueMs < Date.now()\n return (\n <span\n className={cn(\n 'truncate text-sm',\n overdue ? 'font-medium text-red-text' : 'text-muted-foreground'\n )}\n data-testid={`task-due-${task.external_id}`}\n data-overdue={overdue}\n >\n {task.due_at\n ? overdue\n ? lb.overdue(p.formatDate(task.due_at))\n : lb.due(p.formatDate(task.due_at))\n : lb.noDue}\n </span>\n )\n },\n renderShared: (row) => {\n const { l: lb, props: p } = latest.current\n const { task } = row\n // A teammate cannot change the owner's visibility choice.\n if (!p.onToggleShared) return null\n return (\n <VisibilityToggle\n items={{ shared: task.is_shared ?? false }}\n onToggle={(shouldShare) => latest.current.props.onToggleShared?.(task, shouldShare)}\n disabled={task.is_owner === false}\n disabledTooltip={lb.sharedOwnerOnly}\n showLabel={false}\n data-testid={`task-shared-${task.external_id}`}\n />\n )\n },\n showOutputs,\n renderOutputs: (row) => (\n <TaskOutputsCell\n id={row.external_id}\n outputs={latest.current.props.outputsByTask?.[row.external_id]}\n onOpen={(docId) => latest.current.props.onOpenOutput?.(docId, row.task)}\n labels={latest.current.props.outputsLabels}\n />\n ),\n renderStatus: (row) => (\n <TaskStatusPill\n id={row.external_id}\n status={asTaskStatus(row.task.status)}\n runStartedAt={row.task.run_started_at}\n lastError={row.task.last_error}\n awaitingAccess={Boolean(row.task.pending_auth_request_id)}\n labels={latest.current.props.statusPillLabels}\n hint={statusHint(row.task, latest.current)}\n />\n ),\n renderActions: (row) => {\n const { l: lb, props: p } = latest.current\n const { task } = row\n const id = task.external_id\n const status = asTaskStatus(task.status)\n const busy = p.busyId === id\n const isOwner = task.is_owner !== false\n const canEdit = isOwner || Boolean(p.canEditShared)\n const canAdmin = isOwner || Boolean(p.isWorkspaceOwner)\n return (\n <div className=\"flex items-center justify-end gap-2\">\n {!latest.current.narrow &&\n isOwner &&\n task.pending_auth_request_id &&\n p.onGrantAccess && (\n <Button\n size=\"sm\"\n className=\"h-8 gap-1.5 pointer-coarse:h-11\"\n onClick={() => p.onGrantAccess?.(task)}\n data-testid={`task-allow-access-${id}`}\n >\n <KeyRound className=\"size-3.5\" aria-hidden />\n {lb.allowAccess}\n </Button>\n )}\n <TaskRowMenu\n task={task}\n status={status}\n busy={busy}\n isOwner={isOwner}\n canAdmin={canAdmin}\n canEdit={canEdit}\n labels={lb}\n onMarkDone={() => p.onMarkDone(task)}\n onReopen={() => p.onReopen(task)}\n onAddSubtask={p.onAddSubtask ? () => p.onAddSubtask?.(task) : undefined}\n onMoveTo={p.onMove ? () => setMoving(task) : undefined}\n onEdit={() => p.onEdit(task)}\n onDelete={() => p.onDelete(task)}\n onOpenActivity={p.onOpenActivity ? () => p.onOpenActivity?.(task) : undefined}\n onGrantAccess={p.onGrantAccess ? () => p.onGrantAccess?.(task) : undefined}\n />\n </div>\n )\n },\n }),\n // Stable on purpose: only the header texts rebuild the columns (see `latest`).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n l.colTask,\n l.colOwner,\n l.colDue,\n l.colStatus,\n l.colShared,\n l.colOutputs,\n l.shared,\n showOutputs,\n narrow,\n ]\n )\n\n // Cells read their data through `latest`, so a change in the lookups they draw from (people, agents,\n // workflow names, the row in flight) redraws the cells once, rather than on every interaction.\n useEffect(() => {\n apiRef.current?.refreshCells({ force: true })\n }, [\n busyId,\n props.people,\n props.agentNames,\n props.workflowNames,\n props.outputsByTask,\n props.labels,\n props.canEditShared,\n props.isWorkspaceOwner,\n narrow,\n ])\n\n const animate = rows.length <= ANIMATE_ROWS_UP_TO\n const gridOptions = useMemo<Partial<GridOptions<Row<T>>>>(\n () => ({\n suppressClickEdit: true,\n // Keyboard focus lives on the name column only (the others are not navigable): ArrowRight\n // opens a task's sub-tasks and ArrowLeft closes them, or steps up to the parent.\n suppressCellFocus: false,\n suppressColumnVirtualisation: true,\n animateRows: animate,\n getRowClass: (p) => (p.data?.context ? 'opacity-60' : undefined),\n // The grid shows and reports the sort; the table orders each level (see buildTaskRows).\n onSortChanged: (event) => {\n const sorted = event.api.getColumnState().find((c) => c.sort)\n setSort(\n sorted?.colId\n ? { colId: sorted.colId as SortableTaskColumn, dir: sorted.sort ?? 'asc' }\n : null\n )\n },\n onGridSizeChanged: (event) => {\n applyColumnWidthRules(event.api, event.clientWidth, WIDTH_RULES)\n setNarrow(event.clientWidth < NARROW_GRID)\n },\n onCellKeyDown: (event: CellKeyDownEvent<Row<T>>) => {\n const row = event.data\n const key = (event.event as KeyboardEvent | null)?.key\n if (!row || event.column.getColId() !== 'name') return\n if (key === 'ArrowRight' && row.childStats && !row.expanded) {\n event.event?.preventDefault()\n latest.current.setExpanded(row.external_id, true)\n } else if (key === 'ArrowLeft') {\n if (row.childStats && row.expanded) {\n event.event?.preventDefault()\n latest.current.setExpanded(row.external_id, false)\n } else if (row.parentId) {\n event.event?.preventDefault()\n const parent = event.api.getRowNode(row.parentId)\n if (parent?.rowIndex != null) {\n event.api.ensureIndexVisible(parent.rowIndex)\n event.api.setFocusedCell(parent.rowIndex, 'name')\n }\n }\n }\n },\n }),\n [animate]\n )\n\n const clearSelection = () => setSelectedIds(new Set())\n // A Chat chip only once there is a plain chat, so the chips add up to All.\n const filterKeys = (['all', ...STATUS_ORDER] as TaskFilter[]).filter(\n (key) => key !== 'chat' || (counts.get(key) ?? 0) > 0\n )\n const hasChildren = tree.kids.size > 0\n\n return (\n <div\n className=\"flex min-h-0 flex-1 flex-col gap-3\"\n data-testid={testIdOr(testId, { testId: 'task-list' })}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <div role=\"tablist\" aria-label=\"Filter tasks\" className=\"flex flex-wrap gap-1.5\">\n {filterKeys.map((key) => {\n const count = counts.get(key) ?? 0\n const isSelected = filter === key\n return (\n <button\n key={key}\n type=\"button\"\n role=\"tab\"\n aria-selected={isSelected}\n onClick={() => setFilter(key)}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11',\n isSelected\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border text-muted-foreground hover:bg-accent'\n )}\n data-testid={`task-filter-${key}`}\n >\n {key === 'all' ? l.filterAll : l.status[key]}\n <span className=\"tabular-nums opacity-70\">{count}</span>\n </button>\n )\n })}\n </div>\n <Input\n type=\"search\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={l.searchPlaceholder}\n aria-label={l.searchLabel}\n className=\"h-8 max-w-56 text-xs pointer-coarse:h-11\"\n data-testid=\"task-search\"\n />\n {hasChildren && (\n <div className=\"ml-auto flex gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 gap-1.5 text-xs pointer-coarse:h-11\"\n onClick={expandAll}\n data-testid=\"task-expand-all\"\n >\n <ChevronsUpDown className=\"size-3.5\" aria-hidden />\n {l.expandAll}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 gap-1.5 text-xs pointer-coarse:h-11\"\n onClick={collapseAll}\n data-testid=\"task-collapse-all\"\n >\n <ChevronsDownUp className=\"size-3.5\" aria-hidden />\n {l.collapseAll}\n </Button>\n </div>\n )}\n </div>\n {tasks.length === 0 && !isLoading ? (\n <EmptyState\n icon={ListTodo}\n title={l.emptyTitle}\n description={l.emptyMessage}\n testId=\"task-list-empty\"\n />\n ) : (\n <div className=\"min-h-0 flex-1\">\n <GridView<Row<T>>\n testId=\"task-grid\"\n gridId={props.gridId ?? 'tasks-grid-v4'}\n items={rows}\n columnDefs={columnDefs}\n getItemId={(row) => row.external_id}\n getRowTestId={(row) => `task-row-${row.external_id}`}\n isLoading={isLoading}\n showEmpty={rows.length === 0}\n emptyState={{ title: l.noMatches }}\n rowHeight={narrow ? NARROW_ROW_HEIGHT : ROW_HEIGHT}\n height=\"100%\"\n onGridReady={({ api }) => {\n apiRef.current = api\n }}\n selection={{\n mode: 'multiple',\n controlled: true,\n selected: selectedRows,\n onSelectionChange: handleSelectionChange,\n }}\n gridOptions={gridOptions}\n />\n </div>\n )}\n <SelectionBar\n count={selectedTasks.length}\n onClear={clearSelection}\n status={\n selectedTasks.length > 0 && subtasksIncluded > 0 ? (\n <span className=\"text-xs text-muted-foreground\" data-testid=\"task-selection-subtasks\">\n {l.subtasksSelected(subtasksIncluded)}\n </span>\n ) : undefined\n }\n >\n {(isCompact) => (\n <>\n {props.onMarkDoneMany && (\n <SelectionBarAction\n icon={CheckCheck}\n label={l.markDoneMany}\n onClick={() => {\n props.onMarkDoneMany?.(markable)\n clearSelection()\n }}\n disabled={markable.length === 0}\n isCompact={isCompact}\n tooltip={l.markDoneManyHint}\n testId=\"task-bulk-done\"\n />\n )}\n {props.onDeleteMany && (\n <SelectionBarAction\n icon={Trash2}\n label={l.deleteMany}\n onClick={() => {\n props.onDeleteMany?.(deletable)\n clearSelection()\n }}\n disabled={deletable.length === 0}\n isCompact={isCompact}\n className=\"border-red-border text-red-text hover:bg-red-bg hover:text-red-text\"\n testId=\"task-bulk-delete\"\n />\n )}\n </>\n )}\n </SelectionBar>\n {moving && props.onMove && (\n <TaskMoveDialog\n open\n onOpenChange={(open) => !open && setMoving(null)}\n options={moveTargets(tasks, moving).map((t) => ({ id: t.external_id, label: nameOf(t) }))}\n currentParentId={moving.parent_conversation_ext_id}\n onPick={(parentId) => props.onMove?.(moving, parentId)}\n labels={{\n title: l.moveToTitle(nameOf(moving)),\n none: l.moveToNone,\n search: l.moveToSearch,\n empty: l.moveToEmpty,\n cancel: l.moveToCancel,\n }}\n />\n )}\n </div>\n )\n}\n"],
5
- "mappings": ";AAoM+C,SAmkBrC,UAnkBqC,KAwN3B,YAxN2B;AApM/C,SAAS,WAAW,SAAS,QAAQ,gBAAgB;AAErD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,QAAQ,OAAO,kBAAkB,UAAU;AACpD,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB;AACzB,SAAS,cAAc,0BAA0B;AACjD,SAAS,gBAAgB;AACzB,SAAS,kBAAmC;AAC5C,SAAS,uBAAoE;AAC7E,SAAS,sBAAsB;AAC/B,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,yBAAkD;AAC3D,SAAS,6BAAmD;AAC5D,SAAS,eAAe,cAAc,cAAc,oBAAoB;AACxE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,gCAAqD;AA4D9D,MAAM,aAAa;AAEnB,MAAM,oBAAoB;AAE1B,MAAM,mBAAmB;AAEzB,MAAM,qBAAqB;AAG3B,MAAM,cAAc;AAGpB,MAAM,cAA0C;AAAA,EAC9C,EAAE,OAAO,UAAU,UAAU,KAAK;AAAA,EAClC,EAAE,OAAO,OAAO,UAAU,IAAI;AAAA,EAC9B,EAAE,OAAO,WAAW,UAAU,IAAI;AAAA,EAClC,EAAE,OAAO,SAAS,UAAU,IAAI;AAAA,EAChC,EAAE,OAAO,UAAU,UAAU,YAAY;AAC3C;AAKA,SAAS,WACP,MACA,KAIoB;AACpB,QAAM,EAAE,OAAO,GAAG,EAAE,IAAI;AACxB,MAAI,CAAC,EAAE,kBAAkB,CAAC,KAAK,WAAY,QAAO;AAClD,QAAM,MAAM,aAAa,KAAK,MAAM;AACpC,QAAM,OAAO,EAAE,GAAG,iCAAiC,GAAG,EAAE,iBAAiB;AACzE,QAAM,QAAQ,KAAK,0BAA0B,KAAK,mBAAmB,cAAc,GAAG;AACtF,SAAO,EAAE,WAAW,OAAO,EAAE,eAAe,KAAK,UAAU,CAAC;AAC9D;AASO,SAAS,UAAiC,OAA0B;AACzE,QAAM,EAAE,OAAO,UAAU,WAAW,QAAQ,OAAO,IAAI;AACvD,QAAM,IAAoB;AAAA,IACxB,GAAG;AAAA,IACH,GAAG,MAAM;AAAA,IACT,QAAQ,EAAE,GAAG,eAAe,GAAG,MAAM,QAAQ,OAAO;AAAA,EACtD;AACA,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAqB,KAAK;AACtD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAsB,oBAAI,IAAI,CAAC;AACjE,QAAM,CAAC,aAAa,cAAc,IAAI,SAAsB,oBAAI,IAAI,CAAC;AACrE,QAAM,CAAC,MAAM,OAAO,IAAI,SAAoE,IAAI;AAChG,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAmB,IAAI;AACnD,QAAM,QAAQ;AACd,QAAM,SAAS,OAA+B,IAAI;AAElD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,WAAW,OAAO,oBAAI,IAAoB,CAAC;AAEjD,QAAM,OAAO,QAAQ,MAAM,WAAW,KAAK,GAAG,CAAC,KAAK,CAAC;AACrD,QAAM,cAAc;AAAA,IAClB,MAAM,IAAI,KAAK,MAAM,UAAU,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AAAA,IAC9D,CAAC,MAAM,MAAM;AAAA,EACf;AAEA,QAAM,SAAS,CAAC,SACd,KAAK,OAAO,KAAK,KAChB,KAAK,mBAAmB,MAAM,gBAAgB,KAAK,eAAe,KACnE,EAAE;AAEJ,QAAM,QAAQ,CAAC,SAAwB;AACrC,UAAM,KAAK,WAAW,IAAI;AAC1B,UAAM,OAAO,KAAK,aAAa;AAC/B,WAAO;AAAA,MACL;AAAA,MACA,OAAO,OAAO,EAAE,MAAO,MAAM,YAAY,IAAI,EAAE,MAAM,EAAE;AAAA,MACvD,MAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,UAAU,CAAC,SAAwB;AACvC,UAAM,KAAK,KAAK,qBAAqB,KAAK;AAC1C,UAAM,OAAO,KAAK,aAAa;AAC/B,WAAO;AAAA,MACL;AAAA,MACA,OAAO,OAAO,EAAE,MAAO,MAAM,YAAY,IAAI,EAAE,MAAM,EAAE;AAAA,MACvD,MAAM;AAAA,IACR;AAAA,EACF;AACA,QAAM,eAAe,CAAC,WAAuB,oBAAC,cAAW,QAAgB;AAEzE,QAAM,KAAK,MAAM,KAAK,MAAM,MAAM,cAAc,IAAI,KAAK,GAAG,YAAY;AACxE,QAAM,SAAS,QAAQ,MAAM;AAC3B,UAAM,MAAM,IAAI,IAAoB,aAAa,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AACnE,QAAI,MAAM;AACV,eAAW,QAAQ,OAAO;AACxB,YAAM,OAAO,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,GAAG,YAAY;AACrE,UAAI,KAAK,CAAC,KAAK,SAAS,CAAC,EAAG;AAC5B,aAAO;AACP,YAAM,IAAI,aAAa,KAAK,MAAM;AAClC,UAAI,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC;AAAA,IAClC;AACA,QAAI,IAAI,OAAO,GAAG;AAClB,WAAO;AAAA,EAGT,GAAG,CAAC,OAAO,GAAG,MAAM,eAAe,EAAE,QAAQ,CAAC;AAE9C,QAAM,UAAU,QAAQ,MAAM;AAC5B,QAAI,CAAC,KAAM,QAAO;AAElB,UAAM,OAAO,oBAAI,IAAwB;AACzC,UAAM,UAAU,CAAC,MAA0B;AACzC,cAAQ,KAAK,OAAO;AAAA,QAClB,KAAK;AACH,iBAAO,OAAO,CAAC,EAAE,YAAY;AAAA,QAC/B,KAAK;AACH,iBAAO,MAAM,CAAC,EAAE,MAAM,YAAY;AAAA,QACpC,KAAK;AACH,iBAAO,EAAE,aAAa,KAAK,MAAM,EAAE,UAAU,IAAI;AAAA,QACnD,KAAK;AACH,iBAAO,EAAE,iBAAiB;AAAA,QAC5B,KAAK;AACH,iBAAO,EAAE,SAAS,KAAK,MAAM,EAAE,MAAM,IAAI,OAAO;AAAA,QAClD;AACE,iBAAO,aAAa,QAAQ,aAAa,EAAE,MAAM,CAAC;AAAA,MACtD;AAAA,IACF;AACA,UAAM,MAAM,CAAC,MAA0B;AACrC,UAAI,IAAI,KAAK,IAAI,CAAC;AAClB,UAAI,MAAM,QAAW;AACnB,YAAI,QAAQ,CAAC;AACb,aAAK,IAAI,GAAG,CAAC;AAAA,MACf;AACA,aAAO;AAAA,IACT;AACA,UAAM,OAAO,KAAK,QAAQ,QAAQ,IAAI;AACtC,WAAO,CAAC,GAAM,MAAS;AACrB,YAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9B,UAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,SAAQ,IAAI,KAAK;AACrE,aAAO,OAAO,CAAC,EAAE,cAAc,OAAO,CAAC,CAAC,IAAI;AAAA,IAC9C;AAAA,EAGF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,EAAE;AAAA,IACF,EAAE;AAAA,IACF,EAAE;AAAA,IACF,EAAE;AAAA,EACJ,CAAC;AAED,QAAM,OAAO;AAAA,IACX,MACE,cAAc,OAAO,QAAQ,WAAW,SAAS;AAAA,MAC/C,OAAO,MAAM,KAAK,KAAK,MAAM;AAAA,MAC7B,SAAS;AAAA,MACT,OAAO,SAAS;AAAA,IAClB,CAAC;AAAA;AAAA;AAAA,IAGH,CAAC,OAAO,QAAQ,WAAW,SAAS,OAAO,MAAM,YAAY,MAAM,eAAe,EAAE,QAAQ;AAAA,EAC9F;AAIA,QAAM,eAAe;AAAA,IACnB,MAAM,KAAK,OAAO,CAAC,MAAM,YAAY,IAAI,EAAE,WAAW,CAAC;AAAA,IACvD,CAAC,MAAM,WAAW;AAAA,EACpB;AACA,QAAM,gBAAgB;AAAA,IACpB,MAAM,MAAM,OAAO,CAAC,MAAM,YAAY,IAAI,EAAE,WAAW,CAAC;AAAA,IACxD,CAAC,OAAO,WAAW;AAAA,EACrB;AACA,QAAM,mBAAmB;AAAA,IACvB,MACE,cAAc,OAAO,CAAC,MAAM;AAC1B,YAAM,SAAS,KAAK,SAAS,IAAI,EAAE,WAAW;AAC9C,aAAO,WAAW,UAAa,YAAY,IAAI,MAAM;AAAA,IACvD,CAAC,EAAE;AAAA,IACL,CAAC,eAAe,aAAa,IAAI;AAAA,EACnC;AAEA,QAAM,WAAW,cAAc;AAAA,IAC7B,CAAC,MACC,EAAE,UAAU,SACX,EAAE,aAAa,SAAS,MAAM,kBAC/B,YAAY,CAAC,KACb,aAAa,EAAE,MAAM,MAAM;AAAA,EAC/B;AACA,QAAM,YAAY,cAAc,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS,MAAM,gBAAgB;AAE5F,QAAM,UAAU,OAAO,IAAI;AAC3B,UAAQ,UAAU;AAClB,QAAM,wBAAwB,CAAC,WAAqB;AAClD,UAAM,UAAU,IAAI,IAAI,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC;AACjE,UAAM,YAAY,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC;AAC1D,mBAAe,CAAC,SAAS;AACvB,YAAM,QAAQ,CAAC,GAAG,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;AACzD,YAAM,UAAU,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,OAAO,QAAQ,IAAI,EAAE,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC;AAC9E,UAAI,MAAM,WAAW,KAAK,QAAQ,WAAW,EAAG,QAAO;AACvD,YAAM,OAAO,IAAI,IAAI,IAAI;AACzB,YAAM,SAAS;AACf,iBAAW,MAAM,OAAO;AACtB,aAAK,IAAI,EAAE;AACX,YAAI,OAAQ,YAAW,KAAK,cAAc,MAAM,EAAE,EAAG,MAAK,IAAI,CAAC;AAAA,MACjE;AACA,iBAAW,MAAM,SAAS;AACxB,aAAK,OAAO,EAAE;AACd,YAAI,CAAC,OAAQ;AACb,mBAAW,KAAK,cAAc,MAAM,EAAE,EAAG,MAAK,OAAO,CAAC;AAEtD,iBAAS,KAAK,KAAK,SAAS,IAAI,EAAE,GAAG,IAAI,KAAK,KAAK,SAAS,IAAI,EAAE,EAAG,MAAK,OAAO,EAAE;AAAA,MACrF;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,cAAc,CAAC,IAAY,aAC/B,aAAa,CAAC,SAAS;AACrB,QAAI,KAAK,IAAI,EAAE,MAAM,CAAC,SAAU,QAAO;AACvC,UAAM,OAAO,IAAI,IAAI,IAAI;AACzB,QAAI,SAAU,MAAK,OAAO,EAAE;AAAA,QACvB,MAAK,IAAI,EAAE;AAChB,WAAO;AAAA,EACT,CAAC;AACH,QAAM,YAAY,MAAM,aAAa,oBAAI,IAAI,CAAC;AAC9C,QAAM,cAAc,MAAM,aAAa,IAAI,IAAI,KAAK,KAAK,KAAK,CAAC,CAAC;AAIhE,QAAM,SAAS,OAAO,EAAE,OAAO,GAAG,OAAO,SAAS,cAAc,QAAQ,aAAa,OAAO,CAAC;AAC7F,SAAO,UAAU,EAAE,OAAO,GAAG,OAAO,SAAS,cAAc,QAAQ,aAAa,OAAO;AAGvF,QAAM,cAAc,OAAO,OAAO,MAAM,iBAAiB,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC;AACrF,QAAM,aAAa;AAAA,IACjB,MACE,kBAAqB;AAAA,MACnB;AAAA,MACA,QAAQ;AAAA,MACR,cAAc,CAAC,QAAQ,OAAO,QAAQ,MAAM,IAAI,IAAI,EAAE;AAAA,MACtD,YAAY,CAAC,QAAQ;AACnB,cAAM,EAAE,GAAG,IAAI,OAAO,GAAG,QAAQ,KAAK,IAAI,OAAO;AACjD,cAAM,EAAE,MAAM,OAAO,YAAY,SAAS,IAAI;AAC9C,cAAM,KAAK,KAAK;AAChB,cAAM,SAAS,aAAa,KAAK,MAAM;AACvC,cAAM,OAAO,aAAa,IAAI;AAC9B,cAAM,eAAe,KAAK,kBAAkB,EAAE,gBAAgB,KAAK,eAAe,IAAI;AACtF,eACE;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OACE,QAAQ,IACJ,EAAE,aAAa,GAAG,KAAK,IAAI,OAAO,gBAAgB,IAAI,GAAG,MAAM,IAC/D;AAAA,YAEN,cAAY;AAAA,YACZ,cAAY,QAAQ;AAAA,YACpB,gBAAc,IAAI;AAAA,YAClB,iBAAe,IAAI;AAAA,YACnB,gBAAc,IAAI,WAAW;AAAA,YAE5B;AAAA,2BACC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS,MAAM,OAAO,QAAQ,YAAY,IAAI,CAAC,QAAQ;AAAA,kBACvD,iBAAe;AAAA,kBACf,cAAY,WAAW,GAAG,mBAAmB,GAAG;AAAA,kBAChD,WAAU;AAAA,kBACV,eAAa,eAAe,EAAE;AAAA,kBAE7B,qBACC,oBAAC,eAAY,WAAU,UAAS,eAAW,MAAC,IAE5C,oBAAC,gBAAa,WAAU,UAAS,eAAW,MAAC;AAAA;AAAA,cAEjD,IACE,QAAQ,IACV,oBAAC,UAAK,WAAU,mBAAkB,eAAW,MAAC,IAC5C;AAAA,cACJ,qBAAC,SAAI,WAAU,gCACb;AAAA,qCAAC,SAAI,WAAU,mCACb;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,SAAS,MAAM,OAAO,QAAQ,MAAM,aAAa,IAAI,IAAI;AAAA,sBAEzD,OACE,KAAK,eACD,GAAG,WAAW,EAAE,aAAa,KAAK,YAAY,KAAK,GAAG,KAAK,IAC3D;AAAA,sBAEN,WAAW;AAAA;AAAA,wBAET;AAAA,wBACA,WAAW,UAAU;AAAA,sBACvB;AAAA,sBACA,eAAa,aAAa,EAAE;AAAA,sBAE3B,eAAK,IAAI;AAAA;AAAA,kBACZ;AAAA,kBACC,QACC;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAM,KAAK,OAAO,YAAY;AAAA,sBAC9B,eAAa,sBAAsB,EAAE;AAAA,sBAEpC;AAAA,6BAAK,OAAO,YAAO;AAAA,wBACnB,GAAG,QAAQ,KAAK,KAAK,KAAK,KAAK;AAAA;AAAA;AAAA,kBAClC;AAAA,mBAEJ;AAAA,gBAEC,OAAO,QAAQ,UACd,oBAAC,SAAI,WAAU,UACb;AAAA,kBAAC;AAAA;AAAA,oBACC;AAAA,oBACA;AAAA,oBACA,cAAc,KAAK;AAAA,oBACnB,WAAW,KAAK;AAAA,oBAChB,gBAAgB,QAAQ,KAAK,uBAAuB;AAAA,oBACpD,QAAQ,EAAE;AAAA;AAAA,gBACZ,GACF;AAAA,iBAIA,KAAK,eAAe,gBAAgB,eACpC,qBAAC,SAAI,WAAU,iEACZ;AAAA,uBAAK,cACJ,oBAAC,OAAE,WAAU,oBAAoB,eAAK,aAAY,IAChD,eACF;AAAA,oBAAC;AAAA;AAAA,sBACC,WAAU;AAAA,sBACV,eAAa,iBAAiB,EAAE;AAAA,sBAEhC;AAAA,4CAAC,YAAS,WAAU,qBAAoB,eAAW,MAAC;AAAA,wBACpD,oBAAC,UAAK,WAAU,YAAY,aAAG,aAAa,YAAY,GAAE;AAAA;AAAA;AAAA,kBAC5D,IACE;AAAA,kBACH,cACC;AAAA,oBAAC;AAAA;AAAA,sBACC,WAAU;AAAA,sBACV,eAAa,yBAAyB,EAAE;AAAA,sBAEvC,aAAG,aAAa,WAAW,MAAM,WAAW,KAAK;AAAA;AAAA,kBACpD;AAAA,mBAEJ;AAAA,iBAEJ;AAAA;AAAA;AAAA,QACF;AAAA,MAEJ;AAAA;AAAA,MAEA,aAAa,CAAC,QACZ,oBAAC,UAAK,eAAa,cAAc,IAAI,WAAW,IAAI,WAAU,gBAC3D,iBAAO,QAAQ;AAAA,QACd,IAAI,KAAK,SAAS,OAAO,QAAQ,MAAM,IAAI,IAAI,IAAI,OAAO,QAAQ,QAAQ,IAAI,IAAI;AAAA,MACpF,GACF;AAAA,MAEF,WAAW,CAAC,QAAQ;AAClB,cAAM,EAAE,GAAG,IAAI,OAAO,EAAE,IAAI,OAAO;AACnC,cAAM,EAAE,KAAK,IAAI;AACjB,cAAM,QAAQ,KAAK,SAAS,KAAK,MAAM,KAAK,MAAM,IAAI;AACtD,cAAM,UACJ,aAAa,KAAK,MAAM,MAAM,UAAU,CAAC,OAAO,MAAM,KAAK,KAAK,QAAQ,KAAK,IAAI;AACnF,eACE;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,UAAU,8BAA8B;AAAA,YAC1C;AAAA,YACA,eAAa,YAAY,KAAK,WAAW;AAAA,YACzC,gBAAc;AAAA,YAEb,eAAK,SACF,UACE,GAAG,QAAQ,EAAE,WAAW,KAAK,MAAM,CAAC,IACpC,GAAG,IAAI,EAAE,WAAW,KAAK,MAAM,CAAC,IAClC,GAAG;AAAA;AAAA,QACT;AAAA,MAEJ;AAAA,MACA,cAAc,CAAC,QAAQ;AACrB,cAAM,EAAE,GAAG,IAAI,OAAO,EAAE,IAAI,OAAO;AACnC,cAAM,EAAE,KAAK,IAAI;AAEjB,YAAI,CAAC,EAAE,eAAgB,QAAO;AAC9B,eACE;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,EAAE,QAAQ,KAAK,aAAa,MAAM;AAAA,YACzC,UAAU,CAAC,gBAAgB,OAAO,QAAQ,MAAM,iBAAiB,MAAM,WAAW;AAAA,YAClF,UAAU,KAAK,aAAa;AAAA,YAC5B,iBAAiB,GAAG;AAAA,YACpB,WAAW;AAAA,YACX,eAAa,eAAe,KAAK,WAAW;AAAA;AAAA,QAC9C;AAAA,MAEJ;AAAA,MACA;AAAA,MACA,eAAe,CAAC,QACd;AAAA,QAAC;AAAA;AAAA,UACC,IAAI,IAAI;AAAA,UACR,SAAS,OAAO,QAAQ,MAAM,gBAAgB,IAAI,WAAW;AAAA,UAC7D,QAAQ,CAAC,UAAU,OAAO,QAAQ,MAAM,eAAe,OAAO,IAAI,IAAI;AAAA,UACtE,QAAQ,OAAO,QAAQ,MAAM;AAAA;AAAA,MAC/B;AAAA,MAEF,cAAc,CAAC,QACb;AAAA,QAAC;AAAA;AAAA,UACC,IAAI,IAAI;AAAA,UACR,QAAQ,aAAa,IAAI,KAAK,MAAM;AAAA,UACpC,cAAc,IAAI,KAAK;AAAA,UACvB,WAAW,IAAI,KAAK;AAAA,UACpB,gBAAgB,QAAQ,IAAI,KAAK,uBAAuB;AAAA,UACxD,QAAQ,OAAO,QAAQ,MAAM;AAAA,UAC7B,MAAM,WAAW,IAAI,MAAM,OAAO,OAAO;AAAA;AAAA,MAC3C;AAAA,MAEF,eAAe,CAAC,QAAQ;AACtB,cAAM,EAAE,GAAG,IAAI,OAAO,EAAE,IAAI,OAAO;AACnC,cAAM,EAAE,KAAK,IAAI;AACjB,cAAM,KAAK,KAAK;AAChB,cAAM,SAAS,aAAa,KAAK,MAAM;AACvC,cAAM,OAAO,EAAE,WAAW;AAC1B,cAAM,UAAU,KAAK,aAAa;AAClC,cAAM,UAAU,WAAW,QAAQ,EAAE,aAAa;AAClD,cAAM,WAAW,WAAW,QAAQ,EAAE,gBAAgB;AACtD,eACE,qBAAC,SAAI,WAAU,uCACZ;AAAA,WAAC,OAAO,QAAQ,UACf,WACA,KAAK,2BACL,EAAE,iBACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,MAAM,EAAE,gBAAgB,IAAI;AAAA,cACrC,eAAa,qBAAqB,EAAE;AAAA,cAEpC;AAAA,oCAAC,YAAS,WAAU,YAAW,eAAW,MAAC;AAAA,gBAC1C,GAAG;AAAA;AAAA;AAAA,UACN;AAAA,UAEJ;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,QAAQ;AAAA,cACR,YAAY,MAAM,EAAE,WAAW,IAAI;AAAA,cACnC,UAAU,MAAM,EAAE,SAAS,IAAI;AAAA,cAC/B,cAAc,EAAE,eAAe,MAAM,EAAE,eAAe,IAAI,IAAI;AAAA,cAC9D,UAAU,EAAE,SAAS,MAAM,UAAU,IAAI,IAAI;AAAA,cAC7C,QAAQ,MAAM,EAAE,OAAO,IAAI;AAAA,cAC3B,UAAU,MAAM,EAAE,SAAS,IAAI;AAAA,cAC/B,gBAAgB,EAAE,iBAAiB,MAAM,EAAE,iBAAiB,IAAI,IAAI;AAAA,cACpE,eAAe,EAAE,gBAAgB,MAAM,EAAE,gBAAgB,IAAI,IAAI;AAAA;AAAA,UACnE;AAAA,WACF;AAAA,MAEJ;AAAA,IACF,CAAC;AAAA;AAAA;AAAA,IAGH;AAAA,MACE,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAIA,YAAU,MAAM;AACd,WAAO,SAAS,aAAa,EAAE,OAAO,KAAK,CAAC;AAAA,EAC9C,GAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACF,CAAC;AAED,QAAM,UAAU,KAAK,UAAU;AAC/B,QAAM,cAAc;AAAA,IAClB,OAAO;AAAA,MACL,mBAAmB;AAAA;AAAA;AAAA,MAGnB,mBAAmB;AAAA,MACnB,8BAA8B;AAAA,MAC9B,aAAa;AAAA,MACb,aAAa,CAAC,MAAO,EAAE,MAAM,UAAU,eAAe;AAAA;AAAA,MAEtD,eAAe,CAAC,UAAU;AACxB,cAAM,SAAS,MAAM,IAAI,eAAe,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI;AAC5D;AAAA,UACE,QAAQ,QACJ,EAAE,OAAO,OAAO,OAA6B,KAAK,OAAO,QAAQ,MAAM,IACvE;AAAA,QACN;AAAA,MACF;AAAA,MACA,mBAAmB,CAAC,UAAU;AAC5B,8BAAsB,MAAM,KAAK,MAAM,aAAa,WAAW;AAC/D,kBAAU,MAAM,cAAc,WAAW;AAAA,MAC3C;AAAA,MACA,eAAe,CAAC,UAAoC;AAClD,cAAM,MAAM,MAAM;AAClB,cAAM,MAAO,MAAM,OAAgC;AACnD,YAAI,CAAC,OAAO,MAAM,OAAO,SAAS,MAAM,OAAQ;AAChD,YAAI,QAAQ,gBAAgB,IAAI,cAAc,CAAC,IAAI,UAAU;AAC3D,gBAAM,OAAO,eAAe;AAC5B,iBAAO,QAAQ,YAAY,IAAI,aAAa,IAAI;AAAA,QAClD,WAAW,QAAQ,aAAa;AAC9B,cAAI,IAAI,cAAc,IAAI,UAAU;AAClC,kBAAM,OAAO,eAAe;AAC5B,mBAAO,QAAQ,YAAY,IAAI,aAAa,KAAK;AAAA,UACnD,WAAW,IAAI,UAAU;AACvB,kBAAM,OAAO,eAAe;AAC5B,kBAAM,SAAS,MAAM,IAAI,WAAW,IAAI,QAAQ;AAChD,gBAAI,QAAQ,YAAY,MAAM;AAC5B,oBAAM,IAAI,mBAAmB,OAAO,QAAQ;AAC5C,oBAAM,IAAI,eAAe,OAAO,UAAU,MAAM;AAAA,YAClD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,iBAAiB,MAAM,eAAe,oBAAI,IAAI,CAAC;AAErD,QAAM,aAAc,CAAC,OAAO,GAAG,YAAY,EAAmB;AAAA,IAC5D,CAAC,QAAQ,QAAQ,WAAW,OAAO,IAAI,GAAG,KAAK,KAAK;AAAA,EACtD;AACA,QAAM,cAAc,KAAK,KAAK,OAAO;AAErC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,eAAa,SAAS,QAAQ,EAAE,QAAQ,YAAY,CAAC;AAAA,MAErD;AAAA,6BAAC,SAAI,WAAU,qCACb;AAAA,8BAAC,SAAI,MAAK,WAAU,cAAW,gBAAe,WAAU,0BACrD,qBAAW,IAAI,CAAC,QAAQ;AACvB,kBAAM,QAAQ,OAAO,IAAI,GAAG,KAAK;AACjC,kBAAM,aAAa,WAAW;AAC9B,mBACE;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,iBAAe;AAAA,gBACf,SAAS,MAAM,UAAU,GAAG;AAAA,gBAC5B,WAAW;AAAA,kBACT;AAAA,kBACA,aACI,8CACA;AAAA,gBACN;AAAA,gBACA,eAAa,eAAe,GAAG;AAAA,gBAE9B;AAAA,0BAAQ,QAAQ,EAAE,YAAY,EAAE,OAAO,GAAG;AAAA,kBAC3C,oBAAC,UAAK,WAAU,2BAA2B,iBAAM;AAAA;AAAA;AAAA,cAd5C;AAAA,YAeP;AAAA,UAEJ,CAAC,GACH;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,cACxC,aAAa,EAAE;AAAA,cACf,cAAY,EAAE;AAAA,cACd,WAAU;AAAA,cACV,eAAY;AAAA;AAAA,UACd;AAAA,UACC,eACC,qBAAC,SAAI,WAAU,sBACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS;AAAA,gBACT,eAAY;AAAA,gBAEZ;AAAA,sCAAC,kBAAe,WAAU,YAAW,eAAW,MAAC;AAAA,kBAChD,EAAE;AAAA;AAAA;AAAA,YACL;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS;AAAA,gBACT,eAAY;AAAA,gBAEZ;AAAA,sCAAC,kBAAe,WAAU,YAAW,eAAW,MAAC;AAAA,kBAChD,EAAE;AAAA;AAAA;AAAA,YACL;AAAA,aACF;AAAA,WAEJ;AAAA,QACC,MAAM,WAAW,KAAK,CAAC,YACtB;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,OAAO,EAAE;AAAA,YACT,aAAa,EAAE;AAAA,YACf,QAAO;AAAA;AAAA,QACT,IAEA,oBAAC,SAAI,WAAU,kBACb;AAAA,UAAC;AAAA;AAAA,YACC,QAAO;AAAA,YACP,QAAQ,MAAM,UAAU;AAAA,YACxB,OAAO;AAAA,YACP;AAAA,YACA,WAAW,CAAC,QAAQ,IAAI;AAAA,YACxB,cAAc,CAAC,QAAQ,YAAY,IAAI,WAAW;AAAA,YAClD;AAAA,YACA,WAAW,KAAK,WAAW;AAAA,YAC3B,YAAY,EAAE,OAAO,EAAE,UAAU;AAAA,YACjC,WAAW,SAAS,oBAAoB;AAAA,YACxC,QAAO;AAAA,YACP,aAAa,CAAC,EAAE,IAAI,MAAM;AACxB,qBAAO,UAAU;AAAA,YACnB;AAAA,YACA,WAAW;AAAA,cACT,MAAM;AAAA,cACN,YAAY;AAAA,cACZ,UAAU;AAAA,cACV,mBAAmB;AAAA,YACrB;AAAA,YACA;AAAA;AAAA,QACF,GACF;AAAA,QAEF;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,cAAc;AAAA,YACrB,SAAS;AAAA,YACT,QACE,cAAc,SAAS,KAAK,mBAAmB,IAC7C,oBAAC,UAAK,WAAU,iCAAgC,eAAY,2BACzD,YAAE,iBAAiB,gBAAgB,GACtC,IACE;AAAA,YAGL,WAAC,cACA,iCACG;AAAA,oBAAM,kBACL;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAM;AAAA,kBACN,OAAO,EAAE;AAAA,kBACT,SAAS,MAAM;AACb,0BAAM,iBAAiB,QAAQ;AAC/B,mCAAe;AAAA,kBACjB;AAAA,kBACA,UAAU,SAAS,WAAW;AAAA,kBAC9B;AAAA,kBACA,SAAS,EAAE;AAAA,kBACX,QAAO;AAAA;AAAA,cACT;AAAA,cAED,MAAM,gBACL;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAM;AAAA,kBACN,OAAO,EAAE;AAAA,kBACT,SAAS,MAAM;AACb,0BAAM,eAAe,SAAS;AAC9B,mCAAe;AAAA,kBACjB;AAAA,kBACA,UAAU,UAAU,WAAW;AAAA,kBAC/B;AAAA,kBACA,WAAU;AAAA,kBACV,QAAO;AAAA;AAAA,cACT;AAAA,eAEJ;AAAA;AAAA,QAEJ;AAAA,QACC,UAAU,MAAM,UACf;AAAA,UAAC;AAAA;AAAA,YACC,MAAI;AAAA,YACJ,cAAc,CAAC,SAAS,CAAC,QAAQ,UAAU,IAAI;AAAA,YAC/C,SAAS,YAAY,OAAO,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,OAAO,OAAO,CAAC,EAAE,EAAE;AAAA,YACxF,iBAAiB,OAAO;AAAA,YACxB,QAAQ,CAAC,aAAa,MAAM,SAAS,QAAQ,QAAQ;AAAA,YACrD,QAAQ;AAAA,cACN,OAAO,EAAE,YAAY,OAAO,MAAM,CAAC;AAAA,cACnC,MAAM,EAAE;AAAA,cACR,QAAQ,EAAE;AAAA,cACV,OAAO,EAAE;AAAA,cACT,QAAQ,EAAE;AAAA,YACZ;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;",
4
+ "sourcesContent": ["import { useEffect, useMemo, useRef, useState } from 'react'\nimport type { CellKeyDownEvent, GridApi, GridOptions } from 'ag-grid-community'\nimport {\n ChevronDown,\n ChevronRight,\n ChevronsDownUp,\n ChevronsUpDown,\n CheckCheck,\n KeyRound,\n ListTodo,\n Trash2,\n Workflow,\n} from 'lucide-react'\nimport { Button, Input, cn, SharingEntity } from '@arbidocs/react/ui'\nimport { EmptyState } from '../../components/EmptyState'\nimport { ToneBadge } from '../../components/ToneBadge'\nimport { GridView } from '../../files/GridView'\nimport { SelectionBar, SelectionBarAction } from '../../files/SelectionBar'\nimport { testIdOr } from '../../chat/test-id'\nimport { PersonPill, type TaskPerson } from './PersonPill'\nimport { TaskOutputsCell, type TaskOutput, type TaskOutputsCellLabels } from './TaskOutputsCell'\nimport { TaskMoveDialog } from './TaskMoveDialog'\nimport { TaskRowMenu } from './TaskRowMenu'\nimport {\n DEFAULT_TASK_STATUS_PILL_LABELS,\n TaskStatusPill,\n type TaskStatusPillLabels,\n} from './TaskStatusPill'\nimport { createTaskColumns, type SortableTaskColumn } from './taskColumns'\nimport { applyColumnWidthRules, type ColumnWidthRule } from './gridWidth'\nimport { STATUS_LABELS, STATUS_ORDER, asTaskStatus, goalProgress } from './taskLabels'\nimport {\n buildTaskRows,\n ownerExtId,\n descendantIds,\n indexTasks,\n isPlainTodo,\n moveTargets,\n type TaskFilter,\n type TaskGridRow,\n type TaskListRow,\n} from './taskRows'\nimport { DEFAULT_TASK_LIST_LABELS, type TaskListLabels } from './taskTableLabels'\n\nexport interface TaskTableProps<T extends TaskListRow> {\n /** The workspace's tasks: the conversations that have a status (the host drops plain chats). */\n tasks: T[]\n isLoading?: boolean\n /** Friendly display of an ISO timestamp. */\n formatDate: (iso: string) => string\n /** Open the task's thread (its conversation). */\n onOpenThread: (conversationId: string, task: T) => void\n /** A person marks a task done / reopens a finished one. */\n onMarkDone: (task: T) => void\n onReopen: (task: T) => void\n /** People in the workspace, by id: names the Owner column. */\n people?: { id: string; label: string }[]\n /** Agent names by id, for the Assigned to column (falls back to \"Agent\"). */\n agentNames?: Record<string, string>\n /** Workflow names by id: names a task whose title the run has not generated yet, and its origin chip. */\n workflowNames?: Record<string, string>\n /** Share a task with the workspace or make it private (the shared/private toggle appears with it). */\n onToggleShared?: (task: T, shouldShare: boolean) => void\n onEdit: (task: T) => void\n onDelete: (task: T) => void\n /** Start a new task that is a child of this one. */\n onAddSubtask?: (task: T) => void\n /** Re-parent a task (`null` = top level). With it, the row menu offers \"Move to\u2026\". */\n onMove?: (task: T, parentId: string | null) => void\n /** Bulk actions on the selected rows (the selection bar shows only the ones provided). */\n onMarkDoneMany?: (tasks: T[]) => void\n onDeleteMany?: (tasks: T[]) => void\n /** When set, a run waiting for access shows a one-click \"allow access\" action. */\n onGrantAccess?: (task: T) => void\n /** Task id with a request in flight: its row disables its actions. */\n busyId?: string | null\n /** Text from outside the table (a topbar filter) that narrows the rows like the search box does. */\n filterText?: string\n /**\n * The viewer edits the workspace (owner or collaborator): a row they do not own is always shared, and\n * they may then edit, run, move, mark done and add sub-tasks to it. The share toggle, Delete and Allow\n * access stay with the row's owner. A guest leaves this off and only reads.\n */\n canEditShared?: boolean\n /** The viewer owns the workspace: with a row's creator, the only one who deletes it. Who can see it stays the creator's alone. */\n isWorkspaceOwner?: boolean\n /** Saved column state key (AG Grid persists by it). */\n gridId?: string\n labels?: Partial<TaskListLabels>\n testId?: string\n statusPillLabels?: Partial<TaskStatusPillLabels>\n /** Generated documents per task id (latest versions only); a task with none shows a dash. */\n outputsByTask?: Record<string, readonly TaskOutput[]>\n /** Open one generated document (Tasks view's Outputs column). */\n onOpenOutput?: (documentId: string, task: T) => void\n outputsLabels?: Partial<TaskOutputsCellLabels>\n /** Open a task's activity timeline (row menu: \"Activity\"). */\n onOpenActivity?: (task: T) => void\n /** \"2 min ago\" for the status tooltip; without it the tooltip is left out. */\n formatRelative?: (iso: string) => string\n}\n\nconst ROW_HEIGHT = 56\n/** Taller on a phone, where the status sits under the title. */\nconst NARROW_ROW_HEIGHT = 76\n/** Sub-tasks stop indenting after this depth (the table stays readable at any nesting). */\nconst MAX_INDENT_DEPTH = 4\n/** Above this many rows the grid stops animating row changes. */\nconst ANIMATE_ROWS_UP_TO = 500\n\n/** Below this grid width the table is one column and a menu. */\nconst NARROW_GRID = 640\n\n/** What goes first as the grid narrows (the grid is the page minus the sidebar). */\nconst WIDTH_RULES: readonly ColumnWidthRule[] = [\n { colId: 'shared', minWidth: 1050 },\n { colId: 'due', minWidth: 850 },\n { colId: 'outputs', minWidth: 930 },\n { colId: 'owner', minWidth: 730 },\n { colId: 'status', minWidth: NARROW_GRID },\n]\n\ntype Row<T extends TaskListRow> = TaskGridRow<T>\n\n/** The tooltip on the status pill: the latest step and how long ago. */\nfunction statusHint<T extends TaskListRow>(\n task: T,\n ctx: {\n props: TaskTableProps<T>\n l: TaskListLabels\n }\n): string | undefined {\n const { props: p, l } = ctx\n if (!p.formatRelative || !task.updated_at) return undefined\n const key = asTaskStatus(task.status)\n const pill = { ...DEFAULT_TASK_STATUS_PILL_LABELS, ...p.statusPillLabels }\n const label = task.pending_auth_request_id ? pill.waitingForAccess : STATUS_LABELS[key]\n return l.statusHint(label, p.formatRelative(task.updated_at))\n}\n\n/**\n * The tasks of a workspace as a person's work list, in the same grid as every other list in the app:\n * what an agent is generating first, then to-dos and, last, what is done.\n * Sub-tasks sit indented under their parent. Rows are selected with the grid's checkboxes (shift-click\n * for a range; ticking a parent ticks its sub-tasks) and acted on from the selection bar. Agents prepare\n * work; only a person closes it.\n */\nexport function TaskTable<T extends TaskListRow>(props: TaskTableProps<T>) {\n const { tasks: allTasks, isLoading, busyId, testId } = props\n const l: TaskListLabels = {\n ...DEFAULT_TASK_LIST_LABELS,\n ...props.labels,\n status: { ...STATUS_LABELS, ...props.labels?.status },\n }\n const [filter, setFilter] = useState<TaskFilter>('all')\n const [query, setQuery] = useState('')\n const [collapsed, setCollapsed] = useState<Set<string>>(new Set())\n const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())\n const [sort, setSort] = useState<{ colId: SortableTaskColumn; dir: 'asc' | 'desc' } | null>(null)\n const [moving, setMoving] = useState<T | null>(null)\n const tasks = allTasks\n const apiRef = useRef<GridApi<Row<T>> | null>(null)\n // A phone-width grid: one column and a menu, the status under the title (see onGridSizeChanged).\n const [narrow, setNarrow] = useState(false)\n const rowCache = useRef(new Map<string, Row<T>>())\n\n const tree = useMemo(() => indexTasks(tasks), [tasks])\n const peopleNames = useMemo(\n () => new Map((props.people ?? []).map((p) => [p.id, p.label])),\n [props.people]\n )\n /** What a task is called: its title, else the workflow that made it, else \"Untitled\". */\n const nameOf = (task: T): string =>\n task.title?.trim() ||\n (task.workflow_ext_id && props.workflowNames?.[task.workflow_ext_id]) ||\n l.untitled\n /** Who owns the task: its creator. */\n const owner = (task: T): TaskPerson => {\n const id = ownerExtId(task)\n const mine = task.is_owner !== false\n return {\n id,\n label: mine ? l.me : ((id && peopleNames.get(id)) ?? l.someone),\n isMe: mine,\n }\n }\n /** Who started a thread. */\n const starter = (task: T): TaskPerson => {\n const id = task.created_by_ext_id ?? task.owner_ext_id\n const mine = task.is_owner !== false\n return {\n id,\n label: mine ? l.me : ((id && peopleNames.get(id)) ?? l.someone),\n isMe: mine,\n }\n }\n const renderPerson = (person: TaskPerson) => <PersonPill person={person} />\n\n const q = (query.trim() || (props.filterText ?? '').trim()).toLowerCase()\n const counts = useMemo(() => {\n const map = new Map<string, number>(STATUS_ORDER.map((s) => [s, 0]))\n let all = 0\n for (const task of tasks) {\n const text = `${nameOf(task)} ${task.description ?? ''}`.toLowerCase()\n if (q && !text.includes(q)) continue\n all += 1\n const s = asTaskStatus(task.status)\n map.set(s, (map.get(s) ?? 0) + 1)\n }\n map.set('all', all)\n return map\n // nameOf reads the labels and workflow names the table was given.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tasks, q, props.workflowNames, l.untitled])\n\n const compare = useMemo(() => {\n if (!sort) return undefined\n // A sort key is computed once per task, not once per comparison.\n const keys = new Map<T, string | number>()\n const compute = (t: T): string | number => {\n switch (sort.colId) {\n case 'name':\n return nameOf(t).toLowerCase()\n case 'owner':\n return owner(t).label.toLowerCase()\n case 'updated':\n return t.updated_at ? Date.parse(t.updated_at) : 0\n case 'messages':\n return t.message_count ?? 0\n case 'due':\n return t.due_at ? Date.parse(t.due_at) : Number.POSITIVE_INFINITY\n default:\n return STATUS_ORDER.indexOf(asTaskStatus(t.status))\n }\n }\n const key = (t: T): string | number => {\n let k = keys.get(t)\n if (k === undefined) {\n k = compute(t)\n keys.set(t, k)\n }\n return k\n }\n const sign = sort.dir === 'asc' ? 1 : -1\n return (a: T, b: T) => {\n const [x, y] = [key(a), key(b)]\n if (typeof x === 'number' && typeof y === 'number') return (x - y) * sign\n return String(x).localeCompare(String(y)) * sign\n }\n // The name lookups close over the people, agents and workflows the table was given.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n sort,\n peopleNames,\n props.agentNames,\n props.workflowNames,\n l.me,\n l.agent,\n l.someone,\n l.untitled,\n ])\n\n const rows = useMemo(\n () =>\n buildTaskRows(tasks, filter, collapsed, compare, {\n query: query.trim() || props.filterText,\n titleOf: nameOf,\n cache: rowCache.current,\n }),\n // nameOf reads the labels and workflow names the table was given.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [tasks, filter, collapsed, compare, query, props.filterText, props.workflowNames, l.untitled]\n )\n\n // Selection lives here (the grid mirrors it), so a parent can carry its sub-tasks with it, even\n // the collapsed or filtered-out ones the grid does not show.\n const selectedRows = useMemo(\n () => rows.filter((r) => selectedIds.has(r.external_id)),\n [rows, selectedIds]\n )\n const selectedTasks = useMemo(\n () => tasks.filter((t) => selectedIds.has(t.external_id)),\n [tasks, selectedIds]\n )\n const subtasksIncluded = useMemo(\n () =>\n selectedTasks.filter((t) => {\n const parent = tree.parentOf.get(t.external_id)\n return parent !== undefined && selectedIds.has(parent)\n }).length,\n [selectedTasks, selectedIds, tree]\n )\n // Only a task is marked done: a plain chat has no status to finish.\n const markable = selectedTasks.filter(\n (t) =>\n t.status != null &&\n (t.is_owner !== false || props.canEditShared) &&\n isPlainTodo(t) &&\n asTaskStatus(t.status) !== 'done'\n )\n const deletable = selectedTasks.filter((t) => t.is_owner !== false || props.isWorkspaceOwner)\n\n const rowsRef = useRef(rows)\n rowsRef.current = rows\n const handleSelectionChange = (picked: Row<T>[]) => {\n const visible = new Set(rowsRef.current.map((r) => r.external_id))\n const pickedIds = new Set(picked.map((r) => r.external_id))\n setSelectedIds((prev) => {\n const added = [...pickedIds].filter((id) => !prev.has(id))\n const removed = [...prev].filter((id) => visible.has(id) && !pickedIds.has(id))\n if (added.length === 0 && removed.length === 0) return prev\n const next = new Set(prev)\n const nested = true\n for (const id of added) {\n next.add(id)\n if (nested) for (const d of descendantIds(tree, id)) next.add(d)\n }\n for (const id of removed) {\n next.delete(id)\n if (!nested) continue\n for (const d of descendantIds(tree, id)) next.delete(d)\n // A parent is no longer fully selected once one of its sub-tasks is not.\n for (let at = tree.parentOf.get(id); at; at = tree.parentOf.get(at)) next.delete(at)\n }\n return next\n })\n }\n\n const setExpanded = (id: string, expanded: boolean) =>\n setCollapsed((prev) => {\n if (prev.has(id) === !expanded) return prev\n const next = new Set(prev)\n if (expanded) next.delete(id)\n else next.add(id)\n return next\n })\n const expandAll = () => setCollapsed(new Set())\n const collapseAll = () => setCollapsed(new Set(tree.kids.keys()))\n\n // The column definitions are built once. Their cells read the latest props and lookups through\n // this ref, so a selection, a filter or an expand never makes the grid rebuild its columns.\n const latest = useRef({ props, l, owner, starter, renderPerson, nameOf, setExpanded, narrow })\n latest.current = { props, l, owner, starter, renderPerson, nameOf, setExpanded, narrow }\n\n // The Outputs column earns its room once some task has produced something.\n const showOutputs = Object.values(props.outputsByTask ?? {}).some((o) => o.length > 0)\n const columnDefs = useMemo(\n () =>\n createTaskColumns<T>({\n narrow,\n labels: l,\n getOwnerName: (row) => latest.current.owner(row.task).label,\n renderName: (row) => {\n const { l: lb, props: p, nameOf: name } = latest.current\n const { task, depth, childStats, expanded } = row\n const id = task.external_id\n const status = asTaskStatus(task.status)\n const goal = goalProgress(task)\n const workflowName = task.workflow_ext_id ? p.workflowNames?.[task.workflow_ext_id] : null\n return (\n <div\n className=\"flex min-w-0 flex-1 items-center gap-1.5\"\n style={\n depth > 0\n ? { paddingLeft: `${Math.min(depth, MAX_INDENT_DEPTH) * 1.5}rem` }\n : undefined\n }\n data-depth={depth}\n aria-level={depth + 1}\n aria-setsize={row.setSize}\n aria-posinset={row.posInSet}\n data-context={row.context || undefined}\n >\n {childStats ? (\n <button\n type=\"button\"\n onClick={() => latest.current.setExpanded(id, !expanded)}\n aria-expanded={expanded}\n aria-label={expanded ? lb.collapseSubtasks : lb.expandSubtasks}\n className=\"flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-muted hover:text-foreground\"\n data-testid={`task-expand-${id}`}\n >\n {expanded ? (\n <ChevronDown className=\"size-4\" aria-hidden />\n ) : (\n <ChevronRight className=\"size-4\" aria-hidden />\n )}\n </button>\n ) : depth > 0 ? (\n <span className=\"size-5 shrink-0\" aria-hidden />\n ) : null}\n <div className=\"min-w-0 flex-1 leading-tight\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => latest.current.props.onOpenThread(id, task)}\n // The agent that prepared the work is not a column: it is named here, on hover.\n title={\n task.agent_ext_id\n ? lb.preparedBy(p.agentNames?.[task.agent_ext_id] || lb.agent)\n : undefined\n }\n className={cn(\n // The title has priority: it keeps at least 12 characters before it ellipsises.\n 'min-w-[12ch] truncate text-left text-sm font-medium hover:underline focus-visible:underline focus-visible:outline-none',\n status === 'done' && 'text-muted-foreground line-through'\n )}\n data-testid={`task-name-${id}`}\n >\n {name(task)}\n </button>\n {goal && (\n <ToneBadge\n tone={goal.done ? 'success' : 'neutral'}\n data-testid={`task-goal-progress-${id}`}\n >\n {goal.done ? '\u2713 ' : ''}\n {lb.goalMet(goal.met, goal.total)}\n </ToneBadge>\n )}\n </div>\n {/* A phone has no Status column: the status sits under the title. */}\n {latest.current.narrow && (\n <div className=\"pt-0.5\">\n <TaskStatusPill\n id={id}\n status={status}\n runStartedAt={task.run_started_at}\n lastError={task.last_error}\n awaitingAccess={Boolean(task.pending_auth_request_id)}\n labels={p.statusPillLabels}\n />\n </div>\n )}\n {/* Second line: what it is (or where it came from) and the sub-task count, which never\n squeezes the title above it. */}\n {(task.description || workflowName || childStats) && (\n <div className=\"flex min-w-0 items-center gap-2 text-xs text-muted-foreground\">\n {task.description ? (\n <p className=\"min-w-0 truncate\">{task.description}</p>\n ) : workflowName ? (\n <span\n className=\"inline-flex min-w-0 items-center gap-1.5\"\n data-testid={`task-workflow-${id}`}\n >\n <Workflow className=\"size-3.5 shrink-0\" aria-hidden />\n <span className=\"truncate\">{lb.fromWorkflow(workflowName)}</span>\n </span>\n ) : null}\n {childStats && (\n <span\n className=\"shrink-0 tabular-nums\"\n data-testid={`task-subtask-progress-${id}`}\n >\n {lb.subtasksDone(childStats.done, childStats.total)}\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n )\n },\n // Who has the next step: the person pill, with the \"Me\" treatment. A plain chat is its starter's.\n renderOwner: (row) => (\n <span data-testid={`task-owner-${row.external_id}`} className=\"flex min-w-0\">\n {latest.current.renderPerson(\n row.task.status ? latest.current.owner(row.task) : latest.current.starter(row.task)\n )}\n </span>\n ),\n renderDue: (row) => {\n const { l: lb, props: p } = latest.current\n const { task } = row\n const dueMs = task.due_at ? Date.parse(task.due_at) : NaN\n const overdue =\n asTaskStatus(task.status) !== 'done' && !Number.isNaN(dueMs) && dueMs < Date.now()\n return (\n <span\n className={cn(\n 'truncate text-sm',\n overdue ? 'font-medium text-red-text' : 'text-muted-foreground'\n )}\n data-testid={`task-due-${task.external_id}`}\n data-overdue={overdue}\n >\n {task.due_at\n ? overdue\n ? lb.overdue(p.formatDate(task.due_at))\n : lb.due(p.formatDate(task.due_at))\n : lb.noDue}\n </span>\n )\n },\n renderShared: (row) => {\n const { l: lb, props: p } = latest.current\n const { task } = row\n // A teammate cannot change the owner's visibility choice.\n if (!p.onToggleShared) return null\n return (\n <SharingEntity\n shared={task.is_shared ?? false}\n onToggle={(shouldShare) => latest.current.props.onToggleShared?.(task, shouldShare)}\n disabled={task.is_owner === false}\n disabledTooltip={lb.sharedOwnerOnly}\n tooltipActive=\"Shared with this workspace \u2014 click to make private\"\n tooltipInactive=\"Only you can see this \u2014 click to share with this workspace\"\n data-testid={`task-shared-${task.external_id}`}\n />\n )\n },\n showOutputs,\n renderOutputs: (row) => (\n <TaskOutputsCell\n id={row.external_id}\n outputs={latest.current.props.outputsByTask?.[row.external_id]}\n onOpen={(docId) => latest.current.props.onOpenOutput?.(docId, row.task)}\n labels={latest.current.props.outputsLabels}\n />\n ),\n renderStatus: (row) => (\n <TaskStatusPill\n id={row.external_id}\n status={asTaskStatus(row.task.status)}\n runStartedAt={row.task.run_started_at}\n lastError={row.task.last_error}\n awaitingAccess={Boolean(row.task.pending_auth_request_id)}\n labels={latest.current.props.statusPillLabels}\n hint={statusHint(row.task, latest.current)}\n />\n ),\n renderActions: (row) => {\n const { l: lb, props: p } = latest.current\n const { task } = row\n const id = task.external_id\n const status = asTaskStatus(task.status)\n const busy = p.busyId === id\n const isOwner = task.is_owner !== false\n const canEdit = isOwner || Boolean(p.canEditShared)\n const canAdmin = isOwner || Boolean(p.isWorkspaceOwner)\n return (\n <div className=\"flex items-center justify-end gap-2\">\n {!latest.current.narrow &&\n isOwner &&\n task.pending_auth_request_id &&\n p.onGrantAccess && (\n <Button\n size=\"sm\"\n className=\"h-8 gap-1.5 pointer-coarse:h-11\"\n onClick={() => p.onGrantAccess?.(task)}\n data-testid={`task-allow-access-${id}`}\n >\n <KeyRound className=\"size-3.5\" aria-hidden />\n {lb.allowAccess}\n </Button>\n )}\n <TaskRowMenu\n task={task}\n status={status}\n busy={busy}\n isOwner={isOwner}\n canAdmin={canAdmin}\n canEdit={canEdit}\n labels={lb}\n onMarkDone={() => p.onMarkDone(task)}\n onReopen={() => p.onReopen(task)}\n onAddSubtask={p.onAddSubtask ? () => p.onAddSubtask?.(task) : undefined}\n onMoveTo={p.onMove ? () => setMoving(task) : undefined}\n onEdit={() => p.onEdit(task)}\n onDelete={() => p.onDelete(task)}\n onOpenActivity={p.onOpenActivity ? () => p.onOpenActivity?.(task) : undefined}\n onGrantAccess={p.onGrantAccess ? () => p.onGrantAccess?.(task) : undefined}\n />\n </div>\n )\n },\n }),\n // Stable on purpose: only the header texts rebuild the columns (see `latest`).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n l.colTask,\n l.colOwner,\n l.colDue,\n l.colStatus,\n l.colShared,\n l.colOutputs,\n l.shared,\n showOutputs,\n narrow,\n ]\n )\n\n // Cells read their data through `latest`, so a change in the lookups they draw from (people, agents,\n // workflow names, the row in flight) redraws the cells once, rather than on every interaction.\n useEffect(() => {\n apiRef.current?.refreshCells({ force: true })\n }, [\n busyId,\n props.people,\n props.agentNames,\n props.workflowNames,\n props.outputsByTask,\n props.labels,\n props.canEditShared,\n props.isWorkspaceOwner,\n narrow,\n ])\n\n const animate = rows.length <= ANIMATE_ROWS_UP_TO\n const gridOptions = useMemo<Partial<GridOptions<Row<T>>>>(\n () => ({\n suppressClickEdit: true,\n // Keyboard focus lives on the name column only (the others are not navigable): ArrowRight\n // opens a task's sub-tasks and ArrowLeft closes them, or steps up to the parent.\n suppressCellFocus: false,\n suppressColumnVirtualisation: true,\n animateRows: animate,\n getRowClass: (p) => (p.data?.context ? 'opacity-60' : undefined),\n // The grid shows and reports the sort; the table orders each level (see buildTaskRows).\n onSortChanged: (event) => {\n const sorted = event.api.getColumnState().find((c) => c.sort)\n setSort(\n sorted?.colId\n ? { colId: sorted.colId as SortableTaskColumn, dir: sorted.sort ?? 'asc' }\n : null\n )\n },\n onGridSizeChanged: (event) => {\n applyColumnWidthRules(event.api, event.clientWidth, WIDTH_RULES)\n setNarrow(event.clientWidth < NARROW_GRID)\n },\n onCellKeyDown: (event: CellKeyDownEvent<Row<T>>) => {\n const row = event.data\n const key = (event.event as KeyboardEvent | null)?.key\n if (!row || event.column.getColId() !== 'name') return\n if (key === 'ArrowRight' && row.childStats && !row.expanded) {\n event.event?.preventDefault()\n latest.current.setExpanded(row.external_id, true)\n } else if (key === 'ArrowLeft') {\n if (row.childStats && row.expanded) {\n event.event?.preventDefault()\n latest.current.setExpanded(row.external_id, false)\n } else if (row.parentId) {\n event.event?.preventDefault()\n const parent = event.api.getRowNode(row.parentId)\n if (parent?.rowIndex != null) {\n event.api.ensureIndexVisible(parent.rowIndex)\n event.api.setFocusedCell(parent.rowIndex, 'name')\n }\n }\n }\n },\n }),\n [animate]\n )\n\n const clearSelection = () => setSelectedIds(new Set())\n // A Chat chip only once there is a plain chat, so the chips add up to All.\n const filterKeys = (['all', ...STATUS_ORDER] as TaskFilter[]).filter(\n (key) => key !== 'chat' || (counts.get(key) ?? 0) > 0\n )\n const hasChildren = tree.kids.size > 0\n\n return (\n <div\n className=\"flex min-h-0 flex-1 flex-col gap-3\"\n data-testid={testIdOr(testId, { testId: 'task-list' })}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <div role=\"tablist\" aria-label=\"Filter tasks\" className=\"flex flex-wrap gap-1.5\">\n {filterKeys.map((key) => {\n const count = counts.get(key) ?? 0\n const isSelected = filter === key\n return (\n <button\n key={key}\n type=\"button\"\n role=\"tab\"\n aria-selected={isSelected}\n onClick={() => setFilter(key)}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11',\n isSelected\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border text-muted-foreground hover:bg-accent'\n )}\n data-testid={`task-filter-${key}`}\n >\n {key === 'all' ? l.filterAll : l.status[key]}\n <span className=\"tabular-nums opacity-70\">{count}</span>\n </button>\n )\n })}\n </div>\n <Input\n type=\"search\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={l.searchPlaceholder}\n aria-label={l.searchLabel}\n className=\"h-8 max-w-56 text-xs pointer-coarse:h-11\"\n data-testid=\"task-search\"\n />\n {hasChildren && (\n <div className=\"ml-auto flex gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 gap-1.5 text-xs pointer-coarse:h-11\"\n onClick={expandAll}\n data-testid=\"task-expand-all\"\n >\n <ChevronsUpDown className=\"size-3.5\" aria-hidden />\n {l.expandAll}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 gap-1.5 text-xs pointer-coarse:h-11\"\n onClick={collapseAll}\n data-testid=\"task-collapse-all\"\n >\n <ChevronsDownUp className=\"size-3.5\" aria-hidden />\n {l.collapseAll}\n </Button>\n </div>\n )}\n </div>\n {tasks.length === 0 && !isLoading ? (\n <EmptyState\n icon={ListTodo}\n title={l.emptyTitle}\n description={l.emptyMessage}\n testId=\"task-list-empty\"\n />\n ) : (\n <div className=\"min-h-0 flex-1\">\n <GridView<Row<T>>\n testId=\"task-grid\"\n gridId={props.gridId ?? 'tasks-grid-v4'}\n items={rows}\n columnDefs={columnDefs}\n getItemId={(row) => row.external_id}\n getRowTestId={(row) => `task-row-${row.external_id}`}\n isLoading={isLoading}\n showEmpty={rows.length === 0}\n emptyState={{ title: l.noMatches }}\n rowHeight={narrow ? NARROW_ROW_HEIGHT : ROW_HEIGHT}\n height=\"100%\"\n onGridReady={({ api }) => {\n apiRef.current = api\n }}\n selection={{\n mode: 'multiple',\n controlled: true,\n selected: selectedRows,\n onSelectionChange: handleSelectionChange,\n }}\n gridOptions={gridOptions}\n />\n </div>\n )}\n <SelectionBar\n count={selectedTasks.length}\n onClear={clearSelection}\n status={\n selectedTasks.length > 0 && subtasksIncluded > 0 ? (\n <span className=\"text-xs text-muted-foreground\" data-testid=\"task-selection-subtasks\">\n {l.subtasksSelected(subtasksIncluded)}\n </span>\n ) : undefined\n }\n >\n {(isCompact) => (\n <>\n {props.onMarkDoneMany && (\n <SelectionBarAction\n icon={CheckCheck}\n label={l.markDoneMany}\n onClick={() => {\n props.onMarkDoneMany?.(markable)\n clearSelection()\n }}\n disabled={markable.length === 0}\n isCompact={isCompact}\n tooltip={l.markDoneManyHint}\n testId=\"task-bulk-done\"\n />\n )}\n {props.onDeleteMany && (\n <SelectionBarAction\n icon={Trash2}\n label={l.deleteMany}\n onClick={() => {\n props.onDeleteMany?.(deletable)\n clearSelection()\n }}\n disabled={deletable.length === 0}\n isCompact={isCompact}\n className=\"border-red-border text-red-text hover:bg-red-bg hover:text-red-text\"\n testId=\"task-bulk-delete\"\n />\n )}\n </>\n )}\n </SelectionBar>\n {moving && props.onMove && (\n <TaskMoveDialog\n open\n onOpenChange={(open) => !open && setMoving(null)}\n options={moveTargets(tasks, moving).map((t) => ({ id: t.external_id, label: nameOf(t) }))}\n currentParentId={moving.parent_conversation_ext_id}\n onPick={(parentId) => props.onMove?.(moving, parentId)}\n labels={{\n title: l.moveToTitle(nameOf(moving)),\n none: l.moveToNone,\n search: l.moveToSearch,\n empty: l.moveToEmpty,\n cancel: l.moveToCancel,\n }}\n />\n )}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -11,8 +11,8 @@ import {
11
11
  DropdownMenuSeparator,
12
12
  DropdownMenuTrigger,
13
13
  Switch,
14
- VisibilityToggle,
15
- cn
14
+ cn,
15
+ SharingEntity
16
16
  } from "@arbidocs/react/ui";
17
17
  import { TabHeader } from "../../shell/TabHeader.js";
18
18
  import { FilterInput } from "../../shell/FilterInput.js";
@@ -167,13 +167,12 @@ function WorkflowsTable(props) {
167
167
  if (!p.onToggleShared || isSkillRow(w)) return null;
168
168
  const isCreator = w.is_owner !== false;
169
169
  return /* @__PURE__ */ jsx(
170
- VisibilityToggle,
170
+ SharingEntity,
171
171
  {
172
- items: { shared: w.shared ?? false },
172
+ shared: w.shared ?? false,
173
173
  onToggle: (share) => latest.current.props.onToggleShared?.(w, share),
174
174
  disabled: !isCreator || p.busyId === w.external_id,
175
175
  disabledTooltip: lb.sharedOwnerOnly,
176
- showLabel: false,
177
176
  "data-testid": `workflow-shared-${w.external_id}`
178
177
  }
179
178
  );