@burdenoff/microfe-conversations 2026.608.1 → 2026.625.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"ConversationAdminPages.js","names":[],"sources":["../../../src/conversations/pages/ConversationAdminPages.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { gql } from \"@apollo/client\";\nimport { useMutation, useQuery } from \"@apollo/client/react\";\nimport {\n Activity,\n Archive,\n CheckCircle2,\n Package,\n ShieldCheck,\n Trash2,\n} from \"lucide-react\";\n\nimport { EmptyState, PageLayout, PageSection } from \"../components/PageLayout\";\nimport { useConversations } from \"../providers/ConversationsProvider\";\nimport { useTr } from \"../utils/i18n\";\n\nconst GET_MESSAGE_REPORTS = gql`\n query ConversationAdminMessageReports(\n $first: Int\n $filter: MessageReportFilter\n ) {\n messageReports(first: $first, filter: $filter) {\n edges {\n node {\n id\n messageId\n reportedBy\n reason\n status\n notes\n createdAt\n reviewedAt\n message {\n id\n conversationId\n authorId\n content\n isHidden\n createdAt\n }\n }\n }\n }\n }\n`;\n\nconst RESOLVE_MESSAGE_REPORT = gql`\n mutation ConversationAdminResolveMessageReport(\n $input: ResolveMessageReportInput!\n ) {\n resolveMessageReport(input: $input) {\n id\n status\n reviewedAt\n notes\n message {\n id\n isHidden\n }\n }\n }\n`;\n\nconst GET_BULK_CONVERSATIONS = gql`\n query ConversationAdminBulkConversations(\n $first: Int\n $filter: ConversationFilter\n ) {\n conversations(first: $first, filter: $filter) {\n edges {\n node {\n id\n title\n type\n state\n updatedAt\n }\n }\n }\n }\n`;\n\nconst BULK_UPDATE_CONVERSATIONS = gql`\n mutation ConversationAdminBulkUpdate(\n $input: BulkConversationOperationInput!\n ) {\n bulkUpdateConversations(input: $input) {\n success\n processedCount\n successCount\n failureCount\n conversationIds\n errors {\n conversationId\n message\n }\n }\n }\n`;\n\nconst GET_CONVERSATION_AUDIT_LOG = gql`\n query ConversationAdminAuditLog($filter: ActivityLogFilter) {\n getActivities(filter: $filter) {\n id\n action\n description\n resourceId\n resourceType\n userId\n timestamp\n }\n }\n`;\n\nconst GET_APP_INSTALLATIONS = gql`\n query ConversationAdminAppInstallations($workspaceId: ID) {\n appInstallations(workspaceId: $workspaceId) {\n id\n appId\n appVersion\n state\n settings\n permissions\n installedBy\n installedAt\n updatedAt\n }\n }\n`;\n\nconst INSTALL_APP = gql`\n mutation ConversationAdminInstallApp($input: InstallAppInput!) {\n installApp(input: $input) {\n id\n appId\n state\n settings\n installedAt\n }\n }\n`;\n\nconst UPDATE_APP_SETTINGS = gql`\n mutation ConversationAdminUpdateAppSettings($id: ID!, $settings: JSON!) {\n updateAppSettings(id: $id, settings: $settings) {\n id\n settings\n updatedAt\n }\n }\n`;\n\nconst UNINSTALL_APP = gql`\n mutation ConversationAdminUninstallApp($id: ID!) {\n uninstallApp(id: $id) {\n appInstallationId\n success\n }\n }\n`;\n\ninterface MessageReportNode {\n id: string;\n messageId: string;\n reportedBy: string;\n reason: string;\n status: string;\n notes?: string | null;\n createdAt: string;\n reviewedAt?: string | null;\n message: {\n id: string;\n conversationId: string;\n authorId: string;\n content: unknown;\n isHidden: boolean;\n createdAt: string;\n };\n}\n\ninterface ConversationNode {\n id: string;\n title?: string | null;\n type: string;\n state: string;\n updatedAt: string;\n}\n\ninterface ActivityLogNode {\n id: string;\n action: string;\n description?: string | null;\n resourceId?: string | null;\n resourceType?: string | null;\n userId: string;\n timestamp: string;\n}\n\ninterface AppInstallationNode {\n id: string;\n appId: string;\n appVersion: string;\n state: string;\n settings: unknown;\n permissions: string[];\n installedBy: string;\n installedAt: string;\n updatedAt: string;\n}\n\ninterface BulkUpdateConversationsResult {\n bulkUpdateConversations: {\n success: boolean;\n processedCount: number;\n successCount: number;\n failureCount: number;\n conversationIds: string[];\n errors: Array<{ conversationId: string; message: string }>;\n };\n}\n\nfunction formatContent(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (content && typeof content === \"object\" && \"text\" in content) {\n const text = (content as { text?: unknown }).text;\n if (typeof text === \"string\") return text;\n }\n try {\n return JSON.stringify(content);\n } catch {\n return \"Message content unavailable\";\n }\n}\n\nconst DATE_FORMATTER = new Intl.DateTimeFormat(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n});\n\nfunction formatDate(value: string): string {\n return DATE_FORMATTER.format(new Date(value));\n}\n\nfunction StatusPill({ children }: { children: string }) {\n return (\n <span className=\"rounded-full border border-border bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground\">\n {children}\n </span>\n );\n}\n\nexport function ModerationQueuePage() {\n const tr = useTr();\n const { workspaceId } = useConversations();\n const { data, loading, error, refetch } = useQuery<{\n messageReports: { edges: Array<{ node: MessageReportNode }> };\n }>(GET_MESSAGE_REPORTS, {\n variables: { first: 50, filter: { statuses: [\"PENDING\", \"REVIEWING\"] } },\n skip: !workspaceId,\n });\n const [resolveReport, { loading: resolving }] = useMutation(\n RESOLVE_MESSAGE_REPORT,\n {\n onCompleted: () => void refetch(),\n },\n );\n\n const reports = data?.messageReports.edges.map((edge) => edge.node) ?? [];\n\n return (\n <PageLayout\n title={tr(\"conversations.admin.moderationPageTitle\", \"Moderation queue\")}\n subtitle={tr(\n \"conversations.admin.moderationPageDescription\",\n \"Review reported messages and apply moderator decisions.\",\n )}\n icon={<ShieldCheck className=\"size-5\" aria-hidden=\"true\" />}\n maxWidth=\"2xl\"\n >\n {!workspaceId && (\n <EmptyState\n title={tr(\n \"conversations.admin.selectWorkspace\",\n \"Select a workspace\",\n )}\n description={tr(\n \"conversations.admin.selectWorkspaceModerationDescription\",\n \"Choose a workspace to review reported conversation messages.\",\n )}\n icon={<ShieldCheck className=\"size-6\" aria-hidden=\"true\" />}\n />\n )}\n {workspaceId && loading && (\n <p className=\"text-sm text-muted-foreground\">Loading reports…</p>\n )}\n {workspaceId && error && (\n <p className=\"text-sm text-destructive\">{error.message}</p>\n )}\n {workspaceId && !loading && !error && reports.length === 0 && (\n <EmptyState\n title=\"No reports waiting for review\"\n description=\"Reported messages will appear here as they are submitted.\"\n icon={<CheckCircle2 className=\"size-6\" aria-hidden=\"true\" />}\n />\n )}\n <div className=\"grid gap-3\">\n {reports.map((report) => (\n <article\n key={report.id}\n className=\"rounded-lg border border-border bg-card p-4 shadow-sm\"\n >\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusPill>{report.status}</StatusPill>\n {report.message.isHidden && <StatusPill>Hidden</StatusPill>}\n <span className=\"text-xs text-muted-foreground\">\n Reported {formatDate(report.createdAt)}\n </span>\n </div>\n <p className=\"text-sm font-medium text-foreground\">\n {report.reason}\n </p>\n <p className=\"rounded-md bg-muted p-3 text-sm text-muted-foreground\">\n {formatContent(report.message.content)}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n Message {report.messageId} in conversation{\" \"}\n {report.message.conversationId} by {report.message.authorId};\n reported by {report.reportedBy}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n disabled={resolving}\n className=\"rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground hover:bg-accent disabled:opacity-50\"\n onClick={() =>\n void resolveReport({\n variables: {\n input: { reportId: report.id, action: \"DISMISS\" },\n },\n })\n }\n >\n Dismiss\n </button>\n <button\n type=\"button\"\n disabled={resolving}\n className=\"rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n onClick={() =>\n void resolveReport({\n variables: {\n input: { reportId: report.id, action: \"HIDE_MESSAGE\" },\n },\n })\n }\n >\n Hide and resolve\n </button>\n </div>\n </div>\n </article>\n ))}\n </div>\n </PageLayout>\n );\n}\n\nexport function BulkOperationsPage() {\n const tr = useTr();\n const { workspaceId } = useConversations();\n const [selectedIds, setSelectedIds] = useState<Set<string>>(() => new Set());\n const [action, setAction] = useState<\"ARCHIVE\" | \"UNARCHIVE\" | \"DELETE\">(\n \"ARCHIVE\",\n );\n const { data, loading, error, refetch } = useQuery<{\n conversations: { edges: Array<{ node: ConversationNode }> };\n }>(GET_BULK_CONVERSATIONS, {\n variables: { first: 100 },\n skip: !workspaceId,\n });\n const [bulkUpdate, { data: bulkResult, loading: updating }] = useMutation<\n BulkUpdateConversationsResult,\n { input: { conversationIds: string[]; action: typeof action } }\n >(BULK_UPDATE_CONVERSATIONS, {\n onCompleted: () => {\n setSelectedIds(new Set());\n void refetch();\n },\n });\n const conversations =\n data?.conversations.edges.map((edge) => edge.node) ?? [];\n\n const toggle = (id: string) => {\n setSelectedIds((current) => {\n const next = new Set(current);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n };\n\n return (\n <PageLayout\n title={tr(\n \"conversations.admin.bulkOperationsPageTitle\",\n \"Bulk operations\",\n )}\n subtitle={tr(\n \"conversations.admin.bulkOperationsPageDescription\",\n \"Select workspace conversations and apply archive, unarchive, or delete operations.\",\n )}\n icon={<Archive className=\"size-5\" aria-hidden=\"true\" />}\n maxWidth=\"2xl\"\n headerActions={\n <div className=\"flex flex-wrap items-center gap-2\">\n <select\n value={action}\n onChange={(event) => setAction(event.target.value as typeof action)}\n className=\"rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n >\n <option value=\"ARCHIVE\">Archive</option>\n <option value=\"UNARCHIVE\">Unarchive</option>\n <option value=\"DELETE\">Delete</option>\n </select>\n <button\n type=\"button\"\n disabled={selectedIds.size === 0 || updating}\n className=\"rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n onClick={() =>\n void bulkUpdate({\n variables: {\n input: { conversationIds: Array.from(selectedIds), action },\n },\n })\n }\n >\n Apply to {selectedIds.size}\n </button>\n </div>\n }\n >\n {!workspaceId && (\n <EmptyState\n title={tr(\n \"conversations.admin.selectWorkspace\",\n \"Select a workspace\",\n )}\n description={tr(\n \"conversations.admin.selectWorkspaceBulkDescription\",\n \"Choose a workspace to manage conversations in bulk.\",\n )}\n icon={<Archive className=\"size-6\" aria-hidden=\"true\" />}\n />\n )}\n {workspaceId && loading && (\n <p className=\"text-sm text-muted-foreground\">Loading conversations…</p>\n )}\n {workspaceId && error && (\n <p className=\"text-sm text-destructive\">{error.message}</p>\n )}\n {bulkResult?.bulkUpdateConversations && (\n <div className=\"rounded-lg border border-border bg-muted p-3 text-sm text-muted-foreground\">\n {bulkResult.bulkUpdateConversations.successCount} succeeded,{\" \"}\n {bulkResult.bulkUpdateConversations.failureCount} failed.\n </div>\n )}\n {workspaceId && (\n <div className=\"overflow-hidden rounded-lg border border-border bg-card\">\n {conversations.map((conversation) => (\n <label\n key={conversation.id}\n className=\"flex cursor-pointer items-center gap-3 border-b border-border px-4 py-3 last:border-b-0 hover:bg-accent\"\n >\n <input\n type=\"checkbox\"\n aria-label={`Select ${conversation.title || \"untitled conversation\"}`}\n checked={selectedIds.has(conversation.id)}\n onChange={() => toggle(conversation.id)}\n />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-foreground\">\n {conversation.title || \"Untitled conversation\"}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {conversation.type} · {conversation.state} · Updated{\" \"}\n {formatDate(conversation.updatedAt)}\n </p>\n </div>\n </label>\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n\nexport function ConversationAuditLogPage() {\n const tr = useTr();\n const { workspaceId } = useConversations();\n const { data, loading, error } = useQuery<{\n getActivities: ActivityLogNode[];\n }>(GET_CONVERSATION_AUDIT_LOG, {\n variables: {\n filter: { workspaceId, resourceType: \"conversation\", limit: 50 },\n },\n skip: !workspaceId,\n });\n const logs = data?.getActivities ?? [];\n\n return (\n <PageLayout\n title={tr(\"conversations.admin.auditLogPageTitle\", \"Audit log\")}\n subtitle={tr(\n \"conversations.admin.auditLogPageDescription\",\n \"Activity stream for admin and moderator actions on workspace conversations.\",\n )}\n icon={<Activity className=\"size-5\" aria-hidden=\"true\" />}\n maxWidth=\"2xl\"\n >\n {loading && (\n <p className=\"text-sm text-muted-foreground\">Loading activity…</p>\n )}\n {error && <p className=\"text-sm text-destructive\">{error.message}</p>}\n {!loading && !error && logs.length === 0 && (\n <EmptyState\n title=\"No activity found\"\n description=\"Conversation admin actions will appear here.\"\n />\n )}\n <div className=\"grid gap-3\">\n {logs.map((log) => (\n <article\n key={log.id}\n className=\"rounded-lg border border-border bg-card p-4\"\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <p className=\"text-sm font-medium text-foreground\">\n {log.action}\n </p>\n <span className=\"text-xs text-muted-foreground\">\n {formatDate(log.timestamp)}\n </span>\n </div>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {log.description || \"No description provided\"}\n </p>\n <p className=\"mt-2 text-xs text-muted-foreground\">\n User {log.userId} · Resource {log.resourceId ?? \"workspace\"}\n </p>\n </article>\n ))}\n </div>\n </PageLayout>\n );\n}\n\nexport function AppInstallationsPage() {\n const tr = useTr();\n const { workspaceId } = useConversations();\n const [appId, setAppId] = useState(\"\");\n const [settingsInput, setSettingsInput] = useState(\"{}\");\n const [settingsDrafts, setSettingsDrafts] = useState<Record<string, string>>(\n {},\n );\n const [formError, setFormError] = useState<string | null>(null);\n const { data, loading, error, refetch } = useQuery<{\n appInstallations: AppInstallationNode[];\n }>(GET_APP_INSTALLATIONS, {\n variables: { workspaceId },\n skip: !workspaceId,\n });\n const [installApp, { loading: installing }] = useMutation(INSTALL_APP, {\n onCompleted: () => void refetch(),\n });\n const [updateSettings, { loading: saving }] = useMutation(\n UPDATE_APP_SETTINGS,\n { onCompleted: () => void refetch() },\n );\n const [uninstallApp, { loading: uninstalling }] = useMutation(UNINSTALL_APP, {\n onCompleted: () => void refetch(),\n });\n const installations = useMemo(\n () => data?.appInstallations ?? [],\n [data?.appInstallations],\n );\n\n useEffect(() => {\n setSettingsDrafts((current) => {\n if (installations.every((installation) => current[installation.id])) {\n return current;\n }\n const next = { ...current };\n for (const installation of installations) {\n if (!next[installation.id]) {\n next[installation.id] = JSON.stringify(\n installation.settings ?? {},\n null,\n 2,\n );\n }\n }\n return next;\n });\n }, [installations]);\n\n const parsedSettings = (raw: string): Record<string, unknown> | null => {\n try {\n const parsed = JSON.parse(raw) as unknown;\n return parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n };\n\n const handleInstall = () => {\n const settings = parsedSettings(settingsInput);\n if (!appId.trim() || !settings) {\n setFormError(\"Enter an app ID and a valid JSON settings object.\");\n return;\n }\n setFormError(null);\n void installApp({\n variables: { input: { appId: appId.trim(), workspaceId, settings } },\n });\n };\n\n return (\n <PageLayout\n title={tr(\n \"conversations.admin.appInstallationsPageTitle\",\n \"App installations\",\n )}\n subtitle={tr(\n \"conversations.admin.appInstallationsPageDescription\",\n \"Install, configure, and remove conversation apps and integrations.\",\n )}\n icon={<Package className=\"size-5\" aria-hidden=\"true\" />}\n maxWidth=\"2xl\"\n >\n <PageSection\n title=\"Install app\"\n description=\"Install a workspace-scoped conversation app by app ID.\"\n >\n <div className=\"grid gap-3 rounded-lg border border-border bg-card p-4 sm:grid-cols-[minmax(0,1fr)_minmax(0,2fr)_auto]\">\n <input\n value={appId}\n onChange={(event) => setAppId(event.target.value)}\n placeholder=\"app-id\"\n aria-label=\"App ID\"\n className=\"rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n <textarea\n value={settingsInput}\n onChange={(event) => setSettingsInput(event.target.value)}\n rows={3}\n aria-label=\"App settings JSON\"\n className=\"rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n <button\n type=\"button\"\n disabled={installing}\n className=\"rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n onClick={handleInstall}\n >\n Install\n </button>\n </div>\n {formError && <p className=\"text-sm text-destructive\">{formError}</p>}\n </PageSection>\n {loading && (\n <p className=\"text-sm text-muted-foreground\">\n Loading app installations…\n </p>\n )}\n {error && <p className=\"text-sm text-destructive\">{error.message}</p>}\n <div className=\"grid gap-3\">\n {installations.map((installation) => (\n <article\n key={installation.id}\n className=\"rounded-lg border border-border bg-card p-4\"\n >\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-semibold text-foreground\">\n {installation.appId}\n </h3>\n <StatusPill>{installation.state}</StatusPill>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n Version {installation.appVersion} · Installed by{\" \"}\n {installation.installedBy} on{\" \"}\n {formatDate(installation.installedAt)}\n </p>\n </div>\n <button\n type=\"button\"\n disabled={uninstalling}\n className=\"inline-flex items-center gap-2 rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground hover:bg-accent disabled:opacity-50\"\n onClick={() =>\n void uninstallApp({ variables: { id: installation.id } })\n }\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n Uninstall\n </button>\n </div>\n <div className=\"mt-3 grid gap-2\">\n <textarea\n rows={5}\n aria-label={`Settings for ${installation.appId}`}\n value={settingsDrafts[installation.id] ?? \"{}\"}\n onChange={(event) =>\n setSettingsDrafts((current) => ({\n ...current,\n [installation.id]: event.target.value,\n }))\n }\n className=\"rounded-md border border-border bg-background px-3 py-2 font-mono text-xs text-foreground\"\n />\n <button\n type=\"button\"\n disabled={saving}\n className=\"w-fit rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground hover:bg-secondary/90 disabled:opacity-50\"\n onClick={() => {\n const settings = parsedSettings(\n settingsDrafts[installation.id] ?? \"{}\",\n );\n if (!settings) {\n setFormError(\n \"Installation settings must be a valid JSON object.\",\n );\n return;\n }\n setFormError(null);\n void updateSettings({\n variables: { id: installation.id, settings },\n });\n }}\n >\n Save settings\n </button>\n </div>\n </article>\n ))}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ConversationAdminPages.js","names":[],"sources":["../../../src/conversations/pages/ConversationAdminPages.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { gql } from \"@apollo/client\";\nimport { useMutation, useQuery } from \"@apollo/client/react\";\nimport {\n Activity,\n Archive,\n CheckCircle2,\n Package,\n ShieldCheck,\n Trash2,\n} from \"lucide-react\";\n\nimport {\n Button,\n CTAOverflowMenu,\n GlassCard,\n ShowMore,\n} from \"@burdenoff/fe-libs/ui\";\nimport { EmptyState, PageLayout, PageSection } from \"../components/PageLayout\";\nimport { useConversations } from \"../providers/ConversationsProvider\";\nimport { useTr } from \"../utils/i18n\";\n\nconst GET_MESSAGE_REPORTS = gql`\n query ConversationAdminMessageReports(\n $first: Int\n $filter: MessageReportFilter\n ) {\n messageReports(first: $first, filter: $filter) {\n edges {\n node {\n id\n messageId\n reportedBy\n reason\n status\n notes\n createdAt\n reviewedAt\n message {\n id\n conversationId\n authorId\n content\n isHidden\n createdAt\n }\n }\n }\n }\n }\n`;\n\nconst RESOLVE_MESSAGE_REPORT = gql`\n mutation ConversationAdminResolveMessageReport(\n $input: ResolveMessageReportInput!\n ) {\n resolveMessageReport(input: $input) {\n id\n status\n reviewedAt\n notes\n message {\n id\n isHidden\n }\n }\n }\n`;\n\nconst GET_BULK_CONVERSATIONS = gql`\n query ConversationAdminBulkConversations(\n $first: Int\n $filter: ConversationFilter\n ) {\n conversations(first: $first, filter: $filter) {\n edges {\n node {\n id\n title\n type\n state\n updatedAt\n }\n }\n }\n }\n`;\n\nconst BULK_UPDATE_CONVERSATIONS = gql`\n mutation ConversationAdminBulkUpdate(\n $input: BulkConversationOperationInput!\n ) {\n bulkUpdateConversations(input: $input) {\n success\n processedCount\n successCount\n failureCount\n conversationIds\n errors {\n conversationId\n message\n }\n }\n }\n`;\n\nconst GET_CONVERSATION_AUDIT_LOG = gql`\n query ConversationAdminAuditLog($filter: ActivityLogFilter) {\n getActivities(filter: $filter) {\n id\n action\n description\n resourceId\n resourceType\n userId\n timestamp\n }\n }\n`;\n\nconst GET_APP_INSTALLATIONS = gql`\n query ConversationAdminAppInstallations($workspaceId: ID) {\n appInstallations(workspaceId: $workspaceId) {\n id\n appId\n appVersion\n state\n settings\n permissions\n installedBy\n installedAt\n updatedAt\n }\n }\n`;\n\nconst INSTALL_APP = gql`\n mutation ConversationAdminInstallApp($input: InstallAppInput!) {\n installApp(input: $input) {\n id\n appId\n state\n settings\n installedAt\n }\n }\n`;\n\nconst UPDATE_APP_SETTINGS = gql`\n mutation ConversationAdminUpdateAppSettings($id: ID!, $settings: JSON!) {\n updateAppSettings(id: $id, settings: $settings) {\n id\n settings\n updatedAt\n }\n }\n`;\n\nconst UNINSTALL_APP = gql`\n mutation ConversationAdminUninstallApp($id: ID!) {\n uninstallApp(id: $id) {\n appInstallationId\n success\n }\n }\n`;\n\ninterface MessageReportNode {\n id: string;\n messageId: string;\n reportedBy: string;\n reason: string;\n status: string;\n notes?: string | null;\n createdAt: string;\n reviewedAt?: string | null;\n message: {\n id: string;\n conversationId: string;\n authorId: string;\n content: unknown;\n isHidden: boolean;\n createdAt: string;\n };\n}\n\ninterface ConversationNode {\n id: string;\n title?: string | null;\n type: string;\n state: string;\n updatedAt: string;\n}\n\ninterface ActivityLogNode {\n id: string;\n action: string;\n description?: string | null;\n resourceId?: string | null;\n resourceType?: string | null;\n userId: string;\n timestamp: string;\n}\n\ninterface AppInstallationNode {\n id: string;\n appId: string;\n appVersion: string;\n state: string;\n settings: unknown;\n permissions: string[];\n installedBy: string;\n installedAt: string;\n updatedAt: string;\n}\n\ninterface BulkUpdateConversationsResult {\n bulkUpdateConversations: {\n success: boolean;\n processedCount: number;\n successCount: number;\n failureCount: number;\n conversationIds: string[];\n errors: Array<{ conversationId: string; message: string }>;\n };\n}\n\nfunction formatContent(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (content && typeof content === \"object\" && \"text\" in content) {\n const text = (content as { text?: unknown }).text;\n if (typeof text === \"string\") return text;\n }\n try {\n return JSON.stringify(content);\n } catch {\n return \"Message content unavailable\";\n }\n}\n\nconst DATE_FORMATTER = new Intl.DateTimeFormat(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n});\n\nfunction formatDate(value: string): string {\n return DATE_FORMATTER.format(new Date(value));\n}\n\nfunction StatusPill({ children }: { children: string }) {\n return (\n <span className=\"rounded-full border border-border-subtle bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {children}\n </span>\n );\n}\n\nexport function ModerationQueuePage() {\n const tr = useTr();\n const { workspaceId } = useConversations();\n const { data, loading, error, refetch } = useQuery<{\n messageReports: { edges: Array<{ node: MessageReportNode }> };\n }>(GET_MESSAGE_REPORTS, {\n variables: { first: 50, filter: { statuses: [\"PENDING\", \"REVIEWING\"] } },\n skip: !workspaceId,\n });\n const [resolveReport, { loading: resolving }] = useMutation(\n RESOLVE_MESSAGE_REPORT,\n {\n onCompleted: () => void refetch(),\n },\n );\n\n const reports = data?.messageReports.edges.map((edge) => edge.node) ?? [];\n\n return (\n <PageLayout\n title={tr(\"conversations.admin.moderationPageTitle\", \"Moderation queue\")}\n subtitle={tr(\n \"conversations.admin.moderationPageDescription\",\n \"Review reported messages and apply moderator decisions.\",\n )}\n icon={<ShieldCheck className=\"size-5\" aria-hidden=\"true\" />}\n maxWidth=\"2xl\"\n >\n {!workspaceId && (\n <EmptyState\n title={tr(\n \"conversations.admin.selectWorkspace\",\n \"Select a workspace\",\n )}\n description={tr(\n \"conversations.admin.selectWorkspaceModerationDescription\",\n \"Choose a workspace to review reported conversation messages.\",\n )}\n icon={<ShieldCheck className=\"size-6\" aria-hidden=\"true\" />}\n />\n )}\n {workspaceId && loading && (\n <p className=\"text-sm text-text-secondary\">Loading reports…</p>\n )}\n {workspaceId && error && (\n <p className=\"text-sm text-status-error-text\">{error.message}</p>\n )}\n {workspaceId && !loading && !error && reports.length === 0 && (\n <EmptyState\n title=\"No reports waiting for review\"\n description=\"Reported messages will appear here as they are submitted.\"\n icon={<CheckCircle2 className=\"size-6\" aria-hidden=\"true\" />}\n />\n )}\n <div className=\"grid gap-3\">\n {reports.map((report) => (\n <GlassCard\n key={report.id}\n treatment=\"glass\"\n className=\"border-border-seam p-4\"\n >\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-2 min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusPill>{report.status}</StatusPill>\n {report.message.isHidden && <StatusPill>Hidden</StatusPill>}\n <span className=\"text-xs text-text-secondary\">\n Reported {formatDate(report.createdAt)}\n </span>\n </div>\n <p className=\"text-sm font-medium text-text-primary\">\n {report.reason}\n </p>\n <p className=\"rounded-md border border-border-seam bg-bg-sunken p-3 text-sm text-text-secondary\">\n {formatContent(report.message.content)}\n </p>\n <p className=\"text-xs text-text-secondary\">\n Message {report.messageId} in conversation{\" \"}\n {report.message.conversationId} by {report.message.authorId};\n reported by {report.reportedBy}\n </p>\n </div>\n {/* One primary CTA (hide + resolve), the secondary \"Dismiss\"\n collapses into the overflow menu. */}\n <CTAOverflowMenu\n className=\"shrink-0\"\n primary={{\n label: \"Hide and resolve\",\n disabled: resolving,\n onSelect: () =>\n void resolveReport({\n variables: {\n input: { reportId: report.id, action: \"HIDE_MESSAGE\" },\n },\n }),\n }}\n actions={[\n {\n label: \"Dismiss\",\n disabled: resolving,\n onSelect: () =>\n void resolveReport({\n variables: {\n input: { reportId: report.id, action: \"DISMISS\" },\n },\n }),\n },\n ]}\n />\n </div>\n </GlassCard>\n ))}\n </div>\n </PageLayout>\n );\n}\n\nexport function BulkOperationsPage() {\n const tr = useTr();\n const { workspaceId } = useConversations();\n const [selectedIds, setSelectedIds] = useState<Set<string>>(() => new Set());\n const [action, setAction] = useState<\"ARCHIVE\" | \"UNARCHIVE\" | \"DELETE\">(\n \"ARCHIVE\",\n );\n const { data, loading, error, refetch } = useQuery<{\n conversations: { edges: Array<{ node: ConversationNode }> };\n }>(GET_BULK_CONVERSATIONS, {\n variables: { first: 100 },\n skip: !workspaceId,\n });\n const [bulkUpdate, { data: bulkResult, loading: updating }] = useMutation<\n BulkUpdateConversationsResult,\n { input: { conversationIds: string[]; action: typeof action } }\n >(BULK_UPDATE_CONVERSATIONS, {\n onCompleted: () => {\n setSelectedIds(new Set());\n void refetch();\n },\n });\n const conversations =\n data?.conversations.edges.map((edge) => edge.node) ?? [];\n\n const toggle = (id: string) => {\n setSelectedIds((current) => {\n const next = new Set(current);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n };\n\n return (\n <PageLayout\n title={tr(\n \"conversations.admin.bulkOperationsPageTitle\",\n \"Bulk operations\",\n )}\n subtitle={tr(\n \"conversations.admin.bulkOperationsPageDescription\",\n \"Select workspace conversations and apply archive, unarchive, or delete operations.\",\n )}\n icon={<Archive className=\"size-5\" aria-hidden=\"true\" />}\n maxWidth=\"2xl\"\n headerActions={\n <div className=\"flex flex-wrap items-center gap-2\">\n <select\n value={action}\n onChange={(event) => setAction(event.target.value as typeof action)}\n aria-label=\"Bulk action\"\n className=\"min-h-11 rounded-md border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"ARCHIVE\">Archive</option>\n <option value=\"UNARCHIVE\">Unarchive</option>\n <option value=\"DELETE\">Delete</option>\n </select>\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={selectedIds.size === 0 || updating}\n onClick={() =>\n void bulkUpdate({\n variables: {\n input: { conversationIds: Array.from(selectedIds), action },\n },\n })\n }\n >\n Apply to {selectedIds.size}\n </Button>\n </div>\n }\n >\n {!workspaceId && (\n <EmptyState\n title={tr(\n \"conversations.admin.selectWorkspace\",\n \"Select a workspace\",\n )}\n description={tr(\n \"conversations.admin.selectWorkspaceBulkDescription\",\n \"Choose a workspace to manage conversations in bulk.\",\n )}\n icon={<Archive className=\"size-6\" aria-hidden=\"true\" />}\n />\n )}\n {workspaceId && loading && (\n <p className=\"text-sm text-text-secondary\">Loading conversations…</p>\n )}\n {workspaceId && error && (\n <p className=\"text-sm text-status-error-text\">{error.message}</p>\n )}\n {bulkResult?.bulkUpdateConversations && (\n <GlassCard\n treatment=\"metric\"\n className=\"grid grid-cols-2 gap-4 border-border-seam p-4 sm:max-w-md\"\n >\n <div>\n <p className=\"text-2xl font-semibold tabular-nums text-status-success-text\">\n {bulkResult.bulkUpdateConversations.successCount}\n </p>\n <p className=\"text-xs text-text-secondary\">Succeeded</p>\n </div>\n <div>\n <p className=\"text-2xl font-semibold tabular-nums text-text-primary\">\n {bulkResult.bulkUpdateConversations.failureCount}\n </p>\n <p className=\"text-xs text-text-secondary\">Failed</p>\n </div>\n </GlassCard>\n )}\n {workspaceId && (\n <div className=\"overflow-hidden rounded-lg border border-border-seam bg-bg-surface\">\n {conversations.map((conversation) => (\n <label\n key={conversation.id}\n className=\"flex min-h-11 cursor-pointer items-center gap-3 border-b border-border-seam px-4 py-3 last:border-b-0 hover:bg-accent\"\n >\n <input\n type=\"checkbox\"\n aria-label={`Select ${conversation.title || \"untitled conversation\"}`}\n checked={selectedIds.has(conversation.id)}\n onChange={() => toggle(conversation.id)}\n />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {conversation.title || \"Untitled conversation\"}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {conversation.type} · {conversation.state} · Updated{\" \"}\n {formatDate(conversation.updatedAt)}\n </p>\n </div>\n </label>\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n\nexport function ConversationAuditLogPage() {\n const tr = useTr();\n const { workspaceId } = useConversations();\n const { data, loading, error } = useQuery<{\n getActivities: ActivityLogNode[];\n }>(GET_CONVERSATION_AUDIT_LOG, {\n variables: {\n filter: { workspaceId, resourceType: \"conversation\", limit: 50 },\n },\n skip: !workspaceId,\n });\n const logs = data?.getActivities ?? [];\n\n return (\n <PageLayout\n title={tr(\"conversations.admin.auditLogPageTitle\", \"Audit log\")}\n subtitle={tr(\n \"conversations.admin.auditLogPageDescription\",\n \"Activity stream for admin and moderator actions on workspace conversations.\",\n )}\n icon={<Activity className=\"size-5\" aria-hidden=\"true\" />}\n maxWidth=\"2xl\"\n >\n {loading && (\n <p className=\"text-sm text-text-secondary\">Loading activity…</p>\n )}\n {error && <p className=\"text-sm text-status-error-text\">{error.message}</p>}\n {!loading && !error && logs.length === 0 && (\n <EmptyState\n title=\"No activity found\"\n description=\"Conversation admin actions will appear here.\"\n />\n )}\n <div className=\"grid gap-3\">\n {logs.map((log) => (\n <GlassCard\n key={log.id}\n treatment=\"plain\"\n className=\"border-border-seam p-4\"\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">\n {log.action}\n </p>\n <span className=\"text-xs tabular-nums text-text-secondary\">\n {formatDate(log.timestamp)}\n </span>\n </div>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {log.description || \"No description provided\"}\n </p>\n <p className=\"mt-2 text-xs text-text-secondary\">\n User {log.userId} · Resource {log.resourceId ?? \"workspace\"}\n </p>\n </GlassCard>\n ))}\n </div>\n </PageLayout>\n );\n}\n\nexport function AppInstallationsPage() {\n const tr = useTr();\n const { workspaceId } = useConversations();\n const [appId, setAppId] = useState(\"\");\n const [settingsInput, setSettingsInput] = useState(\"{}\");\n const [settingsDrafts, setSettingsDrafts] = useState<Record<string, string>>(\n {},\n );\n const [formError, setFormError] = useState<string | null>(null);\n const { data, loading, error, refetch } = useQuery<{\n appInstallations: AppInstallationNode[];\n }>(GET_APP_INSTALLATIONS, {\n variables: { workspaceId },\n skip: !workspaceId,\n });\n const [installApp, { loading: installing }] = useMutation(INSTALL_APP, {\n onCompleted: () => void refetch(),\n });\n const [updateSettings, { loading: saving }] = useMutation(\n UPDATE_APP_SETTINGS,\n { onCompleted: () => void refetch() },\n );\n const [uninstallApp, { loading: uninstalling }] = useMutation(UNINSTALL_APP, {\n onCompleted: () => void refetch(),\n });\n const installations = useMemo(\n () => data?.appInstallations ?? [],\n [data?.appInstallations],\n );\n\n useEffect(() => {\n setSettingsDrafts((current) => {\n if (installations.every((installation) => current[installation.id])) {\n return current;\n }\n const next = { ...current };\n for (const installation of installations) {\n if (!next[installation.id]) {\n next[installation.id] = JSON.stringify(\n installation.settings ?? {},\n null,\n 2,\n );\n }\n }\n return next;\n });\n }, [installations]);\n\n const parsedSettings = (raw: string): Record<string, unknown> | null => {\n try {\n const parsed = JSON.parse(raw) as unknown;\n return parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n };\n\n const handleInstall = () => {\n const settings = parsedSettings(settingsInput);\n if (!appId.trim() || !settings) {\n setFormError(\"Enter an app ID and a valid JSON settings object.\");\n return;\n }\n setFormError(null);\n void installApp({\n variables: { input: { appId: appId.trim(), workspaceId, settings } },\n });\n };\n\n return (\n <PageLayout\n title={tr(\n \"conversations.admin.appInstallationsPageTitle\",\n \"App installations\",\n )}\n subtitle={tr(\n \"conversations.admin.appInstallationsPageDescription\",\n \"Install, configure, and remove conversation apps and integrations.\",\n )}\n icon={<Package className=\"size-5\" aria-hidden=\"true\" />}\n maxWidth=\"2xl\"\n >\n <PageSection\n title=\"Install app\"\n description=\"Install a workspace-scoped conversation app by app ID.\"\n >\n <div className=\"grid gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 sm:grid-cols-[minmax(0,1fr)_minmax(0,2fr)_auto]\">\n <input\n value={appId}\n onChange={(event) => setAppId(event.target.value)}\n placeholder=\"app-id\"\n aria-label=\"App ID\"\n className=\"min-h-11 rounded-md border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n />\n <textarea\n value={settingsInput}\n onChange={(event) => setSettingsInput(event.target.value)}\n rows={3}\n aria-label=\"App settings JSON\"\n className=\"rounded-md border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n />\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={installing}\n onClick={handleInstall}\n >\n Install\n </Button>\n </div>\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </PageSection>\n {loading && (\n <p className=\"text-sm text-text-secondary\">\n Loading app installations…\n </p>\n )}\n {error && <p className=\"text-sm text-status-error-text\">{error.message}</p>}\n <div className=\"grid gap-3\">\n {installations.map((installation) => (\n <GlassCard\n key={installation.id}\n treatment=\"glass\"\n className=\"border-border-seam p-4\"\n >\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {installation.appId}\n </h3>\n <StatusPill>{installation.state}</StatusPill>\n </div>\n <p className=\"text-xs text-text-secondary\">\n Version {installation.appVersion} · Installed by{\" \"}\n {installation.installedBy} on{\" \"}\n {formatDate(installation.installedAt)}\n </p>\n </div>\n {/* Destructive uninstall lives behind the overflow menu and\n asks for confirmation before firing the mutation. */}\n <CTAOverflowMenu\n className=\"shrink-0\"\n actions={[\n {\n label: \"Uninstall\",\n intent: \"destructive\",\n disabled: uninstalling,\n icon: <Trash2 className=\"size-4\" aria-hidden=\"true\" />,\n onSelect: () => {\n if (\n !window.confirm(\n `Uninstall ${installation.appId}? This removes the app and its settings from this workspace.`,\n )\n ) {\n return;\n }\n void uninstallApp({\n variables: { id: installation.id },\n });\n },\n },\n ]}\n />\n </div>\n {/* The raw JSON settings editor is an advanced surface — collapse\n it behind progressive disclosure so the card stays calm. */}\n <ShowMore\n className=\"mt-3\"\n collapsedHeight={0}\n label=\"Edit settings (JSON)\"\n >\n <div className=\"grid gap-2 pt-2\">\n <textarea\n rows={5}\n aria-label={`Settings for ${installation.appId}`}\n value={settingsDrafts[installation.id] ?? \"{}\"}\n onChange={(event) =>\n setSettingsDrafts((current) => ({\n ...current,\n [installation.id]: event.target.value,\n }))\n }\n className=\"rounded-md border border-border-seam bg-bg-surface px-3 py-2 font-mono text-xs text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n />\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n disabled={saving}\n className=\"w-fit\"\n onClick={() => {\n const settings = parsedSettings(\n settingsDrafts[installation.id] ?? \"{}\",\n );\n if (!settings) {\n setFormError(\n \"Installation settings must be a valid JSON object.\",\n );\n return;\n }\n setFormError(null);\n void updateSettings({\n variables: { id: installation.id, settings },\n });\n }}\n >\n Save settings\n </Button>\n </div>\n </ShowMore>\n </GlassCard>\n ))}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -211,37 +211,37 @@ function _() {
211
211
  }
212
212
  }, [s, q?.contextHref]);
