@arbidocs/blocks 0.4.72 → 0.4.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/index.cjs +401 -262
- package/dist/agents/index.js +7 -4
- package/dist/agents/tasks/TaskActivityTimeline.d.ts +1 -1
- package/dist/agents/tasks/WorkflowThreadStrip.d.ts +58 -0
- package/dist/agents/tasks/index.d.ts +1 -0
- package/dist/agents/workflows/WorkflowRunner.d.ts +86 -0
- package/dist/agents/workflows/WorkflowStepBar.d.ts +23 -0
- package/dist/agents/workflows/index.d.ts +7 -1
- package/dist/agents/workflows/planSteps.d.ts +28 -0
- package/dist/agents/workflows/run.d.ts +98 -0
- package/dist/agents/workflows/skillMarkdown.d.ts +15 -0
- package/dist/agents/workflows/types.d.ts +111 -0
- package/dist/agents/workflows/useWorkflowPreview.d.ts +14 -0
- package/dist/agents/workflows/useWorkflowView.d.ts +54 -0
- package/dist/agents/workflows/workflow.d.ts +3 -1
- package/dist/chat/index.cjs +124 -124
- package/dist/chat/index.js +3 -3
- package/dist/{chunk-DH7C2UJO.cjs → chunk-5LP54CWR.cjs} +299 -526
- package/dist/chunk-5LP54CWR.cjs.map +1 -0
- package/dist/{chunk-3SFFTSOI.cjs → chunk-7CVF3DK2.cjs} +5 -5
- package/dist/{chunk-3SFFTSOI.cjs.map → chunk-7CVF3DK2.cjs.map} +1 -1
- package/dist/chunk-7D737FLE.cjs +43 -0
- package/dist/chunk-7D737FLE.cjs.map +1 -0
- package/dist/{chunk-V3L5DONY.cjs → chunk-B4SRYJLM.cjs} +31 -2
- package/dist/chunk-B4SRYJLM.cjs.map +1 -0
- package/dist/{chunk-LFGJAZ5H.js → chunk-DDF5GPIJ.js} +6 -36
- package/dist/chunk-DDF5GPIJ.js.map +1 -0
- package/dist/chunk-DETZZBG2.cjs +91 -0
- package/dist/chunk-DETZZBG2.cjs.map +1 -0
- package/dist/chunk-EVUEIBNU.js +89 -0
- package/dist/chunk-EVUEIBNU.js.map +1 -0
- package/dist/{chunk-G5QTGKDJ.cjs → chunk-HITAN7JF.cjs} +8 -8
- package/dist/{chunk-G5QTGKDJ.cjs.map → chunk-HITAN7JF.cjs.map} +1 -1
- package/dist/{chunk-3VQYJBOI.js → chunk-HOXKR26S.js} +31 -4
- package/dist/chunk-HOXKR26S.js.map +1 -0
- package/dist/{chunk-KJ3QEKOJ.cjs → chunk-IPGKTUF7.cjs} +7 -33
- package/dist/chunk-IPGKTUF7.cjs.map +1 -0
- package/dist/{chunk-IMC2Z32C.js → chunk-KOSGX3UK.js} +269 -485
- package/dist/chunk-KOSGX3UK.js.map +1 -0
- package/dist/{chunk-KOXUBCLL.js → chunk-MK6NJQGF.js} +4 -4
- package/dist/{chunk-KOXUBCLL.js.map → chunk-MK6NJQGF.js.map} +1 -1
- package/dist/{chunk-THO7DZNN.cjs → chunk-MUMH3Z6K.cjs} +20 -15
- package/dist/chunk-MUMH3Z6K.cjs.map +1 -0
- package/dist/{chunk-5HOAOKZL.js → chunk-OYMWV45N.js} +21 -16
- package/dist/chunk-OYMWV45N.js.map +1 -0
- package/dist/chunk-P2RBE3FD.cjs +1448 -0
- package/dist/chunk-P2RBE3FD.cjs.map +1 -0
- package/dist/{chunk-G5DP27DU.js → chunk-UIWLDSTF.js} +3 -29
- package/dist/chunk-UIWLDSTF.js.map +1 -0
- package/dist/{chunk-VRPRAU3J.js → chunk-WJEKRSPH.js} +3 -3
- package/dist/{chunk-VRPRAU3J.js.map → chunk-WJEKRSPH.js.map} +1 -1
- package/dist/chunk-XD2M6LIG.js +41 -0
- package/dist/chunk-XD2M6LIG.js.map +1 -0
- package/dist/chunk-YWYVIQ7T.js +1402 -0
- package/dist/chunk-YWYVIQ7T.js.map +1 -0
- package/dist/{chunk-WBDK4PIA.cjs → chunk-Z5VUZ6YD.cjs} +6 -37
- package/dist/chunk-Z5VUZ6YD.cjs.map +1 -0
- package/dist/connect/docx.cjs +2 -2
- package/dist/connect/docx.js +1 -1
- package/dist/connect/index.cjs +379 -27
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +1 -0
- package/dist/connect/index.js +362 -11
- package/dist/connect/index.js.map +1 -1
- package/dist/connection/ConnectedWorkflowBuilder.d.ts +44 -0
- package/dist/connection/ConnectedWorkflowRunner.d.ts +31 -0
- package/dist/connection/useWorkflowThread.d.ts +38 -0
- package/dist/facts/index.cjs +1 -1
- package/dist/facts/index.js +1 -1
- package/dist/files/index.cjs +9 -83
- package/dist/files/index.cjs.map +1 -1
- package/dist/files/index.js +6 -83
- package/dist/files/index.js.map +1 -1
- package/dist/home/index.cjs +22 -21
- package/dist/home/index.cjs.map +1 -1
- package/dist/home/index.js +4 -3
- package/dist/home/index.js.map +1 -1
- package/dist/index.cjs +579 -440
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -8
- package/dist/index.js.map +1 -1
- package/dist/shell/index.cjs +1 -1
- package/dist/shell/index.js +1 -1
- package/dist/studio/index.cjs +7 -7
- package/dist/studio/index.js +5 -5
- package/dist/workflow-canvas/StepInspector.d.ts +57 -0
- package/dist/workflow-canvas/TriggerInspector.d.ts +46 -0
- package/dist/workflow-canvas/WorkflowBuilder.d.ts +55 -0
- package/dist/workflow-canvas/WorkflowCanvas.d.ts +69 -0
- package/dist/workflow-canvas/edit.d.ts +54 -0
- package/dist/workflow-canvas/index.cjs +1719 -0
- package/dist/workflow-canvas/index.cjs.map +1 -0
- package/dist/workflow-canvas/index.d.ts +13 -0
- package/dist/workflow-canvas/index.js +1689 -0
- package/dist/workflow-canvas/index.js.map +1 -0
- package/dist/workflow-canvas/trigger.d.ts +51 -0
- package/dist/workflow-canvas/viewport.d.ts +47 -0
- package/package.json +25 -14
- package/src/workflow-canvas/canvas.css +113 -0
- package/dist/chunk-3VQYJBOI.js.map +0 -1
- package/dist/chunk-5HOAOKZL.js.map +0 -1
- package/dist/chunk-DH7C2UJO.cjs.map +0 -1
- package/dist/chunk-G5DP27DU.js.map +0 -1
- package/dist/chunk-IMC2Z32C.js.map +0 -1
- package/dist/chunk-KJ3QEKOJ.cjs.map +0 -1
- package/dist/chunk-LFGJAZ5H.js.map +0 -1
- package/dist/chunk-THO7DZNN.cjs.map +0 -1
- package/dist/chunk-V3L5DONY.cjs.map +0 -1
- package/dist/chunk-WBDK4PIA.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/home/FoldSection.tsx","../src/home/AddFilesFirst.tsx","../src/home/QuickActionDialogHeader.tsx","../src/lib/useScopeSelection.ts","../src/home/ScopePicker.tsx","../src/home/sections.tsx","../src/lib/balanced-columns.ts","../src/home/StartTiles.tsx"],"names":["jsxs","jsx","cn","useMemo","useState"],"mappings":"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","file":"chunk-LFGJAZ5H.js","sourcesContent":["import type { ReactNode } from 'react'\nimport { ChevronDown } from 'lucide-react'\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger, cn } from '@arbidocs/react/ui'\n\nexport interface FoldSectionProps {\n label: string\n /** Shown as plain muted text beside the name; omit or pass 0 to hide. */\n count?: number\n /** A word or two of state for sections a count cannot summarise (shown while shut). */\n hint?: string\n open: boolean\n onOpenChange: (open: boolean) => void\n /** Trigger test id; the caller owns the naming. */\n testId: string\n children: ReactNode\n}\n\n/**\n * One foldable block of a dialog. The chevron and the name are the whole hit\n * target (44px on touch), and the count keeps the selection readable while the\n * section is shut, so you need not re-open it to check.\n */\nexport function FoldSection({\n label,\n count = 0,\n hint,\n open,\n onOpenChange,\n testId,\n children,\n}: FoldSectionProps) {\n return (\n <Collapsible open={open} onOpenChange={onOpenChange} data-slot=\"fold-section\">\n <CollapsibleTrigger\n className=\"mb-1.5 flex w-full items-center gap-1.5 rounded-md text-sm font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [&:hover]:text-muted-foreground pointer-coarse:min-h-11\"\n data-testid={testId}\n >\n <ChevronDown\n className={cn('size-4 shrink-0 transition-transform', !open && '-rotate-90')}\n />\n <span>{label}</span>\n {count > 0 && <span className=\"text-xs tabular-nums text-muted-foreground\">{count}</span>}\n {hint && !open && (\n <span className=\"min-w-0 truncate text-xs font-normal text-muted-foreground\">{hint}</span>\n )}\n </CollapsibleTrigger>\n <CollapsibleContent>{children}</CollapsibleContent>\n </Collapsible>\n )\n}\n","import type { ReactNode } from 'react'\nimport { FolderPlus } from 'lucide-react'\n\n/** Fixed strings of the empty-files state. */\nexport interface AddFilesFirstLabels {\n heading: string\n}\n\nexport const DEFAULT_ADD_FILES_FIRST_LABELS: AddFilesFirstLabels = {\n heading: 'Add files first',\n}\n\nexport interface AddFilesFirstProps {\n /** Why this action needs files, in the action's own words. */\n reason: string\n /** The host's own \"Add\" control. */\n action: ReactNode\n testId?: string\n labels?: Partial<AddFilesFirstLabels>\n}\n\n/**\n * What a quick-action dialog shows when the workspace has no files yet.\n *\n * Greying the action out says you cannot do it without saying how to get\n * there. Offering the same \"Add\" menu the Files view carries turns the dead\n * end into the first step: add files here, then run the action.\n */\nexport function AddFilesFirst({ reason, action, testId, labels }: AddFilesFirstProps) {\n const l = { ...DEFAULT_ADD_FILES_FIRST_LABELS, ...labels }\n return (\n <div\n className=\"flex flex-col items-center gap-3 rounded-lg border border-border bg-card shadow-xs px-4 py-8 text-center\"\n data-slot=\"add-files-first\"\n data-testid={testId}\n >\n <span className=\"flex size-11 items-center justify-center rounded-full bg-ai-soft text-ai-ink\">\n <FolderPlus className=\"size-5\" aria-hidden=\"true\" />\n </span>\n <div className=\"flex flex-col gap-1\">\n <p className=\"text-sm font-semibold text-foreground\">{l.heading}</p>\n <p className=\"text-xs leading-relaxed text-muted-foreground\">{reason}</p>\n </div>\n {action}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { DialogDescription, DialogHeader, DialogTitle } from '@arbidocs/react/ui'\n\nexport interface QuickActionDialogHeaderProps {\n /** The tile's glyph, sized by the caller at `size-5`. */\n icon: ReactNode\n title: string\n /** One sentence on what the dialog does. Keep it to a line or two. */\n description: ReactNode\n /** Test id for the description, where a test asserts on the copy. */\n descriptionTestId?: string\n}\n\n/**\n * The header every \"Start\" quick-action dialog wears: the tile's own mark in\n * its disc, the action's name, and one line saying what the dialog will do.\n *\n * - The disc centres on the TITLE row, so it reads as the title's mark.\n * - The description keeps the title's left edge (`pl-13` = disc + gap), so the\n * header is one text column beside the mark rather than an L.\n * - `max-w-prose` + `text-pretty` cap the measure and stop two-word orphans.\n * - `pr-8` keeps the copy clear of the close button.\n */\nexport function QuickActionDialogHeader({\n icon,\n title,\n description,\n descriptionTestId,\n}: QuickActionDialogHeaderProps) {\n return (\n <DialogHeader className=\"space-y-0 text-left\" data-slot=\"quick-action-dialog-header\">\n <div className=\"flex items-center gap-3 pr-8\">\n <div className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-ai-soft text-ai-ink\">\n {icon}\n </div>\n <DialogTitle className=\"text-xl font-semibold leading-tight\">{title}</DialogTitle>\n </div>\n <DialogDescription\n className=\"mt-2 max-w-prose pl-13 pr-8 text-sm leading-relaxed text-pretty\"\n data-testid={descriptionTestId}\n >\n {description}\n </DialogDescription>\n </DialogHeader>\n )\n}\n","import { useMemo } from 'react'\n\n/** Which folders and labels a run is limited to. Empty = everything. */\nexport interface DocumentScope {\n /** Folder paths; `''` is the \"unfiled\" bucket. */\n folders: string[]\n /** Label (tag) ids. */\n labels: string[]\n}\n\nexport interface UseScopeSelectionOptions {\n /** Every folder path in the tree (not including the unfiled bucket). */\n folderPaths: string[]\n /** Whether the unfiled bucket is shown as a row. */\n hasUnfiled: boolean\n scope: DocumentScope\n onScopeChange: (scope: DocumentScope) => void\n}\n\n/**\n * Headless selection logic for a folder + label scope picker.\n *\n * Folders use hierarchical selection: ticking \"contracts\" also ticks\n * \"contracts/2024\", and unticking removes the whole subtree. \"All\" ticks every\n * row, which is NOT the same as an empty scope: empty means \"the whole\n * workspace, whatever lands in it later\", all-ticked means \"these folders, as\n * they are now\".\n */\nexport function useScopeSelection({\n folderPaths,\n hasUnfiled,\n scope,\n onScopeChange,\n}: UseScopeSelectionOptions) {\n const selectedFolders = useMemo(() => new Set(scope.folders), [scope.folders])\n const selectedLabels = useMemo(() => new Set(scope.labels), [scope.labels])\n\n /** Every row the folder list shows, \"unfiled\" included. */\n const allRowPaths = useMemo(\n () => [...(hasUnfiled ? [''] : []), ...folderPaths],\n [folderPaths, hasUnfiled]\n )\n const allSelected = allRowPaths.length > 0 && allRowPaths.every((p) => selectedFolders.has(p))\n const someSelected = selectedFolders.size > 0 && !allSelected\n\n const descendants = (path: string) => folderPaths.filter((p) => p.startsWith(path + '/'))\n\n const toggleFolder = (path: string) => {\n const next = new Set(selectedFolders)\n const family = [path, ...descendants(path)]\n if (next.has(path)) for (const p of family) next.delete(p)\n else for (const p of family) next.add(p)\n onScopeChange({ folders: [...next], labels: scope.labels })\n }\n\n const toggleAllFolders = () => {\n onScopeChange({ folders: allSelected ? [] : allRowPaths, labels: scope.labels })\n }\n\n const toggleLabel = (labelId: string) => {\n const next = new Set(selectedLabels)\n if (next.has(labelId)) next.delete(labelId)\n else next.add(labelId)\n onScopeChange({ folders: scope.folders, labels: [...next] })\n }\n\n return {\n selectedFolders,\n selectedLabels,\n allSelected,\n someSelected,\n hasSelection: scope.folders.length > 0 || scope.labels.length > 0,\n toggleFolder,\n toggleAllFolders,\n toggleLabel,\n }\n}\n","import { useMemo, useState } from 'react'\nimport { Check, FileCheck2, Minus } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { prefixedTestId, testIdOr } from '../chat/test-id'\nimport { useScopeSelection, type DocumentScope } from '../lib/useScopeSelection'\nimport { formatCount } from '../lib/format'\nimport { FoldSection } from './FoldSection'\n\n/**\n * Fixed strings of the picker. Passed as `uiLabels`: the `labels` prop is already the list of\n * document labels to scope by.\n */\nexport interface ScopePickerLabels {\n folders: string\n /** The Labels section heading. */\n labelsHeading: string\n all: string\n unfiled: string\n noFoldersYet: string\n noLabelsYet: string\n filesToInclude: string\n /** \"3 of 10 files\". */\n matchedOfTotal: (matched: number, total: number) => string\n selectedSuffix: string\n folderCount: (count: number) => string\n labelCount: (count: number) => string\n left: (count: number) => string\n /** \"All 10 files\". */\n allFiles: (total: number) => string\n includedSuffix: string\n}\n\nconst pluralize = (n: number, word: string) => `${n} ${word}${n !== 1 ? 's' : ''}`\n\nexport const DEFAULT_SCOPE_PICKER_LABELS: ScopePickerLabels = {\n folders: 'Folders',\n labelsHeading: 'Labels',\n all: 'All',\n unfiled: 'Unfiled',\n noFoldersYet: 'No folders yet',\n noLabelsYet: 'No labels yet — label files from the Files page to scope by them here.',\n filesToInclude: 'Files to include',\n matchedOfTotal: (matched, total) =>\n `${matched} of ${formatCount(total, { one: 'file', other: 'files' })}`,\n selectedSuffix: ' selected',\n folderCount: (count) => pluralize(count, 'folder'),\n labelCount: (count) => pluralize(count, 'label'),\n left: (count) => `${count} left`,\n allFiles: (total) => `All ${pluralize(total, 'file')}`,\n includedSuffix: ' in the workspace will be included',\n}\n\nexport interface ScopeFolder {\n /** Full path, e.g. `contracts/2024`. */\n path: string\n /** Last segment, shown. */\n label: string\n /** Documents under this folder. */\n count: number\n depth: number\n}\n\nexport interface ScopeLabel {\n id: string\n name: string\n /** Any CSS colour for the dot. */\n color: string\n /** Documents carrying this label. */\n count: number\n}\n\nexport interface ScopePickerProps {\n folders: ScopeFolder[]\n /** Documents with no folder; the \"Unfiled\" row is hidden at 0. */\n unfiledCount: number\n labels: ScopeLabel[]\n /** All documents the picker is scoping. */\n totalCount: number\n /** Documents the current scope matches (computed by the caller). */\n matchedCount: number\n scope: DocumentScope\n onScopeChange: (scope: DocumentScope) => void\n /** Reword the picker's fixed strings. */\n uiLabels?: Partial<ScopePickerLabels>\n /** Sub-element ids; defaults are the current ids. `labelChip` is a prefix (`<prefix>-<label id>`). */\n testIds?: Partial<\n Record<'foldersToggle' | 'labelsToggle' | 'noLabels' | 'labelChip' | 'summary', string>\n >\n}\n\ninterface FolderRowProps {\n label: string\n count: number\n depth: number\n isActive: boolean\n indeterminate?: boolean\n muted?: boolean\n onToggle: () => void\n}\n\n/** A checkbox row: the row is the checkbox (a nested real one would swallow the click). */\nfunction FolderRow({\n label,\n count,\n depth,\n isActive,\n indeterminate,\n muted,\n onToggle,\n}: FolderRowProps) {\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n role=\"checkbox\"\n aria-checked={indeterminate ? 'mixed' : isActive}\n style={{ paddingLeft: `${4 + depth * 14}px` }}\n className={cn(\n 'flex w-full items-center gap-1 rounded-sm py-1 pr-2 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [&:hover]:bg-accent pointer-coarse:min-h-11',\n isActive && 'bg-primary/10',\n muted && !isActive && 'text-muted-foreground'\n )}\n data-slot=\"scope-folder-row\"\n >\n <span className=\"flex w-4 shrink-0 items-center justify-center\">\n <span\n className={cn(\n 'flex size-3.5 items-center justify-center rounded-[3px] border transition-colors',\n isActive || indeterminate\n ? 'border-primary bg-primary text-primary-foreground'\n : 'border-muted-foreground/40'\n )}\n >\n {indeterminate ? (\n <Minus className=\"size-2.5\" />\n ) : (\n isActive && <Check className=\"size-2.5\" />\n )}\n </span>\n </span>\n {label !== '' && (\n <span className={cn('min-w-0 truncate', isActive && 'font-semibold text-primary')}>\n {label}\n </span>\n )}\n <span className=\"ml-auto pl-2 text-sm font-semibold text-muted-foreground\">{count}</span>\n </button>\n )\n}\n\n/**\n * Pick a folder + label scope for a run over documents. Controlled: the caller\n * owns the scope and computes `matchedCount`, so the submit button lives with\n * the caller. Both sections start shut: the default (every file) is what most\n * runs want, and the summary states it plainly.\n */\nexport function ScopePicker({\n folders,\n unfiledCount,\n labels,\n totalCount,\n matchedCount,\n scope,\n onScopeChange,\n uiLabels,\n testIds,\n}: ScopePickerProps) {\n const l = { ...DEFAULT_SCOPE_PICKER_LABELS, ...uiLabels }\n const [foldersOpen, setFoldersOpen] = useState(false)\n const [labelsOpen, setLabelsOpen] = useState(false)\n\n const folderPaths = useMemo(() => folders.map((f) => f.path), [folders])\n const selection = useScopeSelection({\n folderPaths,\n hasUnfiled: unfiledCount > 0,\n scope,\n onScopeChange,\n })\n const hasRows = folders.length > 0 || unfiledCount > 0\n\n return (\n <div className=\"flex flex-col gap-4\" data-slot=\"scope-picker\">\n <FoldSection\n label={l.folders}\n count={scope.folders.length}\n open={foldersOpen}\n onOpenChange={setFoldersOpen}\n testId={testIdOr(testIds?.foldersToggle, { testId: 'scope-picker-folders-toggle' })}\n >\n <div className=\"max-h-[180px] overflow-y-auto rounded-md border border-border p-1\">\n {hasRows && (\n <>\n <FolderRow\n label={l.all}\n count={totalCount}\n depth={0}\n isActive={selection.allSelected}\n indeterminate={selection.someSelected}\n onToggle={selection.toggleAllFolders}\n />\n <div className=\"my-1 border-t border-border\" />\n </>\n )}\n {unfiledCount > 0 && (\n <>\n <FolderRow\n label={l.unfiled}\n count={unfiledCount}\n depth={0}\n isActive={selection.selectedFolders.has('')}\n muted\n onToggle={() => selection.toggleFolder('')}\n />\n {folders.length > 0 && <div className=\"my-1 border-t border-border\" />}\n </>\n )}\n {folders.map((folder) => (\n <FolderRow\n key={folder.path}\n label={folder.label}\n count={folder.count}\n depth={folder.depth}\n isActive={selection.selectedFolders.has(folder.path)}\n onToggle={() => selection.toggleFolder(folder.path)}\n />\n ))}\n {!hasRows && <p className=\"px-2 py-1 text-sm text-muted-foreground\">{l.noFoldersYet}</p>}\n </div>\n </FoldSection>\n\n {/* Always present, like Folders: a workspace with no labels yet reads as\n \"you have not labelled anything\", not \"this cannot scope by label\". */}\n <FoldSection\n label={l.labelsHeading}\n count={scope.labels.length}\n open={labelsOpen}\n onOpenChange={setLabelsOpen}\n testId={testIdOr(testIds?.labelsToggle, { testId: 'scope-picker-labels-toggle' })}\n >\n {labels.length === 0 ? (\n <p\n className=\"px-2 py-1 text-sm text-muted-foreground\"\n data-testid={testIdOr(testIds?.noLabels, { testId: 'scope-picker-no-labels' })}\n >\n {l.noLabelsYet}\n </p>\n ) : (\n <div className=\"flex flex-wrap gap-1.5\">\n {labels.map((label) => {\n const isActive = selection.selectedLabels.has(label.id)\n return (\n <button\n key={label.id}\n type=\"button\"\n onClick={() => selection.toggleLabel(label.id)}\n aria-pressed={isActive}\n data-testid={prefixedTestId(testIds?.labelChip, label.id, {\n testId: `scope-picker-label-chip-${label.id}`,\n })}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-md border px-2 py-1 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11',\n isActive\n ? 'border-primary/40 bg-primary/10 text-primary'\n : 'border-border [&:hover]:bg-accent [&:hover]:text-accent-foreground'\n )}\n >\n <span\n className=\"size-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: label.color }}\n />\n <span className=\"truncate\">{label.name}</span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">({label.count})</span>\n {isActive && <Check className=\"size-3.5 shrink-0\" />}\n </button>\n )\n })}\n </div>\n )}\n </FoldSection>\n\n <div\n className=\"rounded-lg bg-muted p-3\"\n data-testid={testIdOr(testIds?.summary, { testId: 'scope-picker-summary' })}\n >\n <div className=\"mb-2 flex items-center gap-1.5 text-xs font-medium text-muted-foreground\">\n <FileCheck2 className=\"size-4\" />\n {l.filesToInclude}\n </div>\n {selection.hasSelection ? (\n <div className=\"text-sm text-muted-foreground\">\n <span className=\"text-base font-semibold text-foreground\">\n {l.matchedOfTotal(matchedCount, totalCount)}\n </span>\n {l.selectedSuffix}\n {scope.folders.length > 0 && <span> — {l.folderCount(scope.folders.length)}</span>}\n {scope.folders.length > 0 && scope.labels.length > 0 && <span>, </span>}\n {scope.labels.length > 0 && <span>{l.labelCount(scope.labels.length)}</span>}\n <span className=\"text-xs\">\n {' · '}\n {l.left(totalCount - matchedCount)}\n </span>\n </div>\n ) : (\n <div className=\"text-sm text-muted-foreground\">\n <span className=\"text-base font-semibold text-foreground\">\n {l.allFiles(totalCount)}\n </span>\n {l.includedSuffix}\n </div>\n )}\n </div>\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { Plus, type LucideIcon } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { ActionLink } from '../components/ActionLink'\n\n/** The small label that names a band of a page (\"Start\", \"Recent\"). */\nexport function SectionLabel({\n children,\n className,\n testId,\n}: {\n children: ReactNode\n className?: string\n testId?: string\n}) {\n return (\n <p\n className={cn(\n 'flex items-center gap-3 text-sm font-semibold text-foreground after:h-px after:flex-1 after:bg-border',\n className\n )}\n data-slot=\"section-label\"\n data-testid={testId}\n >\n {children}\n </p>\n )\n}\n\nexport interface SectionHeaderProps {\n icon?: LucideIcon\n title: string\n count?: number\n /** Makes the title a button (open the full list). Omit for a static title. */\n onOpen?: () => void\n /** Real link target of the title; `onOpen` still fires on a plain click. */\n openHref?: string\n /** Test id of the title button. */\n openTestId?: string\n /** The section's one quiet action, rendered at the trailing edge. */\n action?: ReactNode\n className?: string\n}\n\n/** Title + count + one quiet action: the head of a list section. */\nexport function SectionHeader({\n icon: Icon,\n title,\n count,\n onOpen,\n openHref,\n openTestId,\n action,\n className,\n}: SectionHeaderProps) {\n return (\n <div\n className={cn('flex items-center justify-between gap-2', className)}\n data-slot=\"section-header\"\n >\n <ActionLink\n href={openHref}\n onSelect={onOpen}\n disabled={!onOpen && !openHref}\n className=\"flex min-w-0 cursor-pointer items-center gap-2 rounded-md py-1.5 pr-2 text-left transition-colors hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default disabled:hover:text-foreground pointer-coarse:min-h-11\"\n data-testid={openTestId}\n >\n {Icon && <Icon className=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />}\n <span className=\"whitespace-nowrap text-sm font-semibold text-foreground\">{title}</span>\n {count !== undefined && (\n <span className=\"text-sm tabular-nums text-muted-foreground\">{count}</span>\n )}\n </ActionLink>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n )\n}\n\nexport interface EmptyStripProps {\n icon?: LucideIcon\n label: ReactNode\n description?: ReactNode\n onSelect?: () => void\n testId?: string\n}\n\n/** One tonal strip that stands in for an empty section: an invitation, not a void. */\nexport function EmptyStrip({\n icon: Icon = Plus,\n label,\n description,\n onSelect,\n testId,\n}: EmptyStripProps) {\n return (\n <button\n type=\"button\"\n onClick={onSelect}\n disabled={!onSelect}\n className=\"flex w-full items-center gap-3 rounded-lg px-4 py-3 text-left border border-border bg-card shadow-xs transition-colors hover:border-ring/50 hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default disabled:hover:bg-card disabled:hover:border-border pointer-coarse:min-h-11\"\n data-slot=\"empty-strip\"\n data-testid={testId}\n >\n <Icon className=\"size-5 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-sm font-semibold text-foreground\">{label}</span>\n {description && (\n <span className=\"block text-sm leading-snug text-muted-foreground\">{description}</span>\n )}\n </span>\n </button>\n )\n}\n","/**\n * The column count for a grid of `count` equal tiles in `width` pixels, chosen so the last row is\n * never left with a lone orphan: of the counts that fit (each column at least `minTile` wide),\n * take the one that leaves the fewest empty cells in the last row, preferring more columns on a\n * tie (never fewer than two columns when two fit). Four tiles resolve to 2x2 where three would fit\n * and 4 across when there is room for four; six resolve to 3x2.\n */\nexport function balancedColumns(count: number, width: number, minTile = 200, gap = 12): number {\n if (count <= 1) return 1\n const fit = Math.max(1, Math.min(count, Math.floor((width + gap) / (minTile + gap))))\n if (fit < 2) return 1\n let best = 2\n let bestEmpty = Number.POSITIVE_INFINITY\n for (let columns = 2; columns <= fit; columns++) {\n const empty = (columns - (count % columns)) % columns\n if (empty < bestEmpty || (empty === bestEmpty && columns > best)) {\n best = columns\n bestEmpty = empty\n }\n }\n return best\n}\n","import { useEffect, useRef, useState, type ReactNode } from 'react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { ActionLink } from '../components/ActionLink'\nimport { balancedColumns } from '../lib/balanced-columns'\nimport { observeResize } from '../lib/observe-resize'\nimport { SectionLabel } from './sections'\n\n/** One \"start something\" tile: an AI-driven action, one click from underway. */\nexport interface StartTile {\n id: string\n /** A Lucide glyph; `iconNode` wins when both are given. */\n icon?: LucideIcon\n /** A ready-made mark (host icon maps), wearing the same AI ink. */\n iconNode?: ReactNode\n title: string\n description: string\n onSelect: () => void\n /** Real link target (ctrl-click / new tab, in-SPA through `BlocksProvider`'s `linkComponent`). `onSelect` still fires on a plain click. */\n href?: string\n /** Rendered non-interactive and dimmed; `disabledReason` replaces the description. */\n disabled?: boolean\n disabledReason?: string\n testId?: string\n}\n\nexport interface StartTilesProps {\n items: StartTile[]\n /** Optional band label above the tiles (\"Start\"). */\n caption?: string\n captionTestId?: string\n className?: string\n testId?: string\n}\n\n/**\n * A band of tonal action tiles. The glyph wears the AI ink, because these are\n * the AI-driven starts. Nothing is hover-only: tiles are always rendered, hover\n * only nudges tone, and touch targets are at least 44px.\n */\nexport function StartTiles({ items, caption, captionTestId, className, testId }: StartTilesProps) {\n // The tiles reflow by their own container width (a docked tablet sidebar narrows it without\n // changing the viewport), choosing a column count that never leaves one tile alone on a row.\n const gridRef = useRef<HTMLDivElement>(null)\n const [columns, setColumns] = useState<number | null>(null)\n const count = items.length\n useEffect(() => {\n const grid = gridRef.current\n if (!grid || count === 0) return\n const measure = () => setColumns(balancedColumns(count, grid.clientWidth))\n measure()\n return observeResize(grid, measure)\n }, [count])\n\n if (count === 0) return null\n return (\n <section\n className={cn('flex flex-col gap-3', className)}\n data-slot=\"start-tiles\"\n data-testid={testId}\n >\n {caption && <SectionLabel testId={captionTestId}>{caption}</SectionLabel>}\n <div\n ref={gridRef}\n data-slot=\"start-tiles-grid\"\n data-columns={columns ?? undefined}\n className=\"grid gap-3\"\n style={{\n gridTemplateColumns:\n columns === null\n ? 'repeat(auto-fit, minmax(200px, 1fr))'\n : `repeat(${columns}, minmax(0, 1fr))`,\n }}\n >\n {items.map((item) => {\n const Icon = item.icon\n return (\n <ActionLink\n key={item.id}\n href={item.href}\n onSelect={item.onSelect}\n disabled={item.disabled}\n title={item.disabled ? item.disabledReason : undefined}\n className={cn(\n 'flex h-full flex-col items-start gap-3 rounded-lg p-4 text-left',\n 'border border-border bg-card shadow-xs transition-colors hover:border-ring/50 hover:bg-accent/40',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n 'disabled:cursor-default disabled:opacity-55 disabled:hover:bg-card disabled:hover:border-border',\n 'pointer-coarse:min-h-11'\n )}\n data-slot=\"start-tile\"\n data-testid={item.testId}\n >\n {item.iconNode ? (\n <span className=\"shrink-0 text-ai-ink [&>svg]:size-5\" aria-hidden=\"true\">\n {item.iconNode}\n </span>\n ) : (\n Icon && <Icon className=\"size-5 shrink-0 text-ai-ink\" aria-hidden=\"true\" />\n )}\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-semibold text-foreground\">{item.title}</span>\n <span className=\"mt-1 block text-sm leading-snug text-muted-foreground\">\n {item.disabled && item.disabledReason ? item.disabledReason : item.description}\n </span>\n </span>\n </ActionLink>\n )\n })}\n </div>\n </section>\n )\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/connection/ConnectionProvider.tsx"],"names":["createContext","useArbi","useState","useRef","useEffect","useCallback","useMemo","jsx","useContext"],"mappings":"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","file":"chunk-THO7DZNN.cjs","sourcesContent":["/**\n * The demo/live connection layer for a host app. Holds auth + workspace\n * selection state and exposes it via {@link useConnection}, so every surface\n * works identically whether it's talking to a live ARBI backend or the seeded\n * demo workspace. Host-specific values (backend URL, demo identity, default\n * workspace/assistant ids) arrive once through {@link ArbiConnectionConfig}.\n */\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport { useArbi, type LoginProfile } from '@arbidocs/react'\nimport type { ArbiMode, ArbiUser, ConnectionStatus, ArbiConnectionConfig } from './types'\n\ninterface ConnectionValue {\n mode: ArbiMode\n status: ConnectionStatus\n user: ArbiUser | null\n workspaceId: string | null\n apiConfigured: boolean\n apiUrl: string\n /**\n * The deployment domain the user's keys are derived for (`arbi.getDeploymentDomain()`), for the\n * document tools' e-signing. `undefined` in demo mode.\n */\n deploymentDomain: string | undefined\n error: string | null\n /** Default assistant config ext_id (for the AI hooks). */\n assistantConfig?: string\n /** Fallback workspace ext_id when none is actively selected. */\n fallbackWorkspaceId?: string\n /** Authenticate. Live login when a backend is configured, otherwise the demo workspace. */\n login: (email: string, password: string) => Promise<void>\n /** One-click demo entry (no backend required). */\n enterDemo: () => void\n logout: () => void\n /**\n * Affirmatively select a workspace: opens it on the server (via the SDK),\n * updates the app-wide state, and persists the choice so it survives future\n * logins. This is the single entry point for \"the user is now in workspace X\".\n */\n setWorkspace: (id: string) => Promise<void>\n /**\n * Re-assert the selected workspace on the server session (idempotent `/open`).\n * Call before a workspace-scoped write when the session may have lost its open\n * workspace (token re-login, backend restart, session expiry) — the server\n * resolves the workspace from the session, so a dropped `/open` yields\n * \"No active workspace\" until it's re-opened.\n */\n ensureWorkspaceOpen: () => Promise<void>\n}\n\nconst ConnectionContext = createContext<ConnectionValue | null>(null)\n\n/**\n * Persist the affirmatively-selected workspace per backend AND per signed-in user, so a returning\n * user lands back in the workspace they last chose, while the next person on a shared browser\n * never starts from someone else's workspace id. Namespaced by apiUrl so distinct deployments\n * (and the demo workspace) don't clobber each other. Cleared on logout.\n */\nconst WORKSPACE_STORAGE_PREFIX = 'arbi:selectedWorkspace'\nconst sessionUserKey = (apiUrl: string) => `arbi:sessionUser:${apiUrl}`\nfunction rememberSessionUser(apiUrl: string, email: string | null) {\n try {\n if (email) window.localStorage.setItem(sessionUserKey(apiUrl), normalizeUserKey(email))\n else window.localStorage.removeItem(sessionUserKey(apiUrl))\n } catch {\n /* Storage may be unavailable. */\n }\n}\nconst normalizeUserKey = (email: string) => email.trim().toLowerCase()\n\n/** Exported for tests. */\nexport const workspaceStorageKey = (apiUrl: string, userKey: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}:${normalizeUserKey(userKey)}`\n\n/** The pre-isolation key (apiUrl only). Never read: removed so it cannot leak across users. */\nconst legacyWorkspaceStorageKey = (apiUrl: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}`\n\nfunction readPersistedWorkspace(apiUrl: string, userKey: string | null): string | null {\n if (!userKey) return null\n try {\n return window.localStorage.getItem(workspaceStorageKey(apiUrl, userKey))\n } catch {\n return null\n }\n}\n\nfunction persistWorkspace(apiUrl: string, userKey: string | null, id: string | null): void {\n if (!userKey) return\n try {\n if (id) window.localStorage.setItem(workspaceStorageKey(apiUrl, userKey), id)\n else window.localStorage.removeItem(workspaceStorageKey(apiUrl, userKey))\n window.localStorage.removeItem(legacyWorkspaceStorageKey(apiUrl))\n } catch {\n // Storage unavailable (private mode, SSR) — selection stays in-memory only.\n }\n}\n\n/** Shown on the sign-in screen after the session could not be recovered. */\nexport const SESSION_EXPIRED_MESSAGE = 'Your session expired. Sign in again.'\n\n/** The connection user for a profile: its full name, falling back to the email local part. */\nfunction userFromProfile(profile: LoginProfile, externalId?: string): ArbiUser {\n const fullName = [profile.givenName, profile.familyName]\n .map((part) => part?.trim())\n .filter(Boolean)\n .join(' ')\n return {\n name: fullName || profile.email.split('@')[0],\n email: profile.email,\n externalId,\n picture: profile.picture,\n }\n}\n\nexport function ConnectionProvider({\n config,\n children,\n}: {\n config: ArbiConnectionConfig\n children: ReactNode\n}) {\n const arbi = useArbi()\n const isLiveConfigured = config.apiUrl.length > 0\n const demoWorkspaceId = config.demoWorkspaceId ?? 'demo-workspace'\n\n const [status, setStatus] = useState<ConnectionStatus>(\n isLiveConfigured ? 'connecting' : 'disconnected'\n )\n const [user, setUser] = useState<ArbiUser | null>(null)\n const [workspaceId, setWorkspaceId] = useState<string | null>(null)\n const [mode, setMode] = useState<ArbiMode>('demo')\n const [error, setError] = useState<string | null>(null)\n // Who the persisted workspace belongs to; set at sign-in, cleared at logout.\n const storageUserRef = useRef<string | null>(null)\n\n // The SDK could not recover the session (token refused, workspace not re-openable): drop to\n // 'disconnected' with a plain message, so the host's gate sends the user to sign in instead of\n // every call failing with a raw backend error. The remembered workspace is kept for next login.\n useEffect(\n () =>\n arbi.onSessionExpired?.(() => {\n rememberSessionUser(config.apiUrl, null)\n storageUserRef.current = null\n setUser(null)\n setWorkspaceId(null)\n setStatus('disconnected')\n setError(SESSION_EXPIRED_MESSAGE)\n }),\n [arbi, config.apiUrl]\n )\n\n // A saved name, picture or email reaches every surface reading `useConnection().user`.\n useEffect(\n () =>\n arbi.user.onProfileChange?.((profile) =>\n setUser((current) => (current ? userFromProfile(profile, current.externalId) : current))\n ),\n [arbi]\n )\n\n const enterDemo = useCallback(() => {\n setMode('demo')\n setStatus('demo')\n setError(null)\n setUser({ name: config.demoUser.name, email: config.demoUser.email })\n setWorkspaceId(demoWorkspaceId)\n }, [config.demoUser.name, config.demoUser.email, demoWorkspaceId])\n\n const login = useCallback(\n async (email: string, password: string, restoring = false) => {\n setError(null)\n // No backend configured → run the seeded demo workspace.\n if (!isLiveConfigured) {\n enterDemo()\n return\n }\n setStatus('connecting')\n setMode('live')\n try {\n if (restoring) {\n if (!(await arbi.restoreSession(email))) {\n rememberSessionUser(config.apiUrl, null)\n setStatus('disconnected')\n return\n }\n } else await arbi.login(email, password)\n storageUserRef.current = normalizeUserKey(email)\n const workspaces = await arbi.workspaces.list()\n if (workspaces?.length) {\n // Prefer the workspace the user last affirmatively selected (persisted),\n // then the configured workspace (there may be several — e.g. a\n // marketing/KM workspace), then whichever happens to be first. Ternary\n // (not `&&`) so an empty value can't leak `\"\"` into `target`.\n const persisted = readPersistedWorkspace(config.apiUrl, storageUserRef.current)\n const preferred = persisted ?? config.workspaceId\n const target =\n (preferred ? workspaces.find((w) => w.external_id === preferred) : undefined) ??\n workspaces[0]\n await arbi.selectWorkspace(target.external_id)\n setWorkspaceId(target.external_id)\n persistWorkspace(config.apiUrl, storageUserRef.current, target.external_id)\n }\n // The profile (name + avatar) comes with the login response. A session restored without\n // a login has none, so fall back to finding ourselves in the workspace roster; the email\n // local part is only the last resort, never the answer when a profile name exists.\n let resolved: ArbiUser = { name: email.split('@')[0], email }\n const me = arbi.user.identity()\n const profile = arbi.user.profile?.()\n if (profile) {\n resolved = userFromProfile(profile, me?.externalId)\n } else {\n try {\n const members = await arbi.workspaces.listUsers()\n const self = members.find((m) => m.user.external_id === me?.externalId)?.user\n if (self) {\n const fullName = [self.given_name, self.family_name].filter(Boolean).join(' ').trim()\n resolved = {\n name: fullName || email.split('@')[0],\n email: self.email || email,\n externalId: self.external_id,\n picture: self.picture ?? null,\n }\n } else if (me?.externalId) {\n resolved.externalId = me.externalId\n }\n } catch {\n // Roster not available (e.g. no workspace) — keep the fallback identity.\n }\n }\n setUser(resolved)\n rememberSessionUser(config.apiUrl, email)\n setStatus('authenticated')\n } catch (e) {\n // Surface the real error — no silent fallback to a fake session.\n setError(e instanceof Error ? e.message : 'Sign-in failed. Check your credentials.')\n setStatus('error')\n }\n },\n [arbi, enterDemo, isLiveConfigured, config.workspaceId, config.apiUrl]\n )\n\n // Run once even under StrictMode; passwords and signing keys are never stored here.\n const recoveryStarted = useRef(false)\n useEffect(() => {\n if (recoveryStarted.current || !isLiveConfigured) return\n recoveryStarted.current = true\n let email: string | null = null\n try {\n email = window.localStorage.getItem(sessionUserKey(config.apiUrl))\n } catch {\n /* unavailable */\n }\n if (email) void login(email, '', true)\n else setStatus('disconnected')\n }, [isLiveConfigured, config.apiUrl, login])\n\n const logout = useCallback(() => {\n rememberSessionUser(config.apiUrl, null)\n if (mode === 'live') {\n void arbi.logout?.()\n }\n setUser(null)\n setWorkspaceId(null)\n persistWorkspace(config.apiUrl, storageUserRef.current, null)\n storageUserRef.current = null\n setStatus('disconnected')\n setError(null)\n }, [arbi, mode, config.apiUrl])\n\n // Affirmative selection: open the workspace on the server (live), then remember\n // it in state + storage so every surface — and the next login — is in sync.\n const setWorkspace = useCallback(\n async (id: string) => {\n if (mode === 'live' && arbi.isLoggedIn) {\n await arbi.selectWorkspace(id)\n }\n setWorkspaceId(id)\n persistWorkspace(config.apiUrl, storageUserRef.current, id)\n },\n [arbi, mode, config.apiUrl]\n )\n\n // Re-open the selected workspace on the session if the server may have dropped\n // it. Idempotent: re-running `/open` for the already-selected workspace is safe.\n const ensureWorkspaceOpen = useCallback(async () => {\n if (mode !== 'live' || !arbi.isLoggedIn) return\n const id =\n workspaceId ??\n readPersistedWorkspace(config.apiUrl, storageUserRef.current) ??\n config.workspaceId\n if (id) await arbi.selectWorkspace(id)\n }, [arbi, mode, workspaceId, config.apiUrl, config.workspaceId])\n\n const value = useMemo<ConnectionValue>(\n () => ({\n mode,\n status,\n user,\n workspaceId,\n apiConfigured: isLiveConfigured,\n apiUrl: config.apiUrl,\n deploymentDomain: isLiveConfigured ? arbi.getDeploymentDomain() : undefined,\n error,\n assistantConfig: config.assistantConfig,\n fallbackWorkspaceId: config.workspaceId,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n }),\n [\n mode,\n status,\n user,\n workspaceId,\n isLiveConfigured,\n config.apiUrl,\n arbi,\n config.assistantConfig,\n config.workspaceId,\n error,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n ]\n )\n\n return <ConnectionContext.Provider value={value}>{children}</ConnectionContext.Provider>\n}\n\nexport function useConnection(): ConnectionValue {\n const ctx = useContext(ConnectionContext)\n if (!ctx) throw new Error('useConnection must be used within ConnectionProvider')\n return ctx\n}\n\nexport const isAuthenticated = (s: ConnectionStatus) => s === 'demo' || s === 'authenticated'\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/chat/useMentionAutocomplete.ts"],"names":["useState","useEffect","useMemo","findMentionQuery","filterMentionCandidates","useCallback","insertMention","useListKeyNav"],"mappings":"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","file":"chunk-V3L5DONY.cjs","sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useState,\n type RefObject,\n type SyntheticEvent,\n} from 'react'\nimport { useListKeyNav, type UseListKeyNav } from '../lib/useListKeyNav'\nimport {\n filterMentionCandidates,\n findMentionQuery,\n insertMention,\n type MentionCandidate,\n} from './mentions'\n\nexport interface UseMentionAutocompleteOptions {\n /** The draft. */\n value: string\n /** Writes the draft (the same setter the composer uses). */\n onValueChange: (next: string) => void\n /** Who can be mentioned: workspace members and the assistant. */\n candidates: ReadonlyArray<MentionCandidate>\n /** The composer textarea; read for the caret and refocused after a pick. */\n textareaRef: RefObject<HTMLTextAreaElement | null>\n}\n\nexport interface UseMentionAutocomplete {\n isOpen: boolean\n /** Filtered candidates for the `@query` at the caret. */\n items: MentionCandidate[]\n /** Keyboard navigation; call `nav.handleKeyDown` first in the textarea's `onKeyDown`. */\n nav: UseListKeyNav\n /** Insert a candidate in place of the `@query`. */\n pick: (candidate: MentionCandidate) => void\n /** Wrap the composer's `onValueChange` with this so the caret is tracked as the user types. */\n onValueChange: (next: string) => void\n /** Spread onto the textarea (via `textareaProps`): tracks caret moves (clicks, arrows). */\n textareaProps: { onSelect: (event: SyntheticEvent<HTMLTextAreaElement>) => void }\n}\n\n/**\n * Headless `@mention` autocomplete for a textarea: finds the `@query` at the caret, filters the\n * candidates, and on pick replaces the query with `@<label> `. Pair with {@link MentionMenu}.\n */\nexport function useMentionAutocomplete({\n value,\n onValueChange,\n candidates,\n textareaRef,\n}: UseMentionAutocompleteOptions): UseMentionAutocomplete {\n const [caret, setCaret] = useState<number | null>(null)\n // Escape dismisses the menu for the `@` it was opened at, until the user starts another one.\n const [dismissedAt, setDismissedAt] = useState<number | null>(null)\n\n // The draft can change from outside (cleared on send, restored on error): once the dismissed\n // `@` is gone, re-arm so the next `@` there opens the menu again.\n useEffect(() => {\n if (dismissedAt !== null && value[dismissedAt] !== '@') setDismissedAt(null)\n }, [value, dismissedAt])\n\n const match = useMemo(() => {\n if (caret === null) return null\n const query = findMentionQuery(value, Math.min(caret, value.length))\n // A completed recipient followed by a space is no longer an autocomplete query.\n return query && candidates.some((candidate) => query.query === `${candidate.label} `)\n ? null\n : query\n }, [value, caret, candidates])\n const items = useMemo(\n () => (match ? filterMentionCandidates(candidates, match.query) : []),\n [match, candidates]\n )\n const isOpen = !!match && items.length > 0 && dismissedAt !== match.start\n\n const readCaret = useCallback(() => {\n const ta = textareaRef.current\n setCaret(ta ? ta.selectionStart : null)\n }, [textareaRef])\n\n const pick = useCallback(\n (candidate: MentionCandidate) => {\n if (!match || caret === null) return\n const next = insertMention(value, match.start, Math.min(caret, value.length), candidate.label)\n onValueChange(next.text)\n setCaret(next.caret)\n // The inserted `@<label> ` is complete: keep the menu shut for this `@`.\n setDismissedAt(match.start)\n requestAnimationFrame(() => {\n const ta = textareaRef.current\n if (!ta) return\n ta.focus()\n ta.setSelectionRange(next.caret, next.caret)\n })\n },\n [match, caret, value, onValueChange, textareaRef]\n )\n\n const nav = useListKeyNav({\n open: isOpen,\n items,\n onPick: pick,\n onDismiss: () => setDismissedAt(match?.start ?? null),\n resetKey: match?.query,\n })\n\n const handleValueChange = useCallback(\n (next: string) => {\n onValueChange(next)\n const ta = textareaRef.current\n setCaret(ta ? ta.selectionStart : next.length)\n // Deleting text (or the `@` itself) re-arms the menu: the user is editing that mention.\n if (dismissedAt !== null && (next.length < value.length || next[dismissedAt] !== '@')) {\n setDismissedAt(null)\n }\n },\n [onValueChange, textareaRef, dismissedAt, value]\n )\n\n return {\n isOpen,\n items,\n nav,\n pick,\n onValueChange: handleValueChange,\n textareaProps: { onSelect: readCaret },\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/home/FoldSection.tsx","../src/home/AddFilesFirst.tsx","../src/home/QuickActionDialogHeader.tsx","../src/lib/useScopeSelection.ts","../src/home/ScopePicker.tsx","../src/home/sections.tsx","../src/lib/balanced-columns.ts","../src/home/StartTiles.tsx"],"names":["jsxs","Collapsible","CollapsibleTrigger","jsx","ChevronDown","cn","CollapsibleContent","FolderPlus","DialogHeader","DialogTitle","DialogDescription","useMemo","formatCount","Minus","Check","useState","testIdOr","Fragment","prefixedTestId","FileCheck2","ActionLink","Plus","useRef","useEffect","observeResize"],"mappings":"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","file":"chunk-WBDK4PIA.cjs","sourcesContent":["import type { ReactNode } from 'react'\nimport { ChevronDown } from 'lucide-react'\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger, cn } from '@arbidocs/react/ui'\n\nexport interface FoldSectionProps {\n label: string\n /** Shown as plain muted text beside the name; omit or pass 0 to hide. */\n count?: number\n /** A word or two of state for sections a count cannot summarise (shown while shut). */\n hint?: string\n open: boolean\n onOpenChange: (open: boolean) => void\n /** Trigger test id; the caller owns the naming. */\n testId: string\n children: ReactNode\n}\n\n/**\n * One foldable block of a dialog. The chevron and the name are the whole hit\n * target (44px on touch), and the count keeps the selection readable while the\n * section is shut, so you need not re-open it to check.\n */\nexport function FoldSection({\n label,\n count = 0,\n hint,\n open,\n onOpenChange,\n testId,\n children,\n}: FoldSectionProps) {\n return (\n <Collapsible open={open} onOpenChange={onOpenChange} data-slot=\"fold-section\">\n <CollapsibleTrigger\n className=\"mb-1.5 flex w-full items-center gap-1.5 rounded-md text-sm font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [&:hover]:text-muted-foreground pointer-coarse:min-h-11\"\n data-testid={testId}\n >\n <ChevronDown\n className={cn('size-4 shrink-0 transition-transform', !open && '-rotate-90')}\n />\n <span>{label}</span>\n {count > 0 && <span className=\"text-xs tabular-nums text-muted-foreground\">{count}</span>}\n {hint && !open && (\n <span className=\"min-w-0 truncate text-xs font-normal text-muted-foreground\">{hint}</span>\n )}\n </CollapsibleTrigger>\n <CollapsibleContent>{children}</CollapsibleContent>\n </Collapsible>\n )\n}\n","import type { ReactNode } from 'react'\nimport { FolderPlus } from 'lucide-react'\n\n/** Fixed strings of the empty-files state. */\nexport interface AddFilesFirstLabels {\n heading: string\n}\n\nexport const DEFAULT_ADD_FILES_FIRST_LABELS: AddFilesFirstLabels = {\n heading: 'Add files first',\n}\n\nexport interface AddFilesFirstProps {\n /** Why this action needs files, in the action's own words. */\n reason: string\n /** The host's own \"Add\" control. */\n action: ReactNode\n testId?: string\n labels?: Partial<AddFilesFirstLabels>\n}\n\n/**\n * What a quick-action dialog shows when the workspace has no files yet.\n *\n * Greying the action out says you cannot do it without saying how to get\n * there. Offering the same \"Add\" menu the Files view carries turns the dead\n * end into the first step: add files here, then run the action.\n */\nexport function AddFilesFirst({ reason, action, testId, labels }: AddFilesFirstProps) {\n const l = { ...DEFAULT_ADD_FILES_FIRST_LABELS, ...labels }\n return (\n <div\n className=\"flex flex-col items-center gap-3 rounded-lg border border-border bg-card shadow-xs px-4 py-8 text-center\"\n data-slot=\"add-files-first\"\n data-testid={testId}\n >\n <span className=\"flex size-11 items-center justify-center rounded-full bg-ai-soft text-ai-ink\">\n <FolderPlus className=\"size-5\" aria-hidden=\"true\" />\n </span>\n <div className=\"flex flex-col gap-1\">\n <p className=\"text-sm font-semibold text-foreground\">{l.heading}</p>\n <p className=\"text-xs leading-relaxed text-muted-foreground\">{reason}</p>\n </div>\n {action}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { DialogDescription, DialogHeader, DialogTitle } from '@arbidocs/react/ui'\n\nexport interface QuickActionDialogHeaderProps {\n /** The tile's glyph, sized by the caller at `size-5`. */\n icon: ReactNode\n title: string\n /** One sentence on what the dialog does. Keep it to a line or two. */\n description: ReactNode\n /** Test id for the description, where a test asserts on the copy. */\n descriptionTestId?: string\n}\n\n/**\n * The header every \"Start\" quick-action dialog wears: the tile's own mark in\n * its disc, the action's name, and one line saying what the dialog will do.\n *\n * - The disc centres on the TITLE row, so it reads as the title's mark.\n * - The description keeps the title's left edge (`pl-13` = disc + gap), so the\n * header is one text column beside the mark rather than an L.\n * - `max-w-prose` + `text-pretty` cap the measure and stop two-word orphans.\n * - `pr-8` keeps the copy clear of the close button.\n */\nexport function QuickActionDialogHeader({\n icon,\n title,\n description,\n descriptionTestId,\n}: QuickActionDialogHeaderProps) {\n return (\n <DialogHeader className=\"space-y-0 text-left\" data-slot=\"quick-action-dialog-header\">\n <div className=\"flex items-center gap-3 pr-8\">\n <div className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-ai-soft text-ai-ink\">\n {icon}\n </div>\n <DialogTitle className=\"text-xl font-semibold leading-tight\">{title}</DialogTitle>\n </div>\n <DialogDescription\n className=\"mt-2 max-w-prose pl-13 pr-8 text-sm leading-relaxed text-pretty\"\n data-testid={descriptionTestId}\n >\n {description}\n </DialogDescription>\n </DialogHeader>\n )\n}\n","import { useMemo } from 'react'\n\n/** Which folders and labels a run is limited to. Empty = everything. */\nexport interface DocumentScope {\n /** Folder paths; `''` is the \"unfiled\" bucket. */\n folders: string[]\n /** Label (tag) ids. */\n labels: string[]\n}\n\nexport interface UseScopeSelectionOptions {\n /** Every folder path in the tree (not including the unfiled bucket). */\n folderPaths: string[]\n /** Whether the unfiled bucket is shown as a row. */\n hasUnfiled: boolean\n scope: DocumentScope\n onScopeChange: (scope: DocumentScope) => void\n}\n\n/**\n * Headless selection logic for a folder + label scope picker.\n *\n * Folders use hierarchical selection: ticking \"contracts\" also ticks\n * \"contracts/2024\", and unticking removes the whole subtree. \"All\" ticks every\n * row, which is NOT the same as an empty scope: empty means \"the whole\n * workspace, whatever lands in it later\", all-ticked means \"these folders, as\n * they are now\".\n */\nexport function useScopeSelection({\n folderPaths,\n hasUnfiled,\n scope,\n onScopeChange,\n}: UseScopeSelectionOptions) {\n const selectedFolders = useMemo(() => new Set(scope.folders), [scope.folders])\n const selectedLabels = useMemo(() => new Set(scope.labels), [scope.labels])\n\n /** Every row the folder list shows, \"unfiled\" included. */\n const allRowPaths = useMemo(\n () => [...(hasUnfiled ? [''] : []), ...folderPaths],\n [folderPaths, hasUnfiled]\n )\n const allSelected = allRowPaths.length > 0 && allRowPaths.every((p) => selectedFolders.has(p))\n const someSelected = selectedFolders.size > 0 && !allSelected\n\n const descendants = (path: string) => folderPaths.filter((p) => p.startsWith(path + '/'))\n\n const toggleFolder = (path: string) => {\n const next = new Set(selectedFolders)\n const family = [path, ...descendants(path)]\n if (next.has(path)) for (const p of family) next.delete(p)\n else for (const p of family) next.add(p)\n onScopeChange({ folders: [...next], labels: scope.labels })\n }\n\n const toggleAllFolders = () => {\n onScopeChange({ folders: allSelected ? [] : allRowPaths, labels: scope.labels })\n }\n\n const toggleLabel = (labelId: string) => {\n const next = new Set(selectedLabels)\n if (next.has(labelId)) next.delete(labelId)\n else next.add(labelId)\n onScopeChange({ folders: scope.folders, labels: [...next] })\n }\n\n return {\n selectedFolders,\n selectedLabels,\n allSelected,\n someSelected,\n hasSelection: scope.folders.length > 0 || scope.labels.length > 0,\n toggleFolder,\n toggleAllFolders,\n toggleLabel,\n }\n}\n","import { useMemo, useState } from 'react'\nimport { Check, FileCheck2, Minus } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { prefixedTestId, testIdOr } from '../chat/test-id'\nimport { useScopeSelection, type DocumentScope } from '../lib/useScopeSelection'\nimport { formatCount } from '../lib/format'\nimport { FoldSection } from './FoldSection'\n\n/**\n * Fixed strings of the picker. Passed as `uiLabels`: the `labels` prop is already the list of\n * document labels to scope by.\n */\nexport interface ScopePickerLabels {\n folders: string\n /** The Labels section heading. */\n labelsHeading: string\n all: string\n unfiled: string\n noFoldersYet: string\n noLabelsYet: string\n filesToInclude: string\n /** \"3 of 10 files\". */\n matchedOfTotal: (matched: number, total: number) => string\n selectedSuffix: string\n folderCount: (count: number) => string\n labelCount: (count: number) => string\n left: (count: number) => string\n /** \"All 10 files\". */\n allFiles: (total: number) => string\n includedSuffix: string\n}\n\nconst pluralize = (n: number, word: string) => `${n} ${word}${n !== 1 ? 's' : ''}`\n\nexport const DEFAULT_SCOPE_PICKER_LABELS: ScopePickerLabels = {\n folders: 'Folders',\n labelsHeading: 'Labels',\n all: 'All',\n unfiled: 'Unfiled',\n noFoldersYet: 'No folders yet',\n noLabelsYet: 'No labels yet — label files from the Files page to scope by them here.',\n filesToInclude: 'Files to include',\n matchedOfTotal: (matched, total) =>\n `${matched} of ${formatCount(total, { one: 'file', other: 'files' })}`,\n selectedSuffix: ' selected',\n folderCount: (count) => pluralize(count, 'folder'),\n labelCount: (count) => pluralize(count, 'label'),\n left: (count) => `${count} left`,\n allFiles: (total) => `All ${pluralize(total, 'file')}`,\n includedSuffix: ' in the workspace will be included',\n}\n\nexport interface ScopeFolder {\n /** Full path, e.g. `contracts/2024`. */\n path: string\n /** Last segment, shown. */\n label: string\n /** Documents under this folder. */\n count: number\n depth: number\n}\n\nexport interface ScopeLabel {\n id: string\n name: string\n /** Any CSS colour for the dot. */\n color: string\n /** Documents carrying this label. */\n count: number\n}\n\nexport interface ScopePickerProps {\n folders: ScopeFolder[]\n /** Documents with no folder; the \"Unfiled\" row is hidden at 0. */\n unfiledCount: number\n labels: ScopeLabel[]\n /** All documents the picker is scoping. */\n totalCount: number\n /** Documents the current scope matches (computed by the caller). */\n matchedCount: number\n scope: DocumentScope\n onScopeChange: (scope: DocumentScope) => void\n /** Reword the picker's fixed strings. */\n uiLabels?: Partial<ScopePickerLabels>\n /** Sub-element ids; defaults are the current ids. `labelChip` is a prefix (`<prefix>-<label id>`). */\n testIds?: Partial<\n Record<'foldersToggle' | 'labelsToggle' | 'noLabels' | 'labelChip' | 'summary', string>\n >\n}\n\ninterface FolderRowProps {\n label: string\n count: number\n depth: number\n isActive: boolean\n indeterminate?: boolean\n muted?: boolean\n onToggle: () => void\n}\n\n/** A checkbox row: the row is the checkbox (a nested real one would swallow the click). */\nfunction FolderRow({\n label,\n count,\n depth,\n isActive,\n indeterminate,\n muted,\n onToggle,\n}: FolderRowProps) {\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n role=\"checkbox\"\n aria-checked={indeterminate ? 'mixed' : isActive}\n style={{ paddingLeft: `${4 + depth * 14}px` }}\n className={cn(\n 'flex w-full items-center gap-1 rounded-sm py-1 pr-2 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [&:hover]:bg-accent pointer-coarse:min-h-11',\n isActive && 'bg-primary/10',\n muted && !isActive && 'text-muted-foreground'\n )}\n data-slot=\"scope-folder-row\"\n >\n <span className=\"flex w-4 shrink-0 items-center justify-center\">\n <span\n className={cn(\n 'flex size-3.5 items-center justify-center rounded-[3px] border transition-colors',\n isActive || indeterminate\n ? 'border-primary bg-primary text-primary-foreground'\n : 'border-muted-foreground/40'\n )}\n >\n {indeterminate ? (\n <Minus className=\"size-2.5\" />\n ) : (\n isActive && <Check className=\"size-2.5\" />\n )}\n </span>\n </span>\n {label !== '' && (\n <span className={cn('min-w-0 truncate', isActive && 'font-semibold text-primary')}>\n {label}\n </span>\n )}\n <span className=\"ml-auto pl-2 text-sm font-semibold text-muted-foreground\">{count}</span>\n </button>\n )\n}\n\n/**\n * Pick a folder + label scope for a run over documents. Controlled: the caller\n * owns the scope and computes `matchedCount`, so the submit button lives with\n * the caller. Both sections start shut: the default (every file) is what most\n * runs want, and the summary states it plainly.\n */\nexport function ScopePicker({\n folders,\n unfiledCount,\n labels,\n totalCount,\n matchedCount,\n scope,\n onScopeChange,\n uiLabels,\n testIds,\n}: ScopePickerProps) {\n const l = { ...DEFAULT_SCOPE_PICKER_LABELS, ...uiLabels }\n const [foldersOpen, setFoldersOpen] = useState(false)\n const [labelsOpen, setLabelsOpen] = useState(false)\n\n const folderPaths = useMemo(() => folders.map((f) => f.path), [folders])\n const selection = useScopeSelection({\n folderPaths,\n hasUnfiled: unfiledCount > 0,\n scope,\n onScopeChange,\n })\n const hasRows = folders.length > 0 || unfiledCount > 0\n\n return (\n <div className=\"flex flex-col gap-4\" data-slot=\"scope-picker\">\n <FoldSection\n label={l.folders}\n count={scope.folders.length}\n open={foldersOpen}\n onOpenChange={setFoldersOpen}\n testId={testIdOr(testIds?.foldersToggle, { testId: 'scope-picker-folders-toggle' })}\n >\n <div className=\"max-h-[180px] overflow-y-auto rounded-md border border-border p-1\">\n {hasRows && (\n <>\n <FolderRow\n label={l.all}\n count={totalCount}\n depth={0}\n isActive={selection.allSelected}\n indeterminate={selection.someSelected}\n onToggle={selection.toggleAllFolders}\n />\n <div className=\"my-1 border-t border-border\" />\n </>\n )}\n {unfiledCount > 0 && (\n <>\n <FolderRow\n label={l.unfiled}\n count={unfiledCount}\n depth={0}\n isActive={selection.selectedFolders.has('')}\n muted\n onToggle={() => selection.toggleFolder('')}\n />\n {folders.length > 0 && <div className=\"my-1 border-t border-border\" />}\n </>\n )}\n {folders.map((folder) => (\n <FolderRow\n key={folder.path}\n label={folder.label}\n count={folder.count}\n depth={folder.depth}\n isActive={selection.selectedFolders.has(folder.path)}\n onToggle={() => selection.toggleFolder(folder.path)}\n />\n ))}\n {!hasRows && <p className=\"px-2 py-1 text-sm text-muted-foreground\">{l.noFoldersYet}</p>}\n </div>\n </FoldSection>\n\n {/* Always present, like Folders: a workspace with no labels yet reads as\n \"you have not labelled anything\", not \"this cannot scope by label\". */}\n <FoldSection\n label={l.labelsHeading}\n count={scope.labels.length}\n open={labelsOpen}\n onOpenChange={setLabelsOpen}\n testId={testIdOr(testIds?.labelsToggle, { testId: 'scope-picker-labels-toggle' })}\n >\n {labels.length === 0 ? (\n <p\n className=\"px-2 py-1 text-sm text-muted-foreground\"\n data-testid={testIdOr(testIds?.noLabels, { testId: 'scope-picker-no-labels' })}\n >\n {l.noLabelsYet}\n </p>\n ) : (\n <div className=\"flex flex-wrap gap-1.5\">\n {labels.map((label) => {\n const isActive = selection.selectedLabels.has(label.id)\n return (\n <button\n key={label.id}\n type=\"button\"\n onClick={() => selection.toggleLabel(label.id)}\n aria-pressed={isActive}\n data-testid={prefixedTestId(testIds?.labelChip, label.id, {\n testId: `scope-picker-label-chip-${label.id}`,\n })}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-md border px-2 py-1 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11',\n isActive\n ? 'border-primary/40 bg-primary/10 text-primary'\n : 'border-border [&:hover]:bg-accent [&:hover]:text-accent-foreground'\n )}\n >\n <span\n className=\"size-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: label.color }}\n />\n <span className=\"truncate\">{label.name}</span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">({label.count})</span>\n {isActive && <Check className=\"size-3.5 shrink-0\" />}\n </button>\n )\n })}\n </div>\n )}\n </FoldSection>\n\n <div\n className=\"rounded-lg bg-muted p-3\"\n data-testid={testIdOr(testIds?.summary, { testId: 'scope-picker-summary' })}\n >\n <div className=\"mb-2 flex items-center gap-1.5 text-xs font-medium text-muted-foreground\">\n <FileCheck2 className=\"size-4\" />\n {l.filesToInclude}\n </div>\n {selection.hasSelection ? (\n <div className=\"text-sm text-muted-foreground\">\n <span className=\"text-base font-semibold text-foreground\">\n {l.matchedOfTotal(matchedCount, totalCount)}\n </span>\n {l.selectedSuffix}\n {scope.folders.length > 0 && <span> — {l.folderCount(scope.folders.length)}</span>}\n {scope.folders.length > 0 && scope.labels.length > 0 && <span>, </span>}\n {scope.labels.length > 0 && <span>{l.labelCount(scope.labels.length)}</span>}\n <span className=\"text-xs\">\n {' · '}\n {l.left(totalCount - matchedCount)}\n </span>\n </div>\n ) : (\n <div className=\"text-sm text-muted-foreground\">\n <span className=\"text-base font-semibold text-foreground\">\n {l.allFiles(totalCount)}\n </span>\n {l.includedSuffix}\n </div>\n )}\n </div>\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { Plus, type LucideIcon } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { ActionLink } from '../components/ActionLink'\n\n/** The small label that names a band of a page (\"Start\", \"Recent\"). */\nexport function SectionLabel({\n children,\n className,\n testId,\n}: {\n children: ReactNode\n className?: string\n testId?: string\n}) {\n return (\n <p\n className={cn(\n 'flex items-center gap-3 text-sm font-semibold text-foreground after:h-px after:flex-1 after:bg-border',\n className\n )}\n data-slot=\"section-label\"\n data-testid={testId}\n >\n {children}\n </p>\n )\n}\n\nexport interface SectionHeaderProps {\n icon?: LucideIcon\n title: string\n count?: number\n /** Makes the title a button (open the full list). Omit for a static title. */\n onOpen?: () => void\n /** Real link target of the title; `onOpen` still fires on a plain click. */\n openHref?: string\n /** Test id of the title button. */\n openTestId?: string\n /** The section's one quiet action, rendered at the trailing edge. */\n action?: ReactNode\n className?: string\n}\n\n/** Title + count + one quiet action: the head of a list section. */\nexport function SectionHeader({\n icon: Icon,\n title,\n count,\n onOpen,\n openHref,\n openTestId,\n action,\n className,\n}: SectionHeaderProps) {\n return (\n <div\n className={cn('flex items-center justify-between gap-2', className)}\n data-slot=\"section-header\"\n >\n <ActionLink\n href={openHref}\n onSelect={onOpen}\n disabled={!onOpen && !openHref}\n className=\"flex min-w-0 cursor-pointer items-center gap-2 rounded-md py-1.5 pr-2 text-left transition-colors hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default disabled:hover:text-foreground pointer-coarse:min-h-11\"\n data-testid={openTestId}\n >\n {Icon && <Icon className=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />}\n <span className=\"whitespace-nowrap text-sm font-semibold text-foreground\">{title}</span>\n {count !== undefined && (\n <span className=\"text-sm tabular-nums text-muted-foreground\">{count}</span>\n )}\n </ActionLink>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n )\n}\n\nexport interface EmptyStripProps {\n icon?: LucideIcon\n label: ReactNode\n description?: ReactNode\n onSelect?: () => void\n testId?: string\n}\n\n/** One tonal strip that stands in for an empty section: an invitation, not a void. */\nexport function EmptyStrip({\n icon: Icon = Plus,\n label,\n description,\n onSelect,\n testId,\n}: EmptyStripProps) {\n return (\n <button\n type=\"button\"\n onClick={onSelect}\n disabled={!onSelect}\n className=\"flex w-full items-center gap-3 rounded-lg px-4 py-3 text-left border border-border bg-card shadow-xs transition-colors hover:border-ring/50 hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default disabled:hover:bg-card disabled:hover:border-border pointer-coarse:min-h-11\"\n data-slot=\"empty-strip\"\n data-testid={testId}\n >\n <Icon className=\"size-5 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-sm font-semibold text-foreground\">{label}</span>\n {description && (\n <span className=\"block text-sm leading-snug text-muted-foreground\">{description}</span>\n )}\n </span>\n </button>\n )\n}\n","/**\n * The column count for a grid of `count` equal tiles in `width` pixels, chosen so the last row is\n * never left with a lone orphan: of the counts that fit (each column at least `minTile` wide),\n * take the one that leaves the fewest empty cells in the last row, preferring more columns on a\n * tie (never fewer than two columns when two fit). Four tiles resolve to 2x2 where three would fit\n * and 4 across when there is room for four; six resolve to 3x2.\n */\nexport function balancedColumns(count: number, width: number, minTile = 200, gap = 12): number {\n if (count <= 1) return 1\n const fit = Math.max(1, Math.min(count, Math.floor((width + gap) / (minTile + gap))))\n if (fit < 2) return 1\n let best = 2\n let bestEmpty = Number.POSITIVE_INFINITY\n for (let columns = 2; columns <= fit; columns++) {\n const empty = (columns - (count % columns)) % columns\n if (empty < bestEmpty || (empty === bestEmpty && columns > best)) {\n best = columns\n bestEmpty = empty\n }\n }\n return best\n}\n","import { useEffect, useRef, useState, type ReactNode } from 'react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { ActionLink } from '../components/ActionLink'\nimport { balancedColumns } from '../lib/balanced-columns'\nimport { observeResize } from '../lib/observe-resize'\nimport { SectionLabel } from './sections'\n\n/** One \"start something\" tile: an AI-driven action, one click from underway. */\nexport interface StartTile {\n id: string\n /** A Lucide glyph; `iconNode` wins when both are given. */\n icon?: LucideIcon\n /** A ready-made mark (host icon maps), wearing the same AI ink. */\n iconNode?: ReactNode\n title: string\n description: string\n onSelect: () => void\n /** Real link target (ctrl-click / new tab, in-SPA through `BlocksProvider`'s `linkComponent`). `onSelect` still fires on a plain click. */\n href?: string\n /** Rendered non-interactive and dimmed; `disabledReason` replaces the description. */\n disabled?: boolean\n disabledReason?: string\n testId?: string\n}\n\nexport interface StartTilesProps {\n items: StartTile[]\n /** Optional band label above the tiles (\"Start\"). */\n caption?: string\n captionTestId?: string\n className?: string\n testId?: string\n}\n\n/**\n * A band of tonal action tiles. The glyph wears the AI ink, because these are\n * the AI-driven starts. Nothing is hover-only: tiles are always rendered, hover\n * only nudges tone, and touch targets are at least 44px.\n */\nexport function StartTiles({ items, caption, captionTestId, className, testId }: StartTilesProps) {\n // The tiles reflow by their own container width (a docked tablet sidebar narrows it without\n // changing the viewport), choosing a column count that never leaves one tile alone on a row.\n const gridRef = useRef<HTMLDivElement>(null)\n const [columns, setColumns] = useState<number | null>(null)\n const count = items.length\n useEffect(() => {\n const grid = gridRef.current\n if (!grid || count === 0) return\n const measure = () => setColumns(balancedColumns(count, grid.clientWidth))\n measure()\n return observeResize(grid, measure)\n }, [count])\n\n if (count === 0) return null\n return (\n <section\n className={cn('flex flex-col gap-3', className)}\n data-slot=\"start-tiles\"\n data-testid={testId}\n >\n {caption && <SectionLabel testId={captionTestId}>{caption}</SectionLabel>}\n <div\n ref={gridRef}\n data-slot=\"start-tiles-grid\"\n data-columns={columns ?? undefined}\n className=\"grid gap-3\"\n style={{\n gridTemplateColumns:\n columns === null\n ? 'repeat(auto-fit, minmax(200px, 1fr))'\n : `repeat(${columns}, minmax(0, 1fr))`,\n }}\n >\n {items.map((item) => {\n const Icon = item.icon\n return (\n <ActionLink\n key={item.id}\n href={item.href}\n onSelect={item.onSelect}\n disabled={item.disabled}\n title={item.disabled ? item.disabledReason : undefined}\n className={cn(\n 'flex h-full flex-col items-start gap-3 rounded-lg p-4 text-left',\n 'border border-border bg-card shadow-xs transition-colors hover:border-ring/50 hover:bg-accent/40',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n 'disabled:cursor-default disabled:opacity-55 disabled:hover:bg-card disabled:hover:border-border',\n 'pointer-coarse:min-h-11'\n )}\n data-slot=\"start-tile\"\n data-testid={item.testId}\n >\n {item.iconNode ? (\n <span className=\"shrink-0 text-ai-ink [&>svg]:size-5\" aria-hidden=\"true\">\n {item.iconNode}\n </span>\n ) : (\n Icon && <Icon className=\"size-5 shrink-0 text-ai-ink\" aria-hidden=\"true\" />\n )}\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-semibold text-foreground\">{item.title}</span>\n <span className=\"mt-1 block text-sm leading-snug text-muted-foreground\">\n {item.disabled && item.disabledReason ? item.disabledReason : item.description}\n </span>\n </span>\n </ActionLink>\n )\n })}\n </div>\n </section>\n )\n}\n"]}
|