@arbidocs/blocks 0.4.5 → 0.4.7

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 (131) hide show
  1. package/README.md +46 -6
  2. package/dist/agents/index.cjs +163 -162
  3. package/dist/agents/index.js +6 -5
  4. package/dist/chat/ChatMessageContent.d.ts +16 -0
  5. package/dist/chat/ChatPage.d.ts +11 -8
  6. package/dist/chat/ChatThreads.d.ts +3 -1
  7. package/dist/chat/CitationMark.d.ts +18 -0
  8. package/dist/chat/chat-page-types.d.ts +75 -1
  9. package/dist/chat/index.cjs +126 -117
  10. package/dist/chat/index.d.ts +3 -1
  11. package/dist/chat/index.js +5 -4
  12. package/dist/{chunk-3MIQASHO.cjs → chunk-23XL6SVZ.cjs} +39 -19
  13. package/dist/chunk-23XL6SVZ.cjs.map +1 -0
  14. package/dist/{chunk-ULWRNGGE.cjs → chunk-2ZTONLT5.cjs} +4 -25
  15. package/dist/chunk-2ZTONLT5.cjs.map +1 -0
  16. package/dist/{chunk-O637DUKS.cjs → chunk-56BUD74K.cjs} +28 -28
  17. package/dist/{chunk-O637DUKS.cjs.map → chunk-56BUD74K.cjs.map} +1 -1
  18. package/dist/{chunk-YLOKCIQJ.cjs → chunk-5SLLMK5K.cjs} +421 -115
  19. package/dist/chunk-5SLLMK5K.cjs.map +1 -0
  20. package/dist/{chunk-SS23F63U.cjs → chunk-5ZBP7TCD.cjs} +55 -3
  21. package/dist/chunk-5ZBP7TCD.cjs.map +1 -0
  22. package/dist/{chunk-3PZPRAAR.cjs → chunk-67HGXV4I.cjs} +14 -14
  23. package/dist/{chunk-3PZPRAAR.cjs.map → chunk-67HGXV4I.cjs.map} +1 -1
  24. package/dist/{chunk-RCP6THBS.js → chunk-7OCFHEE6.js} +3 -3
  25. package/dist/{chunk-RCP6THBS.js.map → chunk-7OCFHEE6.js.map} +1 -1
  26. package/dist/{chunk-TX2ZICS7.js → chunk-CPMNAJLF.js} +4 -24
  27. package/dist/chunk-CPMNAJLF.js.map +1 -0
  28. package/dist/{chunk-5XTZFH65.js → chunk-CVFBSUXL.js} +5 -5
  29. package/dist/{chunk-5XTZFH65.js.map → chunk-CVFBSUXL.js.map} +1 -1
  30. package/dist/chunk-DCDVWPMB.cjs +29 -0
  31. package/dist/chunk-DCDVWPMB.cjs.map +1 -0
  32. package/dist/{chunk-TI4UTYRL.js → chunk-EY2RJW27.js} +258 -10
  33. package/dist/chunk-EY2RJW27.js.map +1 -0
  34. package/dist/{chunk-7YADKWZT.js → chunk-G2E3O3HI.js} +3 -3
  35. package/dist/{chunk-7YADKWZT.js.map → chunk-G2E3O3HI.js.map} +1 -1
  36. package/dist/{chunk-6YHWXMPQ.js → chunk-G2T3KTZ3.js} +419 -115
  37. package/dist/chunk-G2T3KTZ3.js.map +1 -0
  38. package/dist/{chunk-2NNTQLBY.js → chunk-IAKUTBPX.js} +4 -4
  39. package/dist/{chunk-2NNTQLBY.js.map → chunk-IAKUTBPX.js.map} +1 -1
  40. package/dist/{chunk-IZHWP6WQ.cjs → chunk-JG4TFS3Z.cjs} +6 -6
  41. package/dist/{chunk-IZHWP6WQ.cjs.map → chunk-JG4TFS3Z.cjs.map} +1 -1
  42. package/dist/chunk-JLOYWXRB.js +1156 -0
  43. package/dist/chunk-JLOYWXRB.js.map +1 -0
  44. package/dist/{chunk-WJZBJUPX.js → chunk-KXMDOTGW.js} +56 -4
  45. package/dist/chunk-KXMDOTGW.js.map +1 -0
  46. package/dist/{chunk-2VBJ763Y.js → chunk-KZJAG7T3.js} +37 -7
  47. package/dist/chunk-KZJAG7T3.js.map +1 -0
  48. package/dist/{chunk-RIL7G7AS.cjs → chunk-MGUHR3JI.cjs} +4 -4
  49. package/dist/{chunk-RIL7G7AS.cjs.map → chunk-MGUHR3JI.cjs.map} +1 -1
  50. package/dist/{chunk-NPKGUQU5.js → chunk-NJL4LIXX.js} +4 -4
  51. package/dist/{chunk-NPKGUQU5.js.map → chunk-NJL4LIXX.js.map} +1 -1
  52. package/dist/{chunk-DN3NFNIA.cjs → chunk-QMDLPO3M.cjs} +266 -10
  53. package/dist/chunk-QMDLPO3M.cjs.map +1 -0
  54. package/dist/chunk-TJMKFY5P.js +27 -0
  55. package/dist/chunk-TJMKFY5P.js.map +1 -0
  56. package/dist/{chunk-3PJCET7H.js → chunk-UHVNYKV2.js} +38 -18
  57. package/dist/chunk-UHVNYKV2.js.map +1 -0
  58. package/dist/{chunk-6CHMNKXC.cjs → chunk-UTYQPVIW.cjs} +11 -11
  59. package/dist/chunk-UTYQPVIW.cjs.map +1 -0
  60. package/dist/{chunk-KHX2BX3S.cjs → chunk-VGOFFCMT.cjs} +37 -5
  61. package/dist/chunk-VGOFFCMT.cjs.map +1 -0
  62. package/dist/{chunk-67MKU5U7.js → chunk-YMHGF6R5.js} +8 -8
  63. package/dist/chunk-YMHGF6R5.js.map +1 -0
  64. package/dist/chunk-YVIOCITQ.cjs +1186 -0
  65. package/dist/chunk-YVIOCITQ.cjs.map +1 -0
  66. package/dist/{chunk-MVNCQDDE.cjs → chunk-ZVPTFTGV.cjs} +4 -4
  67. package/dist/{chunk-MVNCQDDE.cjs.map → chunk-ZVPTFTGV.cjs.map} +1 -1
  68. package/dist/collaboration/index.cjs +38 -37
  69. package/dist/collaboration/index.js +3 -2
  70. package/dist/connect/index.cjs +358 -19
  71. package/dist/connect/index.cjs.map +1 -1
  72. package/dist/connect/index.d.ts +1 -0
  73. package/dist/connect/index.js +341 -9
  74. package/dist/connect/index.js.map +1 -1
  75. package/dist/connection/ConnectedSettings.d.ts +64 -0
  76. package/dist/facts/index.cjs +2 -2
  77. package/dist/facts/index.js +2 -2
  78. package/dist/files/index.cjs +15 -14
  79. package/dist/files/index.cjs.map +1 -1
  80. package/dist/files/index.js +5 -4
  81. package/dist/files/index.js.map +1 -1
  82. package/dist/home/index.cjs +19 -19
  83. package/dist/home/index.js +4 -4
  84. package/dist/index.cjs +526 -477
  85. package/dist/index.cjs.map +1 -1
  86. package/dist/index.js +17 -16
  87. package/dist/index.js.map +1 -1
  88. package/dist/lib/bottom-inset.d.ts +16 -0
  89. package/dist/lib/useElementSize.d.ts +13 -0
  90. package/dist/lib/useFillHeight.d.ts +10 -0
  91. package/dist/settings/account-views.d.ts +55 -0
  92. package/dist/settings/index.cjs +179 -1148
  93. package/dist/settings/index.cjs.map +1 -1
  94. package/dist/settings/index.d.ts +1 -0
  95. package/dist/settings/index.js +10 -1073
  96. package/dist/settings/index.js.map +1 -1
  97. package/dist/shell/InstallPrompt.d.ts +28 -0
  98. package/dist/shell/MobileBars.d.ts +1 -1
  99. package/dist/shell/index.cjs +85 -45
  100. package/dist/shell/index.d.ts +4 -0
  101. package/dist/shell/index.js +3 -3
  102. package/dist/shell/install-instructions.d.ts +19 -0
  103. package/dist/shell/types.d.ts +6 -0
  104. package/dist/shell/use-install-prompt.d.ts +49 -0
  105. package/dist/site/index.cjs +62 -62
  106. package/dist/site/index.js +2 -2
  107. package/dist/studio/index.cjs +78 -77
  108. package/dist/studio/index.cjs.map +1 -1
  109. package/dist/studio/index.js +8 -7
  110. package/dist/studio/index.js.map +1 -1
  111. package/dist/theme/ThemeEditor.d.ts +4 -2
  112. package/dist/workspaces/index.cjs +4 -3
  113. package/dist/workspaces/index.cjs.map +1 -1
  114. package/dist/workspaces/index.js +3 -2
  115. package/dist/workspaces/index.js.map +1 -1
  116. package/package.json +8 -4
  117. package/src/blocks.css +30 -0
  118. package/dist/chunk-2VBJ763Y.js.map +0 -1
  119. package/dist/chunk-3MIQASHO.cjs.map +0 -1
  120. package/dist/chunk-3PJCET7H.js.map +0 -1
  121. package/dist/chunk-67MKU5U7.js.map +0 -1
  122. package/dist/chunk-6CHMNKXC.cjs.map +0 -1
  123. package/dist/chunk-6YHWXMPQ.js.map +0 -1
  124. package/dist/chunk-DN3NFNIA.cjs.map +0 -1
  125. package/dist/chunk-KHX2BX3S.cjs.map +0 -1
  126. package/dist/chunk-SS23F63U.cjs.map +0 -1
  127. package/dist/chunk-TI4UTYRL.js.map +0 -1
  128. package/dist/chunk-TX2ZICS7.js.map +0 -1
  129. package/dist/chunk-ULWRNGGE.cjs.map +0 -1
  130. package/dist/chunk-WJZBJUPX.js.map +0 -1
  131. package/dist/chunk-YLOKCIQJ.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/settings/AvatarPicker.tsx","../src/settings/SettingsPanel.tsx","../src/settings/ProfileCard.tsx","../src/settings/PasswordChangeDialog.tsx","../src/settings/AccountDialogs.tsx","../src/settings/LogoutDialog.tsx","../src/settings/SettingsSwitchRow.tsx","../src/settings/NotificationCategoryList.tsx","../src/settings/account-views.ts"],"names":["useMemo","useRef","jsxs","Avatar","jsx","AvatarImage","AvatarFallback","cn","Loader2","Camera","ChevronRight","ChevronDown","Input","Button","Check","Pencil","Mail","Tooltip","TooltipTrigger","TooltipContent","Fragment","formatCount","useId","Dialog","DialogContent","testIdOr","DialogHeader","DialogTitle","DialogDescription","CheckCircle2","PasswordStrengthInput","AlertCircle","prefixedTestId","Badge","LogOut","Radio","AlertTriangle","useState","useRestoreFocus","DialogFooter","Collapsible","CollapsibleTrigger","CollapsibleContent","Switch","Checkbox"],"mappings":"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","file":"chunk-YVIOCITQ.cjs","sourcesContent":["import { useMemo, useRef, type ChangeEvent } from 'react'\nimport { Camera, Loader2 } from 'lucide-react'\nimport { Avatar, AvatarFallback, AvatarImage, cn } from '@arbidocs/react/ui'\n\n/** Every fixed string of the avatar picker. */\nexport interface AvatarPickerLabels {\n uploadingPicture: string\n changeProfilePicture: string\n change: string\n}\n\nexport const DEFAULT_AVATAR_PICKER_LABELS: AvatarPickerLabels = {\n uploadingPicture: 'Uploading picture',\n changeProfilePicture: 'Change profile picture',\n change: 'Change',\n}\n\nexport interface AvatarPickerProps {\n labels?: Partial<AvatarPickerLabels>\n /** Image URL / data URL; the initials show when absent. */\n pictureUrl?: string | null\n initials: string\n /** Background class of the initials fallback (a stable per-user colour). */\n fallbackClassName?: string\n isUploading?: boolean\n disabled?: boolean\n /** A file was chosen; the host validates, crops and uploads it. */\n onFileChosen: (file: File) => void\n testId?: string\n}\n\n/**\n * Profile picture with a change affordance. A permanent camera mark says the picture is tappable on\n * touch screens; the overlay (revealed on hover/focus) is the actual control.\n */\nexport function AvatarPicker({\n pictureUrl,\n initials,\n fallbackClassName,\n isUploading,\n disabled,\n onFileChosen,\n testId = 'avatar-uploader-input',\n labels,\n}: AvatarPickerProps) {\n const l = useMemo(() => ({ ...DEFAULT_AVATAR_PICKER_LABELS, ...labels }), [labels])\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n // Reset so choosing the same file again still fires a change.\n e.target.value = ''\n if (file) onFileChosen(file)\n }\n\n return (\n <div data-slot=\"avatar-picker\" className=\"group/avatar relative shrink-0\">\n <Avatar className=\"h-20 w-20 ring-1 ring-border\">\n {pictureUrl && <AvatarImage src={pictureUrl} alt={initials} />}\n <AvatarFallback\n className={cn('text-2xl font-semibold leading-none text-white', fallbackClassName)}\n >\n {initials}\n </AvatarFallback>\n </Avatar>\n\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n disabled={disabled || isUploading}\n className={cn(\n 'absolute inset-0 flex items-center justify-center rounded-full',\n 'bg-foreground/70 text-background',\n 'opacity-0 focus-visible:opacity-100 group-hover/avatar:opacity-100',\n // Touch has no hover: keep the change affordance visible (lighter scrim over the photo).\n 'pointer-coarse:opacity-100',\n 'transition-opacity duration-200',\n 'disabled:cursor-not-allowed disabled:opacity-100'\n )}\n aria-label={isUploading ? l.uploadingPicture : l.changeProfilePicture}\n >\n {isUploading ? (\n <Loader2 className=\"h-6 w-6 animate-spin\" />\n ) : (\n <div className=\"flex flex-col items-center gap-0.5\">\n <Camera className=\"h-5 w-5\" />\n <span className=\"text-xs font-medium\">{l.change}</span>\n </div>\n )}\n </button>\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute -bottom-1 -right-1 flex h-7 w-7 items-center justify-center rounded-full bg-background text-muted-foreground ring-1 ring-border\"\n >\n <Camera className=\"h-3.5 w-3.5\" />\n </span>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp,image/gif\"\n onChange={handleChange}\n hidden\n className=\"hidden\"\n data-testid={testId}\n />\n </div>\n )\n}\n","import { useMemo, type ComponentProps, type ReactNode } from 'react'\nimport { ChevronDown, ChevronRight } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\n\n/** Every fixed string of the danger zone. `label` prop wins. */\nexport interface SettingsDangerZoneLabels {\n dangerZone: string\n}\n\nexport const DEFAULT_SETTINGS_DANGER_ZONE_LABELS: SettingsDangerZoneLabels = {\n dangerZone: 'Danger Zone',\n}\n\nexport interface SettingsPanelProps extends ComponentProps<'div'> {\n /** Stable test id of the panel. */\n testId?: string\n}\n\n/** Centred column of {@link SettingsSection}s with a readable measure. */\nexport function SettingsPanel({ className, testId, ...props }: SettingsPanelProps) {\n return (\n <div\n data-slot=\"settings-panel\"\n data-testid={testId}\n className={cn('mx-auto w-full max-w-xl space-y-6', className)}\n {...props}\n />\n )\n}\n\nexport interface SettingsSectionProps extends Omit<ComponentProps<'section'>, 'title'> {\n /** Small muted icon before the title. */\n icon?: ReactNode\n title?: ReactNode\n description?: ReactNode\n /** Right-aligned control in the heading row (e.g. a Reset button). */\n action?: ReactNode\n testId?: string\n}\n\n/** Titled group of settings: heading row, optional description, then the controls. */\nexport function SettingsSection({\n icon,\n title,\n description,\n action,\n testId,\n className,\n children,\n ...props\n}: SettingsSectionProps) {\n return (\n <section\n data-slot=\"settings-section\"\n data-testid={testId}\n className={cn('space-y-3', className)}\n {...props}\n >\n {(title || action) && (\n <div className=\"flex items-center justify-between gap-3\">\n {title && (\n <div className=\"flex items-center gap-2\">\n {icon && (\n <span className=\"text-muted-foreground [&_svg]:h-4 [&_svg]:w-4\">{icon}</span>\n )}\n <h2 className=\"text-base font-semibold text-foreground\">{title}</h2>\n </div>\n )}\n {action}\n </div>\n )}\n {description && <p className=\"text-sm text-muted-foreground\">{description}</p>}\n {children}\n </section>\n )\n}\n\nexport interface SettingsRowProps extends Omit<ComponentProps<'div'>, 'title'> {\n label: ReactNode\n /** Id of the control: renders the label as a `<label htmlFor>` so it toggles the control. */\n labelFor?: string\n description?: ReactNode\n /** The control: switch, select, button. Sits at the end of the row. */\n children?: ReactNode\n testId?: string\n}\n\n/** One setting: label + help text on the left, its control on the right (stacks on phones). */\nexport function SettingsRow({\n label,\n labelFor,\n description,\n children,\n testId,\n className,\n ...props\n}: SettingsRowProps) {\n return (\n <div\n data-slot=\"settings-row\"\n data-testid={testId}\n className={cn(\n 'flex flex-col gap-2 py-2 @xl:flex-row @xl:items-center @xl:justify-between @xl:gap-6',\n className\n )}\n {...props}\n >\n <div className=\"min-w-0\">\n {labelFor ? (\n <label htmlFor={labelFor} className=\"text-sm font-medium text-foreground\">\n {label}\n </label>\n ) : (\n <div className=\"text-sm font-medium text-foreground\">{label}</div>\n )}\n {description && <div className=\"text-sm text-muted-foreground\">{description}</div>}\n </div>\n {children && <div className=\"flex shrink-0 items-center gap-2\">{children}</div>}\n </div>\n )\n}\n\nexport interface SettingsCardProps extends ComponentProps<'div'> {\n /** `md` for form-like content, `sm` when the card holds a list of full-bleed action rows. */\n padding?: 'md' | 'sm'\n}\n\n/** Tonal tile that groups related settings (surface by tone, no border). */\nexport function SettingsCard({ padding = 'md', className, ...props }: SettingsCardProps) {\n return (\n <div\n data-slot=\"settings-card\"\n className={cn(\n 'rounded-lg bg-muted',\n padding === 'md' ? 'space-y-5 p-5' : 'divide-y divide-border p-2',\n className\n )}\n {...props}\n />\n )\n}\n\nexport interface SettingsActionRowProps {\n title: ReactNode\n description?: ReactNode\n onClick: () => void\n testId?: string\n}\n\n/** Full-width row that opens a dialog or sub-page: title, help text and a chevron. */\nexport function SettingsActionRow({ title, description, onClick, testId }: SettingsActionRowProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n data-slot=\"settings-action-row\"\n data-testid={testId}\n className=\"flex w-full items-center gap-3 rounded-md px-3 py-3 text-left transition-colors hover:bg-background/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11\"\n >\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-sm font-semibold text-foreground\">{title}</div>\n {description && (\n <div className=\"mt-0.5 text-xs leading-relaxed text-muted-foreground\">{description}</div>\n )}\n </div>\n <ChevronRight className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n </button>\n )\n}\n\nexport interface SettingsDangerZoneProps {\n isOpen: boolean\n onToggle: () => void\n /** Heading of the collapsed zone. */\n label?: string\n title: ReactNode\n description: ReactNode\n /** The destructive control (a Button). */\n action: ReactNode\n labels?: Partial<SettingsDangerZoneLabels>\n}\n\n/** Collapsed-by-default zone for irreversible actions. */\nexport function SettingsDangerZone({\n isOpen,\n onToggle,\n label,\n title,\n description,\n action,\n labels,\n}: SettingsDangerZoneProps) {\n const l = useMemo(() => ({ ...DEFAULT_SETTINGS_DANGER_ZONE_LABELS, ...labels }), [labels])\n return (\n <div data-slot=\"settings-danger-zone\" className=\"mt-8 pt-2\">\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={isOpen}\n className=\"flex w-full items-center gap-1.5 text-left pointer-coarse:min-h-11\"\n >\n {isOpen ? (\n <ChevronDown className=\"h-3.5 w-3.5 text-muted-foreground\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5 text-muted-foreground\" />\n )}\n <p className=\"text-sm font-medium text-muted-foreground\">{label ?? l.dangerZone}</p>\n </button>\n {isOpen && (\n <div className=\"mt-3 flex items-center justify-between gap-4 rounded-lg bg-destructive/5 p-4\">\n <div>\n <p className=\"font-medium\">{title}</p>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n <div className=\"shrink-0\">{action}</div>\n </div>\n )}\n </div>\n )\n}\n","import { useMemo, type ReactNode } from 'react'\nimport { Check, Loader2, Mail, Pencil } from 'lucide-react'\nimport { Button, cn, Input, Tooltip, TooltipContent, TooltipTrigger } from '@arbidocs/react/ui'\nimport { SettingsCard } from './SettingsPanel'\n\n/** Every fixed string of the profile card. `ssoTooltip` prop wins over the label. */\nexport interface ProfileCardLabels {\n firstName: string\n lastName: string\n save: string\n cancel: string\n sso: string\n ssoTooltip: string\n change: string\n newEmailAddress: string\n emailPlaceholder: string\n /** Sentence under the new-email field. */\n codeWillBeSent: string\n sendCode: string\n /** Heading of the verify step: \"Verify new@example.com\". */\n verify: (email: string) => string\n codePlaceholder: string\n enterCodeHint: string\n confirm: string\n /** Resend button while cooling down: \"Resend in 30s\". */\n resendIn: (seconds: number) => string\n resendCode: string\n}\n\nexport const DEFAULT_PROFILE_CARD_LABELS: ProfileCardLabels = {\n firstName: 'First name',\n lastName: 'Last name',\n save: 'Save',\n cancel: 'Cancel',\n sso: 'SSO',\n ssoTooltip:\n 'Your email is managed by your sign-in provider. Change it there and it will sync here automatically on your next sign-in.',\n change: 'Change',\n newEmailAddress: 'New email address',\n emailPlaceholder: 'you@example.com',\n codeWillBeSent: 'We\\u2019ll send a 3-word verification code to this address.',\n sendCode: 'Send code',\n verify: (email) => `Verify ${email}`,\n codePlaceholder: 'WORD-WORD-WORD',\n enterCodeHint: 'Enter the 3-word code from the email we just sent.',\n confirm: 'Confirm',\n resendIn: (seconds) => `Resend in ${seconds}s`,\n resendCode: 'Resend code',\n}\n\nexport interface ProfileNameView {\n /** Display name; \"Unnamed\" is the host's call. */\n display: string\n isEditing: boolean\n givenName: string\n familyName: string\n onGivenNameChange: (value: string) => void\n onFamilyNameChange: (value: string) => void\n onStartEdit: () => void\n onSave: () => void\n onCancel: () => void\n isSaving: boolean\n}\n\nexport interface ProfileEmailChangeView {\n step: 'enter' | 'verify'\n newEmail: string\n onNewEmailChange: (value: string) => void\n onSendCode: () => void\n isSending: boolean\n code: string\n onCodeChange: (value: string) => void\n onConfirm: () => void\n isConfirming: boolean\n /** Seconds until a new code may be requested; 0 when allowed. */\n cooldownSeconds: number\n onCancel: () => void\n}\n\nexport interface ProfileCardProps {\n /** The picture with its change control. */\n avatar: ReactNode\n name: ProfileNameView\n email: string\n /** Email is managed by the sign-in provider: shows an \"SSO\" marker instead of \"Change\". */\n isSso: boolean\n onStartEmailChange: () => void\n /** Open email-change flow; hides the plain email row. */\n emailChange?: ProfileEmailChangeView\n ssoTooltip?: string\n labels?: Partial<ProfileCardLabels>\n}\n\n/** Profile identity: avatar, editable name, email and the inline email-change flow. */\nexport function ProfileCard({\n avatar,\n name,\n email,\n isSso,\n onStartEmailChange,\n emailChange,\n ssoTooltip,\n labels,\n}: ProfileCardProps) {\n const l = useMemo(() => ({ ...DEFAULT_PROFILE_CARD_LABELS, ...labels }), [labels])\n return (\n <SettingsCard>\n <div className=\"flex items-start gap-5\">\n {avatar}\n\n <div className=\"min-w-0 flex-1 space-y-3\">\n {name.isEditing ? (\n <div className=\"space-y-2\">\n <div className=\"flex flex-col gap-2 @xl:flex-row\">\n <Input\n value={name.givenName}\n onChange={(e) => name.onGivenNameChange(e.target.value)}\n placeholder={l.firstName}\n className=\"flex-1\"\n autoFocus\n />\n <Input\n value={name.familyName}\n onChange={(e) => name.onFamilyNameChange(e.target.value)}\n placeholder={l.lastName}\n className=\"flex-1\"\n />\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n onClick={name.onSave}\n size=\"sm\"\n disabled={!name.givenName.trim() || name.isSaving}\n >\n {name.isSaving ? (\n <Loader2 className=\"mr-1 h-4 w-4 animate-spin\" />\n ) : (\n <Check className=\"mr-1 h-4 w-4\" />\n )}\n {l.save}\n </Button>\n <Button onClick={name.onCancel} size=\"sm\" variant=\"ghost\" disabled={name.isSaving}>\n {l.cancel}\n </Button>\n </div>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={name.onStartEdit}\n className=\"-mx-2 w-full rounded-md px-2 py-1 text-left transition-colors hover:bg-background/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11\"\n >\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"min-w-0 flex-1 truncate font-heading text-xl font-semibold text-foreground\">\n {name.display}\n </span>\n <Pencil className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n </div>\n </button>\n )}\n\n {!emailChange && (\n <div className=\"-mx-2 flex min-w-0 items-center gap-2 px-2 py-1\">\n <Mail className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate text-sm text-muted-foreground\">{email}</span>\n {isSso ? (\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n className=\"ml-1 shrink-0 cursor-help rounded bg-background px-1.5 py-0.5 text-xs font-medium text-muted-foreground\"\n tabIndex={0}\n >\n {l.sso}\n </span>\n </TooltipTrigger>\n <TooltipContent className=\"max-w-xs\">{ssoTooltip ?? l.ssoTooltip}</TooltipContent>\n </Tooltip>\n ) : (\n <button\n type=\"button\"\n onClick={onStartEmailChange}\n className=\"ml-auto shrink-0 text-xs font-medium text-primary hover:underline pointer-coarse:min-h-11\"\n >\n {l.change}\n </button>\n )}\n </div>\n )}\n </div>\n </div>\n\n {emailChange && !isSso && (\n <div className=\"animate-accordion-down overflow-hidden\">\n <div className=\"space-y-3 rounded-lg bg-background p-4\">\n {emailChange.step === 'enter' ? (\n <>\n <div className=\"flex items-center gap-2 text-xs font-medium text-muted-foreground\">\n <Mail className=\"h-3.5 w-3.5\" />\n {l.newEmailAddress}\n </div>\n <Input\n type=\"email\"\n value={emailChange.newEmail}\n onChange={(e) => emailChange.onNewEmailChange(e.target.value)}\n placeholder={l.emailPlaceholder}\n autoFocus\n />\n <p className=\"text-xs text-muted-foreground\">{l.codeWillBeSent}</p>\n <div className=\"flex items-center gap-2 pt-1\">\n <Button\n onClick={emailChange.onSendCode}\n size=\"sm\"\n disabled={!emailChange.newEmail.trim() || emailChange.isSending}\n >\n {emailChange.isSending ? (\n <Loader2 className=\"mr-1 h-4 w-4 animate-spin\" />\n ) : (\n <Mail className=\"mr-1 h-4 w-4\" />\n )}\n {l.sendCode}\n </Button>\n <Button\n onClick={emailChange.onCancel}\n size=\"sm\"\n variant=\"ghost\"\n disabled={emailChange.isSending}\n >\n {l.cancel}\n </Button>\n </div>\n </>\n ) : (\n <>\n <div className=\"flex items-center gap-2 text-xs font-medium text-muted-foreground\">\n <Mail className=\"h-3.5 w-3.5\" />\n {l.verify(emailChange.newEmail)}\n </div>\n <Input\n value={emailChange.code}\n onChange={(e) =>\n emailChange.onCodeChange(e.target.value.toUpperCase().replace(/\\s+/g, '-'))\n }\n className={cn('text-center font-mono tracking-wider')}\n placeholder={l.codePlaceholder}\n autoFocus\n />\n <p className=\"text-xs text-muted-foreground\">{l.enterCodeHint}</p>\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Button\n onClick={emailChange.onConfirm}\n size=\"sm\"\n disabled={!emailChange.code.trim() || emailChange.isConfirming}\n >\n {emailChange.isConfirming ? (\n <Loader2 className=\"mr-1 h-4 w-4 animate-spin\" />\n ) : (\n <Check className=\"mr-1 h-4 w-4\" />\n )}\n {l.confirm}\n </Button>\n <Button\n onClick={() => {\n if (emailChange.cooldownSeconds > 0) return\n emailChange.onSendCode()\n }}\n size=\"sm\"\n variant=\"ghost\"\n disabled={emailChange.cooldownSeconds > 0 || emailChange.isSending}\n >\n {emailChange.cooldownSeconds > 0\n ? l.resendIn(emailChange.cooldownSeconds)\n : l.resendCode}\n </Button>\n <Button\n onClick={emailChange.onCancel}\n size=\"sm\"\n variant=\"ghost\"\n disabled={emailChange.isConfirming}\n >\n {l.cancel}\n </Button>\n </div>\n </>\n )}\n </div>\n </div>\n )}\n </SettingsCard>\n )\n}\n","import { useMemo, type FormEvent, type ReactNode, useId } from 'react'\nimport { AlertCircle, CheckCircle2, Loader2 } from 'lucide-react'\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n Input,\n} from '@arbidocs/react/ui'\nimport {\n PasswordStrengthInput,\n type PasswordStrengthInputLabels,\n type PasswordStrengthInputTestIds,\n} from '../auth/PasswordStrengthInput'\nimport { testIdOr } from '../chat/test-id'\nimport { formatCount } from '../lib/format'\n\n/** Every fixed string of the password-change dialog. */\nexport interface PasswordChangeDialogLabels {\n setNewPasswordTitle: string\n changeMasterPasswordTitle: string\n recoveryDescription: string\n changeDescription: string\n passwordChanged: string\n done: string\n recoverySuccessful: string\n currentPassword: string\n currentPasswordPlaceholder: string\n masterPassword: string\n newPassword: string\n confirmPassword: string\n confirmNewPassword: string\n /** Re-key notice: \"3 workspaces will be re-keyed with your new password.\" */\n workspacesRekeyed: (count: number) => string\n cancel: string\n settingPassword: string\n changingPassword: string\n continue: string\n changePassword: string\n}\n\nexport const DEFAULT_PASSWORD_CHANGE_DIALOG_LABELS: PasswordChangeDialogLabels = {\n setNewPasswordTitle: 'Set New Password',\n changeMasterPasswordTitle: 'Change Master Password',\n recoveryDescription: 'Set a new password for your recovered account',\n changeDescription: 'Change your master password dialog',\n passwordChanged: 'Password changed',\n done: 'Done',\n recoverySuccessful: 'Recovery successful. Set a new master password to continue.',\n currentPassword: 'Current Password',\n currentPasswordPlaceholder: 'Enter current password',\n masterPassword: 'Master Password',\n newPassword: 'New Password',\n confirmPassword: 'Confirm Password',\n confirmNewPassword: 'Confirm New Password',\n workspacesRekeyed: (count) =>\n `${formatCount(count, { one: 'workspace', other: 'workspaces' })} will be re-keyed with your new password.`,\n cancel: 'Cancel',\n settingPassword: 'Setting Password...',\n changingPassword: 'Changing Password...',\n continue: 'Continue',\n changePassword: 'Change Password',\n}\n\nexport interface PasswordChangeDialogProps {\n labels?: Partial<PasswordChangeDialogLabels>\n /** Labels forwarded to the embedded password input. */\n passwordInputLabels?: Partial<PasswordStrengthInputLabels>\n /** Dialog test id (default `change-password-dialog`). */\n testId?: string\n /** Part ids; defaults are the current ids. */\n testIds?: Partial<\n Record<'done' | 'currentInput' | 'workspaceCount' | 'error' | 'cancel' | 'submit', string>\n >\n /** Ids forwarded to the embedded password input. */\n passwordInputTestIds?: PasswordStrengthInputTestIds\n open: boolean\n /** Dismiss (also fired by Cancel and the close button). */\n onClose: () => void\n /** After recovery with a key: no current password, no Cancel, full-width Continue. */\n recoveryMode: boolean\n currentPassword: string\n onCurrentPasswordChange: (value: string) => void\n newPassword: string\n onNewPasswordChange: (value: string) => void\n confirmPassword: string\n onConfirmPasswordChange: (value: string) => void\n /** The host's password policy (see `PasswordStrengthInput`). */\n getUnmetRequirement: (password: string) => string | null\n /** Number of workspaces that will be re-keyed; the notice is hidden at 0. */\n workspaceCount: number\n error: string | null\n isProcessing: boolean\n isSubmitDisabled: boolean\n onSubmit: () => void\n /**\n * Success state: shown instead of the form once the password changed (the new recovery key\n * download). `null` while the form is showing.\n */\n success: ReactNode | null\n onDone: () => void\n}\n\n/** Change (or set, after recovery) the master password, then offer the new recovery key. */\nexport function PasswordChangeDialog({\n open,\n onClose,\n recoveryMode,\n currentPassword,\n onCurrentPasswordChange,\n newPassword,\n onNewPasswordChange,\n confirmPassword,\n onConfirmPasswordChange,\n getUnmetRequirement,\n workspaceCount,\n error,\n isProcessing,\n isSubmitDisabled,\n onSubmit,\n success,\n onDone,\n labels,\n passwordInputLabels,\n testId,\n testIds,\n passwordInputTestIds,\n}: PasswordChangeDialogProps) {\n const currentPasswordId = useId()\n const l = useMemo(() => ({ ...DEFAULT_PASSWORD_CHANGE_DIALOG_LABELS, ...labels }), [labels])\n const handleSubmit = (e: FormEvent) => {\n e.preventDefault()\n onSubmit()\n }\n\n return (\n <Dialog open={open} onOpenChange={(next) => !next && onClose()}>\n <DialogContent\n presentation=\"sheet\"\n className=\"sm:max-w-md\"\n data-testid={testIdOr(testId, { testId: 'change-password-dialog' })}\n >\n <DialogHeader>\n <DialogTitle>\n {recoveryMode ? l.setNewPasswordTitle : l.changeMasterPasswordTitle}\n </DialogTitle>\n <DialogDescription className=\"sr-only\">\n {recoveryMode ? l.recoveryDescription : l.changeDescription}\n </DialogDescription>\n </DialogHeader>\n\n {success ? (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 text-green-text\">\n <CheckCircle2 className=\"h-5 w-5\" />\n <span className=\"font-medium\">{l.passwordChanged}</span>\n </div>\n {success}\n <div className=\"flex justify-end\">\n <Button\n onClick={onDone}\n data-testid={testIdOr(testIds?.done, { testId: 'change-password-done-button' })}\n >\n {l.done}\n </Button>\n </div>\n </div>\n ) : (\n <form onSubmit={handleSubmit} className=\"space-y-3\">\n {recoveryMode && (\n <p className=\"text-sm font-medium text-green-text\">{l.recoverySuccessful}</p>\n )}\n\n {!recoveryMode && (\n <div className=\"space-y-1.5\">\n <label htmlFor={currentPasswordId} className=\"text-sm font-medium text-foreground\">\n {l.currentPassword} <span className=\"text-red-text\">*</span>\n </label>\n <Input\n id={currentPasswordId}\n type=\"password\"\n value={currentPassword}\n onChange={(e) => onCurrentPasswordChange(e.target.value)}\n disabled={isProcessing}\n placeholder={l.currentPasswordPlaceholder}\n autoComplete=\"current-password\"\n className=\"placeholder:text-muted-foreground\"\n data-testid={testIdOr(testIds?.currentInput, {\n testId: 'change-password-current-input',\n })}\n />\n </div>\n )}\n\n <PasswordStrengthInput\n password={newPassword}\n confirmPassword={confirmPassword}\n onPasswordChange={onNewPasswordChange}\n onConfirmPasswordChange={onConfirmPasswordChange}\n showConfirmation\n disabled={isProcessing}\n passwordLabel={recoveryMode ? l.masterPassword : l.newPassword}\n confirmLabel={recoveryMode ? l.confirmPassword : l.confirmNewPassword}\n labels={passwordInputLabels}\n testIds={passwordInputTestIds}\n layout={recoveryMode ? 'side-by-side' : 'stacked'}\n showStrengthIndicator\n getUnmetRequirement={getUnmetRequirement}\n />\n\n {workspaceCount > 0 && (\n <div\n className=\"rounded-md bg-green-bg p-3\"\n data-testid={testIdOr(testIds?.workspaceCount, {\n testId: 'change-password-workspace-count',\n })}\n >\n <div className=\"flex gap-2\">\n <CheckCircle2 className=\"h-5 w-5 flex-shrink-0 text-green-text\" />\n <p className=\"text-sm text-green-text\">{l.workspacesRekeyed(workspaceCount)}</p>\n </div>\n </div>\n )}\n\n {error && (\n <div\n className=\"rounded-md bg-red-bg p-3\"\n data-testid={testIdOr(testIds?.error, { testId: 'change-password-error' })}\n >\n <div className=\"flex gap-2\">\n <AlertCircle className=\"h-5 w-5 flex-shrink-0 text-red-text\" />\n <p className=\"text-sm text-red-text\">{error}</p>\n </div>\n </div>\n )}\n\n <div className=\"flex flex-col-reverse sm:flex-row sm:justify-end gap-3 pt-4\">\n {!recoveryMode && (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onClose}\n disabled={isProcessing}\n data-testid={testIdOr(testIds?.cancel, {\n testId: 'change-password-cancel-button',\n })}\n >\n {l.cancel}\n </Button>\n )}\n <Button\n type=\"submit\"\n disabled={isSubmitDisabled}\n className={recoveryMode ? 'w-full' : ''}\n data-testid={testIdOr(testIds?.submit, { testId: 'change-password-submit-button' })}\n >\n {isProcessing ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n {recoveryMode ? l.settingPassword : l.changingPassword}\n </>\n ) : recoveryMode ? (\n l.continue\n ) : (\n l.changePassword\n )}\n </Button>\n </div>\n </form>\n )}\n </DialogContent>\n </Dialog>\n )\n}\n","import { useMemo, type ReactNode, useId } from 'react'\nimport { prefixedTestId, testIdOr } from '../chat/test-id'\nimport { AlertTriangle, Loader2, LogOut, Radio } from 'lucide-react'\nimport {\n Badge,\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n Input,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@arbidocs/react/ui'\n\n/** Every fixed string of the active-sessions dialog. */\nexport interface ActiveSessionsDialogLabels {\n title: string\n description: string\n noSessions: string\n thisDevice: string\n agent: string\n endSession: string\n}\n\nexport const DEFAULT_ACTIVE_SESSIONS_DIALOG_LABELS: ActiveSessionsDialogLabels = {\n title: 'Active sessions',\n description:\n 'Devices and agents currently signed in to your account. Ending a session signs it out immediately.',\n noSessions: 'No active sessions.',\n thisDevice: 'This device',\n agent: 'Agent',\n endSession: 'End this session',\n}\n\n/** Every fixed string of the delete-account dialog. */\nexport interface DeleteAccountDialogLabels {\n warningTitle: string\n /** Sentence start, before the emphasised part (keep the trailing space). */\n warningBefore: string\n /** Emphasised (bold) part of the warning. */\n warningEmphasis: string\n /** Sentence end, after the emphasised part. */\n warningAfter: string\n blockersHeading: string\n cancel: string\n continue: string\n confirmTitle: string\n confirmDescription: string\n yourEmail: string\n back: string\n deleting: string\n deleteAccount: string\n}\n\nexport const DEFAULT_DELETE_ACCOUNT_DIALOG_LABELS: DeleteAccountDialogLabels = {\n warningTitle: 'Delete your account?',\n warningBefore: 'Once deleted, your account will be ',\n warningEmphasis: 'immediately closed and you will be logged out',\n warningAfter: '. This action cannot be undone.',\n blockersHeading: 'You must resolve these first:',\n cancel: 'Cancel',\n continue: 'Continue',\n confirmTitle: 'Confirm account deletion',\n confirmDescription:\n 'Type your email address to confirm. Your account will be closed immediately and you will be logged out.',\n yourEmail: 'Your email',\n back: 'Back',\n deleting: 'Deleting...',\n deleteAccount: 'Delete Account',\n}\n\nexport interface ActiveSessionView {\n id: string\n /** Display name, e.g. \"Browser session\". */\n name: string\n /** The session of this device: badged, and cannot be ended here. */\n isCurrent: boolean\n isAgent: boolean\n /** Secondary line, e.g. \"10.0.0.1 · expires in 2h · 3 workspaces\". */\n detail: string\n isTerminating: boolean\n /** Avatar glyph (monitor / bot). */\n icon?: ReactNode\n}\n\nexport interface ActiveSessionsDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n isLoading: boolean\n sessions: ActiveSessionView[]\n onTerminate: (id: string) => void\n labels?: Partial<ActiveSessionsDialogLabels>\n /** Dialog test id (default `active-sessions-dialog`). */\n testId?: string\n /**\n * Part ids; defaults are the current ids. `sessionItem` is a prefix (`<prefix>-<session id>`);\n * `terminateSession` is a prefix (`<prefix>-<session id>-button`).\n */\n testIds?: Partial<Record<'list' | 'sessionItem' | 'terminateSession', string>>\n}\n\nfunction SessionListRow({\n session,\n onTerminate,\n labels,\n testIds,\n}: {\n session: ActiveSessionView\n onTerminate: (id: string) => void\n labels: ActiveSessionsDialogLabels\n testIds?: ActiveSessionsDialogProps['testIds']\n}) {\n return (\n <div\n className=\"flex w-full items-center gap-3 border-b border-border/60 px-4 py-3 last:border-b-0\"\n data-testid={prefixedTestId(testIds?.sessionItem, session.id, {\n testId: `session-item-${session.id}`,\n })}\n >\n <span className=\"flex size-9 shrink-0 items-center justify-center rounded-full bg-muted\">\n {session.icon}\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate text-sm font-semibold text-foreground\">{session.name}</span>\n {session.isCurrent && (\n <Badge className=\"border-transparent bg-accent px-1.5 py-0 text-xs text-accent-foreground shadow-none hover:bg-accent\">\n {labels.thisDevice}\n </Badge>\n )}\n {session.isAgent && (\n <Badge variant=\"default\" className=\"px-1 py-0 text-xs\">\n {labels.agent}\n </Badge>\n )}\n </div>\n <div className=\"mt-0.5 truncate text-xs text-muted-foreground\">{session.detail}</div>\n </div>\n {!session.isCurrent && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 shrink-0 text-muted-foreground hover:text-destructive\"\n aria-label={labels.endSession}\n onClick={() => onTerminate(session.id)}\n disabled={session.isTerminating}\n data-testid={prefixedTestId(\n testIds?.terminateSession,\n session.id,\n { testId: `terminate-session-${session.id}-button` },\n '-button'\n )}\n >\n {session.isTerminating ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <LogOut className=\"h-4 w-4\" />\n )}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{labels.endSession}</TooltipContent>\n </Tooltip>\n )}\n </div>\n )\n}\n\n/**\n * Every session signed in to the account (this device, other devices, agents). Any but the current\n * one can be ended; ending the current one belongs to the Logout flow.\n */\nexport function ActiveSessionsDialog({\n open,\n onOpenChange,\n isLoading,\n sessions,\n onTerminate,\n labels,\n testId,\n testIds,\n}: ActiveSessionsDialogProps) {\n const l = useMemo(() => ({ ...DEFAULT_ACTIVE_SESSIONS_DIALOG_LABELS, ...labels }), [labels])\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n presentation=\"sheet\"\n className=\"sm:max-w-lg\"\n data-testid={testIdOr(testId, { testId: 'active-sessions-dialog' })}\n >\n <DialogHeader>\n <div className=\"flex items-center gap-3\">\n <Radio className=\"h-6 w-6\" />\n <DialogTitle>{l.title}</DialogTitle>\n </div>\n <DialogDescription>{l.description}</DialogDescription>\n </DialogHeader>\n\n {isLoading ? (\n <div className=\"flex justify-center py-8\">\n <Loader2 className=\"h-5 w-5 animate-spin text-muted-foreground\" />\n </div>\n ) : sessions.length === 0 ? (\n <p className=\"py-4 text-center text-sm text-muted-foreground\">{l.noSessions}</p>\n ) : (\n <div\n className=\"-mx-2 max-h-96 overflow-auto rounded-lg bg-muted\"\n data-testid={testIdOr(testIds?.list, { testId: 'session-list' })}\n >\n {sessions.map((session) => (\n <SessionListRow\n key={session.id}\n session={session}\n onTerminate={onTerminate}\n labels={l}\n testIds={testIds}\n />\n ))}\n </div>\n )}\n </DialogContent>\n </Dialog>\n )\n}\n\nexport interface DeleteAccountBlocker {\n key: string\n content: ReactNode\n}\n\nexport interface DeleteAccountDialogProps {\n open: boolean\n onClose: () => void\n step: 'warning' | 'confirm'\n /** Reasons the account cannot be deleted yet; Continue is disabled while any exist. */\n blockers: DeleteAccountBlocker[]\n onContinue: () => void\n onBack: () => void\n userEmail: string\n confirmEmail: string\n onConfirmEmailChange: (email: string) => void\n isDeleting: boolean\n onSubmit: () => void\n labels?: Partial<DeleteAccountDialogLabels>\n /** Dialog test id (default `delete-account-dialog`). */\n testId?: string\n /** Part ids; defaults are the current ids. */\n testIds?: Partial<Record<'cancel' | 'continue' | 'emailInput' | 'back' | 'submit', string>>\n}\n\n/** Two-step account deletion: a warning (with blockers), then type-your-email to confirm. */\nexport function DeleteAccountDialog({\n open,\n onClose,\n step,\n blockers,\n onContinue,\n onBack,\n userEmail,\n confirmEmail,\n onConfirmEmailChange,\n isDeleting,\n onSubmit,\n labels,\n testId,\n testIds,\n}: DeleteAccountDialogProps) {\n const confirmEmailId = useId()\n const l = useMemo(() => ({ ...DEFAULT_DELETE_ACCOUNT_DIALOG_LABELS, ...labels }), [labels])\n const emailMatches = confirmEmail.toLowerCase() === userEmail.toLowerCase()\n\n return (\n <Dialog open={open} onOpenChange={onClose}>\n <DialogContent\n presentation=\"sheet\"\n className=\"sm:max-w-md\"\n data-testid={testIdOr(testId, { testId: 'delete-account-dialog' })}\n >\n {step === 'warning' ? (\n <>\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <AlertTriangle className=\"h-5 w-5 text-destructive\" />\n {l.warningTitle}\n </DialogTitle>\n <DialogDescription>\n {l.warningBefore}\n <strong>{l.warningEmphasis}</strong>\n {l.warningAfter}\n </DialogDescription>\n </DialogHeader>\n {blockers.length > 0 && (\n <div className=\"rounded-md bg-yellow-bg p-3 text-sm text-yellow-text\">\n <p className=\"mb-1 font-semibold\">{l.blockersHeading}</p>\n <ul className=\"list-inside list-disc space-y-1\">\n {blockers.map((blocker) => (\n <li key={blocker.key}>{blocker.content}</li>\n ))}\n </ul>\n </div>\n )}\n <div className=\"flex flex-col-reverse sm:flex-row sm:justify-end gap-2 pt-2\">\n <Button\n variant=\"outline\"\n onClick={onClose}\n data-testid={testIdOr(testIds?.cancel, { testId: 'delete-account-cancel-button' })}\n >\n {l.cancel}\n </Button>\n <Button\n variant=\"destructive\"\n disabled={blockers.length > 0}\n onClick={onContinue}\n data-testid={testIdOr(testIds?.continue, {\n testId: 'delete-account-continue-button',\n })}\n >\n {l.continue}\n </Button>\n </div>\n </>\n ) : (\n <>\n <DialogHeader>\n <DialogTitle>{l.confirmTitle}</DialogTitle>\n <DialogDescription>{l.confirmDescription}</DialogDescription>\n </DialogHeader>\n <div>\n <label htmlFor={confirmEmailId} className=\"mb-1 block text-sm font-medium\">\n {l.yourEmail}\n </label>\n <Input\n id={confirmEmailId}\n type=\"email\"\n placeholder={userEmail}\n value={confirmEmail}\n onChange={(e) => onConfirmEmailChange(e.target.value)}\n autoFocus\n data-testid={testIdOr(testIds?.emailInput, {\n testId: 'delete-account-email-input',\n })}\n />\n </div>\n <div className=\"flex flex-col-reverse sm:flex-row sm:justify-end gap-2 pt-2\">\n <Button\n variant=\"outline\"\n onClick={onBack}\n data-testid={testIdOr(testIds?.back, { testId: 'delete-account-back-button' })}\n >\n {l.back}\n </Button>\n <Button\n variant=\"destructive\"\n disabled={!emailMatches || isDeleting}\n onClick={onSubmit}\n data-testid={testIdOr(testIds?.submit, { testId: 'delete-account-submit-button' })}\n >\n {isDeleting ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n {l.deleting}\n </>\n ) : (\n l.deleteAccount\n )}\n </Button>\n </div>\n </>\n )}\n </DialogContent>\n </Dialog>\n )\n}\n","import { useMemo, useState, type ReactNode } from 'react'\nimport { ChevronDown, ChevronRight, LogOut, Radio } from 'lucide-react'\nimport {\n Badge,\n Button,\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\nimport { useRestoreFocus } from '../lib/useRestoreFocus'\nimport { formatCount } from '../lib/format'\n\n/** Every fixed string of the logout dialog. */\nexport interface LogoutDialogLabels {\n title: string\n descriptionAll: string\n descriptionThis: string\n cancel: string\n allSessions: string\n offlineTooltip: string\n thisSession: string\n offlineNote: string\n /** Disclosure trigger: \"3 active sessions\". */\n activeSessions: (count: number) => string\n /** Session row: \"2 workspaces\". */\n workspaces: (count: number) => string\n /** Session row: \"TTL 2h\". */\n ttl: (ttlLabel: string) => string\n}\n\nexport const DEFAULT_LOGOUT_DIALOG_LABELS: LogoutDialogLabels = {\n title: 'Logout',\n descriptionAll: 'End this session or all active sessions?',\n descriptionThis: 'End this session and return to the login page.',\n cancel: 'Cancel',\n allSessions: 'All sessions',\n offlineTooltip: 'Ending all sessions needs a connection — you can still log out of this device.',\n thisSession: 'This session',\n offlineNote:\n 'You’re offline — ending all sessions needs a connection. You can still log out of this device.',\n activeSessions: (count) =>\n formatCount(count, { one: 'active session', other: 'active sessions' }),\n workspaces: (count) => formatCount(count, { one: 'workspace', other: 'workspaces' }),\n ttl: (ttlLabel) => `TTL ${ttlLabel}`,\n}\n\nexport interface LogoutSessionView {\n id: string\n /** `agent` sessions are shown with the primary badge. */\n status: string\n ipAddress?: string | null\n /** Pre-formatted remaining lifetime, e.g. \"2h\". */\n ttlLabel: string\n workspaceCount: number\n}\n\nexport interface LogoutDialogProps {\n open: boolean\n onClose: () => void\n onLogoutThis: () => void\n onLogoutAll: () => void\n /** False for agent accounts: \"All sessions\" is not offered. */\n canLogoutAll: boolean\n isOnline: boolean\n sessions: LogoutSessionView[]\n /** Icon for a session row (monitor / bot). */\n renderSessionIcon?: (status: string) => ReactNode\n labels?: Partial<LogoutDialogLabels>\n /** Dialog test id (default `logout-modal`). */\n testId?: string\n /** Part ids; defaults are the current ids. */\n testIds?: Partial<Record<'cancel' | 'all' | 'this' | 'offlineNote', string>>\n}\n\nfunction SessionRow({\n session,\n icon,\n labels,\n}: {\n session: LogoutSessionView\n icon?: ReactNode\n labels: LogoutDialogLabels\n}) {\n const { status } = session\n return (\n <div className=\"flex items-center gap-3 rounded-md bg-muted/50 px-3 py-2\">\n {icon && <div className=\"flex-shrink-0\">{icon}</div>}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <code className=\"truncate font-mono text-sm\">{session.id.slice(0, 12)}</code>\n <Badge\n variant={status === 'agent' ? 'default' : 'secondary'}\n className=\"px-1 py-0 text-sm\"\n >\n {status}\n </Badge>\n </div>\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n {session.ipAddress && <span>{session.ipAddress}</span>}\n <span>{labels.ttl(session.ttlLabel)}</span>\n {session.workspaceCount > 0 && <span>{labels.workspaces(session.workspaceCount)}</span>}\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * Logout confirmation: end this session or all sessions, with the list of the\n * user's active sessions (including agent sessions) under a disclosure.\n * \"All sessions\" is disabled while offline because it must reach the server.\n */\nexport function LogoutDialog({\n open,\n onClose,\n onLogoutThis,\n onLogoutAll,\n canLogoutAll,\n isOnline,\n sessions,\n renderSessionIcon,\n labels,\n testId,\n testIds,\n}: LogoutDialogProps) {\n const l = useMemo(() => ({ ...DEFAULT_LOGOUT_DIALOG_LABELS, ...labels }), [labels])\n const [sessionsOpen, setSessionsOpen] = useState(false)\n const restoreFocus = useRestoreFocus()\n\n return (\n <Dialog open={open} onOpenChange={(next) => !next && onClose()}>\n <DialogContent\n {...restoreFocus}\n className=\"sm:max-w-md\"\n data-testid={testIdOr(testId, { testId: 'logout-modal' })}\n >\n <DialogHeader>\n <div className=\"flex items-center gap-3\">\n <LogOut className=\"h-6 w-6\" />\n <DialogTitle>{l.title}</DialogTitle>\n </div>\n <DialogDescription className=\"text-base\">\n {canLogoutAll ? l.descriptionAll : l.descriptionThis}\n </DialogDescription>\n </DialogHeader>\n\n <DialogFooter className=\"gap-2\">\n <Button\n variant=\"outline\"\n onClick={onClose}\n data-testid={testIdOr(testIds?.cancel, { testId: 'logout-modal-cancel-button' })}\n >\n {l.cancel}\n </Button>\n {canLogoutAll && (\n <Button\n variant=\"secondary\"\n onClick={onLogoutAll}\n disabled={!isOnline}\n title={isOnline ? undefined : l.offlineTooltip}\n data-testid={testIdOr(testIds?.all, { testId: 'logout-modal-all-button' })}\n >\n {l.allSessions}\n </Button>\n )}\n <Button\n variant=\"default\"\n onClick={onLogoutThis}\n data-testid={testIdOr(testIds?.this, { testId: 'logout-modal-this-button' })}\n >\n {l.thisSession}\n </Button>\n </DialogFooter>\n\n {canLogoutAll && !isOnline && (\n <p\n className=\"text-sm text-muted-foreground\"\n data-testid={testIdOr(testIds?.offlineNote, { testId: 'logout-offline-note' })}\n >\n {l.offlineNote}\n </p>\n )}\n\n {sessions.length > 0 && (\n <Collapsible open={sessionsOpen} onOpenChange={setSessionsOpen}>\n <CollapsibleTrigger className=\"flex w-full items-center gap-2 py-1 text-left transition-opacity hover:opacity-80 pointer-coarse:py-3\">\n {sessionsOpen ? (\n <ChevronDown className=\"h-4 w-4 flex-shrink-0\" />\n ) : (\n <ChevronRight className=\"h-4 w-4 flex-shrink-0\" />\n )}\n <div className=\"flex items-center gap-1.5 text-sm font-medium text-muted-foreground\">\n <Radio className=\"h-3 w-3\" />\n <span>{l.activeSessions(sessions.length)}</span>\n </div>\n </CollapsibleTrigger>\n <CollapsibleContent>\n <div className=\"max-h-48 space-y-1.5 overflow-auto pt-2\">\n {sessions.map((session) => (\n <SessionRow\n key={session.id}\n session={session}\n icon={renderSessionIcon?.(session.status)}\n labels={l}\n />\n ))}\n </div>\n </CollapsibleContent>\n </Collapsible>\n )}\n </DialogContent>\n </Dialog>\n )\n}\n","import type { ReactNode } from 'react'\nimport { Switch, cn } from '@arbidocs/react/ui'\n\nexport interface SettingsSwitchRowProps {\n /** Id of the switch; also the `htmlFor` of the label so clicking the label toggles it. */\n id: string\n title: ReactNode\n /** Leading glyph of the title. */\n icon?: ReactNode\n description?: ReactNode\n checked: boolean\n onCheckedChange: (checked: boolean) => void\n testId?: string\n disabled?: boolean\n className?: string\n}\n\n/** One on/off setting: icon + title + help text at the start, the switch at the end. */\nexport function SettingsSwitchRow({\n id,\n title,\n icon,\n description,\n checked,\n onCheckedChange,\n testId,\n disabled,\n className,\n}: SettingsSwitchRowProps) {\n return (\n <div\n data-slot=\"settings-switch-row\"\n className={cn('flex items-center justify-between gap-4', className)}\n >\n <div className=\"min-w-0 flex-1\">\n <label htmlFor={id} className=\"flex items-center gap-2 text-sm font-medium text-foreground\">\n {icon}\n {title}\n </label>\n {description && <p className=\"mt-1 text-sm text-muted-foreground\">{description}</p>}\n </div>\n <Switch\n id={id}\n checked={checked}\n onCheckedChange={onCheckedChange}\n disabled={disabled}\n data-testid={testId}\n />\n </div>\n )\n}\n\n/** Indented group of rows that belong to the row above (e.g. the connectors of \"Connectors\"). */\nexport function SettingsSwitchGroup({\n className,\n children,\n}: {\n className?: string\n children: ReactNode\n}) {\n return (\n <div\n data-slot=\"settings-switch-group\"\n className={cn('ml-6 space-y-4 border-l border-border pl-4', className)}\n >\n {children}\n </div>\n )\n}\n","import { Checkbox, cn } from '@arbidocs/react/ui'\nimport { prefixedTestId, testIdOr } from '../chat/test-id'\nimport { SettingsSwitchRow } from './SettingsSwitchRow'\n\nexport interface NotificationCategory {\n key: string\n label: string\n description: string\n checked: boolean\n}\n\nexport interface NotificationCategoryListProps {\n /** Master switch: on while at least one category is on. */\n masterId: string\n masterTitle: string\n masterDescription: string\n masterChecked: boolean\n onMasterChange: (checked: boolean) => void\n masterTestId?: string\n categories: NotificationCategory[]\n onCategoryChange: (key: string, checked: boolean) => void\n /** Prefix of the checkbox ids (`<prefix>-<key>`); default the master id. */\n idPrefix?: string\n /** Prefix of the checkbox test ids (`<prefix>-<key>`); default `toggle-email`. */\n testIdPrefix?: string\n}\n\n/**\n * A master switch with per-category checkboxes under it. The checkboxes are greyed out and\n * disabled while the master is off.\n */\nexport function NotificationCategoryList({\n masterId,\n masterTitle,\n masterDescription,\n masterChecked,\n onMasterChange,\n masterTestId,\n categories,\n onCategoryChange,\n idPrefix = masterId,\n testIdPrefix,\n}: NotificationCategoryListProps) {\n return (\n <div data-slot=\"notification-category-list\">\n <SettingsSwitchRow\n id={masterId}\n title={masterTitle}\n description={masterDescription}\n checked={masterChecked}\n onCheckedChange={onMasterChange}\n testId={testIdOr(masterTestId, { testId: 'toggle-email-notifications' })}\n />\n <div className=\"ml-1 mt-3 space-y-3 border-l border-border pl-4 pointer-coarse:mt-5 pointer-coarse:space-y-5\">\n {categories.map((c) => (\n <label\n key={c.key}\n htmlFor={`${idPrefix}-${c.key}`}\n className={cn(\n 'flex items-start gap-3 pointer-coarse:min-h-11',\n masterChecked ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'\n )}\n >\n <Checkbox\n id={`${idPrefix}-${c.key}`}\n checked={c.checked}\n disabled={!masterChecked}\n onCheckedChange={(value) => onCategoryChange(c.key, value === true)}\n data-testid={prefixedTestId(testIdPrefix, c.key, { testId: `toggle-email-${c.key}` })}\n className=\"mt-0.5 size-5 shrink-0\"\n />\n <div className=\"min-w-0\">\n <span className=\"text-sm\">{c.label}</span>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">{c.description}</p>\n </div>\n </label>\n ))}\n </div>\n </div>\n )\n}\n","/**\n * Pure mappers from the account data the hooks return to the props of the settings parts\n * (`ActiveSessionsDialog`, `LogoutDialog`, `DeleteAccountDialog`, `NotificationCategoryList`).\n * No React Query, no SDK: a host with its own data layer uses them too.\n */\n\nimport type { ReactNode } from 'react'\nimport type { ActiveSessionView, DeleteAccountBlocker } from './AccountDialogs'\nimport type { LogoutSessionView } from './LogoutDialog'\nimport type { NotificationCategory } from './NotificationCategoryList'\n\n/** A session as `GET /v1/user/sessions` reports it (the fields the views read). */\nexport interface SessionLike {\n session_id: string\n name?: string | null\n ip_address?: string | null\n workspaces: readonly string[]\n status?: string | null\n /** Seconds left. */\n ttl: number\n}\n\n/** Remaining seconds as `1d 2h 3m`; `expired` at or below zero. */\nexport function formatSessionTtl(totalSeconds: number): string {\n if (totalSeconds <= 0) return 'expired'\n const days = Math.floor(totalSeconds / 86400)\n const hours = Math.floor((totalSeconds % 86400) / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const parts: string[] = []\n if (days > 0) parts.push(`${days}d`)\n if (hours > 0) parts.push(`${hours}h`)\n if (minutes > 0) parts.push(`${minutes}m`)\n return parts.length > 0 ? parts.join(' ') : '<1m'\n}\n\nexport interface ToActiveSessionViewsOptions {\n /** This device's session id (`useCurrentSessionId`); it is listed first and cannot be ended. */\n currentSessionId: string | null\n /** The session being ended right now, for its spinner. */\n terminatingId?: string | null\n /** Glyph per status (`user` / `agent`). */\n renderIcon?: (status: string) => ReactNode\n formatTtl?: (seconds: number) => string\n}\n\n/** Sessions as `ActiveSessionsDialog` rows: this device first, a detail line, agents marked. */\nexport function toActiveSessionViews(\n sessions: readonly SessionLike[],\n {\n currentSessionId,\n terminatingId,\n renderIcon,\n formatTtl = formatSessionTtl,\n }: ToActiveSessionViewsOptions\n): ActiveSessionView[] {\n return sessions\n .map((session) => {\n const status = session.status || 'user'\n const count = session.workspaces.length\n return {\n id: session.session_id,\n name: session.name || (status === 'agent' ? 'Agent session' : 'Browser session'),\n isCurrent: session.session_id === currentSessionId,\n isAgent: status === 'agent',\n detail: `${session.ip_address ?? 'Unknown IP'} · expires in ${formatTtl(session.ttl)}${\n count > 0 ? ` · ${count} workspace${count > 1 ? 's' : ''}` : ''\n }`,\n isTerminating: terminatingId === session.session_id,\n icon: renderIcon?.(status),\n }\n })\n .sort((a, b) => Number(b.isCurrent) - Number(a.isCurrent))\n}\n\n/** Sessions as `LogoutDialog` rows. */\nexport function toLogoutSessionViews(\n sessions: readonly SessionLike[],\n formatTtl: (seconds: number) => string = formatSessionTtl\n): LogoutSessionView[] {\n return sessions.map((session) => ({\n id: session.session_id,\n status: session.status || 'user',\n ipAddress: session.ip_address,\n ttlLabel: formatTtl(session.ttl),\n workspaceCount: session.workspaces.length,\n }))\n}\n\n/** A reason the account cannot be closed yet (see `parseDeleteAccountBlockers`). */\nexport type DeleteBlockerLike =\n { type: 'active_subscription' } | { type: 'workspace_members'; workspaces: readonly string[] }\n\n/** Blockers as `DeleteAccountDialog` rows. `renderSubscriptionLink` lets the host link its billing page. */\nexport function toDeleteBlockerViews(\n blockers: readonly DeleteBlockerLike[],\n renderSubscriptionLink?: () => ReactNode\n): DeleteAccountBlocker[] {\n return blockers.flatMap<DeleteAccountBlocker>((blocker) =>\n blocker.type === 'active_subscription'\n ? [\n {\n key: 'active_subscription',\n content: renderSubscriptionLink\n ? renderSubscriptionLink()\n : 'Active subscription: cancel it in your subscription settings first',\n },\n ]\n : blocker.workspaces.map((ws) => ({\n key: `workspace-${ws}`,\n content: `You are the sole admin of workspace \"${ws}\" — transfer admin rights or remove all other members first`,\n }))\n )\n}\n\n/** One email category the user can switch: its key in the settings record and its wording. */\nexport interface EmailNotificationCategoryDef {\n key: string\n label: string\n description: string\n}\n\n/** The categories ARBI sends email for today (add one when the backend adds it). */\nexport const EMAIL_NOTIFICATION_CATEGORIES: readonly EmailNotificationCategoryDef[] = [\n { key: 'messages', label: 'New messages', description: 'A direct message while you’re offline' },\n { key: 'workspace_added', label: 'Workspace access', description: 'You’re added to a workspace' },\n {\n key: 'contact_accepted',\n label: 'Invitation accepted',\n description: 'Someone accepts your invitation',\n },\n { key: 'referral_reward', label: 'Rewards', description: 'You earn a reward' },\n {\n key: 'product_updates',\n label: 'ARBI update',\n description: 'Weekly digest of new features and highlights',\n },\n]\n\n/** The category keys, in the order the list shows them. */\nexport const EMAIL_NOTIFICATION_KEYS: readonly string[] = EMAIL_NOTIFICATION_CATEGORIES.map(\n (c) => c.key\n)\n\n/** Category definitions plus their states as `NotificationCategoryList` rows. */\nexport function toNotificationCategories(\n checked: Readonly<Record<string, boolean>>,\n defs: readonly EmailNotificationCategoryDef[] = EMAIL_NOTIFICATION_CATEGORIES\n): NotificationCategory[] {\n return defs.map((def) => ({ ...def, checked: checked[def.key] ?? true }))\n}\n"]}
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkPPCATBOY_cjs = require('./chunk-PPCATBOY.cjs');
5
4
  var chunkOB5F4577_cjs = require('./chunk-OB5F4577.cjs');
6
- var chunkMHVNT4J3_cjs = require('./chunk-MHVNT4J3.cjs');
5
+ var chunkPPCATBOY_cjs = require('./chunk-PPCATBOY.cjs');
7
6
  var chunkKDG6FER6_cjs = require('./chunk-KDG6FER6.cjs');
7
+ var chunkMHVNT4J3_cjs = require('./chunk-MHVNT4J3.cjs');
8
8
  var lucideReact = require('lucide-react');
9
9
  var ui = require('@arbidocs/react/ui');
10
10
  var jsxRuntime = require('react/jsx-runtime');
@@ -513,5 +513,5 @@ exports.SectionHeader = SectionHeader;
513
513
  exports.SectionLabel = SectionLabel;
514
514
  exports.StartTiles = StartTiles;
515
515
  exports.useScopeSelection = useScopeSelection;
516
- //# sourceMappingURL=chunk-MVNCQDDE.cjs.map
517
- //# sourceMappingURL=chunk-MVNCQDDE.cjs.map
516
+ //# sourceMappingURL=chunk-ZVPTFTGV.cjs.map
517
+ //# sourceMappingURL=chunk-ZVPTFTGV.cjs.map
@@ -1 +1 @@
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-MVNCQDDE.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 bg-muted 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('text-sm font-semibold text-foreground', className)}\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 bg-muted px-4 py-3 text-left transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default disabled:hover:bg-muted 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 bg-muted p-4 text-left',\n 'transition-colors hover:bg-accent',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n 'disabled:cursor-default disabled:opacity-55 disabled:hover:bg-muted',\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
+ {"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-ZVPTFTGV.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 bg-muted 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('text-sm font-semibold text-foreground', className)}\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 bg-muted px-4 py-3 text-left transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default disabled:hover:bg-muted 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 bg-muted p-4 text-left',\n 'transition-colors hover:bg-accent',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n 'disabled:cursor-default disabled:opacity-55 disabled:hover:bg-muted',\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"]}