213
213
  return !M && ke ? /* @__PURE__ */ m("div", {
214
- className: "flex items-center justify-center h-[calc(100vh-64px)] text-sm text-muted-foreground",
214
+ className: "flex items-center justify-center h-[calc(100vh-64px)] text-sm text-text-secondary",
215
215
  children: S("conversations.loading", "Loading conversation...")
216
216
  }) : !M || Ae ? /* @__PURE__ */ h("div", {
217
217
  className: "flex flex-col items-center justify-center h-[calc(100vh-64px)] text-center gap-3 px-4",
218
218
  children: [
219
- /* @__PURE__ */ m(me, { className: "size-8 text-muted-foreground" }),
219
+ /* @__PURE__ */ m(me, { className: "size-8 text-text-secondary" }),
220
220
  /* @__PURE__ */ m("p", {
221
- className: "text-sm text-muted-foreground",
221
+ className: "text-sm text-text-secondary",
222
222
  children: Ae ? S("conversations.unavailable", "We couldn't load this conversation. Please try again.") : S("conversations.notFound", "Conversation not found")
223
223
  }),
224
224
  /* @__PURE__ */ m("button", {
225
225
  type: "button",
226
226
  onClick: () => s(_ || "/conversations"),
227
- className: "px-3 py-2 text-sm font-medium rounded-lg border border-border hover:bg-muted/50",
227
+ className: "px-3 py-2 text-sm font-medium rounded-lg border border-border-subtle hover:bg-bg-sunken/50",
228
228
  children: S("conversations.back", "Back to conversations")
229
229
  })
230
230
  ]
231
231
  }) : /* @__PURE__ */ h("div", {
232
- className: "relative flex h-[calc(100vh-64px)] bg-background",
232
+ className: "relative flex h-[calc(100vh-64px)] bg-bg-surface",
233
233
  children: [/* @__PURE__ */ h("div", {
234
234
  className: "flex-1 flex flex-col min-w-0",
235
235
  children: [
236
236
  /* @__PURE__ */ h("header", {
237
237
  "data-tour": "conversation-detail-header",
238
- className: "flex items-center justify-between px-4 py-3 border-b border-border bg-background/95 backdrop-blur-sm",
238
+ className: "flex items-center justify-between px-4 py-3 border-b border-border-seam bg-bg-surface/95 backdrop-blur-sm",
239
239
  children: [/* @__PURE__ */ h("div", {
240
240
  className: "flex items-center gap-3 min-w-0",
241
241
  children: [/* @__PURE__ */ m("button", {
242
242
  type: "button",
243
243
  onClick: () => s(_ || "/conversations"),
244
- className: "flex min-h-10 min-w-10 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
244
+ className: "flex min-h-10 min-w-10 items-center justify-center rounded-lg text-text-secondary transition-colors hover:bg-bg-sunken/50 hover:text-text-primary",
245
245
  children: /* @__PURE__ */ m(se, { size: 18 })
246
246
  }), /* @__PURE__ */ h("div", {
247
247
  className: "min-w-0",
@@ -249,13 +249,13 @@ function _() {
249
249
  className: "flex items-center gap-1.5",
250
250
  children: [M.type === "CHANNEL" && /* @__PURE__ */ m(de, {
251
251
  size: 14,
252
- className: "text-muted-foreground flex-shrink-0"
252
+ className: "text-text-secondary flex-shrink-0"
253
253
  }), /* @__PURE__ */ m("h2", {
254
- className: "text-sm font-semibold text-foreground truncate",
254
+ className: "text-sm font-semibold text-text-primary truncate",
255
255
  children: M.title
256
256
  })]
257
257
  }), /* @__PURE__ */ m("p", {
258
- className: "text-xs text-muted-foreground",
258
+ className: "text-xs text-text-secondary",
259
259
  children: M.type === "DIRECT" ? S("conversations.directConversation", "Direct conversation") : M.type === "CHANNEL" ? `${S("conversations.channel", "Channel")} · ${M.memberCount} ${S("conversations.membersCountLabel", "members")}` : M.type === "ANNOUNCEMENT" ? `${S("conversations.announcement", "Announcement")} · ${M.memberCount} ${S("conversations.membersCountLabel", "members")}` : `${M.memberCount} ${S("conversations.membersCountLabel", "members")}`
260
260
  })]
261
261
  })]
@@ -284,7 +284,7 @@ function _() {
284
284
  active: L,
285
285
  onClick: () => R((e) => !e)
286
286
  }), L && /* @__PURE__ */ h("div", {
287
- className: "absolute right-0 top-full mt-1 w-48 bg-popover border border-border rounded-lg shadow-lg z-50 py-1 animate-in fade-in-0 zoom-in-95 duration-100",
287
+ className: "absolute right-0 top-full mt-1 w-48 bg-popover border border-border-subtle rounded-lg shadow-lg z-50 py-1 animate-in fade-in-0 zoom-in-95 duration-100",
288
288
  children: [
289
289
  /* @__PURE__ */ m(v, {
290
290
  icon: M.isPinned ? /* @__PURE__ */ m(_e, { size: 14 }) : /* @__PURE__ */ m(ge, { size: 14 }),
@@ -319,9 +319,9 @@ function _() {
319
319
  className: "flex-1 overflow-y-auto py-4 space-y-0.5",
320
320
  children: [
321
321
  q?.pagePath && /* @__PURE__ */ h("div", {
322
- className: "mx-4 mb-4 rounded-lg border border-border bg-muted/20 px-3 py-2 text-xs text-muted-foreground",
322
+ className: "mx-4 mb-4 rounded-lg border border-border-subtle bg-bg-sunken/20 px-3 py-2 text-xs text-text-secondary",
323
323
  children: [/* @__PURE__ */ m("span", {
324
- className: "font-medium text-foreground",
324
+ className: "font-medium text-text-primary",
325
325
  children: q.contextTitle || q.pagePath
326
326
  }), q.entityType && q.entityId ? ` · ${q.entityType} ${q.entityId}` : ""]
327
327
  }),
@@ -330,14 +330,14 @@ function _() {
330
330
  children: S("conversations.messagesUnavailable", "Messages couldn't be loaded right now. The conversation header and actions are still available.")
331
331
  }),
332
332
  je && /* @__PURE__ */ h("div", {
333
- className: "mx-4 mb-4 flex items-center gap-2 rounded-lg border border-border bg-muted/20 px-3 py-2 text-sm text-muted-foreground",
333
+ className: "mx-4 mb-4 flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-sunken/20 px-3 py-2 text-sm text-text-secondary",
334
334
  children: [/* @__PURE__ */ m(fe, {
335
335
  size: 14,
336
336
  className: "animate-spin"
337
337
  }), S("conversations.loadingMessages", "Loading messages...")]
338
338
  }),
339
339
  !je && !Me && J.length === 0 && /* @__PURE__ */ m("div", {
340
- className: "mx-4 mb-4 rounded-lg border border-dashed border-border bg-muted/20 px-3 py-6 text-center text-sm text-muted-foreground",
340
+ className: "mx-4 mb-4 rounded-lg border border-dashed border-border-subtle bg-bg-sunken/20 px-3 py-6 text-center text-sm text-text-secondary",
341
341
  children: S("conversations.noMessagesYet", "No messages yet. Start the conversation below.")
342
342
  }),
343
343
  J.map((e, t) => {
@@ -345,11 +345,11 @@ function _() {
345
345
  return /* @__PURE__ */ m("div", { children: z === e.id ? /* @__PURE__ */ h("div", {
346
346
  className: "px-4 py-2",
347
347
  children: [/* @__PURE__ */ h("div", {
348
- className: "flex items-center gap-2 text-xs text-muted-foreground mb-1",
348
+ className: "flex items-center gap-2 text-xs text-text-secondary mb-1",
349
349
  children: [/* @__PURE__ */ m("span", { children: S("conversations.editingMessage", "Editing message") }), /* @__PURE__ */ m("button", {
350
350
  type: "button",
351
351
  onClick: $,
352
- className: "hover:text-foreground",
352
+ className: "hover:text-text-primary",
353
353
  children: /* @__PURE__ */ m(be, { size: 12 })
354
354
  })]
355
355
  }), /* @__PURE__ */ h("div", {
@@ -361,13 +361,13 @@ function _() {
361
361
  onKeyDown: (e) => {
362
362
  e.key === "Enter" && !e.shiftKey && (e.preventDefault(), Ze()), e.key === "Escape" && $();
363
363
  },
364
- className: "flex-1 px-3 py-2 text-sm rounded-lg border border-border bg-muted/30 resize-none focus:outline-none focus:ring-2 focus:ring-ring",
364
+ className: "flex-1 px-3 py-2 text-sm rounded-lg border border-border-subtle bg-bg-sunken/30 resize-none focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
365
365
  rows: 2
366
366
  }), /* @__PURE__ */ m("button", {
367
367
  type: "button",
368
368
  onClick: () => void Ze(),
369
369
  disabled: !V.trim() || I,
370
- className: "px-3 py-2 text-xs font-medium rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50",
370
+ className: "px-3 py-2 text-xs font-medium rounded-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
371
371
  children: S("conversations.save", "Save")
372
372
  })]
373
373
  })]
@@ -388,14 +388,14 @@ function _() {
388
388
  }),
389
389
  /* @__PURE__ */ h("div", {
390
390
  "data-tour": "conversation-message-composer",
391
- className: "border-t border-border px-4 py-3 bg-background",
391
+ className: "border-t border-border-seam px-4 py-3 bg-bg-surface",
392
392
  children: [U && /* @__PURE__ */ h("div", {
393
- className: "flex items-center gap-2 mb-2 px-3 py-1.5 rounded-lg bg-muted/50 text-xs text-muted-foreground",
393
+ className: "flex items-center gap-2 mb-2 px-3 py-1.5 rounded-lg bg-bg-sunken/50 text-xs text-text-secondary",
394
394
  children: [/* @__PURE__ */ h("span", { children: [
395
395
  S("conversations.replyingTo", "Replying to"),
396
396
  " ",
397
397
  /* @__PURE__ */ m("strong", {
398
- className: "text-foreground",
398
+ className: "text-text-primary",
399
399
  children: U.sender
400
400
  }),
401
401
  ": ",
@@ -405,7 +405,7 @@ function _() {
405
405
  type: "button",
406
406
  onClick: () => W(null),
407
407
  "aria-label": S("conversations.cancelReply", "Cancel reply"),
408
- className: "ml-auto flex min-h-9 min-w-9 items-center justify-center rounded-md hover:bg-muted/70 hover:text-foreground",
408
+ className: "ml-auto flex min-h-9 min-w-9 items-center justify-center rounded-md hover:bg-bg-sunken/70 hover:text-text-primary",
409
409
  children: /* @__PURE__ */ m(be, { size: 12 })
410
410
  })]
411
411
  }), /* @__PURE__ */ h("div", {
@@ -419,7 +419,7 @@ function _() {
419
419
  onKeyDown: qe,
420
420
  placeholder: `${S("conversations.messageConversationPrefix", "Message")} ${M.title}...`,
421
421
  rows: 1,
422
- className: t("w-full px-4 py-2.5 text-sm rounded-xl border border-border bg-muted/30", "resize-none overflow-hidden placeholder:text-muted-foreground", "focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent max-h-32"),
422
+ className: t("w-full px-4 py-2.5 text-sm rounded-xl border border-border-subtle bg-bg-sunken/30", "resize-none overflow-hidden placeholder:text-text-secondary", "focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] focus:border-transparent max-h-32"),
423
423
  style: {
424
424
  height: "auto",
425
425
  minHeight: "40px"
@@ -434,7 +434,7 @@ function _() {
434
434
  "aria-label": S("conversations.sendMessage", "Send message"),
435
435
  onClick: () => void Q(),
436
436
  disabled: !D.trim() || F,
437
- className: t("p-2.5 rounded-xl transition-all duration-150", D.trim() && !F ? "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm" : "bg-muted text-muted-foreground cursor-not-allowed"),
437
+ className: t("p-2.5 rounded-xl transition-all duration-150", D.trim() && !F ? "bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90 shadow-sm" : "bg-bg-sunken text-text-secondary cursor-not-allowed"),
438
438
  children: F ? /* @__PURE__ */ m(fe, {
439
439
  size: 18,
440
440
  className: "animate-spin"
@@ -444,13 +444,13 @@ function _() {
444
444
  })
445
445
  ]
446
446
  }), w && M.isGroup && /* @__PURE__ */ m("aside", {
447
- className: "absolute inset-y-0 right-0 z-20 w-full max-w-72 border-l border-border bg-background shadow-lg animate-in slide-in-from-right-4 duration-200 md:relative md:z-auto md:w-64 md:shadow-none",
447
+ className: "absolute inset-y-0 right-0 z-20 w-full max-w-72 border-l border-border-seam bg-bg-surface shadow-lg animate-in slide-in-from-right-4 duration-200 md:relative md:z-auto md:w-64 md:shadow-none",
448
448
  children: /* @__PURE__ */ h("div", {
449
449
  className: "p-4",
450
450
  children: [/* @__PURE__ */ h("div", {
451
451
  className: "flex items-center justify-between mb-4",
452
452
  children: [/* @__PURE__ */ h("h3", {
453
- className: "text-sm font-semibold text-foreground",
453
+ className: "text-sm font-semibold text-text-primary",
454
454
  children: [
455
455
  S("conversations.members", "Members"),
456
456
  " (",
@@ -460,28 +460,28 @@ function _() {
460
460
  }), /* @__PURE__ */ m("button", {
461
461
  type: "button",
462
462
  onClick: E,
463
- className: "p-1 rounded text-muted-foreground hover:text-foreground",
463
+ className: "p-1 rounded text-text-secondary hover:text-text-primary",
464
464
  children: /* @__PURE__ */ m(ge, { size: 14 })
465
465
  })]
466
466
  }), /* @__PURE__ */ h("div", {
467
467
  className: "space-y-1",
468
468
  children: [X.map((e) => /* @__PURE__ */ h("div", {
469
- className: "flex items-center gap-2.5 px-2 py-1.5 rounded-lg hover:bg-muted/50",
469
+ className: "flex items-center gap-2.5 px-2 py-1.5 rounded-lg hover:bg-bg-sunken/50",
470
470
  children: [/* @__PURE__ */ m("div", {
471
- className: "size-7 rounded-full bg-muted flex items-center justify-center text-xs font-medium text-muted-foreground",
471
+ className: "size-7 rounded-full bg-bg-sunken flex items-center justify-center text-xs font-medium text-text-secondary",
472
472
  children: e.name.split(" ").map((e) => e[0]).join("").slice(0, 2)
473
473
  }), /* @__PURE__ */ h("div", {
474
474
  className: "min-w-0",
475
475
  children: [/* @__PURE__ */ m("p", {
476
- className: "text-xs font-medium text-foreground truncate",
476
+ className: "text-xs font-medium text-text-primary truncate",
477
477
  children: e.name
478
478
  }), /* @__PURE__ */ m("p", {
479
- className: "text-[10px] text-muted-foreground",
479
+ className: "text-[10px] text-text-secondary",
480
480
  children: e.role
481
481
  })]
482
482
  })]
483
483
  }, e.id)), Z > 0 && /* @__PURE__ */ h("p", {
484
- className: "px-2 pt-2 text-xs text-muted-foreground",
484
+ className: "px-2 pt-2 text-xs text-text-secondary",
485
485
  children: [
486
486
  S("conversations.moreMembersPrefix", "and"),
487
487
  " ",
@@ -499,7 +499,7 @@ function v({ icon: e, label: n, onClick: r, destructive: i }) {
499
499
  return /* @__PURE__ */ h("button", {
500
500
  type: "button",
501
501
  onClick: r,
502
- className: t("flex items-center gap-2.5 w-full px-3 py-2 text-sm transition-colors text-left", i ? "text-destructive hover:bg-destructive/10" : "text-foreground hover:bg-muted/50"),
502
+ className: t("flex items-center gap-2.5 w-full px-3 py-2 text-sm transition-colors text-left", i ? "text-status-error-text hover:bg-status-error-bg/10" : "text-text-primary hover:bg-bg-sunken/50"),
503
503
  children: [e, /* @__PURE__ */ m("span", { children: n })]
504
504
  });
505
505
  }
@@ -513,7 +513,7 @@ function y({ icon: e, label: n, active: r, dataTour: i, onClick: a }) {
513
513
  onClick: a,
514
514
  "aria-label": n,
515
515
  title: n,
516
- className: t("flex min-h-10 min-w-10 items-center justify-center rounded-lg transition-colors", r ? "bg-primary/10 text-primary" : "text-muted-foreground hover:text-foreground hover:bg-muted/50"),
516
+ className: t("flex min-h-10 min-w-10 items-center justify-center rounded-lg transition-colors", r ? "bg-action-primary-bg/10 text-primary" : "text-text-secondary hover:text-text-primary hover:bg-bg-sunken/50"),
517
517
  children: e
518
518
  })
519
519
  });