{"version":3,"file":"ContactsScreen-I8M58tHr.mjs","names":["ContextMenuPrimitive.Root","ContextMenuPrimitive.Trigger","ContextMenuPrimitive.Portal","ContextMenuPrimitive.Content","ContextMenuPrimitive.Item","ContextMenuPrimitive.Separator","ContextMenuPrimitive.Sub","ContextMenuPrimitive.SubTrigger","ContextMenuPrimitive.SubContent","useUpdateContactMutation","useCoreUpdateContactMutation","useDeleteContactMutation","useCoreDeleteContactMutation","formatDueDate","r","e","t","n","z","X","o","a","l","EmojiPickerPrimitive","HexColorPicker","HexColorInput","useCreateContactMutation","useCoreCreateContactMutation","useIsMobile"],"sources":["../../../platform/api-client-core/src/parse-api-errors.ts","../../../contacts/ui/src/portal/hooks/groups/invalidate-contact-caches.ts","../../../contacts/ui/src/screens/ContactCreateScreen.tsx","../../../contacts/ui/src/portal/hooks/groups/use-groups.ts","../../../contacts/ui/src/portal/components/contacts/rep-layout/utils.ts","../../../contacts/ui/src/portal/components/contacts/rep-layout/ContactsSidebarRow.tsx","../../../contacts/ui/src/portal/components/contacts/rep-layout/ContextMenu.tsx","../../../contacts/ui/src/portal/components/contacts/rep-layout/ContactsSidebar.tsx","../../../contacts/ui/src/shared/components/contacts/contactDetailsForm.tsx","../../../contacts/core/src/hooks/use-contact-detail.ts","../../../contacts/core/src/hooks/use-update-contact-mutation.ts","../../../contacts/ui/src/shared/hooks/useUpdateContactMutation.ts","../../../contacts/core/src/hooks/use-delete-contact-mutation.ts","../../../contacts/ui/src/shared/hooks/useDeleteContactMutation.ts","../../../contacts/ui/src/shared/schemas/contactFormSchema.ts","../../../contacts/ui/src/shared/hooks/useContactDetailPage.ts","../../../contacts/ui/src/portal/hooks/contacts/use-contact-tasks.ts","../../../contacts/ui/src/portal/hooks/notes/use-contact-notes.ts","../../../contacts/ui/src/portal/hooks/groups/use-create-group.ts","../../../contacts/ui/src/portal/hooks/groups/use-update-contact-tags.ts","../../../contacts/ui/src/shared/components/contacts/statusBadge.tsx","../../../contacts/ui/src/portal/components/contacts/rep-layout/InlineGroupsEditor.tsx","../../../contacts/ui/src/portal/components/contacts/rep-layout/ContactDetailHero.tsx","../../../contacts/ui/src/portal/components/contacts/rep-layout/ContactInfoRow.tsx","../../../contacts/ui/src/portal/hooks/contacts/use-toggle-task-completion.ts","../../../contacts/ui/src/portal/hooks/contacts/use-delete-contact-task.ts","../../../contacts/ui/src/portal/hooks/contacts/use-update-contact-task.ts","../../../contacts/ui/src/portal/components/editor/note-task-editor.tsx","../../../contacts/ui/src/portal/components/editor/note-task-modal.tsx","../../../contacts/ui/src/portal/components/tasks/task-list.tsx","../../../contacts/ui/src/portal/hooks/contacts/use-create-contact-task.ts","../../../contacts/ui/src/portal/components/tasks/inline-task-composer.tsx","../../../contacts/ui/src/portal/hooks/notes/use-delete-contact-note.ts","../../../contacts/ui/src/portal/hooks/notes/use-update-contact-note.ts","../../../contacts/ui/src/portal/hooks/notes/use-create-contact-note.ts","../../../contacts/ui/src/portal/components/notes/inline-note-composer.tsx","../../../contacts/ui/src/portal/components/notes/notes-list.tsx","../../../contacts/ui/src/portal/components/contacts/rep-layout/ContactDetailTabs.tsx","../../../contacts/ui/src/portal/components/contacts/rep-layout/ContactDetailPane.tsx","../../../contacts/ui/src/portal/components/contacts/rep-layout/ContactsEmptyState.tsx","../../../contacts/ui/src/portal/components/contacts/rep-layout/RepContactsLayout.tsx","../../../../node_modules/.pnpm/react-colorful@5.6.1_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-colorful/dist/index.mjs","../../../contacts/ui/src/portal/hooks/groups/use-delete-group.ts","../../../contacts/ui/src/portal/hooks/groups/use-update-group.ts","../../../contacts/ui/src/portal/components/contacts/rep-layout/GroupsManagePage.tsx","../../../contacts/core/src/hooks/use-create-contact-mutation.ts","../../../contacts/ui/src/shared/hooks/useCreateContactMutation.ts","../src/screens/contacts-route-state.ts","../src/screens/ContactsScreen.tsx"],"sourcesContent":["/**\n * Framework-agnostic API error parsing utilities.\n *\n * Extracts structured field-level errors from API responses and formats\n * them into human-readable messages. Works with ApiError from this package\n * as well as any error object that has `status`, `data`, and optional `message`.\n */\n\n/**\n * Converts snake_case or camelCase field names to Title Case\n */\nexport function formatFieldName(field: string): string {\n  return field\n    .replace(/_/g, \" \")\n    .replace(/([A-Z])/g, \" $1\")\n    .split(\" \")\n    .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n    .join(\" \")\n    .trim();\n}\n\nexport interface ParsedFieldError {\n  field: string;\n  messages: string[];\n}\n\nconst requestIdLinePrefix = \"Request ID: \";\n\nfunction getStringRequestId(value: unknown): string | undefined {\n  if (typeof value !== \"string\") {\n    return undefined;\n  }\n\n  const trimmed = value.trim();\n  return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction getRequestIdFromJsonBody(body: unknown): string | undefined {\n  if (!body || typeof body !== \"object\" || Array.isArray(body)) {\n    return undefined;\n  }\n\n  const record = body as Record<string, unknown>;\n  const meta = record.meta;\n\n  return (\n    getStringRequestId(record.request_id) ??\n    getStringRequestId(record.requestId) ??\n    (meta && typeof meta === \"object\" && !Array.isArray(meta)\n      ? (getStringRequestId((meta as Record<string, unknown>).request_id) ??\n        getStringRequestId((meta as Record<string, unknown>).requestId))\n      : undefined)\n  );\n}\n\nfunction isRequestIdMetadataKey(key: string, value: unknown): boolean {\n  if (key === \"request_id\" || key === \"requestId\") {\n    return getStringRequestId(value) !== undefined;\n  }\n\n  if (key !== \"meta\") {\n    return false;\n  }\n\n  return getRequestIdFromJsonBody(value) !== undefined;\n}\n\nfunction getStringEnvelopeMessage(value: unknown): string | undefined {\n  if (typeof value !== \"string\") {\n    return undefined;\n  }\n\n  const trimmed = value.trim();\n  return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction isScalarEnvelopeMessageKey(key: string, value: unknown): boolean {\n  return (\n    (key === \"message\" || key === \"error_message\" || key === \"error\") &&\n    getStringEnvelopeMessage(value) !== undefined\n  );\n}\n\nfunction formatArrayFieldErrorMessage(item: unknown): string {\n  if (typeof item === \"string\") {\n    return item;\n  }\n\n  try {\n    const json = JSON.stringify(item);\n    if (typeof json === \"string\") {\n      return json;\n    }\n  } catch {\n    // Fall through to String(item) for values JSON cannot serialize, such as\n    // BigInt or circular objects.\n  }\n\n  return String(item);\n}\n\nfunction hasOwnKey(record: Record<string, unknown>, key: string): boolean {\n  return Object.prototype.hasOwnProperty.call(record, key);\n}\n\nfunction getTopLevelScalarEnvelopeMessage(\n  record: Record<string, unknown>,\n): string | undefined {\n  return (\n    getStringEnvelopeMessage(record.message) ??\n    getStringEnvelopeMessage(record.error_message) ??\n    getStringEnvelopeMessage(record.error)\n  );\n}\n\nfunction matchesParentApiErrorMessage(\n  message: string,\n  parentApiErrorMessage: string | undefined,\n): boolean {\n  return getStringEnvelopeMessage(parentApiErrorMessage) === message;\n}\n\nfunction hasFieldErrorEntries(record: Record<string, unknown>): boolean {\n  for (const [key, value] of Object.entries(record)) {\n    if (\n      isRequestIdMetadataKey(key, value) ||\n      isScalarEnvelopeMessageKey(key, value)\n    ) {\n      continue;\n    }\n\n    if (Array.isArray(value)) {\n      if (value.length > 0) {\n        return true;\n      }\n      continue;\n    }\n\n    if (typeof value === \"string\" && value.length > 0) {\n      return true;\n    }\n\n    if (value && typeof value === \"object\") {\n      if (hasFieldErrorEntries(value as Record<string, unknown>)) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n}\n\nfunction hasEnvelopeMetadata(record: Record<string, unknown>): boolean {\n  return (\n    getRequestIdFromJsonBody(record) !== undefined ||\n    hasOwnKey(record, \"errors\") ||\n    hasOwnKey(record, \"details\") ||\n    hasOwnKey(record, \"detail\") ||\n    hasOwnKey(record, \"status\") ||\n    hasOwnKey(record, \"code\")\n  );\n}\n\nfunction isTopLevelScalarEnvelope(\n  record: Record<string, unknown>,\n  parentApiErrorMessage?: string,\n): boolean {\n  const message = getTopLevelScalarEnvelopeMessage(record);\n  return (\n    message !== undefined &&\n    (hasEnvelopeMetadata(record) ||\n      hasFieldErrorEntries(record) ||\n      matchesParentApiErrorMessage(message, parentApiErrorMessage))\n  );\n}\n\nfunction getNestedErrorEnvelopeMessage(value: unknown): string | undefined {\n  if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n    return undefined;\n  }\n\n  const record = value as Record<string, unknown>;\n  return (\n    getStringEnvelopeMessage(record.message) ??\n    getStringEnvelopeMessage(record.error_message)\n  );\n}\n\nfunction getEnvelopeMessageFromJsonBody(\n  body: unknown,\n  parentApiErrorMessage?: string,\n): string | undefined {\n  if (!body || typeof body !== \"object\" || Array.isArray(body)) {\n    return undefined;\n  }\n\n  const record = body as Record<string, unknown>;\n  if (isTopLevelScalarEnvelope(record, parentApiErrorMessage)) {\n    return getTopLevelScalarEnvelopeMessage(record);\n  }\n\n  return getNestedErrorEnvelopeMessage(record.error);\n}\n\nfunction hasNestedErrorEnvelopeMessage(value: unknown): boolean {\n  return getNestedErrorEnvelopeMessage(value) !== undefined;\n}\n\nfunction appendRequestId(\n  description: string | undefined,\n  requestId: string | undefined,\n): string | undefined {\n  if (!requestId) {\n    return description;\n  }\n\n  const requestIdLine = `${requestIdLinePrefix}${requestId}`;\n  if (!description || description.trim().length === 0) {\n    return requestIdLine;\n  }\n\n  if (description.split(\"\\n\").includes(requestIdLine)) {\n    return description;\n  }\n\n  return `${description}\\n${requestIdLine}`;\n}\n\n/**\n * Type guard to check if an error looks like an API error\n */\nexport function isApiLikeError(error: unknown): error is {\n  message: string | undefined;\n  status: number;\n  data: unknown;\n  requestId?: unknown;\n} {\n  if (!error || typeof error !== \"object\") {\n    return false;\n  }\n\n  const err = error as Record<string, unknown>;\n  return (\n    typeof err.status === \"number\" &&\n    \"data\" in err &&\n    (typeof err.message === \"string\" || err.message === undefined)\n  );\n}\n\n/**\n * Extracts field-level errors from API error data\n */\nexport function extractFieldErrors(data: unknown): ParsedFieldError[] {\n  return extractFieldErrorsFromData(data, { skipScalarEnvelopeKeys: false });\n}\n\nfunction extractFieldErrorsFromData(\n  data: unknown,\n  { skipScalarEnvelopeKeys }: { skipScalarEnvelopeKeys: boolean },\n): ParsedFieldError[] {\n  const errors: ParsedFieldError[] = [];\n\n  if (!data || typeof data !== \"object\") {\n    return errors;\n  }\n\n  const errorObj = data as Record<string, unknown>;\n\n  for (const [key, value] of Object.entries(errorObj)) {\n    if (\n      isRequestIdMetadataKey(key, value) ||\n      (skipScalarEnvelopeKeys && isScalarEnvelopeMessageKey(key, value))\n    ) {\n      continue;\n    }\n\n    if (Array.isArray(value) && value.length > 0) {\n      errors.push({\n        field: formatFieldName(key),\n        messages: value.map(formatArrayFieldErrorMessage),\n      });\n    } else if (typeof value === \"string\" && value.length > 0) {\n      errors.push({\n        field: formatFieldName(key),\n        messages: [value],\n      });\n    } else if (value && typeof value === \"object\" && !Array.isArray(value)) {\n      const nestedErrors = extractFieldErrorsFromData(value, {\n        skipScalarEnvelopeKeys:\n          key === \"error\" && hasNestedErrorEnvelopeMessage(value),\n      });\n      nestedErrors.forEach((nestedError) => {\n        errors.push({\n          field: `${formatFieldName(key)} → ${nestedError.field}`,\n          messages: nestedError.messages,\n        });\n      });\n    }\n  }\n\n  return errors;\n}\n\n/**\n * Formats field errors into a readable description string\n */\nexport function formatErrorDescription(errors: ParsedFieldError[]): string {\n  if (errors.length === 0) {\n    return \"\";\n  }\n\n  if (errors.length === 1) {\n    const err = errors[0];\n    if (!err) return \"\";\n    const message = err.messages[0] || \"is invalid\";\n    return `${err.field} ${message}`;\n  }\n\n  if (errors.length <= 3) {\n    return errors\n      .map((e) => `${e.field} ${e.messages[0] || \"is invalid\"}`)\n      .join(\"\\n\");\n  }\n\n  const shown = errors\n    .slice(0, 3)\n    .map((e) => `${e.field} ${e.messages[0] || \"is invalid\"}`)\n    .join(\"\\n\");\n  const remaining = errors.length - 3;\n  return `${shown}\\n...and ${remaining} more ${remaining === 1 ? \"error\" : \"errors\"}`;\n}\n\nfunction getErrorDataDescription(\n  data: unknown,\n  parentApiErrorMessage?: string,\n): string | undefined {\n  const topLevelScalarEnvelopeMessage =\n    data && typeof data === \"object\" && !Array.isArray(data)\n      ? isTopLevelScalarEnvelope(\n          data as Record<string, unknown>,\n          parentApiErrorMessage,\n        )\n        ? getTopLevelScalarEnvelopeMessage(data as Record<string, unknown>)\n        : undefined\n      : undefined;\n  const fieldErrors = extractFieldErrorsFromData(data, {\n    skipScalarEnvelopeKeys: topLevelScalarEnvelopeMessage !== undefined,\n  });\n  const fieldDescription =\n    fieldErrors.length > 0 ? formatErrorDescription(fieldErrors) : undefined;\n  const envelopeMessage = getEnvelopeMessageFromJsonBody(\n    data,\n    parentApiErrorMessage,\n  );\n\n  if (topLevelScalarEnvelopeMessage && fieldDescription) {\n    return fieldDescription;\n  }\n\n  if (\n    envelopeMessage &&\n    fieldDescription &&\n    fieldDescription !== envelopeMessage\n  ) {\n    return `${envelopeMessage}\\n${fieldDescription}`;\n  }\n\n  return fieldDescription ?? envelopeMessage;\n}\n\nexport function getApiRequestId(error: unknown): string | undefined {\n  if (!error || typeof error !== \"object\") {\n    return undefined;\n  }\n\n  const record = error as Record<string, unknown>;\n  return (\n    getStringRequestId(record.requestId) ??\n    getStringRequestId(record.request_id) ??\n    // `request_id` and `meta` are envelope keys, so they survive on `body`.\n    // `data` only carries them when the body had no `errors` key to unwrap.\n    getRequestIdFromJsonBody(record.body) ??\n    getRequestIdFromJsonBody(record.data)\n  );\n}\n\n/**\n * Parses an error and returns a human-readable description string.\n *\n * Handles:\n * - API-like errors with structured field-level data\n * - API-like errors with a top-level message\n * - Standard Error instances\n * - Falls back to the provided fallback string\n *\n * @param error - The error to parse (ApiError, Error, or unknown)\n * @param fallback - Optional fallback description if error cannot be parsed\n * @returns A human-readable error description, or undefined if nothing could be extracted\n */\nexport function parseApiErrors(\n  error: unknown,\n  fallback?: string,\n): string | undefined {\n  const requestId = getApiRequestId(error);\n  let description: string | undefined;\n\n  if (isApiLikeError(error)) {\n    if (error.data) {\n      description = getErrorDataDescription(error.data, error.message);\n    }\n\n    if (!description && error.message) {\n      description = error.message;\n    }\n  } else if (error instanceof Error) {\n    description = error.message;\n  }\n\n  return appendRequestId(description ?? fallback, requestId);\n}\n","import type { QueryClient } from \"@tanstack/react-query\";\nimport { CONTACTS_QUERY_KEYS } from \"@fluid-app/contacts-core/query-keys\";\n\nexport function invalidateContactCaches(queryClient: QueryClient) {\n  queryClient.invalidateQueries({\n    queryKey: CONTACTS_QUERY_KEYS.all(\"contacts\"),\n  });\n  queryClient.invalidateQueries({\n    queryKey: CONTACTS_QUERY_KEYS.all(\"sdk-contacts\"),\n  });\n  queryClient.invalidateQueries({\n    queryKey: [\"portal-contacts\"],\n  });\n}\n","\"use client\";\n\nimport React, { type ReactNode } from \"react\";\nimport {\n  Breadcrumb,\n  BreadcrumbItem,\n  BreadcrumbLink,\n  BreadcrumbList,\n  BreadcrumbPage,\n  BreadcrumbSeparator,\n  Button,\n} from \"@fluid-app/ui-primitives\";\nimport {\n  ScreenHeaderActions,\n  ScreenHeaderBreadcrumbs,\n} from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\n\nexport interface ContactCreateScreenProps {\n  onNavigateToList: () => void;\n  onSubmit: () => void;\n  isPending: boolean;\n  children: ReactNode;\n}\n\nexport function ContactCreateScreen({\n  onNavigateToList,\n  onSubmit,\n  isPending,\n  children,\n}: ContactCreateScreenProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n\n  return (\n    <>\n      <ScreenHeaderActions>\n        <Button\n          variant=\"outline\"\n          onClick={onNavigateToList}\n          disabled={isPending}\n        >\n          {t(\"cancel\")}\n        </Button>\n        <Button onClick={onSubmit} disabled={isPending}>\n          {isPending ? t(\"adding\") : t(\"add_contact\")}\n        </Button>\n      </ScreenHeaderActions>\n      <ScreenHeaderBreadcrumbs>\n        <Breadcrumb>\n          <BreadcrumbList className=\"text-lg\">\n            <BreadcrumbItem>\n              <BreadcrumbLink\n                href=\"#\"\n                onClick={(e) => {\n                  e.preventDefault();\n                  onNavigateToList();\n                }}\n              >\n                {t(\"breadcrumb\")}\n              </BreadcrumbLink>\n            </BreadcrumbItem>\n            <BreadcrumbSeparator />\n            <BreadcrumbItem>\n              <BreadcrumbPage className=\"font-semibold\">\n                {t(\"breadcrumb_new\")}\n              </BreadcrumbPage>\n            </BreadcrumbItem>\n          </BreadcrumbList>\n        </Breadcrumb>\n      </ScreenHeaderBreadcrumbs>\n      {children}\n    </>\n  );\n}\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useGroupsApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\n\nexport function useGroups() {\n  const api = useGroupsApi();\n\n  return useQuery({\n    queryKey: contactsKeys.groups(),\n    queryFn: () => api!.listGroups(),\n    enabled: !!api,\n    select: (data) => data.groups,\n  });\n}\n","import type { Contact } from \"@fluid-app/contacts-core/types\";\n\n/** Minimal translation function type accepted by utility helpers.\n *  Callers pass the real `t` from `useContactsTranslation()`. */\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\ntype TranslateFn = (...args: any[]) => string;\n\nexport function getDisplayName(contact: Contact, t?: TranslateFn): string {\n  if (contact.full_name && contact.full_name.trim().length > 0) {\n    return contact.full_name;\n  }\n  const parts = [contact.first_name, contact.last_name].filter(Boolean);\n  if (parts.length > 0) return parts.join(\" \");\n  if (contact.email) return contact.email;\n  return t?.(\"contact_label\") ?? \"Contact\";\n}\n\nexport function getInitials(name: string): string {\n  const parts = name.trim().split(/\\s+/);\n  const first = parts[0]?.[0] ?? \"\";\n  const last = parts.length > 1 ? (parts[parts.length - 1]?.[0] ?? \"\") : \"\";\n  return (first + last).toUpperCase() || \"?\";\n}\n\n/** Lowercase relative label derived from `contact.updated_at`.\n *  Returns null if the timestamp is missing or unparseable. Lowercase on\n *  purpose so callers can compose phrases like \"Last updated 3 days ago\"\n *  without an awkward \"Last updated Today\". */\nexport function getRelativeUpdated(\n  contact: Contact,\n  t?: TranslateFn,\n): string | null {\n  const updated =\n    typeof contact.updated_at === \"string\" ? contact.updated_at : null;\n  if (!updated) return null;\n  const date = new Date(updated);\n  if (Number.isNaN(date.getTime())) return null;\n\n  const diffMs = Date.now() - date.getTime();\n  const day = 1000 * 60 * 60 * 24;\n  const diffDays = Math.floor(diffMs / day);\n\n  if (diffDays <= 0) return t?.(\"relative_today\") ?? \"today\";\n  if (diffDays === 1) return t?.(\"relative_yesterday\") ?? \"yesterday\";\n  if (diffDays < 7)\n    return (\n      t?.(\"relative_days_ago\", { count: String(diffDays) }) ??\n      `${diffDays} days ago`\n    );\n  if (diffDays < 30) {\n    const weeks = Math.floor(diffDays / 7);\n    return weeks === 1\n      ? (t?.(\"relative_weeks_ago_one\") ?? \"1 week ago\")\n      : (t?.(\"relative_weeks_ago_other\", { count: String(weeks) }) ??\n          `${weeks} weeks ago`);\n  }\n  if (diffDays < 365) {\n    const months = Math.floor(diffDays / 30);\n    return months === 1\n      ? (t?.(\"relative_months_ago_one\") ?? \"1 month ago\")\n      : (t?.(\"relative_months_ago_other\", { count: String(months) }) ??\n          `${months} months ago`);\n  }\n  const years = Math.floor(diffDays / 365);\n  return years === 1\n    ? (t?.(\"relative_years_ago_one\") ?? \"1 year ago\")\n    : (t?.(\"relative_years_ago_other\", { count: String(years) }) ??\n        `${years} years ago`);\n}\n","\"use client\";\n\nimport React, { useCallback, useEffect, useRef } from \"react\";\nimport { ChevronRight, Trash2 } from \"lucide-react\";\nimport { cn } from \"@fluid-app/ui-primitives\";\nimport type { Contact } from \"@fluid-app/contacts-core/types\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { getDisplayName, getInitials } from \"./utils\";\n\nconst SWIPE_THRESHOLD = 40;\nconst REVEAL_WIDTH = 80;\n\nexport interface ContactsSidebarRowProps {\n  contact: Contact;\n  isSelected: boolean;\n  highlight?: boolean;\n  revealed?: boolean;\n  onRevealChange?: (contactId: string, open: boolean) => void;\n  onDismissRevealed?: () => void;\n  onSelect: (id: string) => void;\n  onContextMenu?: (e: React.MouseEvent, contact: Contact) => void;\n  onPointerTarget?: (contact: Contact) => void;\n  onDelete?: (contact: Contact) => void;\n}\n\nexport function ContactsSidebarRow({\n  contact,\n  isSelected,\n  highlight,\n  revealed = false,\n  onRevealChange,\n  onDismissRevealed,\n  onSelect,\n  onContextMenu,\n  onPointerTarget,\n  onDelete,\n}: ContactsSidebarRowProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const name = getDisplayName(contact, t);\n  const id = String(contact.id);\n  const secondary = contact.email ?? contact.status?.trim() ?? null;\n\n  const cardRef = useRef<HTMLDivElement>(null);\n  const deleteLayerRef = useRef<HTMLButtonElement>(null);\n  const offsetRef = useRef(0);\n  const animateCloseRef = useRef(false);\n  const startXRef = useRef(0);\n  const startYRef = useRef(0);\n  const activeRef = useRef(false);\n  const lockedRef = useRef(false);\n  const horizontalRef = useRef(false);\n  const didSwipeRef = useRef(false);\n  const autoHideRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const mouseDragAbortRef = useRef<AbortController | null>(null);\n\n  // Abort any in-flight mouse-drag listeners if the component unmounts.\n  useEffect(() => {\n    return () => {\n      mouseDragAbortRef.current?.abort();\n    };\n  }, []);\n\n  // Direct DOM manipulation for zero-lag transforms\n  const setOffset = useCallback(\n    (value: number, animate: \"open\" | \"close\" | false) => {\n      offsetRef.current = value;\n\n      // Reveal the destructive layer whenever the row is displaced, including\n      // mid-swipe. React owns the settled interactive state below so re-renders\n      // cannot leave a visible action disabled or a hidden action focusable.\n      const layer = deleteLayerRef.current;\n      if (layer) {\n        layer.style.opacity = value === 0 ? \"0\" : \"1\";\n        layer.style.pointerEvents = value <= -REVEAL_WIDTH ? \"auto\" : \"none\";\n      }\n\n      const el = cardRef.current;\n      if (!el) return;\n      if (animate === \"open\") {\n        el.style.transition =\n          \"transform 0.15s cubic-bezier(0.25, 0.1, 0.25, 1)\";\n      } else if (animate === \"close\") {\n        el.style.transition =\n          \"transform 0.35s cubic-bezier(0.25, 0.1, 0.25, 1)\";\n      } else {\n        el.style.transition = \"none\";\n      }\n      el.style.transform = `translateX(${value}px)`;\n    },\n    [],\n  );\n\n  // Sync with external revealed state\n  useEffect(() => {\n    if (revealed) {\n      setOffset(-REVEAL_WIDTH, false);\n      autoHideRef.current = setTimeout(() => {\n        animateCloseRef.current = true;\n        onRevealChange?.(id, false);\n      }, 2000);\n    } else if (!activeRef.current) {\n      animateCloseRef.current = false;\n      setOffset(0, \"close\");\n    }\n    return () => {\n      if (autoHideRef.current) clearTimeout(autoHideRef.current);\n    };\n  }, [revealed, setOffset, onRevealChange, id]);\n\n  const onStart = useCallback(\n    (x: number, y: number) => {\n      if (!onDelete) return;\n      startXRef.current = x;\n      startYRef.current = y;\n      activeRef.current = true;\n      lockedRef.current = false;\n      horizontalRef.current = false;\n      didSwipeRef.current = false;\n      if (autoHideRef.current) clearTimeout(autoHideRef.current);\n      // Dismiss other revealed rows immediately\n      if (!revealed) onDismissRevealed?.();\n    },\n    [onDelete, revealed, onDismissRevealed],\n  );\n\n  const onMove = useCallback(\n    (x: number, y: number) => {\n      if (!activeRef.current) return;\n      const dx = x - startXRef.current;\n      const dy = y - startYRef.current;\n\n      if (!lockedRef.current) {\n        if (Math.abs(dx) < 4 && Math.abs(dy) < 4) return;\n        lockedRef.current = true;\n        horizontalRef.current = Math.abs(dx) > Math.abs(dy);\n        if (!horizontalRef.current) return;\n      }\n      if (!horizontalRef.current) return;\n\n      didSwipeRef.current = true;\n      const base = revealed ? -REVEAL_WIDTH : 0;\n      const offset = Math.max(-REVEAL_WIDTH, Math.min(0, base + dx));\n      setOffset(offset, false);\n    },\n    [revealed, setOffset],\n  );\n\n  const onEnd = useCallback(() => {\n    if (!activeRef.current) return;\n    activeRef.current = false;\n\n    if (!didSwipeRef.current) return;\n\n    const offset = offsetRef.current;\n    if (offset < -SWIPE_THRESHOLD) {\n      setOffset(-REVEAL_WIDTH, \"open\");\n      onRevealChange?.(id, true);\n    } else {\n      setOffset(0, \"close\");\n      onRevealChange?.(id, false);\n    }\n  }, [setOffset, onRevealChange, id]);\n\n  // Touch\n  const handleTouchStart = useCallback(\n    (e: React.TouchEvent) => {\n      const t = e.touches[0];\n      if (t) onStart(t.clientX, t.clientY);\n    },\n    [onStart],\n  );\n  const handleTouchMove = useCallback(\n    (e: React.TouchEvent) => {\n      const t = e.touches[0];\n      if (t) onMove(t.clientX, t.clientY);\n    },\n    [onMove],\n  );\n\n  // Mouse drag\n  const handleMouseDown = useCallback(\n    (e: React.MouseEvent) => {\n      if (e.button !== 0) return;\n      onStart(e.clientX, e.clientY);\n      mouseDragAbortRef.current?.abort();\n      const controller = new AbortController();\n      mouseDragAbortRef.current = controller;\n      const { signal } = controller;\n      window.addEventListener(\n        \"mousemove\",\n        (me) => onMove(me.clientX, me.clientY),\n        { signal },\n      );\n      window.addEventListener(\n        \"mouseup\",\n        () => {\n          onEnd();\n          controller.abort();\n          if (mouseDragAbortRef.current === controller) {\n            mouseDragAbortRef.current = null;\n          }\n        },\n        { signal },\n      );\n    },\n    [onStart, onMove, onEnd],\n  );\n\n  // Trackpad two-finger swipe\n  const wheelAccum = useRef(0);\n  const wheelTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const handleWheel = useCallback(\n    (e: React.WheelEvent) => {\n      if (!onDelete) return;\n      if (Math.abs(e.deltaX) <= Math.abs(e.deltaY)) return;\n\n      // On first wheel event of a gesture, dismiss others\n      if (!wheelTimer.current && !revealed) {\n        onDismissRevealed?.();\n      }\n\n      wheelAccum.current += e.deltaX;\n      const base = revealed ? -REVEAL_WIDTH : 0;\n      const offset = Math.max(\n        -REVEAL_WIDTH,\n        Math.min(0, base - wheelAccum.current),\n      );\n      setOffset(offset, false);\n\n      if (wheelTimer.current) clearTimeout(wheelTimer.current);\n      wheelTimer.current = setTimeout(() => {\n        const final = offsetRef.current;\n        if (final < -SWIPE_THRESHOLD) {\n          setOffset(-REVEAL_WIDTH, \"open\");\n          onRevealChange?.(id, true);\n        } else {\n          setOffset(0, \"close\");\n          onRevealChange?.(id, false);\n        }\n        wheelAccum.current = 0;\n        wheelTimer.current = null;\n      }, 80);\n    },\n    [onDelete, revealed, onDismissRevealed, setOffset, onRevealChange, id],\n  );\n\n  useEffect(() => {\n    return () => {\n      if (wheelTimer.current) clearTimeout(wheelTimer.current);\n    };\n  }, []);\n\n  const handleActivate = useCallback(() => {\n    if (didSwipeRef.current) {\n      didSwipeRef.current = false;\n      return;\n    }\n    if (revealed) {\n      animateCloseRef.current = true;\n      onRevealChange?.(id, false);\n      return;\n    }\n    onSelect(id);\n  }, [revealed, onRevealChange, onSelect, id]);\n\n  const handleClick = useCallback(() => handleActivate(), [handleActivate]);\n\n  // Record the target on right-click. Do NOT preventDefault here: this row sits\n  // inside Radix's shared ContextMenuTrigger, and Radix skips its own open\n  // handler when the event's default is already prevented. Radix itself calls\n  // preventDefault when it opens, so suppressing it here silently stopped the\n  // desktop context menu from ever opening (CURRENT-875).\n  const handleContextMenu = useCallback(\n    (e: React.MouseEvent) => {\n      onContextMenu?.(e, contact);\n    },\n    [onContextMenu, contact],\n  );\n\n  // Record this row as the context-menu target on the touch/pen pointerdown that\n  // opens it. Radix opens its shared context menu on a long-press via a\n  // pointerdown timer that fires NO native `contextmenu` event, so relying on\n  // onContextMenu alone leaves the target unset on touch (CURRENT-875).\n  //\n  // Skip mouse pointers: desktop right-clicks already set the target via\n  // onContextMenu. Recording on every mouse pointerdown (i.e. left-clicks) would\n  // leave a stale contextTargetId — if the user then right-clicked empty space\n  // in the list wrapper (no row pointerdown fires there), the menu would act on\n  // the previously clicked contact instead of no-oping.\n  const handlePointerTarget = useCallback(\n    (e: React.PointerEvent) => {\n      if (e.pointerType === \"mouse\") return;\n      onPointerTarget?.(contact);\n    },\n    [onPointerTarget, contact],\n  );\n\n  const handleDelete = useCallback(() => {\n    if (!revealed) return;\n    onRevealChange?.(id, false);\n    onDelete?.(contact);\n  }, [revealed, onDelete, onRevealChange, contact, id]);\n\n  return (\n    <div className=\"relative overflow-hidden rounded-xl\">\n      {onDelete && (\n        <button\n          ref={deleteLayerRef}\n          // Visibility is driven imperatively from setOffset so it tracks the\n          // row mid-swipe without a re-render. The rendered style mirrors the\n          // settled state so React re-renders preserve clickability when open.\n          style={{\n            opacity: revealed ? 1 : 0,\n            pointerEvents: revealed ? \"auto\" : \"none\",\n          }}\n          type=\"button\"\n          disabled={!revealed}\n          aria-hidden={!revealed}\n          className=\"bg-destructive text-destructive-foreground absolute inset-y-0 right-0 flex w-[88px] cursor-pointer appearance-none flex-col items-center justify-center gap-1 border-0 p-0 pl-2 transition-opacity disabled:cursor-default\"\n          onPointerDown={(e) => {\n            e.stopPropagation();\n          }}\n          onClick={(e) => {\n            e.stopPropagation();\n            handleDelete();\n          }}\n          aria-label={t(\"delete_contact_aria\", { name })}\n        >\n          <Trash2 className=\"size-5\" />\n          <span className=\"text-xs font-medium\">{t(\"delete\")}</span>\n        </button>\n      )}\n\n      <div\n        ref={cardRef}\n        onClick={handleClick}\n        onContextMenu={handleContextMenu}\n        onPointerDown={onPointerTarget ? handlePointerTarget : undefined}\n        onTouchStart={onDelete ? handleTouchStart : undefined}\n        onTouchMove={onDelete ? handleTouchMove : undefined}\n        onTouchEnd={onDelete ? onEnd : undefined}\n        onMouseDown={onDelete ? handleMouseDown : undefined}\n        onWheel={onDelete ? handleWheel : undefined}\n        role=\"button\"\n        tabIndex={0}\n        aria-current={isSelected ? \"true\" : undefined}\n        onKeyDown={(e) => {\n          if (e.key === \"Enter\" || e.key === \" \") {\n            e.preventDefault();\n            handleActivate();\n          }\n        }}\n        className={cn(\n          \"group relative flex w-full cursor-pointer items-center gap-3.5 rounded-xl px-3 py-3 text-left select-none\",\n          isSelected ? \"bg-muted\" : \"bg-background hover:bg-muted\",\n          highlight && \"animate-highlight-fade\",\n        )}\n      >\n        <div\n          className={cn(\n            \"text-muted-foreground relative flex size-12 shrink-0 items-center justify-center overflow-hidden rounded-xl text-base font-semibold transition-colors\",\n            isSelected ? \"bg-background\" : \"bg-muted\",\n          )}\n        >\n          {contact.avatar_url ? (\n            <img\n              alt={name}\n              src={contact.avatar_url}\n              className=\"size-12 object-cover\"\n            />\n          ) : (\n            <span aria-hidden=\"true\">{getInitials(name)}</span>\n          )}\n        </div>\n\n        <div className=\"min-w-0 flex-1\">\n          <span className=\"text-foreground block truncate text-sm font-semibold tracking-tight\">\n            {name}\n          </span>\n          {secondary && (\n            <span className=\"text-muted-foreground mt-0.5 block truncate text-sm\">\n              {secondary}\n            </span>\n          )}\n        </div>\n\n        {isSelected && (\n          <ChevronRight\n            className=\"text-foreground size-4 shrink-0\"\n            aria-hidden=\"true\"\n          />\n        )}\n      </div>\n    </div>\n  );\n}\n","\"use client\";\n\nimport * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\";\nimport { ChevronRight } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@fluid-app/ui-primitives\";\n\nfunction ContextMenu({\n  ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Root>): React.JSX.Element {\n  return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />;\n}\n\nfunction ContextMenuTrigger({\n  ...props\n}: React.ComponentProps<\n  typeof ContextMenuPrimitive.Trigger\n>): React.JSX.Element {\n  return (\n    <ContextMenuPrimitive.Trigger data-slot=\"context-menu-trigger\" {...props} />\n  );\n}\n\nfunction ContextMenuContent({\n  className,\n  ...props\n}: React.ComponentProps<\n  typeof ContextMenuPrimitive.Content\n>): React.JSX.Element {\n  return (\n    <ContextMenuPrimitive.Portal>\n      <ContextMenuPrimitive.Content\n        data-slot=\"context-menu-content\"\n        className={cn(\n          \"bg-popover text-popover-foreground data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md\",\n          className,\n        )}\n        {...props}\n      />\n    </ContextMenuPrimitive.Portal>\n  );\n}\n\nfunction ContextMenuItem({\n  className,\n  inset,\n  variant = \"default\",\n  ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {\n  inset?: boolean;\n  variant?: \"default\" | \"destructive\";\n}): React.JSX.Element {\n  return (\n    <ContextMenuPrimitive.Item\n      data-slot=\"context-menu-item\"\n      data-inset={inset}\n      data-variant={variant}\n      className={cn(\n        \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:!text-destructive relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction ContextMenuLabel({\n  className,\n  inset,\n  ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {\n  inset?: boolean;\n}): React.JSX.Element {\n  return (\n    <ContextMenuPrimitive.Label\n      data-slot=\"context-menu-label\"\n      data-inset={inset}\n      className={cn(\n        \"text-muted-foreground px-2 py-1.5 text-xs font-medium data-[inset]:pl-8\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction ContextMenuSeparator({\n  className,\n  ...props\n}: React.ComponentProps<\n  typeof ContextMenuPrimitive.Separator\n>): React.JSX.Element {\n  return (\n    <ContextMenuPrimitive.Separator\n      data-slot=\"context-menu-separator\"\n      className={cn(\"bg-border -mx-1 my-1 h-px\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction ContextMenuSub({\n  ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Sub>): React.JSX.Element {\n  return <ContextMenuPrimitive.Sub data-slot=\"context-menu-sub\" {...props} />;\n}\n\nfunction ContextMenuSubTrigger({\n  className,\n  inset,\n  children,\n  ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {\n  inset?: boolean;\n}): React.JSX.Element {\n  return (\n    <ContextMenuPrimitive.SubTrigger\n      data-slot=\"context-menu-sub-trigger\"\n      data-inset={inset}\n      className={cn(\n        \"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className,\n      )}\n      {...props}\n    >\n      {children}\n      <ChevronRight className=\"ml-auto size-4\" />\n    </ContextMenuPrimitive.SubTrigger>\n  );\n}\n\nfunction ContextMenuSubContent({\n  className,\n  ...props\n}: React.ComponentProps<\n  typeof ContextMenuPrimitive.SubContent\n>): React.JSX.Element {\n  return (\n    <ContextMenuPrimitive.Portal>\n      <ContextMenuPrimitive.SubContent\n        data-slot=\"context-menu-sub-content\"\n        className={cn(\n          \"bg-popover text-popover-foreground data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg\",\n          className,\n        )}\n        {...props}\n      />\n    </ContextMenuPrimitive.Portal>\n  );\n}\n\nexport {\n  ContextMenu,\n  ContextMenuContent,\n  ContextMenuItem,\n  ContextMenuLabel,\n  ContextMenuSeparator,\n  ContextMenuSub,\n  ContextMenuSubContent,\n  ContextMenuSubTrigger,\n  ContextMenuTrigger,\n};\n","\"use client\";\n\nimport React, {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from \"react\";\nimport {\n  MoreHorizontal,\n  Plus,\n  Search,\n  Settings,\n  Trash2,\n  Users,\n} from \"lucide-react\";\nimport {\n  Button,\n  cn,\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n  fluidToast,\n  Input,\n  Skeleton,\n} from \"@fluid-app/ui-primitives\";\nimport { MobileActionSheet } from \"@fluid-app/ui-components/components/MobileActionSheet\";\nimport { MobileBottomSheet } from \"@fluid-app/ui-components/components/MobileBottomSheet\";\nimport { useInfiniteContacts } from \"@fluid-app/contacts-core/hooks/use-infinite-contacts\";\nimport { useContactsCrud } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { invalidateContactCaches } from \"../../../hooks/groups/invalidate-contact-caches\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { Contact } from \"@fluid-app/contacts-core/types\";\nimport { useGroups } from \"../../../hooks/groups/use-groups\";\nimport { ContactsSidebarRow } from \"./ContactsSidebarRow\";\nimport {\n  ContextMenu,\n  ContextMenuContent,\n  ContextMenuItem,\n  ContextMenuSeparator,\n  ContextMenuSub,\n  ContextMenuSubContent,\n  ContextMenuSubTrigger,\n  ContextMenuTrigger,\n} from \"./ContextMenu\";\n\nexport interface ContactsSidebarProps {\n  selectedContactId: string | null;\n  highlightContactId?: string | null;\n  onSelect: (id: string | null) => void;\n  onAdd: () => void;\n  onManageGroups?: () => void;\n  onCreateGroup?: () => void;\n  highlightGroupName?: string | null;\n  onDeleteContact?: (contact: Contact) => void;\n}\n\nconst MOBILE_BREAKPOINT = 768;\n\nfunction useIsMobile(): boolean {\n  const [mobile, setMobile] = useState(false);\n  useEffect(() => {\n    const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n    const onChange = () => setMobile(window.innerWidth < MOBILE_BREAKPOINT);\n    mql.addEventListener(\"change\", onChange);\n    onChange();\n    return () => mql.removeEventListener(\"change\", onChange);\n  }, []);\n  return mobile;\n}\n\nconst DEBOUNCE_MS = 200;\n\ntype FilterValue =\n  | { kind: \"all\" }\n  | { kind: \"status\"; status: \"lead\" | \"customer\" }\n  | { kind: \"group\"; tag: string };\n\ninterface BuiltInFilter {\n  id: string;\n  label: string;\n  value: FilterValue;\n}\n\nfunction useBuiltInFilters(): BuiltInFilter[] {\n  const { t } = useContactsTranslation();\n  return useMemo(\n    () => [\n      { id: \"all\", label: t(\"filter_all\"), value: { kind: \"all\" } as const },\n      {\n        id: \"status:lead\",\n        label: t(\"filter_leads\"),\n        value: { kind: \"status\" as const, status: \"lead\" as const },\n      },\n      {\n        id: \"status:customer\",\n        label: t(\"filter_customers\"),\n        value: { kind: \"status\" as const, status: \"customer\" as const },\n      },\n    ],\n    [t],\n  );\n}\n\nfunction filterId(value: FilterValue): string {\n  if (value.kind === \"all\") return \"all\";\n  if (value.kind === \"status\") return `status:${value.status}`;\n  return `group:${value.tag}`;\n}\n\nexport function ContactsSidebar({\n  selectedContactId,\n  highlightContactId,\n  onSelect,\n  onAdd,\n  onManageGroups,\n  onCreateGroup,\n  highlightGroupName,\n  onDeleteContact,\n}: ContactsSidebarProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const builtInFilters = useBuiltInFilters();\n  const [searchInput, setSearchInput] = useState(\"\");\n  const [debouncedSearch, setDebouncedSearch] = useState(\"\");\n  const [revealedContactId, setRevealedContactId] = useState<string | null>(\n    null,\n  );\n  const handleRevealChange = useCallback(\n    (id: string, open: boolean) => setRevealedContactId(open ? id : null),\n    [],\n  );\n  const handleDismissRevealed = useCallback(\n    () => setRevealedContactId(null),\n    [],\n  );\n  const [filter, setFilter] = useState<FilterValue>({ kind: \"all\" });\n  const [contextTargetId, setContextTargetId] = useState<string | null>(null);\n  const [contextActionsOpen, setContextActionsOpen] = useState(false);\n  const [groupSheetOpen, setGroupSheetOpen] = useState(false);\n  // On mobile the \"Add to group\" item opens a Sheet and then the context menu\n  // closes. We must keep contextTargetId alive across that close so the Sheet\n  // can still resolve which contact to act on; this ref flags the handoff.\n  const openingSheetRef = useRef(false);\n  const isMobile = useIsMobile();\n\n  const api = useContactsCrud();\n  const queryClient = useQueryClient();\n\n  useEffect(() => {\n    const handle = window.setTimeout(() => {\n      setDebouncedSearch(searchInput.trim());\n    }, DEBOUNCE_MS);\n    return () => window.clearTimeout(handle);\n  }, [searchInput]);\n\n  const { data: groups = [] } = useGroups();\n\n  const queryParams = useMemo(\n    () => ({\n      search_query: debouncedSearch || undefined,\n      tags: filter.kind === \"group\" ? [filter.tag] : undefined,\n      sort_by: \"full_name\",\n      sort_direction: \"asc\",\n      per_page: 50,\n    }),\n    [debouncedSearch, filter],\n  );\n\n  const {\n    data,\n    isLoading,\n    isFetchingNextPage,\n    hasNextPage,\n    fetchNextPage,\n    isError,\n  } = useInfiniteContacts(queryParams);\n\n  const contacts: Contact[] = useMemo(\n    () => data?.pages.flatMap((page) => page.contacts ?? []) ?? [],\n    [data],\n  );\n\n  const visibleContacts = useMemo(() => {\n    if (filter.kind === \"status\") {\n      return contacts.filter((c) => c.status === filter.status);\n    }\n    return contacts;\n  }, [contacts, filter]);\n\n  const sentinelRef = useRef<HTMLDivElement>(null);\n\n  // Auto-select the first contact on initial load so the right pane shows\n  // detail instead of the empty state. Desktop only — on mobile the layout\n  // hides the sidebar when a contact is selected, so auto-selecting would\n  // drop the rep straight into a detail view with no list visible. Ref\n  // guards re-fires so explicit deselects (back button, post-delete, filter\n  // changes) don't get clobbered.\n  const hasAutoSelectedRef = useRef(false);\n  useEffect(() => {\n    if (hasAutoSelectedRef.current) return;\n    if (selectedContactId) {\n      hasAutoSelectedRef.current = true;\n      return;\n    }\n    if (isLoading || visibleContacts.length === 0) return;\n    const isDesktop =\n      typeof window === \"undefined\" ||\n      window.matchMedia(\"(min-width: 768px)\").matches;\n    if (!isDesktop) {\n      hasAutoSelectedRef.current = true;\n      return;\n    }\n    const first = visibleContacts[0];\n    if (first) {\n      hasAutoSelectedRef.current = true;\n      onSelect(String(first.id));\n    }\n  }, [selectedContactId, isLoading, visibleContacts, onSelect]);\n\n  useEffect(() => {\n    const sentinel = sentinelRef.current;\n    if (!sentinel || !hasNextPage) return;\n\n    const observer = new IntersectionObserver((entries) => {\n      const entry = entries[0];\n      if (entry?.isIntersecting && !isFetchingNextPage) {\n        fetchNextPage();\n      }\n    });\n\n    observer.observe(sentinel);\n    return () => observer.disconnect();\n  }, [hasNextPage, isFetchingNextPage, fetchNextPage]);\n\n  const activeFilterId = filterId(filter);\n\n  const handleContextMenu = useCallback(\n    (event: React.MouseEvent, contact: Contact) => {\n      setContextTargetId(String(contact.id));\n      if (isMobile) {\n        event.preventDefault();\n        setContextActionsOpen(true);\n      }\n    },\n    [isMobile],\n  );\n\n  // Touch long-press opens Radix's context menu with no `contextmenu` event, so\n  // the row reports its identity on pointerdown instead. Keeps the shared menu's\n  // target resolvable regardless of how it was opened (CURRENT-875).\n  const handlePointerTarget = useCallback((contact: Contact) => {\n    setContextTargetId(String(contact.id));\n  }, []);\n\n  const getTargetContacts = useCallback((): Contact[] => {\n    if (contextTargetId) {\n      const single = visibleContacts.find(\n        (c) => String(c.id) === contextTargetId,\n      );\n      return single ? [single] : [];\n    }\n    return [];\n  }, [contextTargetId, visibleContacts]);\n\n  const handleContextDelete = useCallback(() => {\n    const [target] = getTargetContacts();\n    if (!target) return;\n    onDeleteContact?.(target);\n    setContextTargetId(null);\n  }, [getTargetContacts, onDeleteContact]);\n\n  const handleAddToGroup = useCallback(\n    (groupName: string) => {\n      const targets = getTargetContacts();\n      if (targets.length === 0) return;\n      const toUpdate = targets.filter((contact) => {\n        const currentTags = Array.isArray(contact.tags) ? contact.tags : [];\n        return !currentTags.includes(groupName);\n      });\n      if (toUpdate.length === 0) {\n        setContextTargetId(null);\n        return;\n      }\n      const promises = toUpdate.map((contact) => {\n        const currentTags = Array.isArray(contact.tags) ? contact.tags : [];\n        return api.updateContact(String(contact.id), {\n          tags: [...currentTags, groupName],\n        });\n      });\n      Promise.allSettled(promises).then((results) => {\n        invalidateContactCaches(queryClient);\n        const failed = results.filter((r) => r.status === \"rejected\").length;\n        const succeeded = toUpdate.length - failed;\n        if (failed === 0) {\n          fluidToast({\n            title:\n              succeeded === 1\n                ? t(\"contacts_added_to_group_one\", {\n                    count: succeeded,\n                    group: groupName,\n                  })\n                : t(\"contacts_added_to_group_other\", {\n                    count: succeeded,\n                    group: groupName,\n                  }),\n            type: \"success\",\n          });\n        } else {\n          fluidToast({\n            title:\n              toUpdate.length === 1\n                ? t(\"contacts_add_to_group_failed_one\", { group: groupName })\n                : t(\"contacts_add_to_group_failed_other\", { group: groupName }),\n            type: \"error\",\n          });\n        }\n        setContextTargetId(null);\n      });\n    },\n    [getTargetContacts, api, queryClient, t],\n  );\n\n  return (\n    <>\n      <div className=\"border-border/50 border-b px-6 py-3\">\n        <div className=\"flex items-center gap-3\">\n          <div className=\"bg-muted focus-within:ring-foreground/20 flex min-w-0 flex-1 items-center gap-2 rounded-lg px-3 py-1.5 transition focus-within:ring-2\">\n            <Search\n              className=\"text-muted-foreground size-3.5 shrink-0\"\n              aria-hidden=\"true\"\n            />\n            <Input\n              value={searchInput}\n              onChange={(e) => setSearchInput(e.target.value)}\n              placeholder={t(\"search_placeholder\")}\n              type=\"search\"\n              className=\"placeholder:text-muted-foreground/80 h-auto flex-1 border-0 bg-transparent p-0 text-xs font-medium shadow-none focus-visible:ring-0\"\n              aria-label={t(\"search_placeholder\")}\n            />\n          </div>\n          <Button type=\"button\" size=\"sm\" onClick={onAdd}>\n            <Plus className=\"size-3.5\" aria-hidden=\"true\" />\n            {t(\"add\")}\n          </Button>\n        </div>\n      </div>\n\n      <FilterPills\n        activeId={activeFilterId}\n        builtInFilters={builtInFilters}\n        groups={groups.map((g) => g.name)}\n        onChange={setFilter}\n        onManageGroups={onManageGroups}\n        onCreateGroup={onCreateGroup}\n        highlightGroupName={highlightGroupName}\n      />\n\n      <div className=\"flex-1 overflow-y-auto px-3 pb-8\">\n        {isError ? (\n          <div className=\"text-muted-foreground px-4 py-8 text-center text-sm\">\n            {t(\"error_loading_list\")}\n          </div>\n        ) : isLoading ? (\n          <SidebarSkeleton />\n        ) : visibleContacts.length === 0 ? (\n          // Status filters apply client-side, so an empty visible list with\n          // more pages still pending means matching contacts may be on later\n          // pages. Keep the sentinel mounted so the IntersectionObserver can\n          // continue paging until we either find matches or exhaust the data.\n          <div className=\"space-y-2\">\n            {hasNextPage || isFetchingNextPage ? (\n              <div className=\"text-muted-foreground px-4 py-8 text-center text-sm\">\n                {t(\"searching\")}\n              </div>\n            ) : (\n              <div className=\"text-muted-foreground px-4 py-8 text-center text-sm\">\n                {debouncedSearch\n                  ? t(\"no_contacts_search\", { term: debouncedSearch })\n                  : filter.kind === \"all\"\n                    ? t(\"no_contacts_yet\")\n                    : t(\"no_contacts_filter\")}\n              </div>\n            )}\n            {hasNextPage && (\n              <div ref={sentinelRef} aria-hidden=\"true\" className=\"h-4\" />\n            )}\n          </div>\n        ) : (\n          <ContextMenu\n            onOpenChange={(open) => {\n              if (open) {\n                if (isMobile) setContextActionsOpen(true);\n                return;\n              }\n              // Preserve the target when we're handing off to the group Sheet.\n              if (openingSheetRef.current) {\n                openingSheetRef.current = false;\n                return;\n              }\n              setContextTargetId(null);\n            }}\n          >\n            <ContextMenuTrigger asChild>\n              <div className=\"space-y-1\">\n                {visibleContacts.map((contact) => (\n                  <ContactsSidebarRow\n                    key={contact.id}\n                    contact={contact}\n                    isSelected={String(contact.id) === selectedContactId}\n                    highlight={String(contact.id) === highlightContactId}\n                    revealed={revealedContactId === String(contact.id)}\n                    onRevealChange={handleRevealChange}\n                    onDismissRevealed={handleDismissRevealed}\n                    onSelect={onSelect}\n                    onContextMenu={handleContextMenu}\n                    onPointerTarget={handlePointerTarget}\n                    onDelete={onDeleteContact}\n                  />\n                ))}\n                <div ref={sentinelRef} aria-hidden=\"true\" className=\"h-4\" />\n                {isFetchingNextPage && (\n                  <div className=\"text-muted-foreground py-3 text-center text-xs\">\n                    {t(\"loading_more\")}\n                  </div>\n                )}\n              </div>\n            </ContextMenuTrigger>\n            {!isMobile && (\n              <ContextMenuContent className=\"min-w-48\">\n                <ContextMenuSub>\n                  <ContextMenuSubTrigger>\n                    <Users className=\"size-4\" aria-hidden=\"true\" />\n                    {t(\"groups_add_to_group\")}\n                  </ContextMenuSubTrigger>\n                  <ContextMenuSubContent>\n                    {groups.length === 0 ? (\n                      <ContextMenuItem disabled>\n                        {t(\"groups_no_groups_yet\")}\n                      </ContextMenuItem>\n                    ) : (\n                      groups.map((group) => (\n                        <ContextMenuItem\n                          key={group.id}\n                          onSelect={() => handleAddToGroup(group.name)}\n                        >\n                          <div\n                            className=\"flex size-5 shrink-0 items-center justify-center rounded-full text-xs\"\n                            style={{\n                              backgroundColor:\n                                group.avatar_background ?? \"var(--color-muted)\",\n                            }}\n                            aria-hidden=\"true\"\n                          >\n                            {group.avatar ?? (\n                              <Users className=\"text-muted-foreground size-3\" />\n                            )}\n                          </div>\n                          {group.name}\n                        </ContextMenuItem>\n                      ))\n                    )}\n                  </ContextMenuSubContent>\n                </ContextMenuSub>\n                {onDeleteContact && (\n                  <>\n                    <ContextMenuSeparator />\n                    <ContextMenuItem\n                      variant=\"destructive\"\n                      onSelect={handleContextDelete}\n                    >\n                      <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n                      {t(\"delete\")}\n                    </ContextMenuItem>\n                  </>\n                )}\n              </ContextMenuContent>\n            )}\n          </ContextMenu>\n        )}\n\n        {isMobile && (\n          <MobileActionSheet\n            open={contextActionsOpen}\n            onOpenChange={(open) => {\n              setContextActionsOpen(open);\n              if (!open && !openingSheetRef.current) setContextTargetId(null);\n            }}\n            title={t(\"more_actions\")}\n            actions={[\n              {\n                id: \"add-to-group\",\n                label: t(\"groups_add_to_group\"),\n                onSelect: () => {\n                  openingSheetRef.current = true;\n                  setGroupSheetOpen(true);\n                },\n              },\n              ...(onDeleteContact\n                ? [\n                    {\n                      id: \"delete\",\n                      label: t(\"delete\"),\n                      variant: \"destructive\" as const,\n                      onSelect: handleContextDelete,\n                    },\n                  ]\n                : []),\n            ]}\n          />\n        )}\n\n        {isMobile && (\n          <MobileBottomSheet\n            open={groupSheetOpen}\n            onOpenChange={(open) => {\n              setGroupSheetOpen(open);\n              // Fires on Radix-initiated dismiss (overlay/ESC), clearing the\n              // stale target. Picking a group closes the Sheet via a direct\n              // setGroupSheetOpen(false) instead, which does not trigger this,\n              // so handleAddToGroup still reads a valid contextTargetId.\n              if (!open) {\n                openingSheetRef.current = false;\n                setContextTargetId(null);\n              }\n            }}\n            title={t(\"groups_add_to_group\")}\n          >\n            <div className=\"min-h-0 flex-1 overflow-y-auto py-2\">\n              {groups.length === 0 ? (\n                <p className=\"text-muted-foreground px-2 py-4 text-center text-sm\">\n                  {t(\"groups_no_groups_yet\")}\n                </p>\n              ) : (\n                groups.map((group) => (\n                  <button\n                    key={group.id}\n                    type=\"button\"\n                    className=\"hover:bg-accent flex w-full items-center gap-3 rounded-md px-2 py-2.5 text-sm\"\n                    onClick={() => {\n                      setGroupSheetOpen(false);\n                      openingSheetRef.current = false;\n                      handleAddToGroup(group.name);\n                    }}\n                  >\n                    <div\n                      className=\"flex size-8 shrink-0 items-center justify-center rounded-full text-sm\"\n                      style={{\n                        backgroundColor:\n                          group.avatar_background ?? \"var(--color-muted)\",\n                      }}\n                      aria-hidden=\"true\"\n                    >\n                      {group.avatar ?? (\n                        <Users className=\"text-muted-foreground size-4\" />\n                      )}\n                    </div>\n                    {group.name}\n                  </button>\n                ))\n              )}\n            </div>\n          </MobileBottomSheet>\n        )}\n      </div>\n    </>\n  );\n}\n\ninterface FilterPillsProps {\n  activeId: string;\n  builtInFilters: BuiltInFilter[];\n  groups: string[];\n  onChange: (filter: FilterValue) => void;\n  onManageGroups?: () => void;\n  onCreateGroup?: () => void;\n  highlightGroupName?: string | null;\n}\n\nfunction FilterPills({\n  activeId,\n  builtInFilters,\n  groups,\n  onChange,\n  onManageGroups,\n  onCreateGroup,\n  highlightGroupName,\n}: FilterPillsProps) {\n  const { t } = useContactsTranslation();\n  const isMobile = useIsMobile();\n  const [optionsOpen, setOptionsOpen] = useState(false);\n  const allFilters = useMemo<BuiltInFilter[]>(\n    () => [\n      ...builtInFilters,\n      ...groups.map((tag) => ({\n        id: `group:${tag}`,\n        label: tag,\n        value: { kind: \"group\" as const, tag },\n      })),\n    ],\n    [builtInFilters, groups],\n  );\n\n  return (\n    <div className=\"flex items-center pt-4 pb-4\">\n      <div className=\"flex-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\">\n        <div className=\"flex gap-1.5 pl-6\">\n          {allFilters.map(({ id, label, value }) => {\n            const isActive = id === activeId;\n            const isHighlighted =\n              highlightGroupName && id === `group:${highlightGroupName}`;\n            return (\n              <button\n                key={id}\n                type=\"button\"\n                onClick={() => onChange(value)}\n                aria-pressed={isActive}\n                className={cn(\n                  \"shrink-0 rounded-full px-4 py-1.5 text-sm font-semibold capitalize transition-colors\",\n                  isActive\n                    ? \"bg-primary text-primary-foreground\"\n                    : \"border-border/50 bg-muted text-foreground hover:bg-muted/70 border\",\n                  isHighlighted && \"animate-highlight-fade\",\n                )}\n              >\n                {label}\n              </button>\n            );\n          })}\n        </div>\n      </div>\n      {(onManageGroups || onCreateGroup) && (\n        <div className=\"flex shrink-0 items-center gap-2 pr-6 pl-3\">\n          <div className=\"bg-border h-6 w-px\" aria-hidden=\"true\" />\n          {isMobile ? (\n            <>\n              <button\n                type=\"button\"\n                onClick={() => setOptionsOpen(true)}\n                className=\"text-muted-foreground hover:bg-muted hover:text-foreground flex items-center justify-center rounded-full p-1.5 transition-colors\"\n                aria-label={t(\"groups_options_aria\")}\n              >\n                <MoreHorizontal className=\"size-4\" />\n              </button>\n              <MobileActionSheet\n                open={optionsOpen}\n                onOpenChange={setOptionsOpen}\n                title={t(\"groups_options_aria\")}\n                actions={[\n                  ...(onManageGroups\n                    ? [\n                        {\n                          id: \"manage\",\n                          label: t(\"groups_manage_title\"),\n                          onSelect: onManageGroups,\n                        },\n                      ]\n                    : []),\n                  ...(onCreateGroup\n                    ? [\n                        {\n                          id: \"create\",\n                          label: t(\"groups_create_title\"),\n                          onSelect: onCreateGroup,\n                        },\n                      ]\n                    : []),\n                ]}\n              />\n            </>\n          ) : (\n            <DropdownMenu>\n              <DropdownMenuTrigger asChild>\n                <button\n                  type=\"button\"\n                  className=\"text-muted-foreground hover:bg-muted hover:text-foreground flex items-center justify-center rounded-full p-1.5 transition-colors\"\n                  aria-label={t(\"groups_options_aria\")}\n                >\n                  <MoreHorizontal className=\"size-4\" />\n                </button>\n              </DropdownMenuTrigger>\n              <DropdownMenuContent align=\"end\">\n                {onManageGroups && (\n                  <DropdownMenuItem onClick={onManageGroups}>\n                    <Settings className=\"size-4\" aria-hidden=\"true\" />\n                    {t(\"groups_manage_title\")}\n                  </DropdownMenuItem>\n                )}\n                {onCreateGroup && (\n                  <DropdownMenuItem onClick={onCreateGroup}>\n                    <Plus className=\"size-4\" aria-hidden=\"true\" />\n                    {t(\"groups_create_title\")}\n                  </DropdownMenuItem>\n                )}\n              </DropdownMenuContent>\n            </DropdownMenu>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n\nfunction SidebarSkeleton() {\n  return (\n    <div className=\"space-y-1.5 px-1\">\n      {[0, 1, 2, 3, 4].map((i) => (\n        <div\n          key={i}\n          className=\"flex items-center gap-3 rounded-xl p-3\"\n          aria-hidden=\"true\"\n        >\n          <Skeleton className=\"size-12 shrink-0 rounded-xl\" />\n          <div className=\"flex-1 space-y-2\">\n            <Skeleton className=\"h-3.5 w-3/5\" />\n            <Skeleton className=\"h-3 w-4/5\" />\n          </div>\n        </div>\n      ))}\n    </div>\n  );\n}\n","\"use client\";\n\nimport React, { useCallback, useMemo } from \"react\";\nimport { useFormContext, useWatch } from \"react-hook-form\";\nimport type { EditContactFormData } from \"../../schemas/contactFormSchema\";\nimport {\n  cn,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n  Input,\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"@fluid-app/ui-primitives\";\nimport { Combobox } from \"@fluid-app/ui-components/components/Combobox\";\nimport { useOptionalContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\n\nconst formFallbackStrings: Record<string, string> = {\n  label_first_name: \"First Name\",\n  label_last_name: \"Last Name\",\n  label_email: \"Email\",\n  label_phone: \"Phone\",\n  label_status: \"Status\",\n  label_full_address: \"Full Address\",\n  label_city: \"City\",\n  label_state: \"State/Province\",\n  label_postal_code: \"Postal Code\",\n  label_country: \"Country\",\n  placeholder_first_name: \"Enter first name\",\n  placeholder_last_name: \"Enter last name\",\n  placeholder_email: \"Enter email address\",\n  placeholder_phone: \"Enter phone number\",\n  placeholder_full_address: \"Enter street address\",\n  placeholder_city: \"Enter city\",\n  placeholder_state: \"Enter state or province\",\n  placeholder_postal_code: \"Enter postal code\",\n  placeholder_country: \"Select country\",\n  placeholder_status: \"Select status\",\n  status_new: \"New\",\n  status_active: \"Active\",\n  status_inactive: \"Inactive\",\n  status_cold: \"Cold\",\n  status_lead: \"Lead\",\n  status_customer: \"Customer\",\n};\n\nconst DEFAULT_COUNTRIES: { name: string; value: string }[] = [];\n\nconst STATUS_VALUES = [\n  \"new\",\n  \"active\",\n  \"inactive\",\n  \"cold\",\n  \"lead\",\n  \"customer\",\n] as const;\n\nconst STATUS_KEYS = {\n  new: \"status_new\",\n  active: \"status_active\",\n  inactive: \"status_inactive\",\n  cold: \"status_cold\",\n  lead: \"status_lead\",\n  customer: \"status_customer\",\n} as const;\n\ntype AvatarPickerRenderProps = {\n  value: string | null;\n  onChange: (url: string | null) => void;\n};\n\ntype ContactDetailsFormProps = {\n  className?: string;\n  countries?: { name: string; value: string }[];\n  renderAvatarPicker?: (props: AvatarPickerRenderProps) => React.ReactNode;\n};\n\nexport const ContactDetailsForm: React.FC<ContactDetailsFormProps> = ({\n  className,\n  countries = DEFAULT_COUNTRIES,\n  renderAvatarPicker,\n}) => {\n  const { control, watch, setValue } = useFormContext<EditContactFormData>();\n  const i18n = useOptionalContactsTranslation();\n  const t = useCallback(\n    (key: string, params?: Record<string, string>) => {\n      if (i18n) {\n        return (i18n.t as (k: string, p?: Record<string, string>) => string)(\n          key,\n          params,\n        );\n      }\n      let text = formFallbackStrings[key] ?? key;\n      if (params) {\n        for (const [k, v] of Object.entries(params)) {\n          text = text.replaceAll(`{{${k}}}`, v);\n        }\n      }\n      return text;\n    },\n    [i18n],\n  );\n  const currentStatus = useWatch({ control, name: \"status\" });\n  const avatarUrl: string | null =\n    (watch(\"avatar_url\") as string | null | undefined) ?? null;\n\n  const statusOptions = useMemo(\n    () =>\n      STATUS_VALUES.map((value) => ({\n        name: t(STATUS_KEYS[value]),\n        value,\n      })),\n    [t],\n  );\n\n  const effectiveStatusOptions = useMemo(() => {\n    if (\n      currentStatus &&\n      typeof currentStatus === \"string\" &&\n      !statusOptions.some((o) => o.value === currentStatus)\n    ) {\n      return [\n        {\n          name:\n            currentStatus.charAt(0).toUpperCase() +\n            currentStatus.slice(1).replace(/_/g, \" \"),\n          value: currentStatus,\n        },\n        ...statusOptions,\n      ];\n    }\n    return statusOptions;\n  }, [currentStatus, statusOptions]);\n\n  const firstInitial =\n    (watch(\"first_name\") as string | null | undefined)?.[0] ?? \"\";\n  const lastInitial =\n    (watch(\"last_name\") as string | null | undefined)?.[0] ?? \"\";\n  const initials =\n    [firstInitial, lastInitial].filter(Boolean).join(\"\").toUpperCase() || \"?\";\n\n  return (\n    <div className={cn(\"space-y-6\", className)}>\n      {renderAvatarPicker && (\n        <div className=\"flex flex-col items-center gap-3\">\n          <div className=\"border-border bg-background relative size-20 shrink-0 overflow-hidden rounded-full border-2\">\n            {avatarUrl ? (\n              <img\n                src={avatarUrl}\n                alt=\"\"\n                className=\"h-full w-full object-cover\"\n              />\n            ) : (\n              <div className=\"text-muted-foreground flex h-full w-full items-center justify-center text-lg font-semibold\">\n                {initials}\n              </div>\n            )}\n          </div>\n          {renderAvatarPicker({\n            value: avatarUrl,\n            onChange: (url) =>\n              setValue(\"avatar_url\", url ?? \"\", { shouldDirty: true }),\n          })}\n        </div>\n      )}\n      <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-2\">\n        <FormField\n          control={control}\n          name=\"first_name\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className=\"font-inter text-foreground font-medium\">\n                {t(\"label_first_name\")}\n              </FormLabel>\n              <FormControl>\n                <Input\n                  placeholder={t(\"placeholder_first_name\")}\n                  {...field}\n                  value={field.value ?? \"\"}\n                  className=\"ring-input\"\n                />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n\n        <FormField\n          control={control}\n          name=\"last_name\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className=\"font-inter text-foreground font-medium\">\n                {t(\"label_last_name\")}\n              </FormLabel>\n              <FormControl>\n                <Input\n                  placeholder={t(\"placeholder_last_name\")}\n                  {...field}\n                  value={field.value ?? \"\"}\n                  className=\"ring-input\"\n                />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n\n        <FormField\n          control={control}\n          name=\"email\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className=\"font-inter text-foreground font-medium\">\n                {t(\"label_email\")}\n              </FormLabel>\n              <FormControl>\n                <Input\n                  placeholder={t(\"placeholder_email\")}\n                  type=\"email\"\n                  {...field}\n                  value={field.value ?? \"\"}\n                  className=\"ring-input\"\n                />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n\n        <FormField\n          control={control}\n          name=\"phone\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className=\"font-inter text-foreground font-medium\">\n                {t(\"label_phone\")}\n              </FormLabel>\n              <FormControl>\n                <Input\n                  placeholder={t(\"placeholder_phone\")}\n                  {...field}\n                  value={field.value ?? \"\"}\n                  className=\"ring-input\"\n                />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n\n        <FormField\n          control={control}\n          name=\"status\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className=\"font-inter text-foreground font-medium\">\n                {t(\"label_status\")}\n              </FormLabel>\n              <Select value={field.value ?? \"\"} onValueChange={field.onChange}>\n                <FormControl>\n                  <SelectTrigger className=\"w-full\">\n                    <SelectValue placeholder={t(\"placeholder_status\")} />\n                  </SelectTrigger>\n                </FormControl>\n                <SelectContent\n                  position=\"popper\"\n                  sideOffset={4}\n                  className=\"z-[1060]\"\n                >\n                  {effectiveStatusOptions.map((opt) => (\n                    <SelectItem key={opt.value} value={opt.value}>\n                      {opt.name}\n                    </SelectItem>\n                  ))}\n                </SelectContent>\n              </Select>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n\n        <FormField\n          control={control}\n          name=\"address\"\n          render={({ field }) => (\n            <FormItem className=\"lg:col-span-2\">\n              <FormLabel className=\"font-inter text-foreground font-medium\">\n                {t(\"label_full_address\")}\n              </FormLabel>\n              <FormControl>\n                <Input\n                  placeholder={t(\"placeholder_full_address\")}\n                  {...field}\n                  value={field.value ?? \"\"}\n                  className=\"ring-input\"\n                />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n\n        <FormField\n          control={control}\n          name=\"city\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className=\"font-inter text-foreground font-medium\">\n                {t(\"label_city\")}\n              </FormLabel>\n              <FormControl>\n                <Input\n                  placeholder={t(\"placeholder_city\")}\n                  {...field}\n                  value={field.value ?? \"\"}\n                  className=\"ring-input\"\n                />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n\n        <FormField\n          control={control}\n          name=\"state\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className=\"font-inter text-foreground font-medium\">\n                {t(\"label_state\")}\n              </FormLabel>\n              <FormControl>\n                <Input\n                  placeholder={t(\"placeholder_state\")}\n                  {...field}\n                  value={field.value ?? \"\"}\n                  className=\"ring-input\"\n                />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n\n        <FormField\n          control={control}\n          name=\"postal_code\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className=\"font-inter text-foreground font-medium\">\n                {t(\"label_postal_code\")}\n              </FormLabel>\n              <FormControl>\n                <Input\n                  placeholder={t(\"placeholder_postal_code\")}\n                  {...field}\n                  value={field.value ?? \"\"}\n                  className=\"ring-input\"\n                />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n\n        <FormField\n          control={control}\n          name=\"country_code\"\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className=\"font-inter text-foreground font-medium\">\n                {t(\"label_country\")}\n              </FormLabel>\n              <FormControl>\n                <Combobox\n                  options={countries.map((c) => ({\n                    label: c.name,\n                    value: c.value,\n                  }))}\n                  value={field.value ?? \"\"}\n                  onValueChange={field.onChange}\n                  placeholder={t(\"placeholder_country\")}\n                  // Render above the mobile bottom sheet (z-1050) when the\n                  // create form is presented as a sheet.\n                  zIndex={1060}\n                />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n      </div>\n    </div>\n  );\n};\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useContactsCrud } from \"../contacts-api-context\";\nimport { CONTACTS_QUERY_KEYS } from \"../query-keys\";\n\nexport function useContactDetail(\n  contactId: string,\n  queryKeyPrefix = \"contacts\",\n) {\n  const api = useContactsCrud();\n\n  return useQuery({\n    queryKey: CONTACTS_QUERY_KEYS.detail(queryKeyPrefix, contactId),\n    queryFn: () => api.getContact(contactId),\n    enabled: !!contactId,\n  });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { useContactsCrud } from \"../contacts-api-context\";\nimport { CONTACTS_QUERY_KEYS } from \"../query-keys\";\n\nexport interface UpdateContactInput<\n  TData extends object = Record<string, unknown>,\n> {\n  id: string;\n  data: TData;\n}\n\nexport interface UseUpdateContactMutationOptions {\n  onSuccess?: (data: unknown) => void;\n  onError?: (error: unknown) => void;\n}\n\nexport function useUpdateContactMutation<\n  TData extends object = Record<string, unknown>,\n>(queryKeyPrefix = \"contacts\", options?: UseUpdateContactMutationOptions) {\n  const queryClient = useQueryClient();\n  const api = useContactsCrud();\n\n  return useMutation({\n    mutationFn: ({ id, data }: UpdateContactInput<TData>) =>\n      api.updateContact(id, data as Record<string, unknown>),\n    onSuccess: (data) => {\n      queryClient.invalidateQueries({\n        queryKey: CONTACTS_QUERY_KEYS.all(queryKeyPrefix),\n      });\n      options?.onSuccess?.(data);\n    },\n    onError: (error) => {\n      options?.onError?.(error);\n    },\n  });\n}\n","\"use client\";\n\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useUpdateContactMutation as useCoreUpdateContactMutation } from \"@fluid-app/contacts-core/hooks/use-update-contact-mutation\";\nimport { useOptionalContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\n\nexport function useUpdateContactMutation(\n  /** @deprecated Pass the contact ID as part of the mutation variable `{ id, data }` instead. */\n  _contactId?: string,\n  queryKeyPrefix = \"contacts\",\n  options?: {\n    onSuccess?: () => void;\n    onError?: (error: unknown) => void;\n  },\n) {\n  const i18n = useOptionalContactsTranslation();\n\n  return useCoreUpdateContactMutation(queryKeyPrefix, {\n    onSuccess: () => {\n      fluidToast({\n        title: i18n?.t(\"contact_updated\") ?? \"Contact updated successfully\",\n        type: \"success\",\n      });\n      options?.onSuccess?.();\n    },\n    onError: (error) => {\n      fluidToast({\n        title: i18n?.t(\"contact_save_failed\") ?? \"Failed to save contact\",\n        type: \"error\",\n        description: parseApiErrors(error),\n      });\n      options?.onError?.(error);\n    },\n  });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { useContactsCrud } from \"../contacts-api-context\";\nimport { CONTACTS_QUERY_KEYS } from \"../query-keys\";\n\nexport interface UseDeleteContactMutationOptions {\n  onSuccess?: (data: unknown) => void;\n  onError?: (error: unknown) => void;\n}\n\nexport function useDeleteContactMutation(\n  queryKeyPrefix = \"contacts\",\n  options?: UseDeleteContactMutationOptions,\n) {\n  const queryClient = useQueryClient();\n  const api = useContactsCrud();\n\n  return useMutation({\n    mutationFn: (contactId: string) => api.deleteContact(contactId),\n    onSuccess: (data) => {\n      queryClient.invalidateQueries({\n        queryKey: CONTACTS_QUERY_KEYS.all(queryKeyPrefix),\n      });\n      options?.onSuccess?.(data);\n    },\n    onError: (error) => {\n      options?.onError?.(error);\n    },\n  });\n}\n","\"use client\";\n\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useDeleteContactMutation as useCoreDeleteContactMutation } from \"@fluid-app/contacts-core/hooks/use-delete-contact-mutation\";\nimport { useOptionalContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\n\nexport function useDeleteContactMutation(\n  queryKeyPrefix = \"contacts\",\n  options?: {\n    onSuccess?: () => void;\n    onError?: (error: unknown) => void;\n  },\n) {\n  const i18n = useOptionalContactsTranslation();\n\n  return useCoreDeleteContactMutation(queryKeyPrefix, {\n    onSuccess: () => {\n      fluidToast({\n        title: i18n?.t(\"contact_deleted\") ?? \"Contact deleted successfully\",\n        type: \"success\",\n      });\n      options?.onSuccess?.();\n    },\n    onError: (error) => {\n      fluidToast({\n        title: i18n?.t(\"contact_delete_failed\") ?? \"Failed to delete contact\",\n        type: \"error\",\n        description: parseApiErrors(error),\n      });\n      options?.onError?.(error);\n    },\n  });\n}\n","import { z } from \"zod\";\n\ninterface ContactFormMessages {\n  first_name_required?: string;\n  last_name_required?: string;\n}\n\n/**\n * Build the create-contact schema, optionally injecting translated validation\n * messages. When called without arguments the English defaults are used, so\n * existing call-sites (e.g. `createContactFormSchema.shape`) keep working.\n */\nexport function buildCreateContactFormSchema(msgs?: ContactFormMessages) {\n  return z.object({\n    first_name: z.string().min(1, {\n      message: msgs?.first_name_required ?? \"First name is required\",\n    }),\n    last_name: z.string().min(1, {\n      message: msgs?.last_name_required ?? \"Last name is required\",\n    }),\n    status: z.string().nullable().optional(),\n    email: z.string().email().or(z.literal(\"\")).nullable().optional(),\n    phone: z.string().nullable().optional(),\n    address: z.string().nullable().optional(),\n    city: z.string().nullable().optional(),\n    state: z.string().nullable().optional(),\n    postal_code: z.string().nullable().optional(),\n    country_code: z.coerce.string().nullable().optional(),\n    language_code: z.coerce.string().nullable().optional(),\n    affiliate: z.record(z.string(), z.unknown()).nullable().optional(),\n    metadata: z.record(z.string(), z.unknown()).optional(),\n  });\n}\n\n/**\n * Form schema for creating a contact.\n * Matches CompanyContactCreate / ContactCreate from the OpenAPI spec.\n *\n * @see CompanyContactCreate in company_contacts.d.ts\n * @see ContactCreate in users_contacts.d.ts\n */\nexport const createContactFormSchema = buildCreateContactFormSchema();\n\nexport type CreateContactFormData = z.infer<typeof createContactFormSchema>;\n\n/**\n * Build the edit-contact schema with optional translated messages.\n */\nexport function buildEditContactFormSchema(msgs?: ContactFormMessages) {\n  return buildCreateContactFormSchema(msgs).passthrough();\n}\n\n/**\n * Form schema for editing a contact.\n * Same fields as create plus id. Uses .passthrough() so extra fields\n * from the Contact read model (full_name, avatar_url, etc.) don't\n * cause validation failures.\n *\n * @see CompanyContactUpdate in company_contacts.d.ts\n */\nexport const editContactFormSchema = createContactFormSchema.passthrough();\n\nexport type EditContactFormData = z.infer<typeof editContactFormSchema>;\n","\"use client\";\n\nimport { useMemo, useCallback } from \"react\";\nimport { useZodForm, fluidToast } from \"@fluid-app/ui-primitives\";\nimport type { UseFormReturn } from \"react-hook-form\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useOptionalContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { useContactDetail } from \"./useContactDetail\";\nimport { useUpdateContactMutation } from \"./useUpdateContactMutation\";\nimport { useDeleteContactMutation } from \"./useDeleteContactMutation\";\nimport {\n  createContactFormSchema,\n  buildEditContactFormSchema,\n  type EditContactFormData,\n} from \"../schemas/contactFormSchema\";\nimport type { Contact } from \"@fluid-app/contacts-core/types\";\n\nconst mutableKeys = Object.keys(\n  createContactFormSchema.shape,\n) as (keyof EditContactFormData)[];\n\nexport function useContactDetailPage(\n  contactId: string,\n  options?: {\n    queryKeyPrefix?: string;\n    countriesQueryKey?: readonly unknown[];\n    getCountries?: () => Promise<{ id: number; name: string; iso?: string }[]>;\n    onDeleteSuccess?: () => void;\n    onSaveSuccess?: () => void;\n  },\n): {\n  contact: Contact | undefined;\n  isLoading: boolean;\n  methods: UseFormReturn<EditContactFormData>;\n  countryOptions: { name: string; value: string }[];\n  isDirty: boolean;\n  isSubmitting: boolean;\n  isDeleting: boolean;\n  onSave: () => void;\n  onDelete: () => void;\n} {\n  const i18n = useOptionalContactsTranslation();\n  const queryKeyPrefix = options?.queryKeyPrefix ?? \"contacts\";\n\n  const { data, isLoading } = useContactDetail(contactId, queryKeyPrefix);\n\n  const { data: countries } = useQuery({\n    queryKey: options?.countriesQueryKey ?? [\"countries\"],\n    queryFn: options?.getCountries ?? (() => Promise.resolve([])),\n    enabled: !!options?.getCountries,\n  });\n\n  const countryOptions = useMemo(\n    () =>\n      [\n        ...(countries?.map((c) => ({\n          name: c.name,\n          value: c.iso ?? c.id.toString(),\n        })) ?? []),\n      ].sort((a, b) => a.name.localeCompare(b.name)),\n    [countries],\n  );\n\n  const contact = data?.contact;\n\n  // Map nested country object to the ISO code the form select expects\n  const formValues = useMemo(() => {\n    if (!contact) return undefined;\n    return {\n      ...contact,\n      country_code:\n        contact.country?.iso ?? contact.country_id?.toString() ?? null,\n    } as unknown as EditContactFormData;\n  }, [contact]);\n\n  const translatedSchema = useMemo(\n    () =>\n      buildEditContactFormSchema(\n        i18n\n          ? {\n              first_name_required: i18n.t(\"validation_first_name_required\"),\n              last_name_required: i18n.t(\"validation_last_name_required\"),\n            }\n          : undefined,\n      ),\n    [i18n],\n  );\n\n  const methods = useZodForm<EditContactFormData>(translatedSchema, {\n    values: formValues,\n    mode: \"onBlur\",\n  });\n\n  const updateMutation = useUpdateContactMutation(contactId, queryKeyPrefix, {\n    onSuccess: () => {\n      methods.reset(methods.getValues());\n      options?.onSaveSuccess?.();\n    },\n  });\n\n  const deleteMutation = useDeleteContactMutation(queryKeyPrefix, {\n    onSuccess: () => {\n      options?.onDeleteSuccess?.();\n    },\n  });\n\n  const onSave = useCallback(() => {\n    methods.handleSubmit(\n      (formData) => {\n        const payload: Record<string, unknown> = {};\n        for (const key of mutableKeys) {\n          if (key in formData) {\n            payload[key] = formData[key];\n          }\n        }\n\n        updateMutation.mutate({\n          id: contactId,\n          data: payload,\n        });\n      },\n      (errors) => {\n        const errorMessages = Object.entries(errors)\n          .map(([field, err]) => {\n            const msg =\n              typeof err?.message === \"string\" ? err.message : \"invalid\";\n            return `${field.replace(/_/g, \" \")}: ${msg}`;\n          })\n          .join(\", \");\n        fluidToast({\n          title:\n            i18n?.t(\"form_errors_title\") ??\n            \"Please fix the form errors before saving\",\n          description: errorMessages || undefined,\n          type: \"error\",\n        });\n      },\n    )();\n  }, [methods, updateMutation, contactId, i18n]);\n\n  const onDelete = useCallback(() => {\n    deleteMutation.mutate(contactId);\n  }, [deleteMutation, contactId]);\n\n  return {\n    contact,\n    isLoading,\n    methods,\n    countryOptions,\n    isDirty: methods.formState.isDirty,\n    isSubmitting: updateMutation.isPending,\n    isDeleting: deleteMutation.isPending,\n    onSave,\n    onDelete,\n  };\n}\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useTasksApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\nimport type { ContactTask } from \"@fluid-app/contacts-core/types\";\n\nexport type { ContactTask };\n\nexport const CONTACT_TASKS_QUERY_KEY = (contactId: string) =>\n  contactsKeys.tasks(contactId);\n\nexport function useContactTasks(contactId: string) {\n  const api = useTasksApi();\n\n  return useQuery({\n    queryKey: contactsKeys.tasks(contactId),\n    queryFn: () => api.listTasks(contactId),\n    enabled: !!contactId,\n    select: (data) => data.tasks,\n  });\n}\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useNotesApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\nimport type { ContactNote } from \"@fluid-app/contacts-core/types\";\n\nexport type { ContactNote };\n\nexport const CONTACT_NOTES_QUERY_KEY = (contactId: string) =>\n  contactsKeys.notes(contactId);\n\nexport function useContactNotes(contactId: string) {\n  const api = useNotesApi();\n\n  return useQuery({\n    queryKey: contactsKeys.notes(contactId),\n    queryFn: () => api.listNotes(contactId),\n    enabled: !!contactId,\n    select: (data) => data.notes,\n  });\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useGroupsApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport type { CreateGroupInput } from \"@fluid-app/contacts-core/types\";\n\nexport function useCreateGroup() {\n  const api = useGroupsApi();\n  const queryClient = useQueryClient();\n  const { t } = useContactsTranslation();\n\n  return useMutation({\n    mutationFn: (input: CreateGroupInput) => {\n      if (!api) throw new Error(\"GroupsApi is not available\");\n      return api.createGroup(input);\n    },\n    onSuccess: () => {\n      queryClient.invalidateQueries({ queryKey: contactsKeys.groups() });\n    },\n    onError: (error) => {\n      fluidToast({\n        title: t(\"groups_create_failed\"),\n        description: parseApiErrors(error),\n        type: \"error\",\n      });\n    },\n  });\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { useContactsCrud } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { CONTACTS_QUERY_KEYS } from \"@fluid-app/contacts-core/query-keys\";\n\nexport function useUpdateContactTags(\n  contactId: string,\n  queryKeyPrefix = \"sdk-contacts\",\n  options?: {\n    onSuccess?: () => void;\n    onError?: (error: Error) => void;\n  },\n) {\n  const api = useContactsCrud();\n  const queryClient = useQueryClient();\n\n  return useMutation({\n    mutationFn: (tags: string[]) => api.updateContact(contactId, { tags }),\n    onSuccess: () => {\n      queryClient.invalidateQueries({\n        queryKey: CONTACTS_QUERY_KEYS.all(queryKeyPrefix),\n      });\n      queryClient.invalidateQueries({\n        queryKey: [\"portal-contacts\"],\n      });\n      options?.onSuccess?.();\n    },\n    onError: options?.onError,\n  });\n}\n","import React from \"react\";\nimport { cn } from \"@fluid-app/ui-primitives\";\n\nconst statusStyles: Record<string, string> = {\n  // Contact statuses\n  new: \"border-[var(--status-new-border)] bg-[var(--status-new)] text-[var(--status-new-foreground)]\",\n  active:\n    \"border-[var(--status-active-border)] bg-[var(--status-active)] text-[var(--status-active-foreground)]\",\n  inactive: \"border-border bg-muted text-muted-foreground\",\n  lead: \"border-[var(--status-lead-border)] bg-[var(--status-lead)] text-[var(--status-lead-foreground)]\",\n  customer:\n    \"border-[var(--status-customer-border)] bg-[var(--status-customer)] text-[var(--status-customer-foreground)]\",\n  // Semantic categories (orders, subscriptions, etc.)\n  success:\n    \"border-[var(--badge-success-border)] bg-[var(--badge-success)] text-[var(--badge-success-foreground)]\",\n  warning:\n    \"border-[var(--badge-warning-border)] bg-[var(--badge-warning)] text-[var(--badge-warning-foreground)]\",\n  danger:\n    \"border-[var(--badge-danger-border)] bg-[var(--badge-danger)] text-[var(--badge-danger-foreground)]\",\n  info: \"border-[var(--badge-info-border)] bg-[var(--badge-info)] text-[var(--badge-info-foreground)]\",\n  neutral: \"border-border bg-muted text-muted-foreground\",\n  notice:\n    \"border-[var(--badge-notice-border)] bg-[var(--badge-notice)] text-[var(--badge-notice-foreground)]\",\n  accent:\n    \"border-[var(--badge-accent-border)] bg-[var(--badge-accent)] text-[var(--badge-accent-foreground)]\",\n};\n\nconst defaultStyle = \"border-border bg-muted text-muted-foreground\";\n\nexport type StatusBadgeVariant = keyof typeof statusStyles;\n\nexport function getStatusStyle(status: string): string {\n  return statusStyles[status] ?? defaultStyle;\n}\n\nexport function StatusBadge({\n  status,\n  label,\n  className,\n}: {\n  status: string;\n  label?: string;\n  className?: string;\n}): React.JSX.Element {\n  return (\n    <span\n      className={cn(\n        \"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold capitalize\",\n        getStatusStyle(status),\n        className,\n      )}\n    >\n      {label ?? status}\n    </span>\n  );\n}\n","\"use client\";\n\nimport React, {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from \"react\";\nimport { Check, Plus } from \"lucide-react\";\nimport type { ContactGroup } from \"@fluid-app/contacts-core/types\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport {\n  Button,\n  cn,\n  Input,\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from \"@fluid-app/ui-primitives\";\n\nconst DEFAULT_SUGGESTIONS = [\n  \"Customer\",\n  \"Cold\",\n  \"Hot\",\n  \"New\",\n  \"Leaders\",\n  \"Pros\",\n];\n\nexport interface InlineGroupsEditorProps {\n  contactTags: string[];\n  availableGroups: ContactGroup[];\n  onSave: (tags: string[]) => void;\n  onCreateGroup?: (name: string) => void | Promise<void>;\n  isSaving?: boolean;\n}\n\nexport function InlineGroupsEditor({\n  contactTags,\n  availableGroups,\n  onSave,\n  onCreateGroup,\n  isSaving = false,\n}: InlineGroupsEditorProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const [open, setOpen] = useState(false);\n  const [draftTags, setDraftTags] = useState<string[]>([]);\n  const [searchText, setSearchText] = useState(\"\");\n  const [prevTags, setPrevTags] = useState<string[]>([]);\n  const [newTags, setNewTags] = useState<Set<string>>(new Set());\n  const [removingTags, setRemovingTags] = useState<Set<string>>(new Set());\n  const [displayTags, setDisplayTags] = useState<string[]>(contactTags);\n  const prevContactTagsRef = useRef<string[]>(contactTags);\n\n  // Sync displayTags with contactTags, but delay removals for animation.\n  // Comparing the previous and current contactTags (rather than displayTags)\n  // keeps this effect free of a self-referential dependency.\n  useEffect(() => {\n    const prev = prevContactTagsRef.current;\n    const removed = prev.filter((t) => !contactTags.includes(t));\n    const added = contactTags.filter((t) => !prev.includes(t));\n    let timer: ReturnType<typeof setTimeout> | undefined;\n\n    if (removed.length > 0) {\n      setRemovingTags(new Set(removed));\n      timer = setTimeout(() => {\n        setDisplayTags(contactTags);\n        setRemovingTags(new Set());\n      }, 300);\n    } else if (added.length > 0) {\n      setDisplayTags(contactTags);\n    } else if (\n      prev.length !== contactTags.length ||\n      prev.some((t, i) => contactTags[i] !== t)\n    ) {\n      setDisplayTags(contactTags);\n    }\n\n    prevContactTagsRef.current = contactTags;\n    return () => {\n      if (timer) clearTimeout(timer);\n    };\n  }, [contactTags]);\n\n  useEffect(() => {\n    if (newTags.size === 0) return;\n    const timer = setTimeout(() => setNewTags(new Set()), 2000);\n    return () => clearTimeout(timer);\n  }, [newTags]);\n\n  const handleOpen = useCallback(() => {\n    setDraftTags([...contactTags]);\n    setPrevTags([...contactTags]);\n    setSearchText(\"\");\n    setOpen(true);\n  }, [contactTags]);\n\n  const handleCancel = useCallback(() => {\n    setOpen(false);\n    setSearchText(\"\");\n  }, []);\n\n  const handleSave = useCallback(() => {\n    const added = new Set(draftTags.filter((t) => !prevTags.includes(t)));\n    onSave(draftTags);\n    setOpen(false);\n    setSearchText(\"\");\n    if (added.size > 0) {\n      setNewTags(added);\n    }\n  }, [draftTags, prevTags, onSave]);\n\n  const toggleTag = useCallback((tag: string) => {\n    setDraftTags((prev) =>\n      prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag],\n    );\n  }, []);\n\n  const groupsByName = useMemo(() => {\n    const map = new Map<string, ContactGroup>();\n    for (const g of availableGroups) {\n      map.set(g.name, g);\n    }\n    return map;\n  }, [availableGroups]);\n\n  const allGroups = useMemo(() => {\n    const groupNames = availableGroups.map((g) => g.name);\n    return Array.from(new Set([...groupNames, ...DEFAULT_SUGGESTIONS]));\n  }, [availableGroups]);\n\n  const filtered = useMemo(() => {\n    const lower = searchText.toLowerCase();\n    if (!lower) return allGroups;\n    return allGroups.filter((name) => name.toLowerCase().includes(lower));\n  }, [allGroups, searchText]);\n\n  const canCreateNew =\n    !!onCreateGroup &&\n    searchText.trim() &&\n    !allGroups.some((s) => s.toLowerCase() === searchText.trim().toLowerCase());\n\n  return (\n    <Popover open={open} onOpenChange={(v) => !v && handleCancel()}>\n      <PopoverTrigger asChild>\n        <div\n          role=\"button\"\n          tabIndex={0}\n          onClick={handleOpen}\n          onKeyDown={(e) => {\n            if (e.key === \"Enter\" || e.key === \" \") {\n              e.preventDefault();\n              handleOpen();\n            }\n          }}\n          className=\"group/groups flex cursor-pointer flex-wrap items-center gap-1.5\"\n        >\n          {displayTags.map((tag) => (\n            <span\n              key={tag}\n              className={cn(\n                \"bg-muted text-foreground inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium transition-all duration-300\",\n                newTags.has(tag) &&\n                  \"animate-[badge-in_0.3s_ease-out,highlight-fade_2s_ease-out]\",\n                removingTags.has(tag) &&\n                  \"animate-[badge-out_0.3s_ease-in_forwards]\",\n              )}\n            >\n              {tag}\n            </span>\n          ))}\n          <span\n            className={cn(\n              \"bg-muted text-muted-foreground hover:bg-muted/70 inline-flex items-center justify-center rounded-full px-2 py-0.5 text-xs font-medium transition-colors\",\n            )}\n          >\n            <Plus className=\"size-3.5\" />\n          </span>\n        </div>\n      </PopoverTrigger>\n\n      <PopoverContent\n        align=\"start\"\n        className=\"bg-popover border-border z-50 w-72 rounded-lg border p-0 shadow-md\"\n      >\n        {/* Search */}\n        <div className=\"p-1\">\n          <Input\n            type=\"text\"\n            value={searchText}\n            onChange={(e) => setSearchText(e.target.value)}\n            placeholder={t(\"groups_inline_search_placeholder\")}\n          />\n        </div>\n\n        {/* Group list */}\n        <div className=\"max-h-48 overflow-y-auto py-1\">\n          {filtered.map((name) => {\n            const isSelected = draftTags.includes(name);\n            const group = groupsByName.get(name);\n            return (\n              <button\n                key={name}\n                type=\"button\"\n                onClick={() => toggleTag(name)}\n                className=\"hover:bg-muted flex w-full items-center gap-2.5 px-3 py-2.5 text-left text-sm\"\n              >\n                {group?.avatar ? (\n                  <span\n                    className=\"flex size-5 shrink-0 items-center justify-center rounded-full text-xs\"\n                    style={{\n                      backgroundColor:\n                        group.avatar_background ?? \"var(--color-muted)\",\n                    }}\n                  >\n                    {group.avatar}\n                  </span>\n                ) : (\n                  <span className=\"bg-muted flex size-5 shrink-0 items-center justify-center rounded-full text-[10px] font-medium\">\n                    {name[0]?.toUpperCase()}\n                  </span>\n                )}\n                <span className=\"text-foreground flex-1 truncate\">{name}</span>\n                {isSelected && (\n                  <Check className=\"text-foreground size-4 shrink-0\" />\n                )}\n              </button>\n            );\n          })}\n          {canCreateNew && (\n            <button\n              type=\"button\"\n              onClick={async () => {\n                const trimmed = searchText.trim();\n                if (trimmed && !draftTags.includes(trimmed)) {\n                  try {\n                    await onCreateGroup?.(trimmed);\n                  } catch {\n                    return;\n                  }\n                  const updated = [...draftTags, trimmed];\n                  const added = new Set(\n                    updated.filter((t) => !prevTags.includes(t)),\n                  );\n                  onSave(updated);\n                  setOpen(false);\n                  setSearchText(\"\");\n                  setNewTags(added);\n                }\n              }}\n              className=\"hover:bg-muted text-primary flex w-full items-center gap-2 px-3 py-2 text-left text-sm font-medium\"\n            >\n              <Plus className=\"size-3.5\" />\n              {t(\"groups_inline_create\", { name: searchText.trim() })}\n            </button>\n          )}\n          {filtered.length === 0 && !canCreateNew && (\n            <p className=\"text-muted-foreground py-4 text-center text-sm\">\n              {t(\"groups_inline_no_groups_found\")}\n            </p>\n          )}\n        </div>\n\n        {/* Footer */}\n        <div className=\"border-border flex items-center justify-between border-t px-3 py-2\">\n          <span className=\"text-muted-foreground text-xs\">\n            {draftTags.length === 1\n              ? t(\"groups_inline_selected_one\", { count: draftTags.length })\n              : t(\"groups_inline_selected_other\", { count: draftTags.length })}\n          </span>\n          <div className=\"flex gap-2\">\n            <Button variant=\"ghost\" size=\"sm\" onClick={handleCancel}>\n              {t(\"cancel\")}\n            </Button>\n            <Button size=\"sm\" onClick={handleSave} disabled={isSaving}>\n              {isSaving ? t(\"saving\") : t(\"save\")}\n            </Button>\n          </div>\n        </div>\n      </PopoverContent>\n    </Popover>\n  );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { ListTodo, StickyNote } from \"lucide-react\";\nimport type { Contact, ContactGroup } from \"@fluid-app/contacts-core/types\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { StatusBadge } from \"../../../../shared/components/contacts/statusBadge\";\nimport { InlineGroupsEditor } from \"./InlineGroupsEditor\";\nimport { getDisplayName, getInitials, getRelativeUpdated } from \"./utils\";\n\nexport interface ContactDetailHeroProps {\n  contact: Contact;\n  tasksCount: number;\n  notesCount: number;\n  contactTags: string[];\n  availableGroups: ContactGroup[];\n  onTagsSave: (tags: string[]) => void;\n  onCreateGroup?: (name: string) => void | Promise<void>;\n  isTagsSaving?: boolean;\n}\n\nexport function ContactDetailHero({\n  contact,\n  tasksCount,\n  notesCount,\n  contactTags,\n  availableGroups,\n  onTagsSave,\n  onCreateGroup,\n  isTagsSaving,\n}: ContactDetailHeroProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const name = getDisplayName(contact, t);\n  const status = contact.status?.trim();\n  const lastUpdated = getRelativeUpdated(contact, t);\n\n  return (\n    <div className=\"flex flex-col gap-6 md:flex-row md:items-center md:justify-between md:gap-8\">\n      <div className=\"flex flex-col items-start gap-4 md:flex-row md:items-center md:gap-5\">\n        <div className=\"bg-muted relative flex size-20 shrink-0 items-center justify-center overflow-hidden rounded-2xl md:size-24\">\n          {contact.avatar_url ? (\n            <img\n              alt={name}\n              src={contact.avatar_url}\n              className=\"size-full object-cover\"\n            />\n          ) : (\n            <span\n              aria-hidden=\"true\"\n              className=\"text-muted-foreground text-2xl font-bold tracking-tight md:text-3xl\"\n            >\n              {getInitials(name)}\n            </span>\n          )}\n        </div>\n\n        <div className=\"min-w-0 flex-1\">\n          <h2 className=\"text-foreground text-2xl leading-tight font-bold tracking-tight md:text-3xl\">\n            {name}\n          </h2>\n          <div className=\"mt-2.5 flex flex-wrap items-center gap-2\">\n            {status && <StatusBadge status={status} />}\n            <InlineGroupsEditor\n              contactTags={contactTags}\n              availableGroups={availableGroups}\n              onSave={onTagsSave}\n              onCreateGroup={onCreateGroup}\n              isSaving={isTagsSaving}\n            />\n          </div>\n          {lastUpdated && (\n            <span className=\"text-muted-foreground mt-1.5 text-xs\">\n              {t(\"last_updated\", { date: lastUpdated })}\n            </span>\n          )}\n        </div>\n      </div>\n\n      <div className=\"flex shrink-0 items-center gap-6 md:gap-8\">\n        <Stat label={t(\"tab_tasks\")} value={tasksCount} icon={ListTodo} />\n        <div className=\"bg-border h-10 w-px\" aria-hidden=\"true\" />\n        <Stat label={t(\"tab_notes\")} value={notesCount} icon={StickyNote} />\n      </div>\n    </div>\n  );\n}\n\ninterface StatProps {\n  label: string;\n  value: number;\n  icon: React.ComponentType<{ className?: string; \"aria-hidden\"?: boolean }>;\n}\n\nfunction Stat({ label, value, icon: Icon }: StatProps) {\n  return (\n    <div className=\"flex flex-col items-start gap-1\">\n      <div className=\"text-muted-foreground flex items-center gap-1.5\">\n        <Icon className=\"size-3.5\" aria-hidden={true} />\n        <span className=\"text-xs font-medium\">{label}</span>\n      </div>\n      <span className=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">\n        {value}\n      </span>\n    </div>\n  );\n}\n","\"use client\";\n\nimport React, { useState } from \"react\";\nimport { Check, Copy, Mail, MapPin, Phone, Plus } from \"lucide-react\";\nimport type { Contact } from \"@fluid-app/contacts-core/types\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\n\nexport interface ContactInfoRowProps {\n  contact: Contact;\n  /** Click handler invoked when an empty-state row is activated. */\n  onEditEmpty?: () => void;\n}\n\nfunction buildAddressLine(contact: Contact): string | null {\n  const parts = [\n    contact.address,\n    contact.city,\n    contact.state,\n    contact.postal_code,\n  ].filter((part): part is string => Boolean(part?.trim()));\n  if (parts.length === 0) return null;\n  return parts.join(\", \");\n}\n\nexport function ContactInfoRow({\n  contact,\n  onEditEmpty,\n}: ContactInfoRowProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const address = buildAddressLine(contact);\n\n  return (\n    <div className=\"border-border/50 divide-border/50 mt-6 divide-y overflow-hidden rounded-2xl border\">\n      <InfoRow\n        icon={Mail}\n        label={t(\"label_email\")}\n        value={contact.email}\n        href={contact.email ? `mailto:${contact.email}` : undefined}\n        onEditEmpty={onEditEmpty}\n      />\n      <InfoRow\n        icon={Phone}\n        label={t(\"label_phone\")}\n        value={contact.phone}\n        href={contact.phone ? `tel:${contact.phone}` : undefined}\n        onEditEmpty={onEditEmpty}\n      />\n      <InfoRow\n        icon={MapPin}\n        label={t(\"label_address\")}\n        value={address}\n        href={\n          address\n            ? `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`\n            : undefined\n        }\n        external={true}\n        onEditEmpty={onEditEmpty}\n      />\n    </div>\n  );\n}\n\ninterface InfoRowProps {\n  icon: React.ComponentType<{ className?: string; \"aria-hidden\"?: boolean }>;\n  label: string;\n  value: string | null | undefined;\n  href: string | undefined;\n  external?: boolean;\n  onEditEmpty?: () => void;\n}\n\nfunction InfoRow({\n  icon: Icon,\n  label,\n  value,\n  href,\n  external = false,\n  onEditEmpty,\n}: InfoRowProps) {\n  const { t } = useContactsTranslation();\n  const trimmed = value?.trim();\n  const isEmpty = !trimmed;\n  const [copied, setCopied] = useState(false);\n\n  const handleCopy = () => {\n    if (!trimmed) return;\n    if (typeof navigator === \"undefined\" || !navigator.clipboard) return;\n    navigator.clipboard\n      .writeText(trimmed)\n      .then(() => {\n        setCopied(true);\n        window.setTimeout(() => setCopied(false), 1500);\n      })\n      .catch(() => {\n        // clipboard write can fail in insecure contexts; silently noop\n      });\n  };\n\n  if (isEmpty) {\n    const addText = t(\"add_field\", { field: label });\n    if (!onEditEmpty) {\n      return (\n        <div className=\"flex items-center gap-3 px-4 py-2.5 md:px-5\">\n          <div className=\"border-border/50 text-muted-foreground/50 flex size-9 shrink-0 items-center justify-center rounded-full border-2 border-dashed\">\n            <Icon className=\"size-4\" aria-hidden={true} />\n          </div>\n          <div className=\"min-w-0 flex-1\">\n            <div className=\"text-muted-foreground text-xs font-medium\">\n              {label}\n            </div>\n            <div className=\"text-muted-foreground/70 truncate text-sm italic\">\n              {addText}\n            </div>\n          </div>\n          <Plus\n            className=\"text-muted-foreground/40 size-4 shrink-0\"\n            aria-hidden={true}\n          />\n        </div>\n      );\n    }\n    return (\n      <button\n        type=\"button\"\n        onClick={onEditEmpty}\n        aria-label={addText}\n        className=\"hover:bg-muted/60 group flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors md:px-5\"\n      >\n        <div className=\"border-border/50 text-muted-foreground/50 group-hover:border-foreground/30 group-hover:text-muted-foreground flex size-9 shrink-0 items-center justify-center rounded-full border-2 border-dashed transition-colors\">\n          <Icon className=\"size-4\" aria-hidden={true} />\n        </div>\n        <div className=\"min-w-0 flex-1\">\n          <div className=\"text-muted-foreground text-xs font-medium\">\n            {label}\n          </div>\n          <div className=\"text-muted-foreground/70 group-hover:text-muted-foreground truncate text-sm italic transition-colors\">\n            {addText}\n          </div>\n        </div>\n        <Plus\n          className=\"text-muted-foreground/40 group-hover:text-foreground size-4 shrink-0 transition-colors\"\n          aria-hidden={true}\n        />\n      </button>\n    );\n  }\n\n  return (\n    <div className=\"hover:bg-muted/60 group flex items-center transition-colors\">\n      <a\n        href={href}\n        {...(external ? { target: \"_blank\", rel: \"noopener noreferrer\" } : {})}\n        className=\"flex min-w-0 flex-1 items-center gap-3 px-4 py-2.5 md:px-5\"\n      >\n        <div className=\"bg-muted text-muted-foreground group-hover:bg-muted/70 group-hover:text-foreground flex size-9 shrink-0 items-center justify-center rounded-full transition-colors\">\n          <Icon className=\"size-4\" aria-hidden={true} />\n        </div>\n        <div className=\"min-w-0 flex-1\">\n          <div className=\"text-muted-foreground text-xs font-medium\">\n            {label}\n          </div>\n          <div className=\"text-foreground truncate text-sm font-semibold\">\n            {trimmed}\n          </div>\n        </div>\n      </a>\n      <button\n        type=\"button\"\n        onClick={handleCopy}\n        aria-label={\n          copied\n            ? t(\"copied_field\", { field: label })\n            : t(\"copy_field\", { field: label })\n        }\n        className=\"text-muted-foreground hover:bg-muted hover:text-foreground mr-3 flex size-8 shrink-0 items-center justify-center rounded-md transition-colors\"\n      >\n        {copied ? (\n          <Check className=\"text-primary size-3.5\" aria-hidden={true} />\n        ) : (\n          <Copy className=\"size-3.5\" aria-hidden={true} />\n        )}\n      </button>\n    </div>\n  );\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useTasksApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\n\nexport function useToggleTaskCompletion(contactId: string) {\n  const queryClient = useQueryClient();\n  const api = useTasksApi();\n  const { t } = useContactsTranslation();\n\n  return useMutation({\n    mutationFn: ({\n      taskId,\n      isCompleted,\n    }: {\n      taskId: number;\n      isCompleted: boolean;\n    }) =>\n      api.updateTask(taskId, contactId, {\n        completed_at: isCompleted ? null : new Date().toISOString(),\n      }),\n    onSuccess: () => {\n      queryClient.invalidateQueries({\n        queryKey: contactsKeys.tasks(contactId),\n      });\n    },\n    onError: (error) => {\n      fluidToast({\n        title: t(\"task_update_failed\"),\n        type: \"error\",\n        description: parseApiErrors(error),\n      });\n    },\n  });\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useTasksApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\n\nexport function useDeleteContactTask(\n  contactId: string,\n  options?: { onSuccess?: () => void },\n) {\n  const queryClient = useQueryClient();\n  const api = useTasksApi();\n  const { t } = useContactsTranslation();\n\n  return useMutation({\n    mutationFn: (taskId: number) => api.deleteTask(taskId, contactId),\n    onSuccess: () => {\n      fluidToast({ title: t(\"task_deleted\"), type: \"success\" });\n      queryClient.invalidateQueries({\n        queryKey: contactsKeys.tasks(contactId),\n      });\n      options?.onSuccess?.();\n    },\n    onError: (error) => {\n      fluidToast({\n        title: t(\"task_delete_failed\"),\n        type: \"error\",\n        description: parseApiErrors(error),\n      });\n    },\n  });\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useTasksApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\nimport type { UpdateTaskInput } from \"@fluid-app/contacts-core/types\";\n\nexport type { UpdateTaskInput };\n\nexport function useUpdateContactTask(\n  contactId: string,\n  options?: { onSuccess?: () => void },\n) {\n  const queryClient = useQueryClient();\n  const api = useTasksApi();\n  const { t } = useContactsTranslation();\n\n  return useMutation({\n    mutationFn: ({\n      taskId,\n      input,\n    }: {\n      taskId: number;\n      input: UpdateTaskInput;\n    }) => api.updateTask(taskId, contactId, input),\n    onSuccess: () => {\n      fluidToast({ title: t(\"task_updated\"), type: \"success\" });\n      queryClient.invalidateQueries({\n        queryKey: contactsKeys.tasks(contactId),\n      });\n      options?.onSuccess?.();\n    },\n    onError: (error) => {\n      fluidToast({\n        title: t(\"task_update_failed\"),\n        type: \"error\",\n        description: parseApiErrors(error),\n      });\n    },\n  });\n}\n","\"use client\";\n\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { useEditor, EditorContent } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Heading from \"@tiptap/extension-heading\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport TextAlign from \"@tiptap/extension-text-align\";\nimport Underline from \"@tiptap/extension-underline\";\nimport {\n  AlignLeft,\n  AlignCenter,\n  AlignRight,\n  AlignJustify,\n  List,\n  ListOrdered,\n  Calendar,\n  X,\n} from \"lucide-react\";\nimport { cn } from \"@fluid-app/ui-primitives\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { formatDateForDisplay } from \"../../utils/format-date\";\n\nexport interface NoteTaskEditorProps {\n  titlePlaceholder?: string;\n  bodyPlaceholder?: string;\n  onChange?: (content: {\n    title: string;\n    body: string;\n    dueDate?: string;\n  }) => void;\n  className?: string;\n  /** Pre-populate the title (for edit mode) */\n  initialTitle?: string;\n  /** Pre-populate the body (for edit mode) */\n  initialBody?: string;\n  /** Show due date picker */\n  showDueDate?: boolean;\n  /** Pre-populate the due date (ISO string, for edit mode) */\n  initialDueDate?: string;\n  /** When false, the editor is body-only (no H1 title). Default true. */\n  showTitle?: boolean;\n  /** Override for the editor content area min-height class */\n  editorClassName?: string;\n}\n\nfunction extractTitleAndBody(editor: ReturnType<typeof useEditor>): {\n  title: string;\n  body: string;\n} {\n  if (!editor) return { title: \"\", body: \"\" };\n\n  const doc = editor.state.doc;\n  let title = \"\";\n  const bodyParts: string[] = [];\n\n  doc.forEach((node) => {\n    if (node.type.name === \"heading\" && !title) {\n      title = node.textContent.trim();\n    } else {\n      const text = node.textContent.trim();\n      if (text) bodyParts.push(text);\n    }\n  });\n\n  return { title, body: bodyParts.join(\"\\n\") };\n}\n\nfunction extractBodyOnly(editor: ReturnType<typeof useEditor>): string {\n  if (!editor) return \"\";\n  const parts: string[] = [];\n  editor.state.doc.forEach((node) => {\n    const text = node.textContent.trim();\n    if (text) parts.push(text);\n  });\n  return parts.join(\"\\n\");\n}\n\nexport function NoteTaskEditor({\n  titlePlaceholder,\n  bodyPlaceholder,\n  onChange,\n  className,\n  initialTitle,\n  initialBody,\n  showDueDate = false,\n  initialDueDate,\n  showTitle = true,\n  editorClassName,\n}: NoteTaskEditorProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const resolvedTitlePlaceholder =\n    titlePlaceholder ?? t(\"editor_default_title\");\n  const resolvedBodyPlaceholder =\n    bodyPlaceholder ?? t(\"editor_default_body_placeholder\");\n  const [dueDate, setDueDate] = useState<string | undefined>(initialDueDate);\n  const dueDateRef = useRef(initialDueDate);\n  const dateInputRef = useRef<HTMLInputElement>(null);\n\n  // Keep ref in sync with state so onUpdate always reads the latest value\n  useEffect(() => {\n    dueDateRef.current = dueDate;\n  }, [dueDate]);\n\n  const initialContent = showTitle\n    ? initialTitle || initialBody\n      ? `<h1>${initialTitle ?? \"\"}</h1>${initialBody ?? \"\"}`\n      : undefined\n    : initialBody || undefined;\n\n  const extensions = [\n    StarterKit.configure({\n      heading: showTitle ? false : { levels: [] as const },\n      bulletList: {\n        keepMarks: true,\n        keepAttributes: false,\n      },\n      orderedList: {\n        keepMarks: true,\n        keepAttributes: false,\n      },\n    }),\n    ...(showTitle ? [Heading.configure({ levels: [1] })] : []),\n    Placeholder.configure({\n      placeholder: ({ node }) => {\n        if (node.type.name === \"heading\") {\n          return resolvedTitlePlaceholder;\n        }\n        return resolvedBodyPlaceholder;\n      },\n    }),\n    TextAlign.configure({\n      types: showTitle ? [\"heading\", \"paragraph\"] : [\"paragraph\"],\n      alignments: [\"left\", \"center\", \"right\", \"justify\"],\n    }),\n    Underline,\n  ];\n\n  const defaultContent = showTitle\n    ? {\n        type: \"doc\" as const,\n        content: [{ type: \"heading\" as const, attrs: { level: 1 } }],\n      }\n    : undefined;\n\n  const editor = useEditor({\n    extensions,\n    content: initialContent ?? defaultContent,\n    onUpdate: ({ editor }) => {\n      if (showTitle) {\n        const { title, body } = extractTitleAndBody(editor);\n        onChange?.({ title, body, dueDate: dueDateRef.current });\n      } else {\n        const body = extractBodyOnly(editor);\n        onChange?.({ title: \"\", body, dueDate: dueDateRef.current });\n      }\n    },\n  });\n\n  const fireOnChange = () => {\n    if (!editor || !onChange) return;\n    if (showTitle) {\n      const { title, body } = extractTitleAndBody(editor);\n      onChange({ title, body, dueDate });\n    } else {\n      const body = extractBodyOnly(editor);\n      onChange({ title: \"\", body, dueDate });\n    }\n  };\n\n  // Fire onChange once on mount so the parent's ref is populated with the\n  // initial values before the user makes any edits.\n  useEffect(() => {\n    fireOnChange();\n    // We only want this to run once after the editor is first created.\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [editor]);\n\n  // Notify parent when due date changes\n  useEffect(() => {\n    fireOnChange();\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [dueDate]);\n\n  const buttonBase =\n    \"flex h-7 w-7 items-center justify-center rounded text-xs transition-colors\";\n  const buttonActive = \"bg-muted text-primary\";\n  const buttonInactive = \"text-muted-foreground hover:bg-muted/50\";\n\n  const toolbarSeparator = <div className=\"bg-border mx-1 h-5 w-px\" />;\n\n  return (\n    <div\n      className={cn(\n        \"border-border/50 flex flex-col overflow-hidden rounded-lg border\",\n        className,\n      )}\n    >\n      {/* Toolbar */}\n      <div className=\"border-border/50 bg-muted/50 flex items-center gap-0.5 border-b px-2 py-1.5\">\n        {/* Bold */}\n        <button\n          type=\"button\"\n          onClick={() => editor?.chain().focus().toggleBold().run()}\n          disabled={!editor?.can().chain().focus().toggleBold().run()}\n          className={cn(\n            buttonBase,\n            \"font-bold\",\n            editor?.isActive(\"bold\") ? buttonActive : buttonInactive,\n          )}\n          title={t(\"toolbar_bold\")}\n        >\n          B\n        </button>\n\n        {/* Italic */}\n        <button\n          type=\"button\"\n          onClick={() => editor?.chain().focus().toggleItalic().run()}\n          disabled={!editor?.can().chain().focus().toggleItalic().run()}\n          className={cn(\n            buttonBase,\n            \"italic\",\n            editor?.isActive(\"italic\") ? buttonActive : buttonInactive,\n          )}\n          title={t(\"toolbar_italic\")}\n        >\n          I\n        </button>\n\n        {/* Underline */}\n        <button\n          type=\"button\"\n          onClick={() => editor?.chain().focus().toggleUnderline().run()}\n          disabled={!editor?.can().chain().focus().toggleUnderline().run()}\n          className={cn(\n            buttonBase,\n            \"underline\",\n            editor?.isActive(\"underline\") ? buttonActive : buttonInactive,\n          )}\n          title={t(\"toolbar_underline\")}\n        >\n          U\n        </button>\n\n        {toolbarSeparator}\n\n        {/* Align left */}\n        <button\n          type=\"button\"\n          onClick={() => editor?.chain().focus().setTextAlign(\"left\").run()}\n          className={cn(\n            buttonBase,\n            editor?.isActive({ textAlign: \"left\" })\n              ? buttonActive\n              : buttonInactive,\n          )}\n          title={t(\"toolbar_align_left\")}\n        >\n          <AlignLeft className=\"size-3.5\" />\n        </button>\n\n        {/* Align center */}\n        <button\n          type=\"button\"\n          onClick={() => editor?.chain().focus().setTextAlign(\"center\").run()}\n          className={cn(\n            buttonBase,\n            editor?.isActive({ textAlign: \"center\" })\n              ? buttonActive\n              : buttonInactive,\n          )}\n          title={t(\"toolbar_align_center\")}\n        >\n          <AlignCenter className=\"size-3.5\" />\n        </button>\n\n        {/* Align right */}\n        <button\n          type=\"button\"\n          onClick={() => editor?.chain().focus().setTextAlign(\"right\").run()}\n          className={cn(\n            buttonBase,\n            editor?.isActive({ textAlign: \"right\" })\n              ? buttonActive\n              : buttonInactive,\n          )}\n          title={t(\"toolbar_align_right\")}\n        >\n          <AlignRight className=\"size-3.5\" />\n        </button>\n\n        {/* Align justify */}\n        <button\n          type=\"button\"\n          onClick={() => editor?.chain().focus().setTextAlign(\"justify\").run()}\n          className={cn(\n            buttonBase,\n            editor?.isActive({ textAlign: \"justify\" })\n              ? buttonActive\n              : buttonInactive,\n          )}\n          title={t(\"toolbar_justify\")}\n        >\n          <AlignJustify className=\"size-3.5\" />\n        </button>\n\n        {toolbarSeparator}\n\n        {/* Bullet list */}\n        <button\n          type=\"button\"\n          onClick={() => editor?.chain().focus().toggleBulletList().run()}\n          className={cn(\n            buttonBase,\n            editor?.isActive(\"bulletList\") ? buttonActive : buttonInactive,\n          )}\n          title={t(\"toolbar_bullet_list\")}\n        >\n          <List className=\"size-3.5\" />\n        </button>\n\n        {/* Ordered list */}\n        <button\n          type=\"button\"\n          onClick={() => editor?.chain().focus().toggleOrderedList().run()}\n          className={cn(\n            buttonBase,\n            editor?.isActive(\"orderedList\") ? buttonActive : buttonInactive,\n          )}\n          title={t(\"toolbar_ordered_list\")}\n        >\n          <ListOrdered className=\"size-3.5\" />\n        </button>\n\n        {showDueDate && (\n          <>\n            {toolbarSeparator}\n            {/* Due date */}\n            {dueDate ? (\n              <div className=\"bg-primary/10 flex items-center gap-1 rounded px-2 py-1\">\n                <Calendar className=\"text-primary size-3.5\" />\n                <span className=\"text-primary text-xs font-medium\">\n                  {formatDateForDisplay(dueDate)}\n                </span>\n                <button\n                  type=\"button\"\n                  onClick={() => setDueDate(undefined)}\n                  className=\"text-primary/60 hover:text-primary ml-1\"\n                  title={t(\"editor_remove_due_date\")}\n                >\n                  <X className=\"size-3\" />\n                </button>\n              </div>\n            ) : (\n              <>\n                <button\n                  type=\"button\"\n                  onClick={() => dateInputRef.current?.showPicker()}\n                  className=\"text-muted-foreground hover:bg-muted hover:text-foreground flex h-7 cursor-pointer items-center gap-1 rounded px-2 text-xs font-medium transition-colors\"\n                >\n                  <Calendar className=\"size-3.5\" />\n                  <span>{t(\"editor_due_date\")}</span>\n                </button>\n                <input\n                  ref={dateInputRef}\n                  type=\"date\"\n                  className=\"invisible absolute size-0\"\n                  onChange={(e) => {\n                    if (e.target.value) {\n                      // Convert YYYY-MM-DD to ISO datetime at local midnight\n                      const localDate = new Date(e.target.value + \"T00:00:00\");\n                      setDueDate(localDate.toISOString());\n                    }\n                  }}\n                />\n              </>\n            )}\n          </>\n        )}\n      </div>\n\n      {/* Editor area */}\n      <EditorContent\n        editor={editor}\n        className={editorClassName ?? \"min-h-[60vh] flex-1 overflow-y-auto p-4\"}\n      />\n\n      <style>{`\n        .ProseMirror {\n          outline: none;\n        }\n\n        .ProseMirror h1 {\n          font-size: 1.5rem;\n          font-weight: 600;\n          line-height: 1.3;\n          margin-bottom: 0.5rem;\n        }\n\n        .ProseMirror h1.is-empty::before,\n        .ProseMirror p.is-empty::before {\n          color: var(--color-muted-foreground);\n          content: attr(data-placeholder);\n          float: left;\n          height: 0;\n          pointer-events: none;\n        }\n\n        .ProseMirror ul {\n          list-style-type: disc;\n          padding-left: 1.5rem;\n          margin: 0.5rem 0;\n        }\n\n        .ProseMirror ol {\n          list-style-type: decimal;\n          padding-left: 1.5rem;\n          margin: 0.5rem 0;\n        }\n\n        .ProseMirror li {\n          margin: 0.25rem 0;\n          display: list-item;\n        }\n\n        .ProseMirror li > p {\n          margin: 0;\n        }\n      `}</style>\n    </div>\n  );\n}\n","\"use client\";\n\nimport React, { useRef, useState } from \"react\";\nimport { Calendar, X } from \"lucide-react\";\nimport {\n  Button,\n  Input,\n  Sheet,\n  SheetContent,\n  SheetFooter,\n  SheetHeader,\n  SheetTitle,\n  cn,\n} from \"@fluid-app/ui-primitives\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport { MobileBottomSheet } from \"@fluid-app/ui-components/components/MobileBottomSheet\";\nimport { NoteTaskEditor } from \"./note-task-editor\";\nimport {\n  formatDateForDisplay,\n  toDateInputValue,\n} from \"../../utils/format-date\";\n\nexport interface NoteTaskModalProps {\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n  mode: \"create\" | \"edit\";\n  type: \"note\" | \"task\";\n  initialTitle?: string;\n  initialBody?: string;\n  initialDueDate?: string;\n  showDueDate?: boolean;\n  onSave: (data: { title: string; body: string; dueDate?: string }) => void;\n  isPending?: boolean;\n  isCompleted?: boolean;\n  onToggleComplete?: () => void;\n  isTogglePending?: boolean;\n}\n\nexport function NoteTaskModal({\n  open,\n  onOpenChange,\n  mode,\n  type,\n  initialTitle = \"\",\n  initialBody = \"\",\n  initialDueDate,\n  showDueDate = false,\n  onSave,\n  isPending = false,\n  isCompleted,\n  onToggleComplete,\n  isTogglePending = false,\n}: NoteTaskModalProps): React.JSX.Element {\n  const { t, locale } = useContactsTranslation();\n  const { isMobile } = useSidebar();\n  const [title, setTitle] = useState(initialTitle);\n  const [body, setBody] = useState(initialBody);\n  const dateInputRef = useRef<HTMLInputElement>(null);\n\n  const [dueDate, setDueDate] = useState<string | undefined>(initialDueDate);\n  const [showDateInputFallback, setShowDateInputFallback] = useState(false);\n\n  const typeLabel =\n    type === \"note\" ? t(\"modal_note_label\") : t(\"modal_task_label\");\n  const sheetTitle =\n    mode === \"edit\"\n      ? t(\"modal_edit_type\", { type: typeLabel })\n      : t(\"modal_new_type\", { type: typeLabel });\n\n  const requiresBody = type === \"note\";\n  const canSave =\n    !!title.trim() && (!requiresBody || !!body.trim()) && !isPending;\n\n  const handleSave = () => {\n    if (!canSave) return;\n    onSave({\n      title: title.trim(),\n      body,\n      dueDate,\n    });\n  };\n\n  const content = (\n    <>\n      <div className=\"flex min-h-0 flex-1 flex-col gap-3\">\n        <Input\n          placeholder={t(\"modal_type_title_placeholder\", { type: typeLabel })}\n          value={title}\n          onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n            setTitle(e.target.value)\n          }\n        />\n\n        <NoteTaskEditor\n          showTitle={false}\n          bodyPlaceholder={t(\"editor_start_writing\")}\n          initialBody={initialBody}\n          editorClassName=\"min-h-[200px] flex-1 overflow-y-auto p-4\"\n          onChange={(content) => {\n            setBody(content.body);\n          }}\n        />\n\n        {showDueDate && (\n          <div className=\"flex items-center gap-2\">\n            {dueDate ? (\n              <div className=\"bg-primary/10 inline-flex items-center gap-1.5 rounded-md px-2.5 py-1.5\">\n                <Calendar className=\"text-primary size-3.5\" />\n                <span className=\"text-primary text-sm font-medium\">\n                  {t(\"activity_due\")} {formatDateForDisplay(dueDate, locale)}\n                </span>\n                <button\n                  type=\"button\"\n                  onClick={() => {\n                    setDueDate(undefined);\n                    setShowDateInputFallback(false);\n                  }}\n                  aria-label={t(\"editor_remove_due_date\")}\n                  className=\"text-primary/60 hover:text-primary ml-1\"\n                  title={t(\"editor_remove_due_date\")}\n                >\n                  <X className=\"size-3\" />\n                </button>\n              </div>\n            ) : (\n              <div className=\"relative\">\n                <button\n                  type=\"button\"\n                  onClick={() => {\n                    const input = dateInputRef.current;\n                    if (!input) return;\n                    try {\n                      if (typeof input.showPicker === \"function\") {\n                        input.showPicker();\n                      } else {\n                        throw new Error(\"showPicker unavailable\");\n                      }\n                    } catch {\n                      setShowDateInputFallback(true);\n                      queueMicrotask(() => input.focus());\n                    }\n                  }}\n                  className=\"text-muted-foreground hover:text-foreground hover:bg-muted inline-flex cursor-pointer items-center gap-1.5 rounded-md px-2.5 py-1.5 text-sm font-medium transition-colors\"\n                >\n                  <Calendar className=\"size-3.5\" />\n                  <span>{t(\"editor_add_due_date\")}</span>\n                </button>\n                <input\n                  ref={dateInputRef}\n                  type=\"date\"\n                  value={toDateInputValue(dueDate)}\n                  tabIndex={showDateInputFallback ? 0 : -1}\n                  aria-hidden={!showDateInputFallback}\n                  aria-label={t(\"editor_due_date\")}\n                  className={cn(\n                    showDateInputFallback\n                      ? \"rounded-md border p-2 text-sm\"\n                      : \"sr-only\",\n                  )}\n                  onChange={(e) => {\n                    setShowDateInputFallback(false);\n                    setDueDate(e.target.value || undefined);\n                  }}\n                />\n              </div>\n            )}\n          </div>\n        )}\n      </div>\n\n      <SheetFooter className=\"flex-row justify-end gap-2 border-t pt-4\">\n        {mode === \"edit\" && onToggleComplete && (\n          <Button\n            variant=\"outline\"\n            onClick={onToggleComplete}\n            disabled={isTogglePending}\n            className=\"mr-auto\"\n          >\n            {isCompleted\n              ? t(\"modal_mark_incomplete\")\n              : t(\"modal_mark_complete\")}\n          </Button>\n        )}\n        <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n          {t(\"cancel\")}\n        </Button>\n        <Button onClick={handleSave} disabled={!canSave}>\n          {isPending ? t(\"saving\") : t(\"save\")}\n        </Button>\n      </SheetFooter>\n    </>\n  );\n\n  if (isMobile) {\n    return (\n      <MobileBottomSheet\n        open={open}\n        onOpenChange={onOpenChange}\n        title={sheetTitle}\n      >\n        <div className=\"flex min-h-[60dvh] flex-col gap-4 px-2\">{content}</div>\n      </MobileBottomSheet>\n    );\n  }\n\n  return (\n    <Sheet open={open} onOpenChange={onOpenChange}>\n      <SheetContent className=\"flex w-full flex-col sm:max-w-lg\">\n        <SheetHeader>\n          <SheetTitle>{sheetTitle}</SheetTitle>\n        </SheetHeader>\n        {content}\n      </SheetContent>\n    </Sheet>\n  );\n}\n","\"use client\";\n\nimport React, { useState } from \"react\";\nimport { Calendar, CircleCheck, EllipsisVertical } from \"lucide-react\";\nimport {\n  cn,\n  Button,\n  DialogFooter,\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from \"@fluid-app/ui-primitives\";\nimport { MobileActionSheet } from \"@fluid-app/ui-components/components/MobileActionSheet\";\nimport { ResponsiveDialog } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport { parseTaskBody } from \"@fluid-app/contacts-core/parse-task-body\";\nimport { startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { formatDateForDisplay, isAllDay } from \"../../utils/format-date\";\nimport type { ContactTask } from \"../../hooks/contacts/use-contact-tasks\";\nimport { useToggleTaskCompletion } from \"../../hooks/contacts/use-toggle-task-completion\";\nimport { useDeleteContactTask } from \"../../hooks/contacts/use-delete-contact-task\";\nimport { useUpdateContactTask } from \"../../hooks/contacts/use-update-contact-task\";\nimport { NoteTaskModal } from \"../editor/note-task-modal\";\n\n// ---------------------------------------------------------------------------\n// Date helpers\n// ---------------------------------------------------------------------------\n\nfunction formatDueDate(dateStr: string, locale?: string): string {\n  return formatDateForDisplay(dateStr, locale);\n}\n\ntype ContactsT = ReturnType<typeof useContactsTranslation>[\"t\"];\n\nfunction formatRelativeTime(dateStr: string, t: ContactsT): string {\n  const date = new Date(dateStr);\n  const now = new Date();\n  const diffMs = now.getTime() - date.getTime();\n  const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));\n\n  if (diffDays === 0) {\n    return date.toLocaleTimeString(\"en-US\", {\n      hour: \"numeric\",\n      minute: \"2-digit\",\n    });\n  }\n  if (diffDays === 1) return t(\"task_yesterday\");\n  return diffDays === 1\n    ? t(\"task_days_ago_one\")\n    : t(\"task_days_ago_other\", { count: diffDays });\n}\n\ntype DueClassification = {\n  label: string;\n  tone: \"overdue\" | \"today\" | \"tomorrow\" | \"future\" | \"done\";\n};\n\nfunction classifyDue(\n  dueAt: string,\n  isCompleted: boolean,\n  t: ContactsT,\n  locale?: string,\n): DueClassification {\n  if (isCompleted) {\n    return {\n      label: t(\"task_due\", { date: formatDueDate(dueAt, locale) }),\n      tone: \"done\",\n    };\n  }\n  const due = isAllDay(dueAt)\n    ? startOfLocalDay(dueAt)\n    : startOfLocalDay(new Date(dueAt));\n  const today = startOfLocalDay(new Date());\n  const tomorrow = new Date(today);\n  tomorrow.setDate(today.getDate() + 1);\n\n  const dueTime = due.getTime();\n  if (dueTime < today.getTime()) {\n    return {\n      label: t(\"task_overdue_due\", { date: formatDueDate(dueAt, locale) }),\n      tone: \"overdue\",\n    };\n  }\n  if (dueTime === today.getTime())\n    return { label: t(\"quick_today\"), tone: \"today\" };\n  if (dueTime === tomorrow.getTime())\n    return { label: t(\"quick_tomorrow\"), tone: \"tomorrow\" };\n  return { label: formatDueDate(dueAt, locale), tone: \"future\" };\n}\n\nconst DUE_TONE_CLASS: Record<DueClassification[\"tone\"], string> = {\n  overdue: \"bg-destructive/10 text-destructive\",\n  today: \"bg-primary/10 text-primary\",\n  tomorrow: \"bg-primary/10 text-primary\",\n  future: \"bg-muted text-muted-foreground\",\n  done: \"bg-muted text-muted-foreground\",\n};\n\n// ---------------------------------------------------------------------------\n// Task card\n// ---------------------------------------------------------------------------\n\ninterface TaskCardProps {\n  task: ContactTask;\n  toggleCompletion: ReturnType<typeof useToggleTaskCompletion>;\n  onEdit: (task: ContactTask) => void;\n  onDeleteClick: (task: ContactTask) => void;\n}\n\nfunction TaskCard({\n  task,\n  toggleCompletion,\n  onEdit,\n  onDeleteClick,\n}: TaskCardProps) {\n  const { t, locale } = useContactsTranslation();\n  const { isMobile } = useSidebar();\n  const [actionsOpen, setActionsOpen] = useState(false);\n  const isCompleted = !!task.completed_at;\n\n  const { title, body: bodyText } = parseTaskBody(task.body ?? \"\");\n\n  const timestamp = task.created_at\n    ? formatRelativeTime(task.created_at, t)\n    : \"\";\n  const due = task.due_at\n    ? classifyDue(task.due_at, isCompleted, t, locale)\n    : null;\n\n  return (\n    <div\n      role=\"button\"\n      tabIndex={0}\n      onClick={() => onEdit(task)}\n      onKeyDown={(e) => {\n        if (e.key === \"Enter\" || e.key === \" \") {\n          e.preventDefault();\n          onEdit(task);\n        }\n      }}\n      className=\"group border-border/50 hover:border-foreground/20 hover:bg-muted/40 relative cursor-pointer rounded-xl border p-4 transition-all hover:shadow-sm\"\n    >\n      <div className=\"flex items-start gap-3\">\n        {/* Checkbox */}\n        <button\n          type=\"button\"\n          onClick={(e) => {\n            e.stopPropagation();\n            toggleCompletion.mutate({\n              taskId: task.id,\n              isCompleted: isCompleted,\n            });\n          }}\n          disabled={toggleCompletion.isPending}\n          className=\"mt-0.5 shrink-0 transition-transform hover:scale-110 disabled:cursor-not-allowed disabled:opacity-50\"\n          aria-label={isCompleted ? t(\"mark_as_open\") : t(\"mark_as_completed\")}\n        >\n          {isCompleted ? (\n            <CircleCheck className=\"text-primary size-5\" aria-hidden=\"true\" />\n          ) : (\n            <div className=\"border-muted-foreground/40 group-hover:border-primary size-5 rounded-full border-2 transition-colors\" />\n          )}\n        </button>\n\n        {/* Content */}\n        <div className=\"min-w-0 flex-1\">\n          <h4\n            className={cn(\n              \"text-foreground line-clamp-2 text-sm leading-snug font-semibold\",\n              isCompleted && \"text-muted-foreground line-through\",\n            )}\n          >\n            {title}\n          </h4>\n\n          {/* Body text */}\n          {bodyText && (\n            <p\n              className={cn(\n                \"text-muted-foreground mt-1 line-clamp-2 text-xs leading-relaxed\",\n                isCompleted && \"line-through\",\n              )}\n            >\n              {bodyText}\n            </p>\n          )}\n\n          {/* Meta row */}\n          {(due || timestamp) && (\n            <div className=\"mt-2.5 flex flex-wrap items-center gap-1.5\">\n              {due && (\n                <span\n                  className={cn(\n                    \"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium\",\n                    DUE_TONE_CLASS[due.tone],\n                  )}\n                >\n                  <Calendar className=\"size-3\" aria-hidden=\"true\" />\n                  {due.label}\n                </span>\n              )}\n              {timestamp && (\n                <span className=\"text-muted-foreground/60 text-xs\">\n                  {timestamp}\n                </span>\n              )}\n            </div>\n          )}\n        </div>\n      </div>\n\n      {/* Hover-revealed menu */}\n      <div\n        className={cn(\n          \"absolute top-3 right-3 transition-opacity\",\n          isMobile\n            ? \"opacity-100\"\n            : \"opacity-0 group-hover:opacity-100 focus-within:opacity-100\",\n        )}\n      >\n        {isMobile ? (\n          <>\n            <Button\n              variant=\"ghost\"\n              size=\"icon-xs\"\n              onClick={(e) => {\n                e.stopPropagation();\n                setActionsOpen(true);\n              }}\n              aria-label={t(\"task_actions\")}\n            >\n              <EllipsisVertical className=\"size-4\" />\n            </Button>\n            <MobileActionSheet\n              open={actionsOpen}\n              onOpenChange={setActionsOpen}\n              title={t(\"task_actions\")}\n              actions={[\n                {\n                  id: \"delete\",\n                  label: t(\"delete\"),\n                  variant: \"destructive\",\n                  onSelect: () => onDeleteClick(task),\n                },\n              ]}\n            />\n          </>\n        ) : (\n          <DropdownMenu>\n            <DropdownMenuTrigger asChild>\n              <Button\n                variant=\"ghost\"\n                size=\"icon-xs\"\n                onClick={(e) => e.stopPropagation()}\n                aria-label={t(\"task_actions\")}\n              >\n                <EllipsisVertical className=\"size-4\" />\n              </Button>\n            </DropdownMenuTrigger>\n            <DropdownMenuContent align=\"end\">\n              <DropdownMenuItem\n                className=\"text-destructive\"\n                onClick={(e) => {\n                  e.stopPropagation();\n                  onDeleteClick(task);\n                }}\n              >\n                {t(\"delete\")}\n              </DropdownMenuItem>\n            </DropdownMenuContent>\n          </DropdownMenu>\n        )}\n      </div>\n    </div>\n  );\n}\n\n// ---------------------------------------------------------------------------\n// Main component\n// ---------------------------------------------------------------------------\n\nexport interface TaskListProps {\n  tasks: ContactTask[];\n  isLoading?: boolean;\n  contactId: string;\n  /**\n   * Retained for backwards compatibility — currently has no effect since the\n   * inline composer always renders above the list. Will be removed once all\n   * consumers stop passing it.\n   */\n  hideHeader?: boolean;\n}\n\nexport function TaskList({\n  tasks,\n  isLoading,\n  contactId,\n}: TaskListProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const { isMobile } = useSidebar();\n  const [taskToDelete, setTaskToDelete] = useState<ContactTask | null>(null);\n  const [editingTask, setEditingTask] = useState<ContactTask | null>(null);\n\n  const toggleCompletion = useToggleTaskCompletion(contactId);\n  const deleteTask = useDeleteContactTask(contactId, {\n    onSuccess: () => setTaskToDelete(null),\n  });\n  const updateTask = useUpdateContactTask(contactId, {\n    onSuccess: () => setEditingTask(null),\n  });\n\n  const handleSave = (data: {\n    title: string;\n    body: string;\n    dueDate?: string;\n  }) => {\n    if (!editingTask) return;\n    const taskBody = data.body ? `${data.title}\\n\\n${data.body}` : data.title;\n    updateTask.mutate({\n      taskId: editingTask.id,\n      input: { body: taskBody, due_at: data.dueDate ?? null },\n    });\n  };\n\n  const editingParsed = editingTask\n    ? parseTaskBody(editingTask.body ?? \"\")\n    : null;\n\n  const handleModalOpenChange = (open: boolean) => {\n    if (!open) setEditingTask(null);\n  };\n\n  if (isLoading) {\n    return (\n      <div className=\"flex flex-col gap-3\">\n        {[1, 2, 3].map((i) => (\n          <div\n            key={i}\n            className=\"border-border/50 bg-muted/50 h-32 animate-pulse rounded-xl border\"\n          />\n        ))}\n      </div>\n    );\n  }\n\n  if (tasks.length === 0) return <></>;\n\n  return (\n    <div className=\"space-y-4\">\n      <div className=\"flex flex-col gap-3\">\n        {tasks.map((task) => (\n          <TaskCard\n            key={task.id}\n            task={task}\n            toggleCompletion={toggleCompletion}\n            onEdit={setEditingTask}\n            onDeleteClick={setTaskToDelete}\n          />\n        ))}\n      </div>\n\n      {/* Edit modal — create flow lives in InlineTaskComposer */}\n      <NoteTaskModal\n        key={editingTask?.id ?? \"edit\"}\n        open={editingTask !== null}\n        onOpenChange={handleModalOpenChange}\n        mode=\"edit\"\n        type=\"task\"\n        initialTitle={editingParsed?.title ?? \"\"}\n        initialBody={editingParsed?.body ?? \"\"}\n        initialDueDate={editingTask?.due_at ?? undefined}\n        showDueDate\n        onSave={handleSave}\n        isPending={updateTask.isPending}\n        isCompleted={editingTask ? !!editingTask.completed_at : undefined}\n        onToggleComplete={\n          editingTask\n            ? () =>\n                toggleCompletion.mutate(\n                  {\n                    taskId: editingTask.id,\n                    isCompleted: !!editingTask.completed_at,\n                  },\n                  { onSuccess: () => setEditingTask(null) },\n                )\n            : undefined\n        }\n        isTogglePending={toggleCompletion.isPending}\n      />\n\n      {/* Delete confirmation modal */}\n      <ResponsiveDialog\n        open={taskToDelete !== null}\n        onOpenChange={(open) => {\n          if (!open) setTaskToDelete(null);\n        }}\n        title={t(\"delete_task_title\")}\n        description={t(\"delete_task_confirm\")}\n        role=\"alertdialog\"\n        presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n        size=\"compact\"\n      >\n        <DialogFooter>\n          <Button variant=\"secondary\" onClick={() => setTaskToDelete(null)}>\n            {t(\"cancel\")}\n          </Button>\n          <Button\n            variant=\"destructive\"\n            onClick={() => {\n              if (taskToDelete) {\n                deleteTask.mutate(taskToDelete.id);\n              }\n            }}\n          >\n            {t(\"delete\")}\n          </Button>\n        </DialogFooter>\n      </ResponsiveDialog>\n    </div>\n  );\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useTasksApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\nimport type { CreateTaskInput } from \"@fluid-app/contacts-core/types\";\n\nexport type { CreateTaskInput };\n\nexport function useCreateContactTask(\n  contactId: string,\n  options?: { onSuccess?: () => void },\n) {\n  const queryClient = useQueryClient();\n  const api = useTasksApi();\n  const { t } = useContactsTranslation();\n\n  return useMutation({\n    mutationFn: (input: CreateTaskInput) => api.createTask(contactId, input),\n    onSuccess: () => {\n      fluidToast({ title: t(\"task_created\"), type: \"success\" });\n      queryClient.invalidateQueries({\n        queryKey: contactsKeys.tasks(contactId),\n      });\n      options?.onSuccess?.();\n    },\n    onError: (error) => {\n      const description = parseApiErrors(error);\n      fluidToast({\n        title: t(\"task_create_failed\"),\n        type: \"error\",\n        ...(description != null && { description }),\n      });\n    },\n  });\n}\n","\"use client\";\n\nimport React, { useState } from \"react\";\nimport { Plus } from \"lucide-react\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { useCreateContactTask } from \"../../hooks/contacts/use-create-contact-task\";\nimport { TaskComposerForm } from \"./task-composer-form\";\n\nexport interface InlineTaskComposerProps {\n  contactId: string;\n}\n\nexport function InlineTaskComposer({\n  contactId,\n}: InlineTaskComposerProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const [isOpen, setIsOpen] = useState(false);\n  const close = () => setIsOpen(false);\n  const createTask = useCreateContactTask(contactId, { onSuccess: close });\n\n  if (!isOpen) {\n    return (\n      <button\n        type=\"button\"\n        onClick={() => setIsOpen(true)}\n        className=\"border-border/50 text-muted-foreground hover:border-foreground/30 hover:bg-muted/40 hover:text-foreground flex w-full items-center gap-3 rounded-xl border border-dashed px-5 py-4 text-sm font-medium transition-colors\"\n      >\n        <Plus className=\"size-4\" aria-hidden=\"true\" />\n        {t(\"new_task\")}\n      </button>\n    );\n  }\n\n  return (\n    <TaskComposerForm\n      onSubmit={(values) => createTask.mutate(values)}\n      isSubmitting={createTask.isPending}\n      onClose={close}\n    />\n  );\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useNotesApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\n\nexport function useDeleteContactNote(\n  contactId: string,\n  options?: { onSuccess?: () => void },\n) {\n  const queryClient = useQueryClient();\n  const api = useNotesApi();\n  const { t } = useContactsTranslation();\n\n  return useMutation({\n    mutationFn: (noteId: number) => api.deleteNote(noteId, contactId),\n    onSuccess: () => {\n      fluidToast({ title: t(\"note_deleted\"), type: \"success\" });\n      queryClient.invalidateQueries({\n        queryKey: contactsKeys.notes(contactId),\n      });\n      options?.onSuccess?.();\n    },\n    onError: (error) => {\n      fluidToast({\n        title: t(\"note_delete_failed\"),\n        type: \"error\",\n        description: parseApiErrors(error),\n      });\n    },\n  });\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useNotesApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\nimport type { UpdateNoteInput } from \"@fluid-app/contacts-core/types\";\n\nexport type { UpdateNoteInput };\n\nexport function useUpdateContactNote(\n  contactId: string,\n  options?: { onSuccess?: () => void },\n) {\n  const queryClient = useQueryClient();\n  const api = useNotesApi();\n  const { t } = useContactsTranslation();\n\n  return useMutation({\n    mutationFn: ({\n      noteId,\n      input,\n    }: {\n      noteId: number;\n      input: UpdateNoteInput;\n    }) => api.updateNote(noteId, contactId, input),\n    onSuccess: () => {\n      fluidToast({ title: t(\"note_updated\"), type: \"success\" });\n      queryClient.invalidateQueries({\n        queryKey: contactsKeys.notes(contactId),\n      });\n      options?.onSuccess?.();\n    },\n    onError: (error) => {\n      fluidToast({\n        title: t(\"note_update_failed\"),\n        type: \"error\",\n        description: parseApiErrors(error),\n      });\n    },\n  });\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useNotesApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\nimport type { CreateNoteInput } from \"@fluid-app/contacts-core/types\";\n\nexport type { CreateNoteInput };\n\nexport function useCreateContactNote(\n  contactId: string,\n  options?: { onSuccess?: () => void },\n) {\n  const queryClient = useQueryClient();\n  const api = useNotesApi();\n  const { t } = useContactsTranslation();\n\n  return useMutation({\n    mutationFn: (input: CreateNoteInput) => api.createNote(contactId, input),\n    onSuccess: () => {\n      fluidToast({ title: t(\"note_created\"), type: \"success\" });\n      queryClient.invalidateQueries({\n        queryKey: contactsKeys.notes(contactId),\n      });\n      options?.onSuccess?.();\n    },\n    onError: (error) => {\n      fluidToast({\n        title: t(\"note_create_failed\"),\n        type: \"error\",\n        description: parseApiErrors(error),\n      });\n    },\n  });\n}\n","\"use client\";\n\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { cn } from \"@fluid-app/ui-primitives\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { useCreateContactNote } from \"../../hooks/notes/use-create-contact-note\";\n\nexport interface InlineNoteComposerProps {\n  contactId: string;\n}\n\nfunction detectMacPlatform(): boolean {\n  if (typeof navigator === \"undefined\") return false;\n  // Prefer userAgentData.platform when available (modern Chromium); fall back\n  // to userAgent string. navigator.platform is deprecated.\n  const uaData = (\n    navigator as Navigator & {\n      userAgentData?: { platform?: string };\n    }\n  ).userAgentData;\n  const platform = uaData?.platform ?? navigator.userAgent ?? \"\";\n  return /Mac|iPhone|iPad/i.test(platform);\n}\n\nexport function InlineNoteComposer({\n  contactId,\n}: InlineNoteComposerProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const [body, setBody] = useState(\"\");\n  const [isFocused, setIsFocused] = useState(false);\n  const [isMac, setIsMac] = useState(false);\n  const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n  // Detect platform on mount only — avoids SSR hydration mismatch from reading\n  // navigator at module load.\n  useEffect(() => {\n    setIsMac(detectMacPlatform());\n  }, []);\n\n  const createNote = useCreateContactNote(contactId, {\n    onSuccess: () => {\n      setBody(\"\");\n      textareaRef.current?.blur();\n    },\n  });\n\n  const submit = () => {\n    const trimmed = body.trim();\n    if (!trimmed || createNote.isPending) return;\n    const firstLine = trimmed.split(\"\\n\")[0]?.slice(0, 120) ?? \"Note\";\n    createNote.mutate({ title: firstLine, body: trimmed });\n  };\n\n  const canSubmit = body.trim().length > 0 && !createNote.isPending;\n\n  return (\n    <div\n      className={cn(\n        \"border-border/50 focus-within:border-foreground/30 rounded-2xl border p-4 transition-colors\",\n        isFocused && \"border-foreground/30\",\n      )}\n    >\n      <textarea\n        ref={textareaRef}\n        value={body}\n        onChange={(e) => setBody(e.target.value)}\n        onFocus={() => setIsFocused(true)}\n        onBlur={() => setIsFocused(false)}\n        onKeyDown={(e) => {\n          if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n            e.preventDefault();\n            submit();\n          }\n        }}\n        placeholder={t(\"note_placeholder\")}\n        aria-label={t(\"note_body_aria\")}\n        rows={3}\n        className=\"placeholder:text-muted-foreground text-foreground min-h-[80px] w-full resize-none border-0 bg-transparent text-sm leading-relaxed outline-none\"\n      />\n      <div className=\"mt-3 flex items-center justify-between gap-3\">\n        <span className=\"text-muted-foreground text-xs\">\n          {isMac ? t(\"tip_save_shortcut_mac\") : t(\"tip_save_shortcut_other\")}\n        </span>\n        <button\n          type=\"button\"\n          onClick={submit}\n          disabled={!canSubmit}\n          className=\"bg-primary text-primary-foreground hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground inline-flex shrink-0 items-center gap-1.5 rounded-full px-4 py-1.5 text-xs font-semibold transition-colors disabled:cursor-not-allowed\"\n        >\n          {createNote.isPending ? t(\"adding\") : t(\"add_note\")}\n        </button>\n      </div>\n    </div>\n  );\n}\n","\"use client\";\n\nimport React, { useState } from \"react\";\nimport { Calendar, Paperclip, EllipsisVertical } from \"lucide-react\";\nimport {\n  Button,\n  cn,\n  DialogFooter,\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from \"@fluid-app/ui-primitives\";\nimport { MobileActionSheet } from \"@fluid-app/ui-components/components/MobileActionSheet\";\nimport { ResponsiveDialog } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport type { ContactNote } from \"../../hooks/notes/use-contact-notes\";\nimport { useDeleteContactNote } from \"../../hooks/notes/use-delete-contact-note\";\nimport { useUpdateContactNote } from \"../../hooks/notes/use-update-contact-note\";\nimport { NoteTaskModal } from \"../editor/note-task-modal\";\nimport { InlineNoteComposer } from \"./inline-note-composer\";\n\n// ---------------------------------------------------------------------------\n// Date helpers\n// ---------------------------------------------------------------------------\n\nfunction formatDueDate(dateStr: string): string {\n  const date = new Date(dateStr);\n  return date.toLocaleDateString(\"en-US\", {\n    month: \"short\",\n    day: \"numeric\",\n    year: \"numeric\",\n  });\n}\n\ntype ContactsT = ReturnType<typeof useContactsTranslation>[\"t\"];\n\nfunction formatRelativeNote(dateStr: string, t: ContactsT): string {\n  const date = new Date(dateStr);\n  const now = new Date();\n  const diffMs = now.getTime() - date.getTime();\n  const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));\n\n  if (diffDays === 0) {\n    return date.toLocaleTimeString(\"en-US\", {\n      hour: \"numeric\",\n      minute: \"2-digit\",\n    });\n  }\n  if (diffDays === 1) return t(\"task_yesterday\");\n  if (diffDays < 7) return t(\"task_days_ago_other\", { count: diffDays });\n  return formatDueDate(dateStr);\n}\n\n// ---------------------------------------------------------------------------\n// Note card\n// ---------------------------------------------------------------------------\n\nfunction NoteCard({\n  note,\n  onEdit,\n  onDelete,\n}: {\n  note: ContactNote;\n  onEdit: (note: ContactNote) => void;\n  onDelete: (note: ContactNote) => void;\n}) {\n  const { t } = useContactsTranslation();\n  const { isMobile } = useSidebar();\n  const [actionsOpen, setActionsOpen] = useState(false);\n  const assetCount = note.assets?.length ?? 0;\n  const showTitle =\n    !!note.title?.trim() && note.title.trim() !== note.body?.trim();\n  const dueDateValue = note.due_at ?? note.due_date ?? null;\n  const createdLabel = note.created_at\n    ? formatRelativeNote(note.created_at, t)\n    : null;\n\n  return (\n    <div\n      role=\"button\"\n      tabIndex={0}\n      onClick={() => onEdit(note)}\n      onKeyDown={(e) => {\n        if (e.key === \"Enter\" || e.key === \" \") {\n          e.preventDefault();\n          onEdit(note);\n        }\n      }}\n      className=\"group border-border/50 hover:border-foreground/20 hover:bg-muted/40 relative cursor-pointer rounded-xl border p-4 transition-all hover:shadow-sm\"\n    >\n      {showTitle && (\n        <h4 className=\"text-foreground line-clamp-1 text-sm font-semibold\">\n          {note.title}\n        </h4>\n      )}\n\n      <p\n        className={cn(\n          \"text-foreground line-clamp-4 text-sm leading-relaxed whitespace-pre-wrap\",\n          showTitle && \"text-muted-foreground mt-1\",\n        )}\n      >\n        {note.body}\n      </p>\n\n      {(createdLabel || dueDateValue || assetCount > 0) && (\n        <div className=\"mt-2.5 flex flex-wrap items-center gap-3\">\n          {createdLabel && (\n            <span className=\"text-muted-foreground/70 text-xs\">\n              {createdLabel}\n            </span>\n          )}\n          {dueDateValue && (\n            <span className=\"bg-primary/10 text-primary inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium\">\n              <Calendar className=\"size-3\" aria-hidden=\"true\" />\n              {t(\"task_due\", { date: formatDueDate(dueDateValue) })}\n            </span>\n          )}\n          {assetCount > 0 && (\n            <span className=\"text-muted-foreground inline-flex items-center gap-1 text-xs\">\n              <Paperclip className=\"size-3\" aria-hidden=\"true\" />\n              {assetCount === 1\n                ? t(\"attachment_one\")\n                : t(\"attachment_other\", { count: assetCount })}\n            </span>\n          )}\n        </div>\n      )}\n\n      <div\n        className={cn(\n          \"absolute top-3 right-3 transition-opacity\",\n          isMobile\n            ? \"opacity-100\"\n            : \"opacity-0 group-hover:opacity-100 focus-within:opacity-100\",\n        )}\n      >\n        {isMobile ? (\n          <>\n            <Button\n              variant=\"ghost\"\n              size=\"icon-xs\"\n              onClick={(e) => {\n                e.stopPropagation();\n                setActionsOpen(true);\n              }}\n              aria-label={t(\"note_actions\")}\n            >\n              <EllipsisVertical className=\"size-4\" />\n            </Button>\n            <MobileActionSheet\n              open={actionsOpen}\n              onOpenChange={setActionsOpen}\n              title={t(\"note_actions\")}\n              actions={[\n                {\n                  id: \"delete\",\n                  label: t(\"delete\"),\n                  variant: \"destructive\",\n                  onSelect: () => onDelete(note),\n                },\n              ]}\n            />\n          </>\n        ) : (\n          <DropdownMenu>\n            <DropdownMenuTrigger asChild>\n              <Button\n                variant=\"ghost\"\n                size=\"icon-xs\"\n                onClick={(e) => e.stopPropagation()}\n                aria-label={t(\"note_actions\")}\n              >\n                <EllipsisVertical className=\"size-4\" />\n              </Button>\n            </DropdownMenuTrigger>\n            <DropdownMenuContent align=\"end\">\n              <DropdownMenuItem\n                className=\"text-destructive\"\n                onClick={(e) => {\n                  e.stopPropagation();\n                  onDelete(note);\n                }}\n              >\n                {t(\"delete\")}\n              </DropdownMenuItem>\n            </DropdownMenuContent>\n          </DropdownMenu>\n        )}\n      </div>\n    </div>\n  );\n}\n\n// ---------------------------------------------------------------------------\n// Main component\n// ---------------------------------------------------------------------------\n\nexport interface NotesListProps {\n  notes: ContactNote[];\n  isLoading?: boolean;\n  contactId: string;\n}\n\nexport function NotesList({\n  notes,\n  isLoading,\n  contactId,\n}: NotesListProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const { isMobile } = useSidebar();\n  const [noteToDelete, setNoteToDelete] = useState<ContactNote | null>(null);\n  const [editingNote, setEditingNote] = useState<ContactNote | null>(null);\n\n  const deleteNote = useDeleteContactNote(contactId, {\n    onSuccess: () => setNoteToDelete(null),\n  });\n  const updateNote = useUpdateContactNote(contactId, {\n    onSuccess: () => setEditingNote(null),\n  });\n\n  const handleEditSave = (data: { title: string; body: string }) => {\n    if (!editingNote) return;\n    updateNote.mutate({\n      noteId: editingNote.id,\n      input: { title: data.title, body: data.body },\n    });\n  };\n\n  return (\n    <div className=\"space-y-4\">\n      <InlineNoteComposer contactId={contactId} />\n\n      {isLoading ? (\n        <div className=\"flex flex-col gap-3\">\n          {[1, 2, 3].map((i) => (\n            <div\n              key={i}\n              className=\"border-border/50 bg-muted/50 h-20 animate-pulse rounded-xl border\"\n            />\n          ))}\n        </div>\n      ) : notes.length === 0 ? null : (\n        <div className=\"flex flex-col gap-3\">\n          {notes.map((note) => (\n            <NoteCard\n              key={note.id}\n              note={note}\n              onEdit={setEditingNote}\n              onDelete={setNoteToDelete}\n            />\n          ))}\n        </div>\n      )}\n\n      {/* Edit modal — create flow now lives in InlineNoteComposer */}\n      <NoteTaskModal\n        key={editingNote?.id ?? \"edit\"}\n        open={editingNote !== null}\n        onOpenChange={(open) => {\n          if (!open) setEditingNote(null);\n        }}\n        mode=\"edit\"\n        type=\"note\"\n        initialTitle={editingNote?.title ?? \"\"}\n        initialBody={editingNote?.body ?? \"\"}\n        onSave={handleEditSave}\n        isPending={updateNote.isPending}\n      />\n\n      {/* Delete confirmation */}\n      <ResponsiveDialog\n        open={!!noteToDelete}\n        onOpenChange={(open) => {\n          if (!open) setNoteToDelete(null);\n        }}\n        title={t(\"delete_note_title\")}\n        description={t(\"delete_note_irreversible\")}\n        role=\"alertdialog\"\n        presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n        size=\"compact\"\n      >\n        <DialogFooter>\n          <Button variant=\"secondary\" onClick={() => setNoteToDelete(null)}>\n            {t(\"cancel\")}\n          </Button>\n          <Button\n            variant=\"destructive\"\n            onClick={() => {\n              if (noteToDelete) {\n                deleteNote.mutate(noteToDelete.id);\n              }\n            }}\n          >\n            {t(\"delete\")}\n          </Button>\n        </DialogFooter>\n      </ResponsiveDialog>\n    </div>\n  );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { cn } from \"@fluid-app/ui-primitives\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { TaskList } from \"../../tasks/task-list\";\nimport { InlineTaskComposer } from \"../../tasks/inline-task-composer\";\nimport { NotesList } from \"../../notes/notes-list\";\nimport type { ContactTask } from \"../../../hooks/contacts/use-contact-tasks\";\nimport type { ContactNote } from \"../../../hooks/notes/use-contact-notes\";\n\nconst VISIBLE_TABS = [\"Tasks\", \"Notes\"] as const;\nexport type TabType = (typeof VISIBLE_TABS)[number];\n\nexport interface ContactDetailTabsProps {\n  contactId: string;\n  tasks: ContactTask[];\n  isLoadingTasks: boolean;\n  notes: ContactNote[];\n  isLoadingNotes: boolean;\n  activeTab: TabType;\n  onTabChange: (tab: TabType) => void;\n}\n\nexport function ContactDetailTabs({\n  contactId,\n  tasks,\n  isLoadingTasks,\n  notes,\n  isLoadingNotes,\n  activeTab,\n  onTabChange,\n}: ContactDetailTabsProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const tabLabels: Record<TabType, string> = {\n    Tasks: t(\"tab_tasks\"),\n    Notes: t(\"tab_notes\"),\n  };\n  return (\n    <div className=\"mt-8\">\n      <div className=\"border-border/50 flex items-center gap-1 border-b\">\n        {VISIBLE_TABS.map((tab) => {\n          const count = tab === \"Tasks\" ? tasks.length : notes.length;\n          const isActive = activeTab === tab;\n          return (\n            <button\n              key={tab}\n              type=\"button\"\n              onClick={() => onTabChange(tab)}\n              className={cn(\n                \"relative flex items-center gap-1.5 px-3 py-2.5 text-sm font-semibold transition-colors\",\n                isActive\n                  ? \"text-foreground\"\n                  : \"text-muted-foreground hover:text-foreground\",\n              )}\n            >\n              {tabLabels[tab]}\n              <span\n                className={cn(\n                  \"rounded-full px-1.5 text-xs leading-5 font-bold\",\n                  isActive\n                    ? \"bg-primary text-primary-foreground\"\n                    : \"bg-muted text-muted-foreground\",\n                )}\n              >\n                {count}\n              </span>\n              {isActive && (\n                <span\n                  className=\"bg-primary absolute inset-x-0 -bottom-px h-0.5\"\n                  aria-hidden=\"true\"\n                />\n              )}\n            </button>\n          );\n        })}\n      </div>\n\n      <div className=\"pt-6\">\n        {activeTab === \"Tasks\" && (\n          <div className=\"space-y-4\">\n            <InlineTaskComposer contactId={contactId} />\n            <TaskList\n              tasks={tasks}\n              isLoading={isLoadingTasks}\n              contactId={contactId}\n              hideHeader\n            />\n          </div>\n        )}\n\n        {activeTab === \"Notes\" && (\n          <NotesList\n            notes={notes}\n            isLoading={isLoadingNotes}\n            contactId={contactId}\n          />\n        )}\n      </div>\n    </div>\n  );\n}\n","\"use client\";\n\nimport React, { useCallback, useState } from \"react\";\nimport { FormProvider } from \"react-hook-form\";\nimport {\n  ChevronLeft,\n  Mail,\n  MoreHorizontal,\n  Pencil,\n  Phone,\n  Trash2,\n} from \"lucide-react\";\nimport {\n  Button,\n  cn,\n  DialogFooter,\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n  Spinner,\n  fluidToast,\n} from \"@fluid-app/ui-primitives\";\nimport { MobileActionSheet } from \"@fluid-app/ui-components/components/MobileActionSheet\";\nimport { ResponsiveDialog } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { ContactDetailsForm } from \"../../../../shared/components/contacts/contactDetailsForm\";\nimport { useContactDetailPage } from \"../../../../shared/hooks/useContactDetailPage\";\nimport { useContactTasks } from \"../../../hooks/contacts/use-contact-tasks\";\nimport { useContactNotes } from \"../../../hooks/notes/use-contact-notes\";\nimport { useCreateGroup } from \"../../../hooks/groups/use-create-group\";\nimport { useGroups } from \"../../../hooks/groups/use-groups\";\nimport { useUpdateContactTags } from \"../../../hooks/groups/use-update-contact-tags\";\nimport { ContactDetailHero } from \"./ContactDetailHero\";\nimport { ContactInfoRow } from \"./ContactInfoRow\";\nimport { ContactDetailTabs, type TabType } from \"./ContactDetailTabs\";\nimport { getDisplayName } from \"./utils\";\n\nexport interface ContactDetailPaneProps {\n  contactId: string;\n  queryKeyPrefix: string;\n  countriesQueryKey?: readonly unknown[];\n  getCountries: () => Promise<{ id: number; name: string; iso?: string }[]>;\n  /** Callback to clear selection (used by mobile back button + on delete). */\n  onBack: () => void;\n  showMobileBackButton?: boolean;\n}\n\nexport function ContactDetailPane({\n  contactId,\n  queryKeyPrefix,\n  countriesQueryKey,\n  getCountries,\n  onBack,\n  showMobileBackButton = true,\n}: ContactDetailPaneProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const { isMobile } = useSidebar();\n  const {\n    contact,\n    isLoading,\n    methods,\n    countryOptions,\n    isDirty,\n    isSubmitting,\n    isDeleting,\n    onSave,\n    onDelete,\n  } = useContactDetailPage(contactId, {\n    queryKeyPrefix,\n    countriesQueryKey,\n    getCountries,\n    onDeleteSuccess: onBack,\n    onSaveSuccess: () => setEditProfileOpen(false),\n  });\n\n  const { data: tasks = [], isLoading: isLoadingTasks } =\n    useContactTasks(contactId);\n  const { data: notes = [], isLoading: isLoadingNotes } =\n    useContactNotes(contactId);\n\n  const { data: groups = [] } = useGroups();\n  const updateTagsMutation = useUpdateContactTags(contactId, queryKeyPrefix, {\n    onError: (error) => {\n      fluidToast({\n        title: t(\"groups_tags_save_failed\"),\n        description: parseApiErrors(error),\n        type: \"error\",\n      });\n    },\n  });\n  const createGroupMutation = useCreateGroup();\n\n  const [confirmDelete, setConfirmDelete] = useState(false);\n  const [activeTab, setActiveTab] = useState<TabType>(\"Tasks\");\n  const [editProfileOpen, setEditProfileOpen] = useState(false);\n\n  // Close the dialog before dispatching: on success the pane unmounts via\n  // onDeleteSuccess; on a non-throwing failure the dialog would otherwise\n  // dangle open with the toast already shown.\n  const handleConfirmDelete = useCallback(() => {\n    setConfirmDelete(false);\n    onDelete();\n  }, [onDelete]);\n\n  if (isLoading) {\n    return (\n      <ContactDetailSkeleton\n        onBack={onBack}\n        showMobileBackButton={showMobileBackButton}\n      />\n    );\n  }\n\n  if (!contact) {\n    return (\n      <div className=\"flex h-full flex-1 flex-col\">\n        <DetailTopBar\n          onBack={onBack}\n          phone={null}\n          email={null}\n          onDelete={null}\n          onEditProfile={null}\n          showMobileBackButton={showMobileBackButton}\n        />\n        <div className=\"mx-auto flex max-w-md flex-col items-center px-6 py-16 text-center\">\n          <h2 className=\"text-foreground text-base font-semibold\">\n            {t(\"error_loading\")}\n          </h2>\n          <p className=\"text-muted-foreground mt-2 text-sm\">\n            {t(\"error_loading_description\")}\n          </p>\n        </div>\n      </div>\n    );\n  }\n\n  const fullName = getDisplayName(contact, t);\n\n  return (\n    <FormProvider {...methods}>\n      <div className=\"flex h-full flex-1 flex-col\">\n        <DetailTopBar\n          onBack={onBack}\n          phone={contact.phone ?? null}\n          email={contact.email ?? null}\n          onDelete={() => setConfirmDelete(true)}\n          onEditProfile={() => setEditProfileOpen(true)}\n          showMobileBackButton={showMobileBackButton}\n        />\n\n        <div className=\"flex-1 overflow-y-auto\">\n          <div className=\"mx-auto w-full max-w-[900px] px-6 pt-8 pb-16 md:px-8 md:pt-10\">\n            <ContactDetailHero\n              contact={contact}\n              tasksCount={tasks.length}\n              notesCount={notes.length}\n              contactTags={Array.isArray(contact.tags) ? contact.tags : []}\n              availableGroups={groups}\n              onTagsSave={(tags) => updateTagsMutation.mutate(tags)}\n              onCreateGroup={async (name) => {\n                await createGroupMutation.mutateAsync({ name });\n              }}\n              isTagsSaving={updateTagsMutation.isPending}\n            />\n            <ContactInfoRow\n              contact={contact}\n              onEditEmpty={() => setEditProfileOpen(true)}\n            />\n            <ContactDetailTabs\n              contactId={contactId}\n              tasks={tasks}\n              isLoadingTasks={isLoadingTasks}\n              notes={notes}\n              isLoadingNotes={isLoadingNotes}\n              activeTab={activeTab}\n              onTabChange={setActiveTab}\n            />\n          </div>\n        </div>\n\n        <ResponsiveDialog\n          open={editProfileOpen}\n          onOpenChange={(open) => {\n            if (!open && isSubmitting) return;\n            setEditProfileOpen(open);\n          }}\n          title={t(\"edit_contact_name\", { name: fullName })}\n          presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n          size=\"wide\"\n        >\n          <ContactDetailsForm countries={countryOptions} />\n          <DialogFooter>\n            <Button\n              type=\"button\"\n              variant=\"secondary\"\n              onClick={() => setEditProfileOpen(false)}\n              disabled={isSubmitting}\n            >\n              {t(\"cancel\")}\n            </Button>\n            <Button\n              type=\"button\"\n              onClick={onSave}\n              disabled={!isDirty || isSubmitting}\n              aria-busy={isSubmitting}\n            >\n              {isSubmitting && <Spinner className=\"size-4\" />}\n              {isSubmitting ? t(\"saving\") : t(\"save_changes\")}\n            </Button>\n          </DialogFooter>\n        </ResponsiveDialog>\n\n        <ResponsiveDialog\n          open={confirmDelete}\n          onOpenChange={setConfirmDelete}\n          title={t(\"delete_name\", { name: fullName })}\n          description={t(\"delete_confirm_permanent\")}\n          role=\"alertdialog\"\n          presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n          size=\"compact\"\n        >\n          <DialogFooter>\n            <Button\n              variant=\"secondary\"\n              onClick={() => setConfirmDelete(false)}\n              disabled={isDeleting}\n            >\n              {t(\"cancel\")}\n            </Button>\n            <Button\n              variant=\"destructive\"\n              onClick={handleConfirmDelete}\n              disabled={isDeleting}\n            >\n              {isDeleting ? t(\"deleting\") : t(\"delete_contact\")}\n            </Button>\n          </DialogFooter>\n        </ResponsiveDialog>\n      </div>\n    </FormProvider>\n  );\n}\n\ninterface DetailTopBarProps {\n  onBack: () => void;\n  phone: string | null;\n  email: string | null;\n  onDelete: (() => void) | null;\n  onEditProfile: (() => void) | null;\n  showMobileBackButton?: boolean;\n}\n\nfunction DetailTopBar({\n  onBack,\n  phone,\n  email,\n  onDelete,\n  onEditProfile,\n  showMobileBackButton = true,\n}: DetailTopBarProps) {\n  const { t } = useContactsTranslation();\n  const { isMobile } = useSidebar();\n  const [actionsOpen, setActionsOpen] = useState(false);\n  return (\n    <div className=\"border-border/50 bg-background/90 sticky top-0 z-10 flex items-center justify-between border-b px-4 py-3 backdrop-blur md:px-8\">\n      <div className=\"flex items-center gap-3\">\n        {showMobileBackButton ? (\n          <button\n            type=\"button\"\n            onClick={onBack}\n            className=\"text-muted-foreground hover:bg-muted hover:text-foreground flex size-8 items-center justify-center rounded-full transition-colors md:hidden\"\n            aria-label={t(\"back_to_contacts\")}\n          >\n            <ChevronLeft className=\"size-4\" />\n          </button>\n        ) : null}\n        <span className=\"text-muted-foreground hidden text-xs font-semibold tracking-widest uppercase md:inline\">\n          {t(\"contact_label\")}\n        </span>\n      </div>\n      <div className=\"flex items-center gap-1\">\n        {onEditProfile && (\n          <button\n            type=\"button\"\n            onClick={onEditProfile}\n            className=\"text-muted-foreground hover:bg-muted hover:text-foreground flex size-8 items-center justify-center rounded-full transition-colors\"\n            aria-label={t(\"edit_profile\")}\n          >\n            <Pencil className=\"size-4\" aria-hidden=\"true\" />\n          </button>\n        )}\n        <ActionLink\n          href={phone ? `tel:${phone}` : null}\n          label={t(\"label_call\")}\n          icon={<Phone className=\"size-4\" aria-hidden=\"true\" />}\n        />\n        <ActionLink\n          href={email ? `mailto:${email}` : null}\n          label={t(\"label_email\")}\n          icon={<Mail className=\"size-4\" aria-hidden=\"true\" />}\n        />\n        {onDelete && (\n          <>\n            <div className=\"bg-border mx-1 h-5 w-px\" aria-hidden=\"true\" />\n            {isMobile ? (\n              <>\n                <button\n                  type=\"button\"\n                  onClick={() => setActionsOpen(true)}\n                  className=\"text-muted-foreground hover:bg-muted hover:text-foreground flex size-8 items-center justify-center rounded-full transition-colors\"\n                  aria-label={t(\"more_actions\")}\n                >\n                  <MoreHorizontal className=\"size-4\" />\n                </button>\n                <MobileActionSheet\n                  open={actionsOpen}\n                  onOpenChange={setActionsOpen}\n                  title={t(\"more_actions\")}\n                  actions={[\n                    {\n                      id: \"delete\",\n                      label: t(\"delete_contact\"),\n                      variant: \"destructive\",\n                      onSelect: onDelete,\n                    },\n                  ]}\n                />\n              </>\n            ) : (\n              <DropdownMenu>\n                <DropdownMenuTrigger asChild>\n                  <button\n                    type=\"button\"\n                    className=\"text-muted-foreground hover:bg-muted hover:text-foreground flex size-8 items-center justify-center rounded-full transition-colors\"\n                    aria-label={t(\"more_actions\")}\n                  >\n                    <MoreHorizontal className=\"size-4\" />\n                  </button>\n                </DropdownMenuTrigger>\n                <DropdownMenuContent align=\"end\">\n                  <DropdownMenuItem\n                    className=\"text-destructive\"\n                    onClick={onDelete}\n                  >\n                    <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n                    {t(\"delete_contact\")}\n                  </DropdownMenuItem>\n                </DropdownMenuContent>\n              </DropdownMenu>\n            )}\n          </>\n        )}\n      </div>\n    </div>\n  );\n}\n\ninterface ActionLinkProps {\n  href: string | null;\n  label: string;\n  icon: React.ReactNode;\n}\n\nfunction ActionLink({ href, label, icon }: ActionLinkProps) {\n  const { t } = useContactsTranslation();\n  const baseClass =\n    \"flex size-8 items-center justify-center rounded-full transition-colors\";\n  if (!href) {\n    return (\n      <span\n        aria-label={t(\"action_unavailable\", { label })}\n        className={cn(baseClass, \"text-muted-foreground/40 cursor-default\")}\n      >\n        {icon}\n      </span>\n    );\n  }\n  return (\n    <a\n      href={href}\n      aria-label={label}\n      className={cn(\n        baseClass,\n        \"text-muted-foreground hover:bg-muted hover:text-foreground\",\n      )}\n    >\n      {icon}\n    </a>\n  );\n}\n\nfunction ContactDetailSkeleton({\n  onBack,\n  showMobileBackButton = true,\n}: {\n  onBack: () => void;\n  showMobileBackButton?: boolean;\n}) {\n  return (\n    <div className=\"flex h-full flex-1 flex-col\">\n      <DetailTopBar\n        onBack={onBack}\n        phone={null}\n        email={null}\n        onDelete={null}\n        onEditProfile={null}\n        showMobileBackButton={showMobileBackButton}\n      />\n      <div className=\"mx-auto w-full max-w-[900px] flex-1 space-y-6 px-6 pt-8 pb-16 md:px-8 md:pt-10\">\n        <div className=\"flex items-start gap-5\">\n          <div className=\"bg-muted size-20 animate-pulse rounded-xl\" />\n          <div className=\"flex-1 space-y-3\">\n            <div className=\"bg-muted h-7 w-48 animate-pulse rounded\" />\n            <div className=\"bg-muted h-4 w-24 animate-pulse rounded\" />\n          </div>\n        </div>\n        <div className=\"bg-muted h-24 animate-pulse rounded-xl\" />\n        <div className=\"bg-muted h-64 animate-pulse rounded-xl\" />\n      </div>\n    </div>\n  );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { Users } from \"lucide-react\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\n\nexport function ContactsEmptyState(): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  return (\n    <div className=\"hidden h-full flex-1 flex-col items-center justify-center px-8 text-center md:flex\">\n      <div className=\"bg-muted text-muted-foreground flex size-16 items-center justify-center rounded-xl\">\n        <Users className=\"size-7\" aria-hidden=\"true\" />\n      </div>\n      <h2 className=\"text-foreground mt-5 text-base font-semibold\">\n        {t(\"empty_select_contact\")}\n      </h2>\n      <p className=\"text-muted-foreground mt-1 max-w-xs text-sm\">\n        {t(\"empty_select_description\")}\n      </p>\n    </div>\n  );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { cn } from \"@fluid-app/ui-primitives\";\nimport type { Contact } from \"@fluid-app/contacts-core/types\";\nimport { ContactsSidebar } from \"./ContactsSidebar\";\nimport { ContactDetailPane } from \"./ContactDetailPane\";\nimport { ContactsEmptyState } from \"./ContactsEmptyState\";\n\nexport interface RepContactsLayoutProps {\n  selectedContactId: string | null;\n  highlightContactId?: string | null;\n  onSelect: (id: string | null) => void;\n  onAdd: () => void;\n  onManageGroups?: () => void;\n  onCreateGroup?: () => void;\n  highlightGroupName?: string | null;\n  onDeleteContact?: (contact: Contact) => void;\n  queryKeyPrefix: string;\n  countriesQueryKey?: readonly unknown[];\n  getCountries: () => Promise<{ id: number; name: string; iso?: string }[]>;\n  showMobileDetailBackButton?: boolean;\n}\n\nexport function RepContactsLayout({\n  selectedContactId,\n  highlightContactId,\n  onSelect,\n  onAdd,\n  onManageGroups,\n  onCreateGroup,\n  highlightGroupName,\n  onDeleteContact,\n  queryKeyPrefix,\n  countriesQueryKey,\n  getCountries,\n  showMobileDetailBackButton = true,\n}: RepContactsLayoutProps): React.JSX.Element {\n  return (\n    <div className=\"bg-background flex h-full overflow-hidden\">\n      <aside\n        className={cn(\n          \"border-border/50 bg-background w-full shrink-0 overflow-hidden border-r md:flex md:w-[420px] md:flex-col\",\n          selectedContactId ? \"hidden\" : \"flex flex-col\",\n        )}\n      >\n        <ContactsSidebar\n          selectedContactId={selectedContactId}\n          highlightContactId={highlightContactId}\n          onSelect={onSelect}\n          onAdd={onAdd}\n          onManageGroups={onManageGroups}\n          onCreateGroup={onCreateGroup}\n          highlightGroupName={highlightGroupName}\n          onDeleteContact={onDeleteContact}\n        />\n      </aside>\n\n      <main\n        className={cn(\n          \"bg-background relative flex-1 md:flex md:flex-col\",\n          selectedContactId ? \"flex flex-col\" : \"hidden md:flex\",\n        )}\n      >\n        {selectedContactId ? (\n          <ContactDetailPane\n            key={selectedContactId}\n            contactId={selectedContactId}\n            queryKeyPrefix={queryKeyPrefix}\n            countriesQueryKey={countriesQueryKey}\n            getCountries={getCountries}\n            onBack={() => onSelect(null)}\n            showMobileBackButton={showMobileDetailBackButton}\n          />\n        ) : (\n          <ContactsEmptyState />\n        )}\n      </main>\n    </div>\n  );\n}\n","import e,{useRef as r,useMemo as t,useEffect as n,useState as o,useCallback as a,useLayoutEffect as l}from\"react\";function u(){return(u=Object.assign||function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e}).apply(this,arguments)}function c(e,r){if(null==e)return{};var t,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r.indexOf(t=a[n])>=0||(o[t]=e[t]);return o}function i(e){var t=r(e),n=r(function(e){t.current&&t.current(e)});return t.current=e,n.current}var s=function(e,r,t){return void 0===r&&(r=0),void 0===t&&(t=1),e>t?t:e<r?r:e},f=function(e){return\"touches\"in e},v=function(e){return e&&e.ownerDocument.defaultView||self},d=function(e,r,t){var n=e.getBoundingClientRect(),o=f(r)?function(e,r){for(var t=0;t<e.length;t++)if(e[t].identifier===r)return e[t];return e[0]}(r.touches,t):r;return{left:s((o.pageX-(n.left+v(e).pageXOffset))/n.width),top:s((o.pageY-(n.top+v(e).pageYOffset))/n.height)}},h=function(e){!f(e)&&e.preventDefault()},m=e.memo(function(o){var a=o.onMove,l=o.onKey,s=c(o,[\"onMove\",\"onKey\"]),m=r(null),g=i(a),p=i(l),b=r(null),_=r(!1),x=t(function(){var e=function(e){h(e),(f(e)?e.touches.length>0:e.buttons>0)&&m.current?g(d(m.current,e,b.current)):t(!1)},r=function(){return t(!1)};function t(t){var n=_.current,o=v(m.current),a=t?o.addEventListener:o.removeEventListener;a(n?\"touchmove\":\"mousemove\",e),a(n?\"touchend\":\"mouseup\",r)}return[function(e){var r=e.nativeEvent,n=m.current;if(n&&(h(r),!function(e,r){return r&&!f(e)}(r,_.current)&&n)){if(f(r)){_.current=!0;var o=r.changedTouches||[];o.length&&(b.current=o[0].identifier)}n.focus(),g(d(n,r,b.current)),t(!0)}},function(e){var r=e.which||e.keyCode;r<37||r>40||(e.preventDefault(),p({left:39===r?.05:37===r?-.05:0,top:40===r?.05:38===r?-.05:0}))},t]},[p,g]),C=x[0],E=x[1],H=x[2];return n(function(){return H},[H]),e.createElement(\"div\",u({},s,{onTouchStart:C,onMouseDown:C,className:\"react-colorful__interactive\",ref:m,onKeyDown:E,tabIndex:0,role:\"slider\"}))}),g=function(e){return e.filter(Boolean).join(\" \")},p=function(r){var t=r.color,n=r.left,o=r.top,a=void 0===o?.5:o,l=g([\"react-colorful__pointer\",r.className]);return e.createElement(\"div\",{className:l,style:{top:100*a+\"%\",left:100*n+\"%\"}},e.createElement(\"div\",{className:\"react-colorful__pointer-fill\",style:{backgroundColor:t}}))},b=function(e,r,t){return void 0===r&&(r=0),void 0===t&&(t=Math.pow(10,r)),Math.round(t*e)/t},_={grad:.9,turn:360,rad:360/(2*Math.PI)},x=function(e){return L(C(e))},C=function(e){return\"#\"===e[0]&&(e=e.substring(1)),e.length<6?{r:parseInt(e[0]+e[0],16),g:parseInt(e[1]+e[1],16),b:parseInt(e[2]+e[2],16),a:4===e.length?b(parseInt(e[3]+e[3],16)/255,2):1}:{r:parseInt(e.substring(0,2),16),g:parseInt(e.substring(2,4),16),b:parseInt(e.substring(4,6),16),a:8===e.length?b(parseInt(e.substring(6,8),16)/255,2):1}},E=function(e,r){return void 0===r&&(r=\"deg\"),Number(e)*(_[r]||1)},H=function(e){var r=/hsla?\\(?\\s*(-?\\d*\\.?\\d+)(deg|rad|grad|turn)?[,\\s]+(-?\\d*\\.?\\d+)%?[,\\s]+(-?\\d*\\.?\\d+)%?,?\\s*[/\\s]*(-?\\d*\\.?\\d+)?(%)?\\s*\\)?/i.exec(e);return r?N({h:E(r[1],r[2]),s:Number(r[3]),l:Number(r[4]),a:void 0===r[5]?1:Number(r[5])/(r[6]?100:1)}):{h:0,s:0,v:0,a:1}},M=H,N=function(e){var r=e.s,t=e.l;return{h:e.h,s:(r*=(t<50?t:100-t)/100)>0?2*r/(t+r)*100:0,v:t+r,a:e.a}},w=function(e){return K(I(e))},y=function(e){var r=e.s,t=e.v,n=e.a,o=(200-r)*t/100;return{h:b(e.h),s:b(o>0&&o<200?r*t/100/(o<=100?o:200-o)*100:0),l:b(o/2),a:b(n,2)}},q=function(e){var r=y(e);return\"hsl(\"+r.h+\", \"+r.s+\"%, \"+r.l+\"%)\"},k=function(e){var r=y(e);return\"hsla(\"+r.h+\", \"+r.s+\"%, \"+r.l+\"%, \"+r.a+\")\"},I=function(e){var r=e.h,t=e.s,n=e.v,o=e.a;r=r/360*6,t/=100,n/=100;var a=Math.floor(r),l=n*(1-t),u=n*(1-(r-a)*t),c=n*(1-(1-r+a)*t),i=a%6;return{r:b(255*[n,u,l,l,c,n][i]),g:b(255*[c,n,n,u,l,l][i]),b:b(255*[l,l,c,n,n,u][i]),a:b(o,2)}},O=function(e){var r=/hsva?\\(?\\s*(-?\\d*\\.?\\d+)(deg|rad|grad|turn)?[,\\s]+(-?\\d*\\.?\\d+)%?[,\\s]+(-?\\d*\\.?\\d+)%?,?\\s*[/\\s]*(-?\\d*\\.?\\d+)?(%)?\\s*\\)?/i.exec(e);return r?A({h:E(r[1],r[2]),s:Number(r[3]),v:Number(r[4]),a:void 0===r[5]?1:Number(r[5])/(r[6]?100:1)}):{h:0,s:0,v:0,a:1}},j=O,z=function(e){var r=/rgba?\\(?\\s*(-?\\d*\\.?\\d+)(%)?[,\\s]+(-?\\d*\\.?\\d+)(%)?[,\\s]+(-?\\d*\\.?\\d+)(%)?,?\\s*[/\\s]*(-?\\d*\\.?\\d+)?(%)?\\s*\\)?/i.exec(e);return r?L({r:Number(r[1])/(r[2]?100/255:1),g:Number(r[3])/(r[4]?100/255:1),b:Number(r[5])/(r[6]?100/255:1),a:void 0===r[7]?1:Number(r[7])/(r[8]?100:1)}):{h:0,s:0,v:0,a:1}},B=z,D=function(e){var r=e.toString(16);return r.length<2?\"0\"+r:r},K=function(e){var r=e.r,t=e.g,n=e.b,o=e.a,a=o<1?D(b(255*o)):\"\";return\"#\"+D(r)+D(t)+D(n)+a},L=function(e){var r=e.r,t=e.g,n=e.b,o=e.a,a=Math.max(r,t,n),l=a-Math.min(r,t,n),u=l?a===r?(t-n)/l:a===t?2+(n-r)/l:4+(r-t)/l:0;return{h:b(60*(u<0?u+6:u)),s:b(a?l/a*100:0),v:b(a/255*100),a:o}},A=function(e){return{h:b(e.h),s:b(e.s),v:b(e.v),a:b(e.a,2)}},S=e.memo(function(r){var t=r.hue,n=r.onChange,o=g([\"react-colorful__hue\",r.className]);return e.createElement(\"div\",{className:o},e.createElement(m,{onMove:function(e){n({h:360*e.left})},onKey:function(e){n({h:s(t+360*e.left,0,360)})},\"aria-label\":\"Hue\",\"aria-valuenow\":b(t),\"aria-valuemax\":\"360\",\"aria-valuemin\":\"0\"},e.createElement(p,{className:\"react-colorful__hue-pointer\",left:t/360,color:q({h:t,s:100,v:100,a:1})})))}),T=e.memo(function(r){var t=r.hsva,n=r.onChange,o={backgroundColor:q({h:t.h,s:100,v:100,a:1})};return e.createElement(\"div\",{className:\"react-colorful__saturation\",style:o},e.createElement(m,{onMove:function(e){n({s:100*e.left,v:100-100*e.top})},onKey:function(e){n({s:s(t.s+100*e.left,0,100),v:s(t.v-100*e.top,0,100)})},\"aria-label\":\"Color\",\"aria-valuetext\":\"Saturation \"+b(t.s)+\"%, Brightness \"+b(t.v)+\"%\"},e.createElement(p,{className:\"react-colorful__saturation-pointer\",top:1-t.v/100,left:t.s/100,color:q(t)})))}),F=function(e,r){if(e===r)return!0;for(var t in e)if(e[t]!==r[t])return!1;return!0},P=function(e,r){return e.replace(/\\s/g,\"\")===r.replace(/\\s/g,\"\")},X=function(e,r){return e.toLowerCase()===r.toLowerCase()||F(C(e),C(r))};function Y(e,t,l){var u=i(l),c=o(function(){return e.toHsva(t)}),s=c[0],f=c[1],v=r({color:t,hsva:s});n(function(){if(!e.equal(t,v.current.color)){var r=e.toHsva(t);v.current={hsva:r,color:t},f(r)}},[t,e]),n(function(){var r;F(s,v.current.hsva)||e.equal(r=e.fromHsva(s),v.current.color)||(v.current={hsva:s,color:r},u(r))},[s,e,u]);var d=a(function(e){f(function(r){return Object.assign({},r,e)})},[]);return[s,d]}var R,V=\"undefined\"!=typeof window?l:n,$=function(){return R||(\"undefined\"!=typeof __webpack_nonce__?__webpack_nonce__:void 0)},G=function(e){R=e},J=new Map,Q=function(e){V(function(){var r=e.current?e.current.ownerDocument:document;if(void 0!==r&&!J.has(r)){var t=r.createElement(\"style\");t.innerHTML='.react-colorful{position:relative;display:flex;flex-direction:column;width:200px;height:200px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.react-colorful__saturation{position:relative;flex-grow:1;border-color:transparent;border-bottom:12px solid #000;border-radius:8px 8px 0 0;background-image:linear-gradient(0deg,#000,transparent),linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.react-colorful__alpha-gradient,.react-colorful__pointer-fill{content:\"\";position:absolute;left:0;top:0;right:0;bottom:0;pointer-events:none;border-radius:inherit}.react-colorful__alpha-gradient,.react-colorful__saturation{box-shadow:inset 0 0 0 1px rgba(0,0,0,.05)}.react-colorful__alpha,.react-colorful__hue{position:relative;height:24px}.react-colorful__hue{background:linear-gradient(90deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.react-colorful__last-control{border-radius:0 0 8px 8px}.react-colorful__interactive{position:absolute;left:0;top:0;right:0;bottom:0;border-radius:inherit;outline:none;touch-action:none}.react-colorful__pointer{position:absolute;z-index:1;box-sizing:border-box;width:28px;height:28px;transform:translate(-50%,-50%);background-color:#fff;border:2px solid #fff;border-radius:50%;box-shadow:0 2px 4px rgba(0,0,0,.2)}.react-colorful__interactive:focus .react-colorful__pointer{transform:translate(-50%,-50%) scale(1.1)}.react-colorful__alpha,.react-colorful__alpha-pointer{background-color:#fff;background-image:url(\\'data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill-opacity=\".05\"><path d=\"M8 0h8v8H8zM0 8h8v8H0z\"/></svg>\\')}.react-colorful__saturation-pointer{z-index:3}.react-colorful__hue-pointer{z-index:2}',J.set(r,t);var n=$();n&&t.setAttribute(\"nonce\",n),r.head.appendChild(t)}},[])},U=function(t){var n=t.className,o=t.colorModel,a=t.color,l=void 0===a?o.defaultColor:a,i=t.onChange,s=c(t,[\"className\",\"colorModel\",\"color\",\"onChange\"]),f=r(null);Q(f);var v=Y(o,l,i),d=v[0],h=v[1],m=g([\"react-colorful\",n]);return e.createElement(\"div\",u({},s,{ref:f,className:m}),e.createElement(T,{hsva:d,onChange:h}),e.createElement(S,{hue:d.h,onChange:h,className:\"react-colorful__last-control\"}))},W={defaultColor:\"000\",toHsva:x,fromHsva:function(e){return w({h:e.h,s:e.s,v:e.v,a:1})},equal:X},Z=function(r){return e.createElement(U,u({},r,{colorModel:W}))},ee=function(r){var t=r.className,n=r.hsva,o=r.onChange,a={backgroundImage:\"linear-gradient(90deg, \"+k(Object.assign({},n,{a:0}))+\", \"+k(Object.assign({},n,{a:1}))+\")\"},l=g([\"react-colorful__alpha\",t]),u=b(100*n.a);return e.createElement(\"div\",{className:l},e.createElement(\"div\",{className:\"react-colorful__alpha-gradient\",style:a}),e.createElement(m,{onMove:function(e){o({a:e.left})},onKey:function(e){o({a:s(n.a+e.left)})},\"aria-label\":\"Alpha\",\"aria-valuetext\":u+\"%\",\"aria-valuenow\":u,\"aria-valuemin\":\"0\",\"aria-valuemax\":\"100\"},e.createElement(p,{className:\"react-colorful__alpha-pointer\",left:n.a,color:k(n)})))},re=function(t){var n=t.className,o=t.colorModel,a=t.color,l=void 0===a?o.defaultColor:a,i=t.onChange,s=c(t,[\"className\",\"colorModel\",\"color\",\"onChange\"]),f=r(null);Q(f);var v=Y(o,l,i),d=v[0],h=v[1],m=g([\"react-colorful\",n]);return e.createElement(\"div\",u({},s,{ref:f,className:m}),e.createElement(T,{hsva:d,onChange:h}),e.createElement(S,{hue:d.h,onChange:h}),e.createElement(ee,{hsva:d,onChange:h,className:\"react-colorful__last-control\"}))},te={defaultColor:\"0001\",toHsva:x,fromHsva:w,equal:X},ne=function(r){return e.createElement(re,u({},r,{colorModel:te}))},oe={defaultColor:{h:0,s:0,l:0,a:1},toHsva:N,fromHsva:y,equal:F},ae=function(r){return e.createElement(re,u({},r,{colorModel:oe}))},le={defaultColor:\"hsla(0, 0%, 0%, 1)\",toHsva:H,fromHsva:k,equal:P},ue=function(r){return e.createElement(re,u({},r,{colorModel:le}))},ce={defaultColor:{h:0,s:0,l:0},toHsva:function(e){return N({h:e.h,s:e.s,l:e.l,a:1})},fromHsva:function(e){return{h:(r=y(e)).h,s:r.s,l:r.l};var r},equal:F},ie=function(r){return e.createElement(U,u({},r,{colorModel:ce}))},se={defaultColor:\"hsl(0, 0%, 0%)\",toHsva:M,fromHsva:q,equal:P},fe=function(r){return e.createElement(U,u({},r,{colorModel:se}))},ve={defaultColor:{h:0,s:0,v:0,a:1},toHsva:function(e){return e},fromHsva:A,equal:F},de=function(r){return e.createElement(re,u({},r,{colorModel:ve}))},he={defaultColor:\"hsva(0, 0%, 0%, 1)\",toHsva:O,fromHsva:function(e){var r=A(e);return\"hsva(\"+r.h+\", \"+r.s+\"%, \"+r.v+\"%, \"+r.a+\")\"},equal:P},me=function(r){return e.createElement(re,u({},r,{colorModel:he}))},ge={defaultColor:{h:0,s:0,v:0},toHsva:function(e){return{h:e.h,s:e.s,v:e.v,a:1}},fromHsva:function(e){var r=A(e);return{h:r.h,s:r.s,v:r.v}},equal:F},pe=function(r){return e.createElement(U,u({},r,{colorModel:ge}))},be={defaultColor:\"hsv(0, 0%, 0%)\",toHsva:j,fromHsva:function(e){var r=A(e);return\"hsv(\"+r.h+\", \"+r.s+\"%, \"+r.v+\"%)\"},equal:P},_e=function(r){return e.createElement(U,u({},r,{colorModel:be}))},xe={defaultColor:{r:0,g:0,b:0,a:1},toHsva:L,fromHsva:I,equal:F},Ce=function(r){return e.createElement(re,u({},r,{colorModel:xe}))},Ee={defaultColor:\"rgba(0, 0, 0, 1)\",toHsva:z,fromHsva:function(e){var r=I(e);return\"rgba(\"+r.r+\", \"+r.g+\", \"+r.b+\", \"+r.a+\")\"},equal:P},He=function(r){return e.createElement(re,u({},r,{colorModel:Ee}))},Me={defaultColor:{r:0,g:0,b:0},toHsva:function(e){return L({r:e.r,g:e.g,b:e.b,a:1})},fromHsva:function(e){return{r:(r=I(e)).r,g:r.g,b:r.b};var r},equal:F},Ne=function(r){return e.createElement(U,u({},r,{colorModel:Me}))},we={defaultColor:\"rgb(0, 0, 0)\",toHsva:B,fromHsva:function(e){var r=I(e);return\"rgb(\"+r.r+\", \"+r.g+\", \"+r.b+\")\"},equal:P},ye=function(r){return e.createElement(U,u({},r,{colorModel:we}))},qe=/^#?([0-9A-F]{3,8})$/i,ke=function(r){var t=r.color,l=void 0===t?\"\":t,s=r.onChange,f=r.onBlur,v=r.escape,d=r.validate,h=r.format,m=r.process,g=c(r,[\"color\",\"onChange\",\"onBlur\",\"escape\",\"validate\",\"format\",\"process\"]),p=o(function(){return v(l)}),b=p[0],_=p[1],x=i(s),C=i(f),E=a(function(e){var r=v(e.target.value);_(r),d(r)&&x(m?m(r):r)},[v,m,d,x]),H=a(function(e){d(e.target.value)||_(v(l)),C(e)},[l,v,d,C]);return n(function(){_(v(l))},[l,v]),e.createElement(\"input\",u({},g,{value:h?h(b):b,spellCheck:\"false\",onChange:E,onBlur:H}))},Ie=function(e){return\"#\"+e},Oe=function(r){var t=r.prefixed,n=r.alpha,o=c(r,[\"prefixed\",\"alpha\"]),l=a(function(e){return e.replace(/([^0-9A-F]+)/gi,\"\").substring(0,n?8:6)},[n]),i=a(function(e){return function(e,r){var t=qe.exec(e),n=t?t[1].length:0;return 3===n||6===n||!!r&&4===n||!!r&&8===n}(e,n)},[n]);return e.createElement(ke,u({},o,{escape:l,format:t?Ie:void 0,process:Ie,validate:i}))};export{ne as HexAlphaColorPicker,Oe as HexColorInput,Z as HexColorPicker,ie as HslColorPicker,fe as HslStringColorPicker,ae as HslaColorPicker,ue as HslaStringColorPicker,pe as HsvColorPicker,_e as HsvStringColorPicker,de as HsvaColorPicker,me as HsvaStringColorPicker,Ne as RgbColorPicker,ye as RgbStringColorPicker,Ce as RgbaColorPicker,He as RgbaStringColorPicker,G as setNonce};\n//# sourceMappingURL=index.module.js.map\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useGroupsApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { invalidateContactCaches } from \"./invalidate-contact-caches\";\n\nexport function useDeleteGroup() {\n  const api = useGroupsApi();\n  const queryClient = useQueryClient();\n  const { t } = useContactsTranslation();\n\n  return useMutation({\n    mutationFn: (groupId: number) => {\n      if (!api) throw new Error(\"GroupsApi is not available\");\n      return api.deleteGroup(groupId);\n    },\n    onSuccess: () => {\n      queryClient.invalidateQueries({ queryKey: contactsKeys.groups() });\n      invalidateContactCaches(queryClient);\n    },\n    onError: (error) => {\n      fluidToast({\n        title: t(\"groups_delete_failed\"),\n        description: parseApiErrors(error),\n        type: \"error\",\n      });\n    },\n  });\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useGroupsApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { invalidateContactCaches } from \"./invalidate-contact-caches\";\nimport type { UpdateGroupInput } from \"@fluid-app/contacts-core/types\";\n\nexport function useUpdateGroup() {\n  const api = useGroupsApi();\n  const queryClient = useQueryClient();\n  const { t } = useContactsTranslation();\n\n  return useMutation({\n    mutationFn: ({\n      groupId,\n      input,\n    }: {\n      groupId: number;\n      input: UpdateGroupInput;\n    }) => {\n      if (!api) throw new Error(\"GroupsApi is not available\");\n      return api.updateGroup(groupId, input);\n    },\n    onSuccess: () => {\n      queryClient.invalidateQueries({ queryKey: contactsKeys.groups() });\n      invalidateContactCaches(queryClient);\n    },\n    onError: (error) => {\n      fluidToast({\n        title: t(\"groups_update_failed\"),\n        description: parseApiErrors(error),\n        type: \"error\",\n      });\n    },\n  });\n}\n","\"use client\";\n\nimport React, { useCallback, useEffect, useState } from \"react\";\nimport {\n  ChevronLeft,\n  Loader,\n  Pencil,\n  Plus,\n  Search,\n  Trash2,\n  Users,\n  X,\n} from \"lucide-react\";\nimport {\n  EmojiPicker as EmojiPickerPrimitive,\n  type EmojiPickerListCategoryHeaderProps,\n  type EmojiPickerListEmojiProps,\n  type EmojiPickerListRowProps,\n} from \"frimousse\";\nimport { HexColorPicker, HexColorInput } from \"react-colorful\";\nimport {\n  Button,\n  cn,\n  DialogFooter,\n  IconButton,\n  Input,\n  Label,\n  Sheet,\n  SheetContent,\n  SheetDescription,\n  SheetHeader,\n  SheetTitle,\n  Skeleton,\n  Tabs,\n  TabsContent,\n  TabsList,\n  TabsTrigger,\n  fluidToast,\n} from \"@fluid-app/ui-primitives\";\nimport { MobileBottomSheet } from \"@fluid-app/ui-components/components/MobileBottomSheet\";\nimport { ResponsiveDialog } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useContactsCrud } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { contactsKeys } from \"@fluid-app/contacts-core/query-keys\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { Contact, ContactGroup } from \"@fluid-app/contacts-core/types\";\nimport { invalidateContactCaches } from \"../../../hooks/groups/invalidate-contact-caches\";\nimport { useGroups } from \"../../../hooks/groups/use-groups\";\nimport { useCreateGroup } from \"../../../hooks/groups/use-create-group\";\nimport { useDeleteGroup } from \"../../../hooks/groups/use-delete-group\";\nimport { useUpdateGroup } from \"../../../hooks/groups/use-update-group\";\n\nconst PRESET_COLORS = [\n  \"#ef4444\",\n  \"#f97316\",\n  \"#eab308\",\n  \"#22c55e\",\n  \"#14b8a6\",\n  \"#06b6d4\",\n  \"#3b82f6\",\n  \"#6366f1\",\n  \"#8b5cf6\",\n  \"#ec4899\",\n] as const;\n\ntype ColorTranslationKey =\n  | \"groups_color_red\"\n  | \"groups_color_orange\"\n  | \"groups_color_yellow\"\n  | \"groups_color_green\"\n  | \"groups_color_teal\"\n  | \"groups_color_cyan\"\n  | \"groups_color_blue\"\n  | \"groups_color_indigo\"\n  | \"groups_color_purple\"\n  | \"groups_color_pink\";\n\nconst PRESET_COLOR_KEYS = {\n  \"#ef4444\": \"groups_color_red\",\n  \"#f97316\": \"groups_color_orange\",\n  \"#eab308\": \"groups_color_yellow\",\n  \"#22c55e\": \"groups_color_green\",\n  \"#14b8a6\": \"groups_color_teal\",\n  \"#06b6d4\": \"groups_color_cyan\",\n  \"#3b82f6\": \"groups_color_blue\",\n  \"#6366f1\": \"groups_color_indigo\",\n  \"#8b5cf6\": \"groups_color_purple\",\n  \"#ec4899\": \"groups_color_pink\",\n} as const satisfies Record<\n  (typeof PRESET_COLORS)[number],\n  ColorTranslationKey\n>;\n\nexport interface GroupsManagePageProps {\n  onBack: () => void;\n  onSelectContact?: (contactId: string) => void;\n  initialCreateOpen?: boolean;\n  showMobileBackButton?: boolean;\n}\n\nexport function GroupsManagePage({\n  onBack,\n  onSelectContact,\n  initialCreateOpen,\n  showMobileBackButton = true,\n}: GroupsManagePageProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const { isMobile } = useSidebar();\n  const { data: groups = [], isLoading } = useGroups();\n  const deleteGroup = useDeleteGroup();\n\n  const [dialogMode, setDialogMode] = useState<\n    { mode: \"create\" } | { mode: \"edit\"; group: ContactGroup } | null\n  >(initialCreateOpen ? { mode: \"create\" } : null);\n  const [deleteTarget, setDeleteTarget] = useState<ContactGroup | null>(null);\n  const [highlightGroupId, setHighlightGroupId] = useState<number | null>(null);\n\n  useEffect(() => {\n    if (highlightGroupId == null) return;\n    const timer = setTimeout(() => setHighlightGroupId(null), 2000);\n    return () => clearTimeout(timer);\n  }, [highlightGroupId]);\n\n  const handleDelete = useCallback(() => {\n    if (!deleteTarget) return;\n    deleteGroup.mutate(deleteTarget.id, {\n      onSuccess: () => {\n        fluidToast({\n          title: t(\"groups_deleted_toast\", { name: deleteTarget.name }),\n          type: \"success\",\n        });\n        setDeleteTarget(null);\n      },\n      onError: () => {\n        setDeleteTarget(null);\n      },\n    });\n  }, [deleteTarget, deleteGroup, t]);\n\n  return (\n    <div className=\"flex h-full flex-col\">\n      <div className=\"border-border/50 flex items-center justify-between border-b px-6 py-4\">\n        <div className=\"flex items-center gap-3\">\n          <IconButton\n            icon={ChevronLeft}\n            onClick={onBack}\n            className={cn(\n              \"text-muted-foreground hover:bg-muted hover:text-foreground rounded-full\",\n              showMobileBackButton ? null : \"max-md:hidden\",\n            )}\n            aria-label={t(\"groups_back_to_contacts\")}\n          />\n          <h2 className=\"text-foreground text-lg font-semibold\">\n            {t(\"groups_manage_title\")}\n          </h2>\n        </div>\n        <Button size=\"sm\" onClick={() => setDialogMode({ mode: \"create\" })}>\n          <Plus className=\"size-4\" />\n          {t(\"groups_new_group\")}\n        </Button>\n      </div>\n\n      <div className=\"flex-1 overflow-y-auto px-6 py-6\">\n        <div className=\"mx-auto max-w-[857px]\">\n          {isLoading ? (\n            <GroupsSkeleton />\n          ) : groups.length === 0 ? (\n            <div className=\"text-muted-foreground py-16 text-center text-sm\">\n              {t(\"groups_empty\")}\n            </div>\n          ) : (\n            <div className=\"space-y-2\">\n              {groups.map((group) => (\n                <GroupRow\n                  key={group.id}\n                  group={group}\n                  highlight={highlightGroupId === group.id}\n                  onEdit={() => setDialogMode({ mode: \"edit\", group })}\n                  onDelete={() => setDeleteTarget(group)}\n                  onSelectContact={onSelectContact}\n                />\n              ))}\n            </div>\n          )}\n        </div>\n      </div>\n\n      {/* Create / Edit group dialog */}\n      {dialogMode && (\n        <GroupDialog\n          key={dialogMode.mode === \"edit\" ? dialogMode.group.id : \"create\"}\n          mode={dialogMode.mode}\n          group={dialogMode.mode === \"edit\" ? dialogMode.group : undefined}\n          open={!!dialogMode}\n          onOpenChange={(open) => !open && setDialogMode(null)}\n          onGroupCreated={(groupId) => {\n            setHighlightGroupId(groupId);\n          }}\n        />\n      )}\n\n      {/* Delete confirmation dialog */}\n      <ResponsiveDialog\n        open={!!deleteTarget}\n        onOpenChange={(open) => !open && setDeleteTarget(null)}\n        title={t(\"groups_delete_title\")}\n        description={t(\"groups_delete_confirm\", {\n          name: deleteTarget?.name ?? \"\",\n        })}\n        role=\"alertdialog\"\n        presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n        size=\"compact\"\n      >\n        <DialogFooter>\n          <Button\n            variant=\"secondary\"\n            onClick={() => setDeleteTarget(null)}\n            disabled={deleteGroup.isPending}\n          >\n            {t(\"cancel\")}\n          </Button>\n          <Button\n            variant=\"destructive\"\n            onClick={handleDelete}\n            disabled={deleteGroup.isPending}\n          >\n            {deleteGroup.isPending ? t(\"deleting\") : t(\"delete\")}\n          </Button>\n        </DialogFooter>\n      </ResponsiveDialog>\n    </div>\n  );\n}\n\n// ---- Shared Group Dialog (Create + Edit) ----\n\nexport interface GroupDialogProps {\n  mode: \"create\" | \"edit\";\n  group?: ContactGroup;\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n  onGroupCreated?: (groupId: number) => void;\n  onGroupCreatedWithName?: (name: string) => void;\n}\n\nexport function GroupDialog({\n  mode,\n  group,\n  open,\n  onOpenChange,\n  onGroupCreated,\n  onGroupCreatedWithName,\n}: GroupDialogProps): React.JSX.Element {\n  const { t } = useContactsTranslation();\n  const { isMobile } = useSidebar();\n  const createGroup = useCreateGroup();\n  const updateGroup = useUpdateGroup();\n  const isPending =\n    mode === \"create\" ? createGroup.isPending : updateGroup.isPending;\n\n  const [name, setName] = useState(group?.name ?? \"\");\n  const [avatar, setAvatar] = useState(group?.avatar ?? \"\");\n  const [avatarBackground, setAvatarBackground] = useState(\n    group?.avatar_background ?? \"#6366f1\",\n  );\n\n  const handleSave = useCallback(() => {\n    const trimmedName = name.trim();\n    if (!trimmedName) return;\n\n    if (mode === \"create\") {\n      createGroup.mutate(\n        {\n          name: trimmedName,\n          avatar: avatar || undefined,\n          avatar_background: avatarBackground || undefined,\n        },\n        {\n          onSuccess: (data) => {\n            fluidToast({\n              title: t(\"groups_created_toast\", { name: trimmedName }),\n              type: \"success\",\n            });\n            onOpenChange(false);\n            if (data.group.id) onGroupCreated?.(data.group.id);\n            onGroupCreatedWithName?.(trimmedName);\n          },\n        },\n      );\n    } else if (group) {\n      updateGroup.mutate(\n        {\n          groupId: group.id,\n          input: {\n            name: trimmedName,\n            avatar: avatar || undefined,\n            avatar_background: avatarBackground || undefined,\n          },\n        },\n        {\n          onSuccess: () => {\n            fluidToast({ title: t(\"groups_updated_toast\"), type: \"success\" });\n            onOpenChange(false);\n          },\n        },\n      );\n    }\n  }, [\n    mode,\n    name,\n    avatar,\n    avatarBackground,\n    group,\n    createGroup,\n    updateGroup,\n    onOpenChange,\n    onGroupCreated,\n    onGroupCreatedWithName,\n    t,\n  ]);\n\n  const previewBg = avatarBackground || \"#6366f1\";\n\n  return (\n    <ResponsiveDialog\n      open={open}\n      onOpenChange={onOpenChange}\n      title={\n        mode === \"create\" ? t(\"groups_create_title\") : t(\"groups_edit_title\")\n      }\n      presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n    >\n      <div className=\"space-y-5 py-2\">\n        {/* Avatar preview + name */}\n        <div className=\"flex items-center gap-5\">\n          <div className=\"flex flex-col items-center gap-1\">\n            <div className=\"relative\">\n              <div\n                className=\"flex size-20 items-center justify-center rounded-full text-4xl transition-colors\"\n                style={{ backgroundColor: previewBg }}\n              >\n                {avatar || <Users className=\"size-8 text-white/60\" />}\n              </div>\n              {avatar && (\n                <IconButton\n                  icon={X}\n                  onClick={() => setAvatar(\"\")}\n                  className=\"bg-foreground/80 text-background hover:bg-foreground absolute -top-1 -right-1 size-5 rounded-full [&_svg:not([class*='size-'])]:size-3\"\n                  aria-label={t(\"groups_remove_emoji\")}\n                />\n              )}\n            </div>\n            <span className=\"text-muted-foreground text-xs\">\n              {t(\"groups_avatar\")}\n            </span>\n          </div>\n          <div className=\"flex-1 space-y-1.5\">\n            <Label className=\"text-foreground\">{t(\"groups_name_label\")}</Label>\n            <Input\n              value={name}\n              onChange={(e) => setName(e.target.value)}\n              placeholder={t(\"groups_name_placeholder\")}\n            />\n          </div>\n        </div>\n\n        {/* Tabs: Change Emoji / Change Color */}\n        <Tabs defaultValue=\"emoji\">\n          <TabsList className=\"border-border h-auto w-full justify-center gap-6 rounded-none border-b bg-transparent p-0\">\n            <TabsTrigger\n              value=\"emoji\"\n              className=\"text-muted-foreground hover:text-foreground data-[state=active]:text-primary data-[state=active]:border-primary h-auto flex-none rounded-none border-0 border-b-2 border-transparent bg-transparent pb-2 shadow-none data-[state=active]:bg-transparent data-[state=active]:shadow-none\"\n            >\n              {t(\"groups_tab_change_emoji\")}\n            </TabsTrigger>\n            <TabsTrigger\n              value=\"color\"\n              className=\"text-muted-foreground hover:text-foreground data-[state=active]:text-primary data-[state=active]:border-primary h-auto flex-none rounded-none border-0 border-b-2 border-transparent bg-transparent pb-2 shadow-none data-[state=active]:bg-transparent data-[state=active]:shadow-none\"\n            >\n              {t(\"groups_tab_change_color\")}\n            </TabsTrigger>\n          </TabsList>\n\n          <TabsContent value=\"emoji\" className=\"pt-4\">\n            <EmojiPickerPrimitive.Root\n              className=\"bg-popover flex h-64 w-full flex-col overflow-hidden rounded-lg\"\n              onEmojiSelect={(emoji) => setAvatar(emoji.emoji)}\n            >\n              <EmojiPickerPrimitive.Viewport className=\"relative flex-1 outline-hidden\">\n                <EmojiPickerPrimitive.Loading className=\"text-muted-foreground absolute inset-0 flex items-center justify-center\">\n                  <Loader className=\"size-4 animate-spin\" />\n                </EmojiPickerPrimitive.Loading>\n                <EmojiPickerPrimitive.Empty className=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm\">\n                  {t(\"groups_no_emoji_found\")}\n                </EmojiPickerPrimitive.Empty>\n                <EmojiPickerPrimitive.List\n                  className=\"pb-1 select-none\"\n                  components={{\n                    Row: EmojiPickerRow,\n                    Emoji: EmojiPickerEmoji,\n                    CategoryHeader: EmojiPickerCategoryHeader,\n                  }}\n                />\n              </EmojiPickerPrimitive.Viewport>\n            </EmojiPickerPrimitive.Root>\n          </TabsContent>\n\n          <TabsContent value=\"color\" className=\"pt-4\">\n            <div className=\"space-y-4\">\n              <HexColorPicker\n                color={avatarBackground || \"#6366f1\"}\n                onChange={setAvatarBackground}\n                className=\"h-40 w-full\"\n              />\n              <div className=\"flex items-center gap-3\">\n                <div className=\"border-input flex items-center gap-1 rounded-md border px-3 py-1.5\">\n                  <span className=\"text-muted-foreground text-sm\">#</span>\n                  <HexColorInput\n                    color={avatarBackground || \"6366f1\"}\n                    onChange={setAvatarBackground}\n                    className=\"text-foreground w-20 bg-transparent text-sm outline-none\"\n                  />\n                </div>\n              </div>\n              <div className=\"flex justify-between\">\n                {PRESET_COLORS.map((color) => (\n                  <button\n                    key={color}\n                    type=\"button\"\n                    onClick={() => setAvatarBackground(color)}\n                    className={cn(\n                      \"size-7 rounded-full transition-all\",\n                      avatarBackground === color\n                        ? \"ring-primary ring-2 ring-offset-2\"\n                        : \"hover:scale-110\",\n                    )}\n                    style={{ backgroundColor: color }}\n                    aria-label={t(PRESET_COLOR_KEYS[color])}\n                  />\n                ))}\n              </div>\n            </div>\n          </TabsContent>\n        </Tabs>\n      </div>\n\n      <DialogFooter>\n        <Button\n          variant=\"outline\"\n          onClick={() => onOpenChange(false)}\n          disabled={isPending}\n        >\n          {t(\"groups_close\")}\n        </Button>\n        <Button onClick={handleSave} disabled={!name.trim() || isPending}>\n          {isPending\n            ? mode === \"create\"\n              ? t(\"groups_creating\")\n              : t(\"saving\")\n            : mode === \"create\"\n              ? t(\"groups_create\")\n              : t(\"save\")}\n        </Button>\n      </DialogFooter>\n    </ResponsiveDialog>\n  );\n}\n\n// ---- Frimousse sub-components ----\n// Visually distinct from @fluid-app/messaging-ui's EmojiPicker (larger emoji\n// size-12 vs size-8, centered row layout). Sharing would require a more\n// flexible component API; for now this small duplication is intentional.\n\nfunction EmojiPickerRow({\n  children,\n  ref: _ref,\n  ...props\n}: EmojiPickerListRowProps) {\n  return (\n    <div {...props} className=\"flex scroll-my-1 justify-center px-1\">\n      {children}\n    </div>\n  );\n}\n\nfunction EmojiPickerEmoji({\n  emoji,\n  className,\n  ref: _ref,\n  ...props\n}: EmojiPickerListEmojiProps) {\n  return (\n    <button\n      {...props}\n      className={cn(\n        \"data-[active]:bg-foreground/10 flex aspect-square size-12 items-center justify-center rounded-md text-3xl\",\n        className,\n      )}\n    >\n      {emoji.emoji}\n    </button>\n  );\n}\n\nfunction EmojiPickerCategoryHeader({\n  category,\n  ref: _ref,\n  ...props\n}: EmojiPickerListCategoryHeaderProps) {\n  return (\n    <div\n      {...props}\n      className=\"bg-popover text-muted-foreground px-3 pt-3.5 pb-2 text-xs leading-none\"\n    >\n      {category.label}\n    </div>\n  );\n}\n\n// ---- Group Row ----\n\nfunction GroupRow({\n  group,\n  highlight,\n  onEdit,\n  onDelete,\n  onSelectContact,\n}: {\n  group: ContactGroup;\n  highlight?: boolean;\n  onEdit: () => void;\n  onDelete: () => void;\n  onSelectContact?: (contactId: string) => void;\n}) {\n  const { t } = useContactsTranslation();\n  const backgroundColor = group.avatar_background ?? \"var(--color-muted)\";\n  const [drawerOpen, setDrawerOpen] = useState(false);\n\n  return (\n    <>\n      <div\n        className={cn(\n          \"group/row border-border/50 hover:bg-muted/50 focus-within:bg-muted/50 flex cursor-pointer items-center gap-4 rounded-lg border px-4 py-3 transition-colors\",\n          highlight && \"animate-highlight-fade\",\n        )}\n        onClick={() => setDrawerOpen(true)}\n        role=\"button\"\n        tabIndex={0}\n        onKeyDown={(e) => {\n          if (e.key === \"Enter\" || e.key === \" \") {\n            e.preventDefault();\n            setDrawerOpen(true);\n          }\n        }}\n      >\n        <div\n          className=\"flex size-10 shrink-0 items-center justify-center rounded-full text-lg\"\n          style={{ backgroundColor }}\n        >\n          {group.avatar ?? <Users className=\"text-muted-foreground size-4\" />}\n        </div>\n        <div className=\"min-w-0 flex-1\">\n          <p className=\"text-foreground text-sm font-semibold\">{group.name}</p>\n          <p className=\"text-muted-foreground text-xs\">\n            {group.contacts_count === 1\n              ? t(\"groups_contact_one\", { count: group.contacts_count })\n              : t(\"groups_contact_other\", { count: group.contacts_count })}\n          </p>\n        </div>\n        <div className=\"flex items-center gap-1 opacity-100 transition-opacity md:opacity-0 md:group-focus-within/row:opacity-100 md:group-hover/row:opacity-100\">\n          <IconButton\n            icon={Pencil}\n            onClick={(e) => {\n              e.stopPropagation();\n              onEdit();\n            }}\n            className=\"text-muted-foreground hover:text-foreground rounded-full focus:opacity-100\"\n            aria-label={t(\"groups_edit_aria\", { name: group.name })}\n          />\n          <IconButton\n            icon={Trash2}\n            onClick={(e) => {\n              e.stopPropagation();\n              onDelete();\n            }}\n            className=\"text-muted-foreground hover:text-destructive rounded-full focus:opacity-100\"\n            aria-label={t(\"groups_delete_aria\", { name: group.name })}\n          />\n        </div>\n      </div>\n\n      <GroupMembersDrawer\n        group={group}\n        open={drawerOpen}\n        onOpenChange={setDrawerOpen}\n        contactCount={group.contacts_count}\n        onSelectContact={onSelectContact}\n      />\n    </>\n  );\n}\n\n// ---- Group Members Drawer ----\n\ninterface GroupMembersDrawerProps {\n  group: ContactGroup;\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n  contactCount: number;\n  onSelectContact?: (contactId: string) => void;\n}\n\nfunction GroupMembersDrawer({\n  group,\n  open,\n  onOpenChange,\n  contactCount,\n  onSelectContact,\n}: GroupMembersDrawerProps) {\n  const { t } = useContactsTranslation();\n  const { isMobile } = useSidebar();\n  const api = useContactsCrud();\n  const queryClient = useQueryClient();\n  const backgroundColor = group.avatar_background ?? \"var(--color-muted)\";\n  const [addSearch, setAddSearch] = useState(\"\");\n  const [recentlyAddedId, setRecentlyAddedId] = useState<number | null>(null);\n\n  useEffect(() => {\n    if (recentlyAddedId == null) return;\n    const timer = setTimeout(() => setRecentlyAddedId(null), 2000);\n    return () => clearTimeout(timer);\n  }, [recentlyAddedId]);\n\n  const { data: members, isLoading: isLoadingMembers } = useQuery({\n    queryKey: contactsKeys.groupMembers(group.name),\n    queryFn: async () => {\n      const result = await api.listContacts({\n        tags: [group.name],\n        per_page: 100,\n      });\n      return result.contacts;\n    },\n    enabled: open,\n  });\n\n  const { data: searchResults } = useQuery({\n    queryKey: contactsKeys.groupAddSearch(group.name, addSearch),\n    queryFn: () =>\n      api.listContacts({\n        search_query: addSearch,\n        per_page: 10,\n      }),\n    enabled: addSearch.length > 0 && open,\n  });\n\n  const nonMembers = (searchResults?.contacts ?? []).filter(\n    (c) => !members?.some((m) => m.id === c.id),\n  );\n\n  const handleRemoveContact = useCallback(\n    (contact: Contact) => {\n      const currentTags = Array.isArray(contact.tags) ? contact.tags : [];\n      const newTags = currentTags.filter((tag) => tag !== group.name);\n      api\n        .updateContact(String(contact.id), { tags: newTags })\n        .then(() => {\n          queryClient.invalidateQueries({\n            queryKey: contactsKeys.groupMembers(group.name),\n          });\n          invalidateContactCaches(queryClient);\n          fluidToast({\n            title: t(\"groups_member_removed_toast\", {\n              contact: contact.full_name ?? \"\",\n              group: group.name,\n            }),\n            type: \"success\",\n          });\n        })\n        .catch((error) => {\n          fluidToast({\n            title: t(\"groups_member_remove_failed\", {\n              contact: contact.full_name ?? \"\",\n              group: group.name,\n            }),\n            description: parseApiErrors(error),\n            type: \"error\",\n          });\n        });\n    },\n    [api, group.name, queryClient, t],\n  );\n\n  const handleAddContact = useCallback(\n    (contact: Contact) => {\n      const currentTags = Array.isArray(contact.tags) ? contact.tags : [];\n      if (currentTags.includes(group.name)) return;\n      const newTags = [...currentTags, group.name];\n      api\n        .updateContact(String(contact.id), { tags: newTags })\n        .then(() => {\n          queryClient.invalidateQueries({\n            queryKey: contactsKeys.groupMembers(group.name),\n          });\n          invalidateContactCaches(queryClient);\n          setAddSearch(\"\");\n          setRecentlyAddedId(contact.id);\n          fluidToast({\n            title: t(\"groups_member_added_toast\", {\n              contact: contact.full_name ?? \"\",\n              group: group.name,\n            }),\n            type: \"success\",\n          });\n        })\n        .catch((error) => {\n          fluidToast({\n            title: t(\"groups_member_add_failed\", {\n              contact: contact.full_name ?? \"\",\n              group: group.name,\n            }),\n            description: parseApiErrors(error),\n            type: \"error\",\n          });\n        });\n    },\n    [api, group.name, queryClient, t],\n  );\n\n  const content = (\n    <>\n      {/* Drawer header */}\n      {!isMobile && (\n        <SheetHeader className=\"border-border/50 border-b px-6 pt-6 pb-4\">\n          <div className=\"flex items-center gap-4\">\n            <div\n              className=\"flex size-12 shrink-0 items-center justify-center rounded-full text-xl\"\n              style={{ backgroundColor }}\n            >\n              {group.avatar ?? <Users className=\"size-5 text-white/60\" />}\n            </div>\n            <div>\n              <SheetTitle>{group.name}</SheetTitle>\n              <SheetDescription>\n                {contactCount === 1\n                  ? t(\"groups_member_one\", { count: contactCount })\n                  : t(\"groups_member_other\", { count: contactCount })}\n              </SheetDescription>\n            </div>\n          </div>\n        </SheetHeader>\n      )}\n\n      {/* Search to add contacts */}\n      <div className=\"relative border-b px-6 py-3\">\n        <div className=\"relative\">\n          <Search className=\"text-muted-foreground pointer-events-none absolute top-1/2 left-3 size-3.5 -translate-y-1/2\" />\n          <Input\n            type=\"text\"\n            value={addSearch}\n            onChange={(e) => setAddSearch(e.target.value)}\n            placeholder={t(\"groups_search_contacts_to_add\")}\n            className=\"pl-8\"\n          />\n        </div>\n        {addSearch && nonMembers.length > 0 && (\n          <div className=\"bg-popover border-border absolute right-6 left-6 z-10 mt-1 max-h-48 overflow-y-auto rounded-md border shadow-md\">\n            {nonMembers.map((contact) => (\n              <button\n                key={contact.id}\n                type=\"button\"\n                onClick={() => handleAddContact(contact)}\n                className=\"hover:bg-muted flex w-full items-center gap-3 px-3 py-2 text-left text-sm\"\n              >\n                <div className=\"bg-muted flex size-7 shrink-0 items-center justify-center rounded-full text-xs font-medium\">\n                  {contact.first_name?.[0] ?? \"\"}\n                  {contact.last_name?.[0] ?? \"\"}\n                </div>\n                <div className=\"min-w-0 flex-1\">\n                  <p className=\"text-foreground truncate text-sm\">\n                    {contact.full_name}\n                  </p>\n                  {contact.email && (\n                    <p className=\"text-muted-foreground truncate text-xs\">\n                      {contact.email}\n                    </p>\n                  )}\n                </div>\n                <Plus className=\"text-primary size-4 shrink-0\" />\n              </button>\n            ))}\n          </div>\n        )}\n        {addSearch && nonMembers.length === 0 && searchResults && (\n          <div className=\"bg-popover border-border absolute right-6 left-6 z-10 mt-1 rounded-md border p-3 shadow-md\">\n            <p className=\"text-muted-foreground text-center text-sm\">\n              {t(\"groups_no_contacts_found\")}\n            </p>\n          </div>\n        )}\n      </div>\n\n      {/* Members list */}\n      <div className=\"flex-1 overflow-y-auto px-6 py-3\">\n        {isLoadingMembers ? (\n          <div className=\"text-muted-foreground py-8 text-center text-sm\">\n            {t(\"groups_loading_members\")}\n          </div>\n        ) : !members || members.length === 0 ? (\n          <div className=\"text-muted-foreground py-8 text-center text-sm\">\n            {t(\"groups_empty_members\")}\n          </div>\n        ) : (\n          <div className=\"space-y-1\">\n            {members.map((contact) => (\n              <div\n                key={contact.id}\n                className={cn(\n                  \"group/member hover:bg-muted/50 focus-within:bg-muted/50 flex cursor-pointer items-center gap-3 rounded-md px-2 py-2 transition-colors duration-1000\",\n                  recentlyAddedId === contact.id && \"animate-highlight-fade\",\n                )}\n                onClick={() => {\n                  if (onSelectContact) {\n                    onOpenChange(false);\n                    onSelectContact(String(contact.id));\n                  }\n                }}\n                role=\"button\"\n                tabIndex={0}\n                onKeyDown={(e) => {\n                  if ((e.key === \"Enter\" || e.key === \" \") && onSelectContact) {\n                    e.preventDefault();\n                    onOpenChange(false);\n                    onSelectContact(String(contact.id));\n                  }\n                }}\n              >\n                <div className=\"bg-muted text-muted-foreground flex size-9 shrink-0 items-center justify-center rounded-full text-xs font-semibold\">\n                  {contact.first_name?.[0] ?? \"\"}\n                  {contact.last_name?.[0] ?? \"\"}\n                </div>\n                <div className=\"min-w-0 flex-1\">\n                  <p className=\"text-foreground text-sm font-medium\">\n                    {contact.full_name}\n                  </p>\n                  {contact.email && (\n                    <p className=\"text-muted-foreground truncate text-xs\">\n                      {contact.email}\n                    </p>\n                  )}\n                </div>\n                <IconButton\n                  icon={X}\n                  onClick={(e) => {\n                    e.stopPropagation();\n                    handleRemoveContact(contact);\n                  }}\n                  className=\"text-muted-foreground hover:text-destructive size-7 rounded-full opacity-0 group-focus-within/member:opacity-100 group-hover/member:opacity-100 focus:opacity-100 [&_svg:not([class*='size-'])]:size-3.5\"\n                  aria-label={t(\"groups_remove_member_aria\", {\n                    name: contact.full_name ?? \"\",\n                  })}\n                />\n              </div>\n            ))}\n          </div>\n        )}\n      </div>\n    </>\n  );\n\n  if (isMobile) {\n    return (\n      <MobileBottomSheet\n        open={open}\n        onOpenChange={onOpenChange}\n        title={group.name}\n      >\n        {content}\n      </MobileBottomSheet>\n    );\n  }\n\n  return (\n    <Sheet open={open} onOpenChange={onOpenChange}>\n      <SheetContent side=\"right\" className=\"flex flex-col overflow-hidden p-0\">\n        {content}\n      </SheetContent>\n    </Sheet>\n  );\n}\n\nfunction GroupsSkeleton() {\n  return (\n    <div className=\"space-y-2\">\n      {[0, 1, 2, 3].map((i) => (\n        <div\n          key={i}\n          className=\"flex items-center gap-4 rounded-lg px-4 py-3\"\n          aria-hidden=\"true\"\n        >\n          <Skeleton className=\"size-10 rounded-full\" />\n          <div className=\"flex-1 space-y-2\">\n            <Skeleton className=\"h-4 w-32\" />\n            <Skeleton className=\"h-3 w-24\" />\n          </div>\n        </div>\n      ))}\n    </div>\n  );\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { useContactsCrud } from \"../contacts-api-context\";\nimport { CONTACTS_QUERY_KEYS } from \"../query-keys\";\n\nexport interface UseCreateContactMutationOptions {\n  onSuccess?: (data: unknown) => void;\n  onError?: (error: unknown) => void;\n}\n\nexport function useCreateContactMutation<\n  TInput extends object = Record<string, unknown>,\n>(queryKeyPrefix = \"contacts\", options?: UseCreateContactMutationOptions) {\n  const queryClient = useQueryClient();\n  const api = useContactsCrud();\n\n  return useMutation({\n    mutationFn: (data: TInput) =>\n      api.createContact(data as Record<string, unknown>),\n    onSuccess: (data) => {\n      queryClient.invalidateQueries({\n        queryKey: CONTACTS_QUERY_KEYS.all(queryKeyPrefix),\n      });\n      if (queryKeyPrefix !== \"contacts\") {\n        queryClient.invalidateQueries({\n          queryKey: CONTACTS_QUERY_KEYS.all(\"contacts\"),\n        });\n      }\n      options?.onSuccess?.(data);\n    },\n    onError: (error) => {\n      options?.onError?.(error);\n    },\n  });\n}\n","\"use client\";\n\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport { useCreateContactMutation as useCoreCreateContactMutation } from \"@fluid-app/contacts-core/hooks/use-create-contact-mutation\";\nimport { useOptionalContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport type { CreateContactFormData } from \"../schemas/contactFormSchema\";\n\nexport function useCreateContactMutation(\n  queryKeyPrefix = \"contacts\",\n  options?: {\n    onSuccess?: (data: { contact: { id: number } }) => void;\n    onError?: (error: unknown) => void;\n  },\n) {\n  const i18n = useOptionalContactsTranslation();\n\n  return useCoreCreateContactMutation<CreateContactFormData>(queryKeyPrefix, {\n    onSuccess: (data) => {\n      fluidToast({\n        title: i18n?.t(\"contact_created\") ?? \"Contact created successfully\",\n        type: \"success\",\n      });\n      options?.onSuccess?.(data as { contact: { id: number } });\n    },\n    onError: (error) => {\n      if (options?.onError) {\n        options.onError(error);\n      } else {\n        fluidToast({\n          title: i18n?.t(\"contact_create_failed\") ?? \"Failed to create contact\",\n          type: \"error\",\n          description: parseApiErrors(error),\n        });\n      }\n    },\n  });\n}\n","import {\n  decodeSlugSegment,\n  encodeSlugSegment,\n  splitSlug,\n} from \"./screen-route-slug-utils\";\n\nexport type ContactsNavState =\n  | { view: \"browse\"; selectedContactId: string | null }\n  | { view: \"new\" };\n\nexport type ContactsRouteState = {\n  nav: ContactsNavState;\n  subPage: \"manage-groups\" | null;\n};\n\nexport function getContactsBaseSlug(currentSlug: string): string {\n  return splitSlug(currentSlug)[0] ?? \"contacts\";\n}\n\nexport function resolveContactsRouteState(\n  currentSlug: string,\n): ContactsRouteState {\n  const [, rawSubPage] = splitSlug(currentSlug);\n  const subPage = rawSubPage ? decodeSlugSegment(rawSubPage) : undefined;\n\n  if (subPage === \"manage-groups\") {\n    return {\n      nav: { view: \"browse\", selectedContactId: null },\n      subPage: \"manage-groups\",\n    };\n  }\n\n  if (subPage === \"new\") {\n    return {\n      nav: { view: \"new\" },\n      subPage: null,\n    };\n  }\n\n  if (subPage) {\n    return {\n      nav: { view: \"browse\", selectedContactId: subPage },\n      subPage: null,\n    };\n  }\n\n  return {\n    nav: { view: \"browse\", selectedContactId: null },\n    subPage: null,\n  };\n}\n\nexport function buildContactsSlug(\n  baseSlug: string,\n  state: ContactsNavState,\n): string {\n  const normalizedBaseSlug = getContactsBaseSlug(baseSlug);\n\n  if (state.view === \"new\") {\n    return `${normalizedBaseSlug}/new`;\n  }\n\n  if (!state.selectedContactId) {\n    return normalizedBaseSlug;\n  }\n\n  return `${normalizedBaseSlug}/${encodeSlugSegment(state.selectedContactId)}`;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { FormProvider } from \"react-hook-form\";\nimport { useZodForm, fluidToast, cn, Button } from \"@fluid-app/ui-primitives\";\nimport { MobileBottomSheet } from \"@fluid-app/ui-components/components/MobileBottomSheet\";\nimport { useIsMobile } from \"@fluid-app/portal-react/shell/use-mobile\";\nimport { parseApiErrors } from \"@fluid-app/api-client-core\";\nimport type { ComponentProps } from \"react\";\nimport type { Contact as ContactType } from \"@fluid-app/contacts-core/types\";\nimport type { ContactsDomainApi } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { useContactsCrud } from \"@fluid-app/contacts-core/contacts-api-context\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport { invalidateContactCaches } from \"@fluid-app/contacts-ui/portal/hooks/groups/invalidate-contact-caches\";\nimport type {\n  BackgroundValue,\n  BorderRadiusOptions,\n  ColorOptions,\n  PaddingOptions,\n} from \"../types\";\nimport type { WidgetPropertySchema } from \"../registries/property-schema-types\";\nimport { ContactCreateScreen } from \"@fluid-app/contacts-ui/screens/ContactCreateScreen\";\nimport { RepContactsLayout } from \"@fluid-app/contacts-ui/portal/components/contacts/rep-layout/RepContactsLayout\";\nimport {\n  GroupsManagePage,\n  GroupDialog,\n} from \"@fluid-app/contacts-ui/portal/components/contacts/rep-layout/GroupsManagePage\";\nimport { ContactDetailsForm } from \"@fluid-app/contacts-ui/shared/components/contacts/contactDetailsForm\";\nimport { useCreateContactMutation } from \"@fluid-app/contacts-ui/shared/hooks/useCreateContactMutation\";\nimport {\n  createContactFormSchema,\n  type CreateContactFormData,\n} from \"@fluid-app/contacts-ui/shared/schemas/contactFormSchema\";\nimport { useActiveLocale } from \"@fluid-app/i18n/locale-context\";\nimport { useCountriesApi } from \"@fluid-app/store-core/countries-api-context\";\nimport { PortalContactsApiProvider } from \"../contacts/PortalContactsApiProvider\";\nimport { ContactsTranslationBridge } from \"../providers/ContactsTranslationBridge\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\nimport { storeKeys } from \"../account/query-keys\";\nimport {\n  buildContactsSlug,\n  getContactsBaseSlug,\n  resolveContactsRouteState,\n  type ContactsNavState,\n} from \"./contacts-route-state\";\n\ntype ContactsScreenProps = ComponentProps<\"div\"> & {\n  api?: ContactsDomainApi;\n  // Styling\n  background?: BackgroundValue;\n  textColor?: ColorOptions;\n  accentColor?: ColorOptions;\n  padding?: PaddingOptions;\n  borderRadius?: BorderRadiusOptions;\n\n  // Display\n  defaultViewMode?: \"list\" | \"grid\";\n\n  // Callbacks\n  onContactSelect?: (contactId: string) => void;\n  onCreateContact?: () => void;\n};\n\nconst QUERY_KEY_PREFIX = \"sdk-contacts\";\n\nfunction ContactBrowseView({\n  selectedContactId,\n  highlightContactId,\n  onSelect,\n  onAdd,\n  onManageGroups,\n  onCreateGroup,\n  highlightGroupName,\n  showMobileDetailBackButton = true,\n}: {\n  selectedContactId: string | null;\n  highlightContactId?: string | null;\n  highlightGroupName?: string | null;\n  onSelect: (id: string | null) => void;\n  onAdd: () => void;\n  onManageGroups: () => void;\n  onCreateGroup: () => void;\n  showMobileDetailBackButton?: boolean;\n}) {\n  const { t } = useContactsTranslation();\n  const { locale } = useActiveLocale();\n  const countriesAdapter = useCountriesApi();\n  const contactsApi = useContactsCrud();\n  const queryClient = useQueryClient();\n  const contactDetailCountriesQueryKey = useMemo(\n    () => [...storeKeys.countries(locale), \"contact-detail\"] as const,\n    [locale],\n  );\n\n  const getCountries = useCallback(async () => {\n    const result = await countriesAdapter.listCountries({\n      languageIso: locale,\n    });\n    return result.countries.map((c) => ({ id: 0, name: c.name, iso: c.code }));\n  }, [countriesAdapter, locale]);\n\n  const handleDeleteContact = useCallback(\n    (contact: ContactType) => {\n      const name = contact.full_name || t(\"contact_label\");\n      contactsApi\n        .deleteContact(String(contact.id))\n        .then(() => {\n          invalidateContactCaches(queryClient);\n          if (selectedContactId === String(contact.id)) {\n            onSelect(null);\n          }\n          fluidToast({\n            title: t(\"contact_deleted_toast\", { name }),\n            type: \"success\",\n          });\n        })\n        .catch((error) => {\n          fluidToast({\n            title: t(\"contact_delete_failed\"),\n            description: parseApiErrors(error),\n            type: \"error\",\n          });\n        });\n    },\n    [contactsApi, queryClient, selectedContactId, onSelect, t],\n  );\n\n  return (\n    <RepContactsLayout\n      selectedContactId={selectedContactId}\n      highlightContactId={highlightContactId}\n      onSelect={onSelect}\n      onAdd={onAdd}\n      onManageGroups={onManageGroups}\n      onCreateGroup={onCreateGroup}\n      highlightGroupName={highlightGroupName}\n      onDeleteContact={handleDeleteContact}\n      queryKeyPrefix={QUERY_KEY_PREFIX}\n      countriesQueryKey={contactDetailCountriesQueryKey}\n      getCountries={getCountries}\n      showMobileDetailBackButton={showMobileDetailBackButton}\n    />\n  );\n}\n\nconst CREATE_DEFAULT_VALUES: CreateContactFormData = {\n  first_name: \"\",\n  last_name: \"\",\n  email: \"\",\n  phone: \"\",\n  status: \"new\",\n  address: \"\",\n  city: \"\",\n  state: \"\",\n  postal_code: \"\",\n  country_code: null,\n  language_code: null,\n  metadata: {},\n  affiliate: {},\n};\n\nfunction ContactCreateView({\n  onNavigate,\n  onCreateContact,\n  asSheet = false,\n}: {\n  onNavigate: (state: ContactsNavState) => void;\n  onCreateContact?: () => void;\n  asSheet?: boolean;\n}) {\n  const { t } = useContactsTranslation();\n  const formRef = useRef<HTMLFormElement>(null);\n  const { locale } = useActiveLocale();\n  const countriesAdapter = useCountriesApi();\n\n  const { data: countriesResponse } = useQuery({\n    queryKey: storeKeys.countries(locale),\n    queryFn: () => countriesAdapter.listCountries({ languageIso: locale }),\n  });\n\n  const countryOptions = useMemo(\n    () =>\n      (countriesResponse?.countries ?? [])\n        .map((c) => ({ name: c.name, value: c.code }))\n        .sort((a, b) => a.name.localeCompare(b.name)),\n    [countriesResponse],\n  );\n\n  const methods = useZodForm<CreateContactFormData>(createContactFormSchema, {\n    defaultValues: CREATE_DEFAULT_VALUES,\n  });\n\n  const mutation = useCreateContactMutation(QUERY_KEY_PREFIX, {\n    onSuccess: (data) => {\n      onCreateContact?.();\n      const newContactId = data?.contact?.id;\n      if (newContactId) {\n        onNavigate({\n          view: \"browse\",\n          selectedContactId: String(newContactId),\n        });\n      } else {\n        onNavigate({ view: \"browse\", selectedContactId: null });\n      }\n    },\n  });\n\n  const { mutate } = mutation;\n\n  const onSubmit = useMemo(\n    () =>\n      methods.handleSubmit(\n        (data) => {\n          const { affiliate, ...contactFields } = data;\n          const payload: Record<string, unknown> = {};\n\n          for (const [key, value] of Object.entries(contactFields)) {\n            if (value !== \"\" && value !== null && value !== undefined) {\n              payload[key] = value;\n            }\n          }\n\n          if (affiliate && Object.keys(affiliate).length > 0) {\n            payload.affiliate = affiliate;\n          }\n\n          mutate(payload as CreateContactFormData);\n        },\n        () => {\n          // Validation errors are shown inline by react-hook-form field controllers.\n          // handleSubmit already populates field errors before calling this callback.\n        },\n      ),\n    [methods, mutate],\n  );\n\n  const handleNavigateToList = useCallback(() => {\n    onNavigate({ view: \"browse\", selectedContactId: null });\n  }, [onNavigate]);\n\n  if (asSheet) {\n    return (\n      <MobileBottomSheet\n        open\n        onOpenChange={(nextOpen) => {\n          if (!nextOpen) handleNavigateToList();\n        }}\n        title={t(\"breadcrumb_new\")}\n      >\n        <FormProvider {...methods}>\n          <form\n            ref={formRef}\n            onSubmit={onSubmit}\n            className=\"space-y-6 px-2 pb-2\"\n          >\n            <ContactDetailsForm countries={countryOptions} />\n            <div className=\"flex justify-end gap-2\">\n              <Button\n                type=\"button\"\n                variant=\"outline\"\n                onClick={handleNavigateToList}\n              >\n                {t(\"cancel\")}\n              </Button>\n              <Button type=\"submit\" disabled={mutation.isPending}>\n                {mutation.isPending ? t(\"adding\") : t(\"add_contact\")}\n              </Button>\n            </div>\n          </form>\n        </FormProvider>\n      </MobileBottomSheet>\n    );\n  }\n\n  return (\n    <ContactCreateScreen\n      onNavigateToList={handleNavigateToList}\n      onSubmit={() => formRef.current?.requestSubmit()}\n      isPending={mutation.isPending}\n    >\n      <FormProvider {...methods}>\n        <div className=\"mx-auto max-w-7xl space-y-12 md:px-10 md:py-8\">\n          <form\n            ref={formRef}\n            onSubmit={onSubmit}\n            className=\"mx-auto space-y-6 lg:max-w-2xl\"\n          >\n            <ContactDetailsForm countries={countryOptions} />\n          </form>\n        </div>\n      </FormProvider>\n    </ContactCreateScreen>\n  );\n}\n\nexport function ContactsScreen({\n  api,\n  onContactSelect,\n  onCreateContact,\n  /* eslint-disable @typescript-eslint/no-unused-vars -- destructured to exclude from divProps spread */\n  background,\n  textColor,\n  accentColor,\n  padding,\n  borderRadius,\n  defaultViewMode,\n  /* eslint-enable @typescript-eslint/no-unused-vars */\n  ...divProps\n}: ContactsScreenProps): React.JSX.Element {\n  const { currentSlug, navigate } = useAppNavigation();\n  const contactsBaseSlug = useMemo(\n    () => getContactsBaseSlug(currentSlug),\n    [currentSlug],\n  );\n  const { nav, subPage } = useMemo(\n    () => resolveContactsRouteState(currentSlug),\n    [currentSlug],\n  );\n  const isMobile = useIsMobile();\n  const [mobileCreateOpen, setMobileCreateOpen] = useState(false);\n\n  const [highlightContactId, setHighlightContactId] = useState<string | null>(\n    null,\n  );\n\n  useEffect(() => {\n    if (highlightContactId == null) return;\n    const timer = setTimeout(() => setHighlightContactId(null), 2000);\n    return () => clearTimeout(timer);\n  }, [highlightContactId]);\n\n  const handleNavigate = useCallback(\n    (state: ContactsNavState) => {\n      navigate(buildContactsSlug(contactsBaseSlug, state));\n    },\n    [contactsBaseSlug, navigate],\n  );\n\n  const handleSelect = useCallback(\n    (id: string | null) => {\n      handleNavigate({ view: \"browse\", selectedContactId: id });\n      if (id) onContactSelect?.(id);\n    },\n    [handleNavigate, onContactSelect],\n  );\n\n  const handleAdd = useCallback(() => {\n    if (isMobile) {\n      setMobileCreateOpen(true);\n      return;\n    }\n    handleNavigate({ view: \"new\" });\n  }, [handleNavigate, isMobile]);\n\n  const handleManageGroups = useCallback(() => {\n    navigate(`${contactsBaseSlug}/manage-groups`);\n  }, [contactsBaseSlug, navigate]);\n\n  const handleCreateNavigate = useCallback(\n    (state: ContactsNavState) => {\n      handleNavigate(state);\n      if (state.view === \"browse\" && state.selectedContactId) {\n        setHighlightContactId(state.selectedContactId);\n      }\n    },\n    [handleNavigate],\n  );\n  const handleCreateViewNavigate = useCallback(\n    (state: ContactsNavState) => {\n      setMobileCreateOpen(false);\n      if (\n        nav.view === \"new\" ||\n        state.view === \"new\" ||\n        (state.view === \"browse\" && state.selectedContactId)\n      ) {\n        handleCreateNavigate(state);\n      }\n    },\n    [handleCreateNavigate, nav.view],\n  );\n\n  const [createGroupOpen, setCreateGroupOpen] = useState(false);\n  const [highlightGroupName, setHighlightGroupName] = useState<string | null>(\n    null,\n  );\n\n  useEffect(() => {\n    if (highlightGroupName == null) return;\n    const timer = setTimeout(() => setHighlightGroupName(null), 2000);\n    return () => clearTimeout(timer);\n  }, [highlightGroupName]);\n\n  const handleCreateGroup = useCallback(() => {\n    setCreateGroupOpen(true);\n  }, []);\n\n  const createViewOpen = mobileCreateOpen || nav.view === \"new\";\n  const showBrowseView = isMobile || !createViewOpen;\n\n  return (\n    <ContactsTranslationBridge>\n      <PortalContactsApiProvider api={api}>\n        <div {...divProps} className={cn(\"h-full\", divProps.className)}>\n          {subPage === \"manage-groups\" ? (\n            <GroupsManagePage\n              onBack={() => navigate(contactsBaseSlug)}\n              onSelectContact={(contactId) => {\n                setHighlightContactId(contactId);\n                navigate(\n                  buildContactsSlug(contactsBaseSlug, {\n                    view: \"browse\",\n                    selectedContactId: contactId,\n                  }),\n                );\n              }}\n              showMobileBackButton={false}\n            />\n          ) : (\n            <>\n              {showBrowseView ? (\n                <ContactBrowseView\n                  selectedContactId={\n                    nav.view === \"browse\" ? nav.selectedContactId : null\n                  }\n                  highlightContactId={highlightContactId}\n                  onSelect={handleSelect}\n                  onAdd={handleAdd}\n                  onManageGroups={handleManageGroups}\n                  onCreateGroup={handleCreateGroup}\n                  highlightGroupName={highlightGroupName}\n                  showMobileDetailBackButton={false}\n                />\n              ) : null}\n              {createViewOpen ? (\n                <ContactCreateView\n                  asSheet={isMobile}\n                  onNavigate={handleCreateViewNavigate}\n                  onCreateContact={onCreateContact}\n                />\n              ) : null}\n            </>\n          )}\n          <GroupDialog\n            key={createGroupOpen ? \"open\" : \"closed\"}\n            mode=\"create\"\n            open={createGroupOpen}\n            onOpenChange={(open) => setCreateGroupOpen(open)}\n            onGroupCreatedWithName={(name) => {\n              setHighlightGroupName(name);\n            }}\n          />\n        </div>\n      </PortalContactsApiProvider>\n    </ContactsTranslationBridge>\n  );\n}\n\nexport const contactsScreenPropertySchema: WidgetPropertySchema = {\n  widgetType: \"ContactsScreen\",\n  displayName: \"Contacts Screen\",\n  tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n  fields: [],\n} as const satisfies WidgetPropertySchema;\n"],"x_google_ignoreList":[41],"mappings":"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"}