@workspace-platform/ui 0.2.0 → 0.2.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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/api/client.ts","../src/socket/client.ts","../src/types/index.ts","../src/types/activity.ts","../src/api/index.ts","../src/store/useWorkspaceListStore.ts","../src/hooks/useWorkspaceApi.ts","../src/utils/constants.ts","../src/utils/formatExport.ts","../src/components/ui/Modal.tsx","../src/components/ui/cn.ts","../src/components/MemberAvatar.tsx","../src/components/MembersPanel.tsx","../src/components/CreateWorkspaceModal.tsx","../src/components/CreatePrivateWorkspaceModal.tsx","../src/components/SyncPanel.tsx","../src/components/Pagination.tsx"],"sourcesContent":["// ─── @workspace-platform/ui ───────────────────────────────────────────────────\n// Main barrel export\n\n// Provider\nexport { WorkspaceProvider, useWorkspaceContext } from './provider';\nexport type { WorkspaceConfig, WorkspaceContextValue, UserSearchResult } from './provider';\n\n// Types\nexport * from './types';\nexport type { SyncLink, SyncStatus, SyncProviderInfo, ToggleReactionResponse, WorkspaceApis } from './api';\n\n// Activity types\nexport * from './types/activity';\n\n// API\nexport { createWorkspaceApis } from './api';\nexport { createWorkspaceClient } from './api/client';\nexport type { WorkspaceClient } from './api/client';\n\n// Socket\nexport { createWorkspaceSocket } from './socket/client';\nexport type { WorkspaceSocketManager } from './socket/client';\n\n// Store\nexport { createWorkspaceListStore } from './store/useWorkspaceListStore';\nexport type { WorkspaceListState, WorkspaceListFilters, WorkspaceTab } from './store/useWorkspaceListStore';\n\n// Hooks\nexport { useWorkspaceApi } from './hooks/useWorkspaceApi';\n\n// Utils\nexport { getInitials, ROLE_LABELS, STATUS_LABELS, AVAILABLE_AGENTS } from './utils/constants';\nexport { formatWorkspaceExport } from './utils/formatExport';\nexport type { WorkspaceExportData } from './utils/formatExport';\n\n// UI Primitives\nexport { Modal } from './components/ui/Modal';\nexport type { ModalProps, ModalSize } from './components/ui/Modal';\nexport { cn } from './components/ui/cn';\n\n// Components\nexport { MemberAvatar } from './components/MemberAvatar';\nexport type { MemberAvatarProps } from './components/MemberAvatar';\nexport { MembersPanel } from './components/MembersPanel';\nexport type { AvatarUser } from './components/MembersPanel';\nexport { CreateWorkspaceModal } from './components/CreateWorkspaceModal';\nexport { CreatePrivateWorkspaceModal } from './components/CreatePrivateWorkspaceModal';\nexport { SyncPanel } from './components/SyncPanel';\nexport { Pagination } from './components/Pagination';\n","import React, { createContext, useContext, useMemo } from 'react';\nimport { createWorkspaceClient, type WorkspaceClient } from './api/client';\nimport { createWorkspaceSocket, type WorkspaceSocketManager } from './socket/client';\n\n// ─── Config types ─────────────────────────────────────────────────────────────\n\nexport interface UserSearchResult {\n id: string;\n email: string;\n displayName: string;\n avatarUrl?: string;\n}\n\nexport interface WorkspaceConfig {\n /** Base URL of the workspace-platform server (e.g. http://localhost:3100) */\n baseUrl: string;\n /** Function that returns the current Bearer token (JWT) */\n getAuthToken: () => string | null;\n /** Current user identifier (email or ID) — used for socket auth & UI */\n currentUserId: string | null;\n /** Current user display name */\n currentUserName?: string | null;\n /** Optional: additional headers for API requests (e.g. { 'x-auth-mode': 'keycloak' }) */\n extraHeaders?: Record<string, string>;\n /** Optional: function to search users for member invitation */\n searchUsers?: (query: string) => Promise<UserSearchResult[]>;\n /** Optional: function to resolve user avatar URLs by email */\n resolveAvatars?: (memberIds: string[]) => Promise<Record<string, string>>;\n /** Optional: callback when navigating to a workspace */\n onNavigateToWorkspace?: (workspaceId: string) => void;\n}\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport interface WorkspaceContextValue {\n config: WorkspaceConfig;\n apiClient: WorkspaceClient;\n socket: WorkspaceSocketManager;\n}\n\nconst WorkspaceContext = createContext<WorkspaceContextValue | null>(null);\n\nexport function WorkspaceProvider({\n config,\n children,\n}: {\n config: WorkspaceConfig;\n children: React.ReactNode;\n}) {\n const value = useMemo(() => {\n const apiClient = createWorkspaceClient(config);\n const socket = createWorkspaceSocket(config);\n return { config, apiClient, socket };\n }, [config.baseUrl, config.currentUserId]);\n\n return (\n <WorkspaceContext.Provider value={value}>\n {children}\n </WorkspaceContext.Provider>\n );\n}\n\nexport function useWorkspaceContext(): WorkspaceContextValue {\n const ctx = useContext(WorkspaceContext);\n if (!ctx)\n throw new Error(\n 'useWorkspaceContext must be used within <WorkspaceProvider>'\n );\n return ctx;\n}\n","import type { WorkspaceConfig } from '../provider';\n\n// ─── Decoupled Workspace API HTTP Client ──────────────────────────────────────\n// Uses config from WorkspaceProvider instead of localStorage.\n\nexport interface WorkspaceClient {\n get: <T>(path: string) => Promise<T>;\n post: <T>(path: string, body: unknown) => Promise<T>;\n patch: <T>(path: string, body: unknown) => Promise<T>;\n delete: <T>(path: string) => Promise<T>;\n upload: <T>(path: string, formData: FormData) => Promise<T>;\n getBlob: (path: string) => Promise<Blob>;\n}\n\nexport function createWorkspaceClient(config: WorkspaceConfig): WorkspaceClient {\n function buildHeaders(extra?: HeadersInit): Record<string, string> {\n const base: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(extra as Record<string, string> | undefined),\n };\n const token = config.getAuthToken();\n if (token) base['Authorization'] = `Bearer ${token}`;\n if (config.extraHeaders) Object.assign(base, config.extraHeaders);\n return base;\n }\n\n async function req<T>(path: string, options?: RequestInit): Promise<T> {\n const res = await fetch(`${config.baseUrl}${path}`, {\n ...options,\n headers: buildHeaders(options?.headers),\n });\n if (res.status === 204) return undefined as T;\n const json = await res.json();\n if (!res.ok) {\n const rawMessage = json?.message ?? `Error ${res.status}`;\n const errorMessage = Array.isArray(rawMessage)\n ? rawMessage.join(', ')\n : typeof rawMessage === 'string'\n ? rawMessage\n : JSON.stringify(rawMessage);\n throw new Error(errorMessage);\n }\n return json as T;\n }\n\n async function reqBlob(path: string): Promise<Blob> {\n const res = await fetch(`${config.baseUrl}${path}`, {\n headers: buildHeaders(),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`Error ${res.status}: ${text}`);\n }\n return res.blob();\n }\n\n async function upload<T>(path: string, formData: FormData): Promise<T> {\n const headers: Record<string, string> = {};\n const token = config.getAuthToken();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n if (config.extraHeaders) Object.assign(headers, config.extraHeaders);\n // Do NOT set Content-Type — browser handles multipart boundary\n const res = await fetch(`${config.baseUrl}${path}`, {\n method: 'POST',\n headers,\n body: formData,\n });\n if (!res.ok) {\n const json = await res.json().catch(() => ({}));\n throw new Error(\n (json as { message?: string })?.message ??\n `Upload failed (${res.status})`\n );\n }\n return res.json();\n }\n\n return {\n get: <T>(path: string) => req<T>(path),\n post: <T>(path: string, body: unknown) =>\n req<T>(path, { method: 'POST', body: JSON.stringify(body) }),\n patch: <T>(path: string, body: unknown) =>\n req<T>(path, { method: 'PATCH', body: JSON.stringify(body) }),\n delete: <T>(path: string) => req<T>(path, { method: 'DELETE' }),\n upload: <T>(path: string, formData: FormData) => upload<T>(path, formData),\n getBlob: (path: string) => reqBlob(path),\n };\n}\n","import { io, Socket } from 'socket.io-client';\nimport type { WorkspaceConfig } from '../provider';\n\n// ─── Decoupled Workspace Socket.IO Client ─────────────────────────────────────\n\nexport interface WorkspaceSocketManager {\n getSocket: () => Socket;\n connect: (userId?: string) => Socket;\n disconnect: () => void;\n}\n\nexport function createWorkspaceSocket(\n config: WorkspaceConfig\n): WorkspaceSocketManager {\n let socket: Socket | null = null;\n\n function getSocket(): Socket {\n if (!socket) {\n const token = config.getAuthToken();\n socket = io(`${config.baseUrl}/workspaces`, {\n autoConnect: false,\n auth: { token: token ?? '' },\n });\n }\n return socket;\n }\n\n function connect(userId?: string): Socket {\n const s = getSocket();\n if (!s.connected) s.connect();\n const uid = userId ?? config.currentUserId;\n if (uid) {\n if (s.connected) {\n s.emit('authenticate', { userId: uid });\n } else {\n s.once('connect', () => {\n s.emit('authenticate', { userId: uid });\n });\n }\n }\n return s;\n }\n\n function disconnect() {\n socket?.disconnect();\n socket = null;\n }\n\n return { getSocket, connect, disconnect };\n}\n","// ─── Workspace Platform Types ─────────────────────────────────────────────────\n// Mirrors workspace-platform server schemas.\n\nexport type WorkspaceStatus = 'ACTIVE' | 'CLOSED' | 'ARCHIVED';\nexport type ArtefactType = 'NOTE' | 'EXPORT' | 'DECISION' | 'FILE' | 'TASK';\nexport type MemberType = 'user' | 'agent';\nexport type MemberRole = 'owner' | 'participant' | 'viewer';\n\n// ─── Socket / Webhook Event Enum ──────────────────────────────────────────────\n// Must stay synchronised with WebhookEvent in workspace-platform server\n// (webhook-dispatcher.service.ts).\n\nexport enum WorkspaceEvent {\n // ── Workspace lifecycle ──────────────────────────────────────────────────\n WORKSPACE_CREATED = 'workspace.created',\n WORKSPACE_UPDATED = 'workspace.updated',\n WORKSPACE_DELETED = 'workspace.deleted',\n WORKSPACE_STATUS_CHANGED = 'workspace.statusChanged',\n\n // ── Personal-room events (list-level) ────────────────────────────────────\n /** Sent to user's personal room when they are added as a member */\n WORKSPACE_ADDED = 'workspace.added',\n /** Sent to user's personal room when they are removed as a member */\n WORKSPACE_REMOVED = 'workspace.removed',\n\n // ── Workspace room events (detail-level) ─────────────────────────────────\n WORKSPACE_MEMBER_ADDED = 'workspace.member.added',\n WORKSPACE_MEMBER_UPDATED = 'workspace.member.updated',\n WORKSPACE_MEMBER_REMOVED = 'workspace.member.removed',\n WORKSPACE_MESSAGE_CREATED = 'workspace.message.created',\n WORKSPACE_MESSAGE_UPDATED = 'workspace.message.updated',\n WORKSPACE_MESSAGE_DELETED = 'workspace.message.deleted',\n WORKSPACE_MEMBER_USER_MENTIONED = 'workspace.member.user.mentioned',\n WORKSPACE_MEMBER_AGENT_MENTIONED = 'workspace.member.agent.mentioned',\n WORKSPACE_ARTEFACT_CREATED = 'workspace.artefact.created',\n WORKSPACE_TYPING_STARTED = 'workspace.typing.started',\n WORKSPACE_TYPING_STOPPED = 'workspace.typing.stopped',\n WORKSPACE_MESSAGE_REACTION_CREATED = 'workspace.message.reaction.created',\n WORKSPACE_MESSAGE_REACTION_DELETED = 'workspace.message.reaction.deleted',\n WORKSPACE_MESSAGE_PINNED = 'workspace.message.pinned',\n\n // ── Private workspace events ────────────────────────────────────────────\n PRIVATE_WORKSPACE_CREATED = 'private.workspace.created',\n PRIVATE_WORKSPACE_MESSAGE_CREATED = 'private.workspace.message.created',\n PRIVATE_WORKSPACE_MEMBER_ADDED = 'private.workspace.member.added',\n}\n\n// ─── API Response Wrapper ─────────────────────────────────────────────────────\n\nexport interface PaginatedResponse<T> {\n data: T[];\n total: number;\n offset: number;\n limit: number;\n}\n\n// ─── Domain Models ────────────────────────────────────────────────────────────\n\nexport interface EntityWithSecret {\n key: string;\n value: string;\n isSecret: boolean;\n}\n\nexport interface WorkspaceType {\n _id: string;\n name: string;\n entitiesWithSecrets?: EntityWithSecret[];\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface Workspace {\n _id: string;\n name: string;\n isPrivate?: boolean;\n type?: WorkspaceType | string;\n scope?: string;\n entitiesWithSecrets?: EntityWithSecret[];\n status: WorkspaceStatus;\n syncWithSlack?: boolean;\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface WorkspaceMember {\n _id: string;\n workspace: string;\n memberId: string;\n memberName: string;\n memberType: MemberType;\n role: MemberRole;\n createdBy?: string;\n updatedBy?: string;\n joinedAt: string;\n createdAt?: string;\n}\n\n/** Subset of WorkspaceMessage returned when populated as a reply reference */\nexport interface ReplyMessage {\n _id: string;\n senderId: string;\n senderName: string;\n senderType: MemberType;\n content: string;\n createdAt: string;\n /** Set locally when the replied-to message is soft-deleted */\n deleted?: boolean;\n}\n\nexport interface WorkspaceMessage {\n _id: string;\n workspace: string;\n senderId: string;\n senderName: string;\n senderType: MemberType;\n sender?: WorkspaceMessageSender;\n content: string;\n mentionedUsers?: string[];\n mentionedAgents?: string[];\n replyToMessage?: ReplyMessage | null;\n metadata?: Record<string, unknown>;\n deleted?: boolean;\n editedAt?: string;\n pinned?: boolean;\n pinnedAt?: string;\n pinnedBy?: string;\n createdBy?: string;\n createdAt: string;\n}\n\nexport interface WorkspaceMessageSender {\n _id: string;\n memberId: string;\n memberName: string;\n memberType: MemberType;\n role: MemberRole;\n}\n\nexport interface FileRecord {\n _id: string;\n filename: string;\n originalName: string;\n mimetype: string;\n size: number;\n bucket: string;\n key: string;\n storageProvider: string;\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface WorkspaceArtefact {\n _id: string;\n workspace: string;\n message?: string;\n file: FileRecord;\n type: ArtefactType;\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface WorkspaceMessageReaction {\n _id: string;\n reaction: string;\n message: string;\n member?: string;\n memberId?: string;\n memberName?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface MessageWithArtefacts extends WorkspaceMessage {\n artefacts: WorkspaceArtefact[];\n reactions: WorkspaceMessageReaction[];\n}\n\nexport interface WorkspaceAgent {\n _id: string;\n agentId: string;\n agentName: string;\n webhookCount: number;\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface AgentDeleteInfo {\n webhookCount: number;\n memberCount: number;\n}\n\nexport interface WebhookSubscription {\n _id: string;\n name: string;\n targetUrl: string;\n secretKey: string;\n secretValue: string;\n eventTypes: string[];\n active: boolean;\n isAgent: boolean;\n agentId?: string;\n metadata?: Record<string, unknown>;\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface WorkspaceSummary {\n _id: string;\n workspace: string;\n keyPoints: string[];\n keyTasks: string[];\n keyDecisions: string[];\n messageCount: number;\n lastMessage?: {\n _id: string;\n senderId: string;\n senderName: string;\n senderType: MemberType;\n content: string;\n createdAt: string;\n } | null;\n wasTruncated: boolean;\n generatedAt: string;\n threadId?: string;\n threadState?: 'queued' | 'running' | 'succeeded' | 'failed';\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface LatestSummaryResponse {\n summary: WorkspaceSummary | null;\n messagesAfterCount: number;\n}\n\n// ─── API Payload Types ────────────────────────────────────────────────────────\n\nexport interface CreateWorkspacePayload {\n name: string;\n isPrivate?: boolean;\n type?: string;\n scope?: string;\n entitiesWithSecrets?: EntityWithSecret[];\n members?: {\n memberId: string;\n memberName: string;\n memberType?: MemberType;\n role?: string;\n }[];\n syncWithSlack?: boolean;\n}\n\nexport interface SendMessagePayload {\n senderType?: MemberType;\n content: string;\n metadata?: Record<string, unknown>;\n replyToMessageId?: string;\n}\n\nexport interface UpdateMessagePayload {\n content: string;\n}\n\n// ─── Socket Event Payload Types ───────────────────────────────────────────────\n// These mirror exactly what workspace.gateway.ts emits over Socket.IO.\n\n/** workspace.created → emitted to each member's personal room */\nexport interface WsPayloadWorkspaceCreated {\n workspace: Workspace;\n}\n\n/** workspace.added → emitted to the new member's personal room */\nexport interface WsPayloadWorkspaceAdded {\n workspaceId: string;\n workspace?: Workspace;\n}\n\n/** workspace.removed → emitted to the removed member's personal room */\nexport interface WsPayloadWorkspaceRemoved {\n workspaceId: string;\n}\n\n/** workspace.updated → emitted to workspace room */\nexport interface WsPayloadWorkspaceUpdated {\n workspace: Workspace;\n}\n\n/** workspace.statusChanged → emitted to workspace room */\nexport interface WsPayloadWorkspaceStatusChanged {\n workspace: Workspace;\n}\n\n/** workspace.member.added → emitted to workspace room */\nexport interface WsPayloadMemberAdded {\n workspaceId: string;\n member: WorkspaceMember;\n}\n\n/** workspace.member.updated → emitted to workspace room */\nexport interface WsPayloadMemberUpdated {\n workspaceId: string;\n member: WorkspaceMember;\n}\n\n/**\n * workspace.member.removed → emitted to workspace room.\n * `memberId` = the WorkspaceMember document _id (ObjectId string)\n * `memberId_field` = the actual userId/email of the removed member\n */\nexport interface WsPayloadMemberRemoved {\n workspaceId: string;\n memberId: string;\n memberId_field: string;\n}\n\n/** workspace.message.created → emitted to workspace room */\nexport interface WsPayloadMessageCreated {\n workspaceId: string;\n message: WorkspaceMessage;\n}\n\n/** workspace.artefact.created → emitted to workspace room */\nexport interface WsPayloadArtefactCreated {\n workspaceId: string;\n artefacts: WorkspaceArtefact[];\n}\n\n/** workspace.typing.started / workspace.typing.stopped */\nexport interface WsPayloadTyping {\n workspaceId: string;\n member: {\n memberId: string;\n memberName: string;\n memberType?: 'user' | 'agent' | string;\n };\n}\n\n/** workspace.message.updated → emitted to workspace room */\nexport interface WsPayloadMessageUpdated {\n workspaceId: string;\n message: WorkspaceMessage;\n}\n\n/** workspace.message.deleted → emitted to workspace room */\nexport interface WsPayloadMessageDeleted {\n workspaceId: string;\n messageId: string;\n}\n\n/** workspace.message.reaction.created → emitted to workspace room */\nexport interface WsPayloadReactionCreated {\n workspaceId: string;\n messageId: string;\n reaction: WorkspaceMessageReaction;\n}\n\n/** workspace.message.reaction.deleted → emitted to workspace room */\nexport interface WsPayloadReactionDeleted {\n workspaceId: string;\n messageId: string;\n reaction: string;\n memberId: string;\n memberName: string;\n}\n\n/** workspace.message.pinned → emitted to workspace room */\nexport interface WsPayloadMessagePinned {\n workspaceId: string;\n message: WorkspaceMessage;\n action: 'pinned' | 'unpinned';\n author: string;\n}\n\n// ─── UI Helpers ───────────────────────────────────────────────────────────────\n\n/** User with an optional avatar photo URL, for member avatar display. */\nexport interface AvatarUser {\n email: string;\n avatarUrl?: string;\n}\n","// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Payload shape sent by the backend Atlas Change Stream trigger */\nexport interface ChangeLogData {\n /** Full document snapshot (insert / replace events) */\n fullDocument?: Record<string, unknown>;\n /** Flat fields sent directly on data (legacy / simplified events) */\n updatedFields?: Record<string, unknown>;\n name?: string;\n memberName?: string;\n role?: string;\n originalName?: string;\n filename?: string;\n /** MongoDB update description (update events) */\n updateDescription?: {\n updatedFields?: Record<string, unknown>;\n removedFields?: string[];\n };\n}\n\n/** Matches the backend ChangeLog schema */\nexport interface ChangeLog {\n _id: string;\n event: string;\n timestamp: number;\n type: string;\n entityId: string;\n data?: ChangeLogData;\n createdBy?: string;\n updatedBy?: string;\n}\n\nexport type ActivityIcon =\n | 'created'\n | 'updated'\n | 'deleted'\n | 'member_added'\n | 'member_removed'\n | 'member_role'\n | 'artefact_added'\n | 'artefact_deleted'\n | 'archived'\n | 'generic';\n\nexport type EntityCategory = 'context' | 'members' | 'artefacts' | 'other';\n\nexport interface ActivityEntry {\n _id: string;\n title: string;\n description: string;\n date: string;\n author: string;\n icon: ActivityIcon;\n category: EntityCategory;\n}\n\nexport interface FilterPill {\n label: string;\n value: string | undefined; // undefined = Tout\n entityType: string | undefined; // sent to backend\n category: EntityCategory | undefined;\n}\n\n// ─── Filtre pills ─────────────────────────────────────────────────────────────\n\nexport const FILTER_PILLS: FilterPill[] = [\n {\n label: 'Tout',\n value: undefined,\n entityType: undefined,\n category: undefined,\n },\n {\n label: 'Contexte',\n value: 'context',\n entityType: 'workspaces',\n category: 'context',\n },\n {\n label: 'Membres',\n value: 'members',\n entityType: 'workspace_members',\n category: 'members',\n },\n {\n label: 'Artefacts',\n value: 'artefacts',\n entityType: 'workspace_artefacts',\n category: 'artefacts',\n },\n];\n\n// ─── Mapping helpers ──────────────────────────────────────────────────────────\n\nexport const WORKSPACE_FIELD_LABELS: Record<string, string> = {\n name: 'Nom',\n type: 'Type',\n scope: 'Périmètre',\n entities: 'Entités',\n entitiesWithSecrets: 'Entités',\n status: 'Statut',\n description: 'Description',\n};\n\nexport const WORKSPACE_STATUS_LABELS: Record<string, string> = {\n ACTIVE: 'Actif',\n ARCHIVED: 'Archivé',\n DRAFT: 'Brouillon',\n CLOSED: 'Clôturé',\n};\n\nexport const MEMBER_ROLE_LABELS: Record<string, string> = {\n owner: 'Propriétaire',\n participant: 'Participant',\n viewer: 'Lecteur',\n};\n\nexport const IGNORED_FIELDS = [\n '_id',\n '__v',\n 'updatedAt',\n 'createdAt',\n 'createdBy',\n 'updatedBy',\n 'workspace',\n];\n\n// ─── Icon / category style maps ───────────────────────────────────────────────\n\nexport const CATEGORY_STYLES: Record<\n EntityCategory,\n { dot: string; badge: string; label: string }\n> = {\n context: {\n dot: 'bg-primary/15 border-primary/30',\n badge: 'bg-primary/10 text-primary',\n label: 'Contexte',\n },\n members: {\n dot: 'bg-info/15 border-info/30',\n badge: 'bg-info/10 text-info',\n label: 'Membre',\n },\n artefacts: {\n dot: 'bg-success/15 border-success/30',\n badge: 'bg-success/10 text-success',\n label: 'Artefact',\n },\n other: {\n dot: 'bg-border',\n badge: 'bg-border text-text-muted',\n label: 'Autre',\n },\n};\n\nexport const ICON_COLOR: Record<ActivityIcon, string> = {\n created: 'text-primary',\n updated: 'text-primary',\n deleted: 'text-danger',\n member_added: 'text-info',\n member_removed: 'text-danger',\n member_role: 'text-info',\n artefact_added: 'text-success',\n artefact_deleted: 'text-danger',\n archived: 'text-text-muted',\n generic: 'text-text-muted',\n};\n","import type { WorkspaceClient } from './client';\nimport type {\n Workspace,\n WorkspaceType,\n WorkspaceMember,\n WorkspaceMessage,\n WorkspaceArtefact,\n WorkspaceMessageReaction,\n MessageWithArtefacts,\n PaginatedResponse,\n CreateWorkspacePayload,\n SendMessagePayload,\n UpdateMessagePayload,\n WebhookSubscription,\n WorkspaceStatus,\n MemberRole,\n MemberType,\n ArtefactType,\n WorkspaceAgent,\n AgentDeleteInfo,\n EntityWithSecret,\n WorkspaceSummary,\n LatestSummaryResponse,\n} from '../types';\n\n// ─── Sync types (co-located with API for convenience) ─────────────────────────\n\nexport interface SyncLink {\n provider: string;\n externalId: string;\n externalName?: string;\n externalTeamId?: string;\n active: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface SyncStatus {\n syncWithSlack: boolean;\n syncProviders?: string[];\n links: SyncLink[];\n}\n\nexport interface SyncProviderInfo {\n id: string;\n enabled: boolean;\n}\n\nexport interface ToggleReactionResponse {\n action: 'created' | 'deleted';\n reaction: WorkspaceMessageReaction | null;\n}\n\n// ─── API factory ──────────────────────────────────────────────────────────────\n// Each API object uses the injected client (from WorkspaceProvider).\n\nexport function createWorkspaceApis(client: WorkspaceClient) {\n // ── Workspace Types ──\n const workspaceTypeApi = {\n list: () => client.get<WorkspaceType[]>('/workspace-types'),\n get: (id: string) => client.get<WorkspaceType>(`/workspace-types/${id}`),\n create: (payload: { name: string; entitiesWithSecrets?: EntityWithSecret[] }) =>\n client.post<WorkspaceType>('/workspace-types', payload),\n update: (id: string, payload: { name?: string; entitiesWithSecrets?: EntityWithSecret[] }) =>\n client.patch<WorkspaceType>(`/workspace-types/${id}`, payload),\n delete: (id: string) => client.delete<void>(`/workspace-types/${id}`),\n };\n\n // ── Workspaces ──\n const workspaceApi = {\n list: (params?: {\n search?: string;\n status?: string;\n type?: string;\n isPrivate?: boolean;\n limit?: number;\n skip?: number;\n }) => {\n const cleanParams = Object.fromEntries(\n Object.entries(params || {})\n .filter(([, v]) => v != null && v !== '' && v !== 'all')\n .map(([k, v]) => [k, String(v)])\n );\n const qs =\n Object.keys(cleanParams).length > 0\n ? '?' + new URLSearchParams(cleanParams as Record<string, string>).toString()\n : '';\n return client.get<PaginatedResponse<Workspace>>(`/workspaces${qs}`);\n },\n get: (id: string) => client.get<Workspace>(`/workspaces/${id}`),\n create: (payload: CreateWorkspacePayload) =>\n client.post<Workspace>('/workspaces', payload),\n update: (id: string, payload: Partial<Omit<CreateWorkspacePayload, 'members'>>) =>\n client.patch<Workspace>(`/workspaces/${id}`, payload),\n updateStatus: (id: string, status: WorkspaceStatus) =>\n client.patch<Workspace>(`/workspaces/${id}/status`, { status }),\n delete: (id: string) => client.delete<void>(`/workspaces/${id}`),\n startTyping: (id: string) => client.post<void>(`/workspaces/${id}/writing/start`, {}),\n stopTyping: (id: string) => client.post<void>(`/workspaces/${id}/writing/stop`, {}),\n timeline: (\n workspaceId: string,\n params?: { limit?: number; offset?: number; entityType?: string }\n ) => {\n const qs = params\n ? '?' +\n new URLSearchParams(\n Object.fromEntries(\n Object.entries(params)\n .filter(([, v]) => v != null)\n .map(([k, v]) => [k, String(v)])\n )\n ).toString()\n : '';\n return client.get<PaginatedResponse<any>>(`/workspaces/${workspaceId}/timeline${qs}`);\n },\n };\n\n // ── Members ──\n const memberApi = {\n list: (workspaceId: string) =>\n client.get<WorkspaceMember[]>(`/workspaces/${workspaceId}/members`),\n add: (\n workspaceId: string,\n payload: { memberId: string; memberName: string; memberType?: MemberType; role?: MemberRole }\n ) => client.post<WorkspaceMember>(`/workspaces/${workspaceId}/members`, payload),\n updateRole: (workspaceId: string, memberId: string, role: MemberRole) =>\n client.patch<WorkspaceMember>(`/workspaces/${workspaceId}/members/${memberId}`, { role }),\n remove: (workspaceId: string, memberId: string) =>\n client.delete<void>(`/workspaces/${workspaceId}/members/${memberId}`),\n };\n\n // ── Messages ──\n const messageApi = {\n list: (\n workspaceId: string,\n params?: { limit?: number; offset?: number; sort?: 'asc' | 'desc' }\n ) => {\n const qs = params\n ? '?' +\n new URLSearchParams(\n Object.fromEntries(\n Object.entries(params)\n .filter(([, v]) => v != null)\n .map(([k, v]) => [k, String(v)])\n )\n ).toString()\n : '';\n return client.get<PaginatedResponse<WorkspaceMessage>>(`/workspaces/${workspaceId}/messages${qs}`);\n },\n send: (workspaceId: string, payload: SendMessagePayload) =>\n client.post<WorkspaceMessage>(`/workspaces/${workspaceId}/messages`, payload),\n update: (workspaceId: string, messageId: string, payload: UpdateMessagePayload) =>\n client.patch<WorkspaceMessage>(`/workspaces/${workspaceId}/messages/${messageId}`, payload),\n delete: (workspaceId: string, messageId: string) =>\n client.delete<WorkspaceMessage>(`/workspaces/${workspaceId}/messages/${messageId}`),\n togglePin: (workspaceId: string, messageId: string) =>\n client.patch<WorkspaceMessage>(`/workspaces/${workspaceId}/messages/${messageId}/pin`, {}),\n };\n\n // ── Artefacts ──\n const artefactApi = {\n upload: async (\n workspaceId: string,\n files: File[],\n messageId?: string,\n artefactType?: string\n ): Promise<{ success: boolean; count: number; results: WorkspaceArtefact[] }> => {\n const formData = new FormData();\n files.forEach((f) => formData.append('files', f));\n if (messageId) formData.append('messageId', messageId);\n if (artefactType) formData.append('type', artefactType);\n return client.upload(`/workspaces/${workspaceId}/artefacts`, formData);\n },\n list: (workspaceId: string, artefactType?: ArtefactType) => {\n const query = artefactType ? `?type=${artefactType}` : '';\n return client.get<{ data: WorkspaceArtefact[]; total: number }>(\n `/workspaces/${workspaceId}/artefacts${query}`\n );\n },\n listPaginated: (\n workspaceId: string,\n params?: { type?: ArtefactType; limit?: number; offset?: number }\n ) => {\n const entries: [string, string][] = [];\n if (params) {\n if (params.type) entries.push(['type', params.type]);\n if (params.limit != null) entries.push(['limit', String(params.limit)]);\n if (params.offset != null) entries.push(['offset', String(params.offset)]);\n }\n const qs = entries.length > 0 ? '?' + new URLSearchParams(entries).toString() : '';\n return client.get<PaginatedResponse<WorkspaceArtefact>>(\n `/workspaces/${workspaceId}/artefacts${qs}`\n );\n },\n delete: (workspaceId: string, artefactId: string) =>\n client.delete(`/workspaces/${workspaceId}/artefacts/${artefactId}`),\n getSignedUrl: (fileId: string) =>\n client.get<{ url: string }>(`/files/${fileId}/signed-url`),\n getDownloadBlob: (fileId: string) => client.getBlob(`/files/${fileId}/download`),\n messagesWithArtefacts: (\n workspaceId: string,\n params?: {\n limit?: number;\n offset?: number;\n sort?: 'asc' | 'desc';\n members?: string[];\n concernsMe?: boolean;\n pinned?: boolean;\n }\n ) => {\n const entries: [string, string][] = [];\n if (params) {\n if (params.limit != null) entries.push(['limit', String(params.limit)]);\n if (params.offset != null) entries.push(['offset', String(params.offset)]);\n if (params.sort) entries.push(['sort', params.sort]);\n if (params.members && params.members.length > 0)\n entries.push(['members', params.members.join(',')]);\n if (params.concernsMe) entries.push(['concernsMe', 'true']);\n if (params.pinned) entries.push(['pinned', 'true']);\n }\n const qs = entries.length > 0 ? '?' + new URLSearchParams(entries).toString() : '';\n return client.get<PaginatedResponse<MessageWithArtefacts>>(\n `/workspaces/${workspaceId}/messages/with-artefacts${qs}`\n );\n },\n };\n\n // ── Reactions ──\n const reactionApi = {\n toggle: (workspaceId: string, messageId: string, reaction: string) =>\n client.post<ToggleReactionResponse>(\n `/workspaces/${workspaceId}/messages/${messageId}/reactions/toggle`,\n { reaction }\n ),\n };\n\n // ── Agents ──\n const agentApi = {\n list: (search?: string) => {\n const qs = search ? `?search=${encodeURIComponent(search)}` : '';\n return client.get<WorkspaceAgent[]>(`/workspace-agents${qs}`);\n },\n create: (body: { agentId: string; agentName: string }) =>\n client.post<WorkspaceAgent>('/workspace-agents', body),\n update: (id: string, body: { agentName: string }) =>\n client.patch<WorkspaceAgent>(`/workspace-agents/${id}`, body),\n delete: (id: string) => client.delete<void>(`/workspace-agents/${id}`),\n getDeleteInfo: (id: string) =>\n client.get<AgentDeleteInfo>(`/workspace-agents/${id}/delete-info`),\n };\n\n // ── Summaries ──\n const summaryApi = {\n generate: (workspaceId: string) =>\n client.post<WorkspaceSummary>(`/workspaces/${workspaceId}/summaries/generate`, {}),\n getLatest: (workspaceId: string) =>\n client.get<LatestSummaryResponse>(`/workspaces/${workspaceId}/summaries/latest`),\n getHistory: (workspaceId: string) =>\n client.get<WorkspaceSummary[]>(`/workspaces/${workspaceId}/summaries`),\n create: (\n workspaceId: string,\n payload: {\n keyPoints: string[];\n keyTasks: string[];\n keyDecisions: string[];\n messageCount: number;\n lastMessage?: string;\n wasTruncated?: boolean;\n generatedAt?: string;\n }\n ) => client.post<WorkspaceSummary>(`/workspaces/${workspaceId}/summaries`, payload),\n update: (\n workspaceId: string,\n summaryId: string,\n payload: Partial<{\n keyPoints: string[];\n keyTasks: string[];\n keyDecisions: string[];\n messageCount: number;\n wasTruncated: boolean;\n }>\n ) =>\n client.patch<WorkspaceSummary>(\n `/workspaces/${workspaceId}/summaries/${summaryId}`,\n payload\n ),\n };\n\n // ── Webhooks ──\n const webhookApi = {\n list: (params?: { search?: string; isAgent?: string; agentId?: string }) => {\n const cleanParams = Object.fromEntries(\n Object.entries(params || {}).filter(([, v]) => v !== undefined && v !== '')\n );\n const qs =\n Object.keys(cleanParams).length > 0\n ? '?' + new URLSearchParams(cleanParams as Record<string, string>).toString()\n : '';\n return client.get<WebhookSubscription[]>(`/webhook-subscriptions${qs}`);\n },\n create: (data: {\n name: string;\n targetUrl: string;\n secretKey: string;\n secretValue: string;\n eventTypes?: string[];\n active?: boolean;\n isAgent?: boolean;\n agentId?: string;\n metadata?: Record<string, unknown>;\n }) => client.post<WebhookSubscription>('/webhook-subscriptions', data),\n update: (\n id: string,\n data: Partial<{\n name: string;\n targetUrl: string;\n secretKey: string;\n secretValue: string;\n eventTypes: string[];\n active: boolean;\n isAgent: boolean;\n agentId: string;\n metadata: Record<string, unknown>;\n }>\n ) => client.patch<WebhookSubscription>(`/webhook-subscriptions/${id}`, data),\n delete: (id: string) => client.delete(`/webhook-subscriptions/${id}`),\n };\n\n // ── Sync ──\n const syncApi = {\n getAvailableProviders: () =>\n client\n .get<{ providers: SyncProviderInfo[] }>('/workspaces/sync/providers')\n .then((res) => res.providers),\n getStatus: (workspaceId: string) =>\n client.get<SyncStatus>(`/workspaces/${workspaceId}/sync-status`),\n toggleSync: (workspaceId: string, provider: string, enabled: boolean) =>\n client.patch<Workspace>(`/workspaces/${workspaceId}/sync`, { provider, enabled }),\n };\n\n return {\n workspaceTypeApi,\n workspaceApi,\n memberApi,\n messageApi,\n artefactApi,\n reactionApi,\n agentApi,\n summaryApi,\n webhookApi,\n syncApi,\n };\n}\n\nexport type WorkspaceApis = ReturnType<typeof createWorkspaceApis>;\n","import { create, type StoreApi, type UseBoundStore } from 'zustand';\nimport type { Workspace, WorkspaceMember, WorkspaceType } from '../types';\nimport type { WorkspaceApis } from '../api';\n\n// ─── Workspace List Store ─────────────────────────────────────────────────────\n// Zustand store for workspace list with in-memory cache, pagination,\n// group/private tabs, and real-time prepend/remove.\n\nconst PAGE_SIZE = 12;\n\nexport type WorkspaceTab = 'group' | 'private';\n\nexport interface WorkspaceListFilters {\n search: string;\n status: string;\n type: string;\n}\n\nexport interface WorkspaceListState {\n workspaces: Workspace[];\n total: number;\n membersMap: Record<string, WorkspaceMember[]>;\n types: WorkspaceType[];\n tab: WorkspaceTab;\n page: number;\n pageSize: number;\n totalPages: number;\n filters: WorkspaceListFilters;\n initialLoading: boolean;\n fetching: boolean;\n hydrated: boolean;\n\n setTab: (tab: WorkspaceTab) => void;\n setFilters: (filters: WorkspaceListFilters) => void;\n setPage: (page: number) => void;\n fetchWorkspaces: () => Promise<void>;\n fetchTypes: () => Promise<void>;\n prependWorkspace: (ws: Workspace, members?: WorkspaceMember[]) => void;\n removeWorkspace: (workspaceId: string) => void;\n refresh: () => Promise<void>;\n}\n\n/**\n * Factory that creates a Zustand store bound to the injected API client.\n * Call this inside your WorkspaceProvider or in a hook.\n */\nexport function createWorkspaceListStore(\n apis: WorkspaceApis\n): UseBoundStore<StoreApi<WorkspaceListState>> {\n return create<WorkspaceListState>()((set, get) => ({\n workspaces: [],\n total: 0,\n membersMap: {},\n types: [],\n tab: 'group',\n page: 1,\n pageSize: PAGE_SIZE,\n totalPages: 0,\n filters: { search: '', status: 'ACTIVE', type: 'all' },\n initialLoading: true,\n fetching: false,\n hydrated: false,\n\n setTab: (tab) => {\n const prev = get().tab;\n if (prev === tab) return;\n set({\n tab,\n page: 1,\n workspaces: [],\n total: 0,\n totalPages: 0,\n membersMap: {},\n });\n get().fetchWorkspaces();\n },\n\n setFilters: (filters) => {\n set({ filters, page: 1 });\n },\n\n setPage: (page) => {\n set({ page });\n },\n\n fetchTypes: async () => {\n try {\n const types = await apis.workspaceTypeApi.list();\n set({ types });\n } catch (err) {\n console.error('Failed to load workspace types:', err);\n }\n },\n\n fetchWorkspaces: async () => {\n const { filters, page, pageSize, hydrated, tab } = get();\n if (!hydrated) set({ initialLoading: true });\n set({ fetching: true });\n\n try {\n const skip = (page - 1) * pageSize;\n const result = await apis.workspaceApi.list({\n ...filters,\n isPrivate: tab === 'private',\n limit: pageSize,\n skip,\n });\n\n const wsList = result.data;\n const totalPages = Math.ceil(result.total / pageSize);\n\n const map: Record<string, WorkspaceMember[]> = {};\n await Promise.all(\n wsList.map(async (ws) => {\n try {\n map[ws._id] = await apis.memberApi.list(ws._id);\n } catch {\n map[ws._id] = [];\n }\n })\n );\n\n set({\n workspaces: wsList,\n total: result.total,\n totalPages,\n membersMap: map,\n hydrated: true,\n initialLoading: false,\n fetching: false,\n });\n } catch (err) {\n console.error('Failed to load workspaces:', err);\n set({ initialLoading: false, fetching: false });\n }\n },\n\n prependWorkspace: (ws, members = []) => {\n set((state) => {\n if (state.workspaces.some((w) => w._id === ws._id)) return state;\n return {\n workspaces: [ws, ...state.workspaces],\n total: state.total + 1,\n totalPages: Math.ceil((state.total + 1) / state.pageSize),\n membersMap: { ...state.membersMap, [ws._id]: members },\n };\n });\n },\n\n removeWorkspace: (workspaceId) => {\n set((state) => {\n const next = { ...state.membersMap };\n delete next[workspaceId];\n const newTotal = Math.max(0, state.total - 1);\n return {\n workspaces: state.workspaces.filter((w) => w._id !== workspaceId),\n total: newTotal,\n totalPages: Math.ceil(newTotal / state.pageSize),\n membersMap: next,\n };\n });\n },\n\n refresh: async () => {\n const { fetchWorkspaces } = get();\n await fetchWorkspaces();\n },\n }));\n}\n","import { useMemo } from 'react';\nimport { createWorkspaceApis, type WorkspaceApis } from '../api';\nimport { useWorkspaceContext } from '../provider';\n\n/**\n * Hook to access all workspace API modules within a WorkspaceProvider.\n * The APIs are memoized and only recreated when the client changes.\n */\nexport function useWorkspaceApi(): WorkspaceApis {\n const { apiClient } = useWorkspaceContext();\n return useMemo(() => createWorkspaceApis(apiClient), [apiClient]);\n}\n","import type { MemberType } from '../types';\n\n// ─── Static Agent Members ─────────────────────────────────────────────────────\n\nexport const AVAILABLE_AGENTS: {\n memberId: string;\n memberName: string;\n memberType: MemberType;\n}[] = [\n { memberId: 'james-agent', memberName: 'James', memberType: 'agent' },\n { memberId: 'eclaireur-agent', memberName: 'Éclaireur IA', memberType: 'agent' },\n { memberId: 'sentinelle-agent', memberName: 'Sentinelle', memberType: 'agent' },\n { memberId: 'archiviste-agent', memberName: 'Archiviste', memberType: 'agent' },\n { memberId: 'stratege-agent', memberName: 'Stratège', memberType: 'agent' },\n];\n\n// ─── Role Labels (French) ─────────────────────────────────────────────────────\n\nexport const ROLE_LABELS: Record<string, string> = {\n owner: 'Propriétaire',\n participant: 'Participant',\n viewer: 'Observateur',\n};\n\n// ─── Status Labels (French) ───────────────────────────────────────────────────\n\nexport const STATUS_LABELS: Record<string, string> = {\n ACTIVE: 'Actif',\n CLOSED: 'Fermé',\n ARCHIVED: 'Archivé',\n};\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nexport function getInitials(name: string): string {\n return name\n .split(/\\s+/)\n .map((w) => w[0])\n .join('')\n .toUpperCase()\n .slice(0, 2);\n}\n\n/**\n * Fix mojibake: corrects filenames that were incorrectly decoded as Latin-1\n * when they are actually UTF-8 (common with some multipart upload implementations).\n */\nexport function fixMojibake(str: string): string {\n try {\n // Attempt to re-encode as Latin-1 bytes then decode as UTF-8\n const bytes = new Uint8Array(str.split('').map((c) => c.charCodeAt(0)));\n return new TextDecoder('utf-8').decode(bytes);\n } catch {\n return str;\n }\n}\n","import type {\n Workspace,\n WorkspaceType,\n WorkspaceMember,\n MessageWithArtefacts,\n} from '../types';\n\n// ─── Role labels ──────────────────────────────────────────────────────────────\n\nconst ROLE_LABELS: Record<string, string> = {\n owner: 'Propriétaire',\n participant: 'Participant',\n viewer: 'Observateur',\n};\n\nconst MEMBER_TYPE_LABELS: Record<string, string> = {\n user: 'Utilisateur',\n agent: 'Agent IA',\n};\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction formatDate(iso: string): string {\n return new Date(iso).toLocaleDateString('fr-FR', {\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n}\n\nfunction formatDateTime(iso: string): string {\n return new Date(iso).toLocaleString('fr-FR', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nfunction getTypeName(workspace: Workspace): string {\n if (!workspace.type) return '—';\n if (typeof workspace.type === 'object') return (workspace.type as WorkspaceType).name;\n return workspace.type;\n}\n\n/**\n * Attempt to fix common mojibake patterns (UTF-8 decoded as Latin-1).\n * Simplified version — consumers can override with their own implementation.\n */\nfunction fixMojibake(text: string): string {\n return text\n .replace(/é/g, 'é')\n .replace(/è/g, 'è')\n .replace(/à /g, 'à')\n .replace(/ç/g, 'ç')\n .replace(/ô/g, 'ô')\n .replace(/î/g, 'î')\n .replace(/â/g, 'â')\n .replace(/ë/g, 'ë')\n .replace(/ü/g, 'ü');\n}\n\n// ─── Main export function ─────────────────────────────────────────────────────\n\nexport interface WorkspaceExportData {\n workspace: Workspace;\n members: WorkspaceMember[];\n messages: MessageWithArtefacts[];\n}\n\n/**\n * Generates a formatted Markdown string representing the full workspace export.\n * Includes context, members, and the complete discussion thread.\n */\nexport function formatWorkspaceExport(data: WorkspaceExportData): string {\n const { workspace, members, messages } = data;\n const lines: string[] = [];\n\n lines.push(`# 📋 Export — ${workspace.name}`);\n lines.push('');\n lines.push(`> Export généré le **${formatDateTime(new Date().toISOString())}**`);\n lines.push('');\n lines.push('---');\n lines.push('');\n\n lines.push('## 📌 Contexte');\n lines.push('');\n lines.push(`| Champ | Valeur |`);\n lines.push(`| ----- | ------ |`);\n lines.push(`| **Nom** | ${workspace.name} |`);\n lines.push(`| **Type** | ${getTypeName(workspace)} |`);\n lines.push(`| **Scope** | ${workspace.scope || '—'} |`);\n lines.push(`| **Statut** | ${workspace.status} |`);\n lines.push(`| **Créé le** | ${formatDate(workspace.createdAt)} |`);\n lines.push(`| **Mis à jour le** | ${formatDate(workspace.updatedAt)} |`);\n\n const displayEntities = workspace.entitiesWithSecrets ?? [];\n if (displayEntities.length > 0) {\n lines.push('');\n lines.push('### Entités');\n lines.push('');\n lines.push('| Clé | Valeur | Secret |');\n lines.push('| --- | ------ | ------ |');\n for (const ent of displayEntities) {\n lines.push(\n `| ${ent.key} | ${ent.isSecret ? '••••••' : ent.value} | ${ent.isSecret ? '🔒 Oui' : 'Non'} |`\n );\n }\n }\n\n lines.push('');\n lines.push('---');\n lines.push('');\n\n lines.push(`## 👥 Membres (${members.length})`);\n lines.push('');\n lines.push('| Nom | Type | Rôle | Rejoint le |');\n lines.push('| --- | ---- | ---- | ---------- |');\n for (const m of members) {\n lines.push(\n `| ${m.memberName} | ${MEMBER_TYPE_LABELS[m.memberType] || m.memberType} | ${ROLE_LABELS[m.role] || m.role} | ${m.joinedAt || m.createdAt ? formatDate(m.joinedAt || m.createdAt!) : '—'} |`\n );\n }\n\n lines.push('');\n lines.push('---');\n lines.push('');\n\n lines.push(`## 💬 Discussion (${messages.length} messages)`);\n lines.push('');\n\n if (messages.length === 0) {\n lines.push('_Aucun message dans ce workspace._');\n } else {\n let currentDay = '';\n for (const msg of messages) {\n const day = formatDate(msg.createdAt);\n if (day !== currentDay) {\n currentDay = day;\n lines.push(`### 📅 ${day}`);\n lines.push('');\n }\n const timeStr = new Date(msg.createdAt).toLocaleTimeString('fr-FR', {\n hour: '2-digit',\n minute: '2-digit',\n });\n const senderIcon = msg.senderType === 'agent' ? '🤖' : '👤';\n lines.push(`**${senderIcon} ${msg.senderName}** — _${timeStr}_`);\n lines.push('');\n lines.push(msg.content);\n lines.push('');\n if (msg.artefacts && msg.artefacts.length > 0) {\n lines.push('> 📎 Pièces jointes :');\n for (const art of msg.artefacts) {\n lines.push(`> - \\`${fixMojibake(art.file.originalName)}\\` (${art.type})`);\n }\n lines.push('');\n }\n lines.push('---');\n lines.push('');\n }\n }\n\n lines.push('');\n lines.push(`_Fin de l'export — ${workspace.name}_`);\n\n return lines.join('\\n');\n}\n","import React, { useEffect, useId, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X } from 'lucide-react';\nimport { cn } from './cn';\n\n/** Preset width for the centered panel */\nexport type ModalSize =\n | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | '7xl' | 'full';\n\nexport type ModalHeaderVariant = 'strip' | 'plain';\n\nconst MODAL_SIZE_CLASS: Record<ModalSize, string> = {\n sm: 'w-full min-w-0 max-w-sm',\n md: 'w-full min-w-0 max-w-md',\n lg: 'w-full min-w-0 max-w-lg',\n xl: 'w-full min-w-0 max-w-xl',\n '2xl': 'w-full min-w-0 max-w-2xl',\n '3xl': 'w-full min-w-0 max-w-3xl',\n '4xl': 'w-full min-w-0 max-w-4xl',\n '5xl': 'w-full min-w-0 max-w-5xl',\n '6xl': 'w-full min-w-0 max-w-6xl',\n '7xl': 'w-full min-w-0 max-w-7xl',\n full: 'w-full min-w-0 max-w-[calc(100vw-2rem)] sm:max-w-[min(96vw,90rem)]',\n};\n\nexport interface ModalProps {\n open: boolean;\n onClose: () => void;\n children: React.ReactNode;\n zIndexClass?: string;\n backdropClassName?: string;\n size?: ModalSize;\n panelClassName?: string;\n className?: string;\n closeOnBackdropClick?: boolean;\n closeOnEscape?: boolean;\n ariaLabelledBy?: string;\n ariaDescribedBy?: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n titleIcon?: React.ReactNode;\n headingId?: string;\n modalHeaderVariant?: ModalHeaderVariant;\n hideCloseButton?: boolean;\n headerTrailing?: React.ReactNode;\n closeButtonAriaLabel?: string;\n closeButtonDisabled?: boolean;\n closeButtonClassName?: string;\n closeIconSize?: number;\n headerClassName?: string;\n titleClassName?: string;\n descriptionClassName?: string;\n}\n\nexport function Modal({\n open,\n onClose,\n children,\n zIndexClass = 'z-[100]',\n backdropClassName = 'bg-black/40 backdrop-blur-sm',\n size,\n panelClassName,\n className,\n closeOnBackdropClick = false,\n closeOnEscape = true,\n ariaLabelledBy: ariaLabelledByProp,\n ariaDescribedBy: ariaDescribedByProp,\n title,\n description,\n titleIcon,\n headingId,\n modalHeaderVariant = 'strip',\n hideCloseButton = false,\n headerTrailing,\n closeButtonAriaLabel = 'Fermer',\n closeButtonDisabled = false,\n closeButtonClassName,\n closeIconSize = 20,\n headerClassName,\n titleClassName,\n descriptionClassName = 'text-text-secondary mt-1 text-sm',\n}: ModalProps) {\n const [mounted, setMounted] = useState(false);\n const autoHeadingId = useId();\n const autoDescIdByModal = useId();\n\n const hasHeader = title != null;\n const resolvedHeadingId = headingId ?? ariaLabelledByProp ?? autoHeadingId;\n\n const assignAutoDescriptionId =\n hasHeader &&\n description != null &&\n ariaDescribedByProp === undefined &&\n (typeof description === 'string' || typeof description === 'number');\n\n const resolvedAriaDescribedBy = assignAutoDescriptionId\n ? autoDescIdByModal\n : ariaDescribedByProp;\n\n const resolvedAriaLabelledBy = hasHeader\n ? ariaLabelledByProp ?? resolvedHeadingId\n : ariaLabelledByProp;\n\n useEffect(() => { setMounted(true); }, []);\n\n useEffect(() => {\n if (!open) return;\n const prevOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => { document.body.style.overflow = prevOverflow; };\n }, [open]);\n\n useEffect(() => {\n if (!open || !closeOnEscape) return;\n const onKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [open, closeOnEscape, onClose]);\n\n const defaultCloseClasses =\n closeButtonClassName ?? 'text-text-secondary hover:text-text rounded p-1 transition-colors';\n\n const trailing =\n headerTrailing ??\n (!hideCloseButton ? (\n <button\n type=\"button\"\n disabled={closeButtonDisabled}\n onClick={onClose}\n className={cn(defaultCloseClasses, closeButtonDisabled && 'opacity-40')}\n aria-label={closeButtonAriaLabel}\n >\n <X size={closeIconSize} />\n </button>\n ) : null);\n\n const descriptionSlot =\n description == null ? null : typeof description === 'string' ||\n typeof description === 'number' ? (\n <p\n id={assignAutoDescriptionId ? autoDescIdByModal : undefined}\n className={descriptionClassName}\n >\n {description}\n </p>\n ) : (\n description\n );\n\n const headerShellClass =\n modalHeaderVariant === 'strip'\n ? 'border-border flex shrink-0 items-start justify-between gap-3 border-b px-6 py-4'\n : 'mb-4 flex shrink-0 items-start justify-between gap-3';\n\n const modalHeaderMarkup = hasHeader ? (\n <div className={cn(headerShellClass, headerClassName)}>\n <div className=\"flex min-w-0 flex-1 items-start gap-3\">\n {titleIcon != null ? <div className=\"mt-0.5 shrink-0\">{titleIcon}</div> : null}\n <div className=\"min-w-0 flex-1\">\n <h2\n id={resolvedHeadingId}\n className={cn('text-text text-lg font-semibold', titleClassName)}\n >\n {title}\n </h2>\n {descriptionSlot}\n </div>\n </div>\n {trailing ? <div className=\"flex shrink-0 items-start\">{trailing}</div> : null}\n </div>\n ) : null;\n\n if (!mounted || !open) return null;\n\n return createPortal(\n <div\n className={cn(\n 'fixed inset-0 flex items-center justify-center p-4',\n zIndexClass,\n backdropClassName,\n className,\n )}\n onClick={closeOnBackdropClick ? onClose : undefined}\n aria-hidden={false}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={resolvedAriaLabelledBy}\n aria-describedby={resolvedAriaDescribedBy}\n className={cn(size ? MODAL_SIZE_CLASS[size] : undefined, panelClassName)}\n onClick={(e) => e.stopPropagation()}\n >\n {modalHeaderMarkup}\n {children}\n </div>\n </div>,\n document.body,\n );\n}\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import React from 'react';\nimport { Brain } from 'lucide-react';\nimport { cn } from './ui/cn';\nimport { getInitials } from '../utils/constants';\n\ntype AvatarSize = 'xs' | 'sm' | 'md' | 'lg';\n\nconst SIZES: Record<AvatarSize, { container: string; text: string; icon: number }> = {\n xs: { container: 'h-6 w-6', text: 'text-[9px]', icon: 10 },\n sm: { container: 'h-7 w-7', text: 'text-[10px]', icon: 12 },\n md: { container: 'h-9 w-9', text: 'text-xs', icon: 16 },\n lg: { container: 'h-10 w-10', text: 'text-sm', icon: 18 },\n};\n\nexport interface MemberAvatarProps {\n memberName: string;\n memberType: 'user' | 'agent';\n avatarUrl?: string | null;\n size?: AvatarSize;\n className?: string;\n variant?: 'primary' | 'owner' | 'currentUser';\n}\n\nexport const MemberAvatar: React.FC<MemberAvatarProps> = ({\n memberName, memberType, avatarUrl, size = 'md', className, variant = 'primary',\n}) => {\n const s = SIZES[size];\n if (memberType === 'agent') {\n return (\n <span className={cn('flex flex-shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-violet-100 to-indigo-100 ring-1 ring-indigo-200/60', s.container, className)}>\n <Brain size={s.icon} className=\"text-indigo-600\" />\n </span>\n );\n }\n if (avatarUrl) {\n return <img src={avatarUrl} alt={memberName} className={cn('flex-shrink-0 rounded-full object-cover ring-2 ring-white', s.container, className)} />;\n }\n return (\n <span className={cn('flex flex-shrink-0 items-center justify-center rounded-full font-semibold', s.container, s.text, variant === 'currentUser' ? 'bg-primary text-white shadow-md' : variant === 'owner' ? 'bg-warning-light text-warning' : 'bg-primary-light text-primary', className)}>\n {getInitials(memberName)}\n </span>\n );\n};\n","import React, { useState, useEffect, useMemo } from 'react';\nimport { UserPlus, Crown, Eye, Users, X, Search, Plus, Brain, Loader2, Check } from 'lucide-react';\nimport type { WorkspaceMember, MemberRole, MemberType, WorkspaceAgent } from '../types';\nimport { useWorkspaceContext } from '../provider';\nimport { useWorkspaceApi } from '../hooks/useWorkspaceApi';\nimport { getInitials, ROLE_LABELS } from '../utils/constants';\nimport { MemberAvatar } from './MemberAvatar';\n\nexport interface AvatarUser { email: string; avatarUrl?: string }\n\ninterface MembersPanelProps {\n members: WorkspaceMember[];\n avatarUsers?: AvatarUser[];\n onAddMember?: (payload: { memberId: string; memberName: string; memberType: MemberType; role?: MemberRole }) => void;\n onRemoveMember?: (memberId: string) => void;\n onUpdateRole?: (memberId: string, role: MemberRole) => void;\n readonly?: boolean;\n /** Hide the agents section entirely (e.g. for private workspaces between two users) */\n hideAgents?: boolean;\n}\n\nconst roleIcon = (role: MemberRole) => {\n switch (role) {\n case 'owner': return <Crown size={11} className=\"text-warning\" />;\n case 'viewer': return <Eye size={11} className=\"text-text-muted\" />;\n default: return <Users size={11} className=\"text-primary\" />;\n }\n};\n\nexport const MembersPanel: React.FC<MembersPanelProps> = ({\n members, avatarUsers, onAddMember, onRemoveMember, onUpdateRole, readonly, hideAgents = false,\n}) => {\n const { config } = useWorkspaceContext();\n const apis = useWorkspaceApi();\n const [showUserSearch, setShowUserSearch] = useState(false);\n const [search, setSearch] = useState('');\n const [searchResults, setSearchResults] = useState<{ id: string; email: string; displayName: string; avatarUrl?: string }[]>([]);\n const [searchingUsers, setSearchingUsers] = useState(false);\n const [allAgents, setAllAgents] = useState<WorkspaceAgent[]>([]);\n\n useEffect(() => {\n apis.agentApi.list().then(setAllAgents).catch(() => setAllAgents([]));\n }, []);\n\n // User search via injected searchUsers callback\n useEffect(() => {\n if (search.length < 2 || !showUserSearch || !config.searchUsers) {\n setSearchResults([]);\n return;\n }\n let cancelled = false;\n setSearchingUsers(true);\n config.searchUsers(search).then((results) => {\n if (!cancelled) setSearchResults(results);\n }).catch(() => {\n if (!cancelled) setSearchResults([]);\n }).finally(() => {\n if (!cancelled) setSearchingUsers(false);\n });\n return () => { cancelled = true; };\n }, [search, showUserSearch, config.searchUsers]);\n\n const filteredUsers = useMemo(() => {\n return searchResults.filter(\n (u) => u.email !== config.currentUserId && !members.some((m) => m.memberId === u.email)\n );\n }, [searchResults, members, config.currentUserId]);\n\n const userMembers = members.filter((m) => m.memberType === 'user');\n const agentMembers = members.filter((m) => m.memberType === 'agent');\n const agentMemberIds = useMemo(() => new Set(agentMembers.map((m) => m.memberId)), [agentMembers]);\n const agentMemberIdMap = useMemo(() => new Map(agentMembers.map((m) => [m.memberId, m._id])), [agentMembers]);\n\n const handleAddUser = (user: { email: string; displayName: string }) => {\n onAddMember?.({ memberId: user.email, memberName: user.displayName, memberType: 'user', role: 'participant' });\n setSearch('');\n setShowUserSearch(false);\n };\n\n const handleAddAgent = (agent: WorkspaceAgent) => {\n onAddMember?.({ memberId: agent.agentId, memberName: agent.agentName, memberType: 'agent', role: 'participant' });\n };\n\n return (\n <div className=\"flex flex-col gap-4\">\n {/* Users section */}\n <div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-muted flex items-center gap-1.5 text-xs font-semibold tracking-wider uppercase\">\n <Users size={14} className=\"text-primary\" /> Utilisateurs\n </span>\n <span className=\"flex items-center gap-1\">\n <span className=\"bg-primary-light text-primary rounded-full px-2 py-0.5 text-[10px] font-bold\">{userMembers.length}</span>\n {!readonly && (\n <button className=\"text-primary hover:bg-primary-light flex items-center gap-1 rounded px-2 py-1 text-xs transition-colors\" onClick={() => setShowUserSearch(!showUserSearch)}>\n <UserPlus size={12} /> Inviter\n </button>\n )}\n </span>\n </div>\n {showUserSearch && (\n <>\n <div className=\"relative mt-2\">\n <Search size={12} className=\"text-text-muted absolute top-1/2 left-2 -translate-y-1/2\" />\n <input className=\"border-border bg-surface text-text focus:border-primary w-full rounded-lg border py-1.5 pr-2 pl-7 text-xs focus:outline-none\" placeholder=\"Rechercher par nom ou email...\" value={search} onChange={(e) => setSearch(e.target.value)} autoFocus />\n </div>\n {search.length >= 2 && searchingUsers && (\n <div className=\"flex items-center justify-center py-3\"><Loader2 size={14} className=\"text-primary animate-spin\" /></div>\n )}\n {filteredUsers.length > 0 && !searchingUsers && (\n <div className=\"bg-surface border-border mt-1 flex flex-col rounded-lg border shadow-sm\">\n {filteredUsers.map((u) => (\n <div key={u.id} className=\"hover:bg-primary-light flex cursor-pointer items-center gap-2 px-3 py-2 text-xs transition-colors first:rounded-t-lg last:rounded-b-lg\" onClick={() => handleAddUser(u)}>\n <span className=\"bg-primary-light text-primary flex h-6 w-6 items-center justify-center rounded-full text-[10px] font-semibold\">{getInitials(u.displayName)}</span>\n <span className=\"text-text\">{u.displayName}</span>\n <Plus size={12} className=\"text-primary ml-auto\" />\n </div>\n ))}\n </div>\n )}\n </>\n )}\n <div className=\"mt-2 flex flex-col gap-1\">\n {userMembers.map((m) => (\n <div key={m._id} className=\"bg-bg group flex items-center gap-2 rounded-lg p-2\">\n <MemberAvatar memberName={m.memberName} memberType={m.memberType} avatarUrl={avatarUsers?.find((u) => u.email.toLowerCase() === m.memberId.toLowerCase())?.avatarUrl} size=\"sm\" variant={m.role === 'owner' ? 'owner' : 'primary'} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-text truncate text-xs font-medium\">{m.memberName}</div>\n <div className=\"text-text-muted flex items-center gap-1 text-[10px]\">{roleIcon(m.role)} {ROLE_LABELS[m.role] ?? m.role}</div>\n </div>\n {!(readonly || (m.role === 'owner' && members.filter((x) => x.role === 'owner').length === 1)) && (\n <select className=\"border-border bg-surface text-text-muted rounded border px-1 py-0.5 text-[10px] opacity-0 transition-opacity group-hover:opacity-100 focus:opacity-100\" value={m.role} onChange={(e) => { e.stopPropagation(); onUpdateRole?.(m._id, e.target.value as MemberRole); }} disabled={readonly || (m.role === 'owner' && members.filter((x) => x.role === 'owner').length === 1)}>\n <option value=\"owner\">Propriétaire</option>\n <option value=\"participant\">Participant</option>\n <option value=\"viewer\">Observateur</option>\n </select>\n )}\n {m.role !== 'owner' && !readonly && (\n <button className=\"text-text-muted hover:text-danger rounded p-0.5 opacity-0 transition-all group-hover:opacity-100\" onClick={(e) => { e.stopPropagation(); onRemoveMember?.(m._id); }}>\n <X size={14} />\n </button>\n )}\n </div>\n ))}\n </div>\n </div>\n {/* Agents section */}\n {!hideAgents && (\n <div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-muted flex items-center gap-1.5 text-xs font-semibold tracking-wider uppercase\">\n <Brain size={14} className=\"text-primary\" /> Agents IA\n </span>\n <span className=\"bg-primary-light text-primary rounded-full px-2 py-0.5 text-[10px] font-bold\">{agentMembers.length}/{allAgents.length}</span>\n </div>\n <div className=\"mt-2 flex flex-col gap-1\">\n {allAgents.map((agent) => {\n const isMember = agentMemberIds.has(agent.agentId);\n const memberId = agentMemberIdMap.get(agent.agentId);\n return (\n <div key={agent.agentId} className=\"bg-bg group flex items-center gap-2 rounded-lg p-2\">\n <span className=\"bg-surface border-border flex h-7 w-7 items-center justify-center rounded-full border\"><Brain size={14} className=\"text-primary\" /></span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-text truncate text-xs font-medium\">{agent.agentName}</div>\n <div className=\"text-text-muted text-[10px]\">Agent IA</div>\n </div>\n {!readonly && (\n isMember ? (\n <button className=\"relative flex h-6 w-6 items-center justify-center rounded-full transition-colors\" onClick={(e) => { e.stopPropagation(); if (memberId) onRemoveMember?.(memberId); }}>\n <Check size={14} className=\"text-success absolute transition-opacity group-hover:opacity-0\" />\n <X size={14} className=\"text-danger absolute opacity-0 transition-opacity group-hover:opacity-100\" />\n </button>\n ) : (\n <button className=\"text-text-muted hover:text-primary hover:bg-primary-light flex h-6 w-6 items-center justify-center rounded-full transition-colors\" onClick={(e) => { e.stopPropagation(); handleAddAgent(agent); }}>\n <Plus size={14} />\n </button>\n )\n )}\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n};\n","import React, { useState, useEffect, useMemo, useId, useRef } from 'react';\nimport { X, ArrowRight, ArrowLeft, Plus, Trash2, Check, Users, Brain, Loader2, Lock, Unlock, Slack } from 'lucide-react';\nimport { cn } from './ui/cn';\nimport { useWorkspaceContext } from '../provider';\nimport { useWorkspaceApi } from '../hooks/useWorkspaceApi';\nimport type { WorkspaceType, CreateWorkspacePayload, MemberType, WorkspaceAgent, EntityWithSecret } from '../types';\nimport { getInitials } from '../utils/constants';\nimport { Modal } from './ui/Modal';\nimport { MemberAvatar } from './MemberAvatar';\n\ninterface CreateWorkspaceModalProps {\n open: boolean;\n onClose: () => void;\n onCreated?: (workspace: unknown) => void;\n}\n\ninterface MemberEntry {\n memberId: string;\n memberName: string;\n memberType: MemberType;\n role: string;\n}\n\nconst STEP_TITLES = ['Type de workspace', 'Contexte', 'Membres', 'Confirmation'];\n\nexport const CreateWorkspaceModal: React.FC<CreateWorkspaceModalProps> = ({ open, onClose, onCreated }) => {\n const titleId = useId();\n const stepDescriptionId = useId();\n const { config } = useWorkspaceContext();\n const apis = useWorkspaceApi();\n\n const [step, setStep] = useState(0);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Step 0: Type\n const [types, setTypes] = useState<WorkspaceType[]>([]);\n const [typesLoading, setTypesLoading] = useState(false);\n const [selectedTypeId, setSelectedTypeId] = useState<string | null>(null);\n\n // Step 1: Context\n const [name, setName] = useState('');\n const [scope, setScope] = useState('');\n const [entities, setEntities] = useState<{ key: string; value: string; isSecret: boolean }[]>([]);\n const [syncWithSlack, setSyncWithSlack] = useState(false);\n const [slackAvailable, setSlackAvailable] = useState(false);\n\n // Step 2: Members\n const [memberSearch, setMemberSearch] = useState('');\n const [members, setMembers] = useState<MemberEntry[]>([]);\n const [agents, setAgents] = useState<WorkspaceAgent[]>([]);\n const [searchResults, setSearchResults] = useState<{ id: string; email: string; displayName: string; avatarUrl?: string }[]>([]);\n const [searchingUsers, setSearchingUsers] = useState(false);\n const [avatarMap, setAvatarMap] = useState<Record<string, string>>({});\n\n // Agent autocomplete\n const [agentSearch, setAgentSearch] = useState('');\n const [showAgentDropdown, setShowAgentDropdown] = useState(false);\n const [agentSearchFocused, setAgentSearchFocused] = useState(false);\n const agentSearchInputRef = useRef<HTMLInputElement>(null);\n\n const invitedUsers = useMemo(() => members.filter((m) => m.memberType === 'user'), [members]);\n const invitedAgents = useMemo(() => members.filter((m) => m.memberType === 'agent'), [members]);\n const unselectedAgents = useMemo(() => agents.filter((a) => !members.some((m) => m.memberId === a.agentId) && (agentSearch.trim() === '' || a.agentName.toLowerCase().includes(agentSearch.toLowerCase()))), [agents, members, agentSearch]);\n\n // Resolve avatars when members change\n useEffect(() => {\n if (!config.resolveAvatars || invitedUsers.length === 0) return;\n config.resolveAvatars(invitedUsers.map((m) => m.memberId)).then(setAvatarMap).catch(() => {});\n }, [invitedUsers.length]);\n\n // User search via injected searchUsers\n useEffect(() => {\n if (memberSearch.length < 2 || !config.searchUsers) { setSearchResults([]); return; }\n let cancelled = false;\n setSearchingUsers(true);\n config.searchUsers(memberSearch).then((r) => { if (!cancelled) setSearchResults(r); }).catch(() => { if (!cancelled) setSearchResults([]); }).finally(() => { if (!cancelled) setSearchingUsers(false); });\n return () => { cancelled = true; };\n }, [memberSearch]);\n\n const filteredUsers = useMemo(() => searchResults.filter((u) => u.email !== config.currentUserId && !members.some((m) => m.memberId === u.email)), [searchResults, members, config.currentUserId]);\n\n // Load types on mount\n useEffect(() => {\n if (!open) return;\n setTypesLoading(true);\n Promise.all([apis.workspaceTypeApi.list(), apis.agentApi.list()])\n .then(([wt, ag]) => { setTypes(wt); setAgents(ag); })\n .catch(() => { setTypes([]); setAgents([]); })\n .finally(() => setTypesLoading(false));\n apis.syncApi.getAvailableProviders().then((providers) => setSlackAvailable(providers.some((p) => p.id === 'slack' && p.enabled))).catch(() => setSlackAvailable(false));\n }, [open]);\n\n // Pre-fill entities when type changes\n useEffect(() => {\n if (!selectedTypeId) return;\n const t = types.find((tp) => tp._id === selectedTypeId);\n if (t?.entitiesWithSecrets && t.entitiesWithSecrets.length > 0) {\n setEntities(t.entitiesWithSecrets.map((e) => ({ key: e.key, value: e.value, isSecret: e.isSecret })));\n }\n }, [selectedTypeId, types]);\n\n // Reset on close\n useEffect(() => {\n if (!open) { setStep(0); setSelectedTypeId(null); setName(''); setScope(''); setEntities([]); setSyncWithSlack(false); setMembers([]); setMemberSearch(''); setError(null); }\n }, [open]);\n\n const selectedType = types.find((t) => t._id === selectedTypeId);\n const canAdvance = () => { switch (step) { case 0: return !!selectedTypeId; case 1: return name.trim().length > 0; default: return true; } };\n\n const addMember = (memberId: string, memberName: string, memberType: MemberType) => {\n if (members.some((m) => m.memberId === memberId)) return;\n setMembers((prev) => [...prev, { memberId, memberName, memberType, role: 'participant' }]);\n setMemberSearch('');\n };\n\n const removeMember = (memberId: string) => setMembers((prev) => prev.filter((m) => m.memberId !== memberId));\n\n const handleCreate = async () => {\n setLoading(true); setError(null);\n try {\n const entitiesWithSecrets: EntityWithSecret[] = entities.filter((e) => e.key.trim()).map((e) => ({ key: e.key.trim(), value: e.value, isSecret: e.isSecret }));\n const payload: CreateWorkspacePayload = {\n name: name.trim(), type: selectedTypeId || undefined, scope: scope.trim() || undefined,\n entitiesWithSecrets: entitiesWithSecrets.length > 0 ? entitiesWithSecrets : undefined,\n members: members.length > 0 ? members.map((m) => ({ memberId: m.memberId, memberName: m.memberName, memberType: m.memberType, role: m.role })) : undefined,\n syncWithSlack: syncWithSlack || undefined,\n };\n const ws = await apis.workspaceApi.create(payload);\n onCreated?.(ws); onClose();\n } catch (err) { setError((err as Error).message); }\n finally { setLoading(false); }\n };\n\n return (\n <Modal open={open} onClose={onClose} zIndexClass=\"z-50\" size=\"md\" closeOnBackdropClick={false} backdropClassName=\"bg-black/40\" panelClassName=\"bg-surface border-border flex h-[600px] max-h-[min(90dvh,100vh)] flex-col overflow-hidden rounded-2xl border shadow-xl\" headingId={titleId} ariaLabelledBy={titleId} ariaDescribedBy={stepDescriptionId} title=\"Nouveau Workspace\" description={<p id={stepDescriptionId} className=\"text-text-muted text-xs\">Étape {step + 1}/4 — {STEP_TITLES[step]}</p>} headerClassName=\"items-center\" closeButtonClassName=\"text-text-muted hover:text-text transition-colors\">\n {/* Step progress bar */}\n <div className=\"flex shrink-0 gap-1 px-6 pt-4\">\n {[0, 1, 2, 3].map((s) => (<div key={s} className={cn('h-1 flex-1 rounded-full transition-colors', s <= step ? 'bg-primary' : 'bg-border-light')} />))}\n </div>\n\n {/* Content */}\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n {/* Step 0: Type */}\n {step === 0 && (typesLoading ? (<div className=\"flex h-[220px] items-center justify-center\"><Loader2 size={20} className=\"text-primary animate-spin\" /></div>) : types.length === 0 ? (<p className=\"text-text-muted py-8 text-center text-sm\">Aucun type disponible</p>) : (\n <div className=\"grid grid-cols-2 gap-2\">\n {types.map((t) => (<button key={t._id} className={cn('flex flex-col items-start gap-1 rounded-xl border p-3 text-left transition-all', selectedTypeId === t._id ? 'border-primary bg-primary-light shadow-sm' : 'border-border hover:border-primary/50 hover:bg-bg')} onClick={() => setSelectedTypeId(t._id)}><span className=\"text-text text-sm font-medium\">{t.name}</span></button>))}\n </div>\n ))}\n\n {/* Step 1: Context */}\n {step === 1 && (\n <div className=\"flex flex-col gap-4\">\n <div>\n <label className=\"text-text-muted mb-1 block text-xs font-medium\">Nom du workspace</label>\n <input className=\"border-border bg-bg text-text focus:border-primary w-full rounded-lg border px-3 py-2 text-sm focus:outline-none\" placeholder={`Ex: ${selectedType?.name ?? 'Workspace'} - ...`} value={name} onChange={(e) => setName(e.target.value)} autoFocus />\n </div>\n <div>\n <label className=\"text-text-muted mb-1 block text-xs font-medium\">Scope</label>\n <input className=\"border-border bg-bg text-text focus:border-primary w-full rounded-lg border px-3 py-2 text-sm focus:outline-none\" placeholder=\"Ex: production, engineering...\" value={scope} onChange={(e) => setScope(e.target.value)} />\n </div>\n <div>\n <label className=\"text-text-muted mb-1 block text-xs font-medium\">Entités</label>\n <div className=\"flex flex-col gap-2\">\n {entities.map((e, idx) => (\n <div key={idx} className=\"flex items-center gap-2\">\n <input className=\"border-border bg-bg text-text focus:border-primary w-28 rounded border px-2 py-1 text-xs focus:outline-none\" value={e.key} onChange={(ev) => { const arr = [...entities]; arr[idx].key = ev.target.value; setEntities(arr); }} placeholder=\"Clé\" />\n <input className=\"border-border bg-bg text-text focus:border-primary flex-1 rounded border px-2 py-1 text-xs focus:outline-none\" value={e.value} onChange={(ev) => { const arr = [...entities]; arr[idx].value = ev.target.value; setEntities(arr); }} placeholder=\"Valeur\" />\n <button type=\"button\" className={`rounded p-1 transition-colors ${e.isSecret ? 'bg-warning/15 text-warning' : 'text-text-muted hover:text-text hover:bg-bg'}`} onClick={() => { const arr = [...entities]; arr[idx].isSecret = !arr[idx].isSecret; setEntities(arr); }}>{e.isSecret ? <Lock size={12} /> : <Unlock size={12} />}</button>\n <button className=\"text-text-muted hover:text-danger\" onClick={() => setEntities(entities.filter((_, i) => i !== idx))}><Trash2 size={14} /></button>\n </div>\n ))}\n <button className=\"text-primary hover:bg-primary-light flex items-center gap-1 rounded px-2 py-1 text-xs transition-colors\" onClick={() => setEntities([...entities, { key: '', value: '', isSecret: false }])}><Plus size={12} /> Ajouter une entité</button>\n </div>\n </div>\n {slackAvailable && (\n <label className={cn('border-border bg-bg hover:border-primary/50 flex cursor-pointer items-start gap-3 rounded-xl border p-3 transition-colors', syncWithSlack && 'border-primary bg-primary-light/40')}>\n <input type=\"checkbox\" className=\"accent-primary mt-0.5 h-4 w-4 shrink-0 cursor-pointer\" checked={syncWithSlack} onChange={(e) => setSyncWithSlack(e.target.checked)} />\n <div className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span className=\"text-text flex items-center gap-1.5 text-sm font-medium\"><Slack size={14} className=\"text-primary\" /> Synchroniser avec Slack</span>\n <span className=\"text-text-muted text-[11px] leading-snug\">Un canal Slack privé sera créé et les membres utilisateurs y seront invités automatiquement.</span>\n </div>\n </label>\n )}\n </div>\n )}\n\n {/* Step 2: Members */}\n {step === 2 && (\n <div className=\"flex flex-col gap-5\">\n {/* USER INVITATIONS */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <label className=\"text-text-muted flex items-center gap-1.5 text-xs font-semibold tracking-wider uppercase\"><Users size={14} className=\"text-primary\" /> Membres Utilisateurs</label>\n {invitedUsers.length > 0 && <span className=\"bg-primary-light text-primary rounded-full px-2 py-0.5 text-[10px] font-bold\">{invitedUsers.length} invité{invitedUsers.length > 1 ? 's' : ''}</span>}\n </div>\n <div className=\"relative\">\n <input type=\"search\" name=\"workspace-member-search\" autoComplete=\"off\" data-lpignore=\"true\" data-1p-ignore=\"true\" className=\"border-border bg-bg text-text focus:border-primary focus:ring-primary/10 placeholder:text-text-muted/65 w-full rounded-xl border px-3.5 py-2.5 text-sm transition-all focus:ring-2 focus:outline-none\" placeholder=\"Rechercher un membre par nom ou identifiant...\" value={memberSearch} onChange={(e) => setMemberSearch(e.target.value)} />\n {memberSearch.length >= 2 && searchingUsers && (<div className=\"absolute top-1/2 right-3.5 flex -translate-y-1/2 items-center justify-center py-3\"><Loader2 size={16} className=\"text-primary animate-spin\" /></div>)}\n {filteredUsers.length > 0 && memberSearch.length >= 2 && !searchingUsers && (\n <div className=\"border-border bg-surface divide-border/30 absolute top-full left-0 z-20 mt-1 flex max-h-48 w-full flex-col divide-y overflow-y-auto rounded-xl border shadow-md\">\n {filteredUsers.slice(0, 5).map((u) => (\n <div key={u.id} className=\"hover:bg-primary-light/50 flex cursor-pointer items-center justify-between px-3.5 py-2.5 text-xs transition-colors\" onClick={() => addMember(u.email, u.displayName, 'user')}>\n <div className=\"flex items-center gap-2.5\">\n <span className=\"bg-primary-light text-primary ring-primary/10 flex h-7 w-7 items-center justify-center rounded-full text-[10px] font-semibold ring-1\">{getInitials(u.displayName)}</span>\n <div className=\"flex flex-col\"><span className=\"text-text font-medium\">{u.displayName}</span><span className=\"text-text-muted text-[10px]\">{u.email}</span></div>\n </div>\n <Plus size={14} className=\"text-primary/75\" />\n </div>\n ))}\n </div>\n )}\n </div>\n <div className=\"mt-1 flex flex-col gap-1.5\">\n {invitedUsers.length === 0 ? (\n <div className=\"bg-bg/40 border-border/40 flex items-center justify-center rounded-xl border border-dashed py-4 text-center\"><p className=\"text-text-muted text-xs italic\">Aucun utilisateur invité pour le moment.</p></div>\n ) : invitedUsers.map((m) => (\n <div key={m.memberId} className=\"bg-bg-subtle hover:bg-bg border-border/30 flex items-center gap-3 rounded-xl border p-2.5 transition-all duration-200\">\n <MemberAvatar memberName={m.memberName} memberType=\"user\" avatarUrl={avatarMap[m.memberId.toLowerCase()]} size=\"sm\" variant={m.role === 'owner' ? 'owner' : 'primary'} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-text truncate text-xs font-semibold\">{m.memberName}</div>\n <div className=\"text-text-muted truncate text-[10px]\">{m.memberId}</div>\n </div>\n <div className=\"flex items-center gap-2\">\n <select className=\"border-border bg-surface text-text focus:border-primary rounded-lg border px-2 py-1 text-[10px] font-medium focus:outline-none\" value={m.role} onChange={(e) => setMembers(members.map((x) => x.memberId === m.memberId ? { ...x, role: e.target.value } : x))}>\n <option value=\"owner\">Propriétaire</option><option value=\"participant\">Participant</option><option value=\"viewer\">Observateur</option>\n </select>\n <button type=\"button\" className=\"text-text-muted hover:text-danger hover:bg-danger-light/20 rounded-lg p-1.5 transition-colors\" onClick={() => removeMember(m.memberId)}><X size={14} /></button>\n </div>\n </div>\n ))}\n </div>\n </div>\n {/* AGENT INVITATIONS */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <label className=\"text-text-muted flex items-center gap-1.5 text-xs font-semibold tracking-wider uppercase\"><Brain size={14} className=\"text-primary\" /> Agents IA</label>\n <span className=\"bg-primary-light text-primary rounded-full px-2 py-0.5 text-[10px] font-bold\">{invitedAgents.length}/{agents.length}</span>\n </div>\n <div className=\"relative\">\n <div className={cn('border-border bg-bg focus-within:border-primary focus-within:ring-primary/10 flex min-h-[44px] cursor-text flex-wrap items-center gap-1.5 rounded-xl border px-3 py-1.5 text-sm transition-all focus-within:ring-2', agentSearchFocused && 'border-primary ring-primary/10 ring-2')} onClick={() => agentSearchInputRef.current?.focus()}>\n {invitedAgents.map((m) => (\n <span key={m.memberId} className=\"bg-primary-light/50 border-primary/20 text-primary flex items-center gap-1 rounded-lg border py-1 pr-1.5 pl-2 text-xs font-medium\">\n <Brain size={10} className=\"text-primary/80\" />{m.memberName}\n <button type=\"button\" className=\"hover:bg-primary-light text-primary rounded-md p-0.5 transition-colors\" onClick={(e) => { e.stopPropagation(); removeMember(m.memberId); }}><X size={10} /></button>\n </span>\n ))}\n <input ref={agentSearchInputRef} type=\"search\" name=\"workspace-agent-search\" autoComplete=\"off\" data-lpignore=\"true\" data-1p-ignore=\"true\" className=\"text-text placeholder:text-text-muted/65 min-w-[100px] flex-1 border-none bg-transparent p-0.5 text-xs focus:ring-0 focus:outline-none\" placeholder={invitedAgents.length === 0 ? 'Rechercher et inviter des agents...' : ''} value={agentSearch} onChange={(e) => { setAgentSearch(e.target.value); setShowAgentDropdown(true); }} onFocus={() => { setAgentSearchFocused(true); setShowAgentDropdown(true); }} onBlur={() => setTimeout(() => { setAgentSearchFocused(false); setShowAgentDropdown(false); }, 200)} />\n </div>\n {showAgentDropdown && (\n <div className=\"border-border bg-surface divide-border/30 absolute z-20 mt-1.5 flex max-h-48 w-full flex-col divide-y overflow-y-auto rounded-xl border shadow-lg\">\n {unselectedAgents.length === 0 ? (<p className=\"text-text-muted p-3 text-center text-xs italic\">{agentSearch.trim().length > 0 ? 'Aucun agent ne correspond.' : 'Tous les agents ont été invités.'}</p>) : unselectedAgents.map((agent) => (\n <div key={agent.agentId} className=\"hover:bg-primary-light/50 flex cursor-pointer items-center justify-between px-3.5 py-2.5 text-xs transition-colors\" onClick={() => { addMember(agent.agentId, agent.agentName, 'agent'); setAgentSearch(''); }}>\n <div className=\"flex items-center gap-2.5\"><span className=\"bg-surface border-border flex h-7 w-7 items-center justify-center rounded-full border\"><Brain size={12} className=\"text-primary\" /></span><span className=\"text-text font-medium\">{agent.agentName}</span></div>\n <Plus size={14} className=\"text-primary/75\" />\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n )}\n\n {/* Step 3: Confirmation */}\n {step === 3 && (\n <div className=\"flex flex-col gap-3\">\n <div className=\"bg-bg rounded-xl p-4\">\n <div className=\"mb-3 flex items-center gap-2\"><div><div className=\"text-text text-sm font-semibold\">{name || 'Sans nom'}</div><div className=\"text-text-muted text-xs\">{selectedType?.name ?? '—'} • {scope || 'Sans scope'}</div></div></div>\n {entities.filter((e) => e.key.trim() && e.value.trim()).length > 0 && (\n <div className=\"mb-2 flex flex-wrap gap-1\">\n {entities.filter((e) => e.key.trim() && e.value.trim()).map((e, i) => (\n <span key={i} className=\"border-border inline-flex items-center gap-1 rounded border px-2 py-0.5 text-xs\">\n {e.isSecret && <Lock size={10} className=\"text-warning shrink-0\" />}\n <span className=\"text-text-muted mr-1 font-medium\">{e.key}:</span>\n <span className=\"text-text\">{e.isSecret ? '••••••' : e.value}</span>\n </span>\n ))}\n </div>\n )}\n <div className=\"text-text-muted flex items-center gap-3 text-xs\">\n <span className=\"flex items-center gap-1\"><Users size={12} /> {members.length} membre{members.length > 1 ? 's' : ''}</span>\n {syncWithSlack && <span className=\"text-primary flex items-center gap-1 font-medium\"><Slack size={12} /> Synchronisé avec Slack</span>}\n </div>\n {members.length > 0 && (\n <div className=\"border-border/30 mt-3 border-t pt-3\">\n <span className=\"text-text-muted mb-2 block text-[10px] font-bold tracking-wider uppercase\">Membres et Agents invités ({members.length})</span>\n <div className=\"flex max-h-40 flex-col gap-1.5 overflow-y-auto pr-1\">\n {members.map((m) => (\n <div key={m.memberId} className=\"bg-bg-subtle/50 flex items-center gap-2.5 rounded-lg p-2 text-xs\">\n <MemberAvatar memberName={m.memberName} memberType={m.memberType} avatarUrl={m.memberType === 'user' ? avatarMap[m.memberId.toLowerCase()] : undefined} size=\"xs\" variant={m.role === 'owner' ? 'owner' : 'primary'} />\n <div className=\"min-w-0 flex-1\"><span className=\"text-text truncate font-medium\">{m.memberName}</span><span className=\"text-text-muted ml-2 text-[10px]\">({m.memberType === 'agent' ? 'Agent' : m.role === 'owner' ? 'Propriétaire' : m.role === 'viewer' ? 'Observateur' : 'Participant'})</span></div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n {error && <div className=\"bg-danger-light text-danger rounded-lg px-3 py-2 text-xs\">{error}</div>}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"border-border flex shrink-0 items-center justify-between border-t px-6 py-4\">\n <button type=\"button\" className={cn('text-text-muted hover:text-text flex items-center gap-1 text-sm transition-colors', step === 0 && 'invisible')} onClick={() => setStep((s) => s - 1)} disabled={loading}><ArrowLeft size={14} /> Précédent</button>\n {step < 3 ? (\n <button type=\"button\" className={cn('flex items-center gap-1 rounded-lg px-4 py-2 text-sm font-medium text-white transition-colors', canAdvance() ? 'bg-primary hover:bg-primary-hover' : 'bg-border cursor-not-allowed')} onClick={() => setStep((s) => s + 1)} disabled={!canAdvance()}>Suivant <ArrowRight size={14} /></button>\n ) : (\n <button type=\"button\" className=\"bg-primary hover:bg-primary-hover flex items-center gap-1 rounded-lg px-4 py-2 text-sm font-medium text-white transition-colors disabled:opacity-50\" onClick={handleCreate} disabled={loading}>{loading ? <Loader2 size={14} className=\"animate-spin\" /> : <Check size={14} />} Créer le workspace</button>\n )}\n </div>\n </Modal>\n );\n};\n","import React, { useState, useEffect, useMemo, useId, useRef } from 'react';\nimport { X, Loader2, Lock, MessageSquare, Search } from 'lucide-react';\nimport { cn } from './ui/cn';\nimport { useWorkspaceContext } from '../provider';\nimport { useWorkspaceApi } from '../hooks/useWorkspaceApi';\nimport type { CreateWorkspacePayload } from '../types';\nimport { getInitials } from '../utils/constants';\nimport { Modal } from './ui/Modal';\nimport { MemberAvatar } from './MemberAvatar';\n\ninterface CreatePrivateWorkspaceModalProps {\n open: boolean;\n onClose: () => void;\n onCreated?: (workspace: unknown) => void;\n}\n\nexport const CreatePrivateWorkspaceModal: React.FC<CreatePrivateWorkspaceModalProps> = ({ open, onClose, onCreated }) => {\n const titleId = useId();\n const { config } = useWorkspaceContext();\n const apis = useWorkspaceApi();\n\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [search, setSearch] = useState('');\n const [searchResults, setSearchResults] = useState<{ id: string; email: string; displayName: string; avatarUrl?: string }[]>([]);\n const [searchingUsers, setSearchingUsers] = useState(false);\n const [selectedUser, setSelectedUser] = useState<{ id: string; email: string; displayName: string; avatarUrl?: string } | null>(null);\n const searchInputRef = useRef<HTMLInputElement>(null);\n\n // User search via injected searchUsers\n useEffect(() => {\n if (search.length < 2 || !config.searchUsers) { setSearchResults([]); return; }\n let cancelled = false;\n setSearchingUsers(true);\n config.searchUsers(search).then((r) => { if (!cancelled) setSearchResults(r); }).catch(() => { if (!cancelled) setSearchResults([]); }).finally(() => { if (!cancelled) setSearchingUsers(false); });\n return () => { cancelled = true; };\n }, [search]);\n\n const filteredUsers = useMemo(() => searchResults.filter((u) => u.email !== config.currentUserId), [searchResults, config.currentUserId]);\n\n // Reset on close\n useEffect(() => {\n if (!open) { setSearch(''); setSelectedUser(null); setError(null); setLoading(false); }\n else { setTimeout(() => searchInputRef.current?.focus(), 100); }\n }, [open]);\n\n const handleCreate = async () => {\n if (!selectedUser || !config.currentUserId) return;\n setLoading(true); setError(null);\n try {\n const payload: CreateWorkspacePayload = {\n name: `${config.currentUserName ?? config.currentUserId} ↔ ${selectedUser.displayName}`,\n isPrivate: true,\n members: [{ memberId: selectedUser.email, memberName: selectedUser.displayName, memberType: 'user', role: 'participant' }],\n };\n const ws = await apis.workspaceApi.create(payload);\n onCreated?.(ws); onClose();\n } catch (err) { setError((err as Error).message); }\n finally { setLoading(false); }\n };\n\n return (\n <Modal open={open} onClose={onClose} zIndexClass=\"z-50\" size=\"sm\" closeOnBackdropClick={false} backdropClassName=\"bg-black/40\" panelClassName=\"bg-surface border-border flex max-h-[min(70dvh,500px)] flex-col overflow-hidden rounded-2xl border shadow-xl\" headingId={titleId} ariaLabelledBy={titleId} title=\"Conversation Privée\" description={<p className=\"text-text-muted text-xs\">Choisissez un utilisateur pour démarrer une conversation privée.</p>} headerClassName=\"items-center\" closeButtonClassName=\"text-text-muted hover:text-text transition-colors\" titleIcon={<span className=\"bg-primary-light text-primary flex h-8 w-8 items-center justify-center rounded-lg\"><Lock size={16} /></span>}>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n {/* Selected user */}\n {selectedUser ? (\n <div className=\"mb-4\">\n <div className=\"bg-primary-light/30 border-primary/20 flex items-center gap-3 rounded-xl border p-3\">\n <MemberAvatar memberName={selectedUser.displayName} memberType=\"user\" avatarUrl={selectedUser.avatarUrl} size=\"md\" variant=\"primary\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-text text-sm font-semibold\">{selectedUser.displayName}</div>\n <div className=\"text-text-muted text-xs\">{selectedUser.email}</div>\n </div>\n <button type=\"button\" className=\"text-text-muted hover:text-danger rounded p-1 transition-colors\" onClick={() => setSelectedUser(null)}><X size={16} /></button>\n </div>\n </div>\n ) : (\n <div>\n <div className=\"relative\">\n <Search size={14} className=\"text-text-muted absolute top-1/2 left-3 -translate-y-1/2\" />\n <input ref={searchInputRef} type=\"search\" autoComplete=\"off\" data-lpignore=\"true\" data-1p-ignore=\"true\" className=\"border-border bg-bg text-text focus:border-primary focus:ring-primary/10 placeholder:text-text-muted/65 w-full rounded-xl border py-2.5 pr-3 pl-9 text-sm transition-all focus:ring-2 focus:outline-none\" placeholder=\"Rechercher un utilisateur...\" value={search} onChange={(e) => setSearch(e.target.value)} />\n {search.length >= 2 && searchingUsers && <div className=\"absolute top-1/2 right-3 -translate-y-1/2\"><Loader2 size={16} className=\"text-primary animate-spin\" /></div>}\n </div>\n {search.length >= 2 && !searchingUsers && filteredUsers.length > 0 && (\n <div className=\"border-border bg-surface mt-2 flex max-h-48 flex-col overflow-y-auto rounded-xl border shadow-sm\">\n {filteredUsers.slice(0, 8).map((u) => (\n <button key={u.id} type=\"button\" className=\"hover:bg-primary-light/50 flex items-center gap-3 px-3.5 py-2.5 text-left transition-colors first:rounded-t-xl last:rounded-b-xl\" onClick={() => { setSelectedUser(u); setSearch(''); }}>\n <span className=\"bg-primary-light text-primary flex h-8 w-8 items-center justify-center rounded-full text-xs font-semibold\">{getInitials(u.displayName)}</span>\n <div className=\"min-w-0 flex-1\"><div className=\"text-text text-sm font-medium\">{u.displayName}</div><div className=\"text-text-muted text-[11px]\">{u.email}</div></div>\n </button>\n ))}\n </div>\n )}\n {search.length >= 2 && !searchingUsers && filteredUsers.length === 0 && <p className=\"text-text-muted mt-3 text-center text-xs italic\">Aucun utilisateur trouvé.</p>}\n {search.length < 2 && <p className=\"text-text-muted mt-4 text-center text-xs\">Saisissez au moins 2 caractères pour rechercher.</p>}\n </div>\n )}\n {error && <div className=\"bg-danger-light text-danger mt-3 rounded-lg px-3 py-2 text-xs\">{error}</div>}\n </div>\n <div className=\"border-border flex shrink-0 items-center justify-end gap-2 border-t px-6 py-4\">\n <button type=\"button\" className=\"text-text-muted hover:text-text text-sm transition-colors\" onClick={onClose} disabled={loading}>Annuler</button>\n <button type=\"button\" className={cn('flex items-center gap-1.5 rounded-lg px-4 py-2 text-sm font-medium text-white transition-colors disabled:opacity-50', selectedUser ? 'bg-primary hover:bg-primary-hover' : 'bg-border cursor-not-allowed')} onClick={handleCreate} disabled={!selectedUser || loading}>\n {loading ? <Loader2 size={14} className=\"animate-spin\" /> : <MessageSquare size={14} />} Démarrer\n </button>\n </div>\n </Modal>\n );\n};\n","\n\nimport React, { useState, useEffect, useCallback } from 'react';\nimport {\n RefreshCw,\n ExternalLink,\n Info,\n CheckCircle2,\n XCircle,\n Loader2,\n Hash,\n AlertTriangle,\n} from 'lucide-react';\nimport { type SyncLink, type SyncStatus } from '../api';\nimport { useWorkspaceApi } from '../hooks/useWorkspaceApi';\nimport { cn } from './ui/cn';\n\n// ─── Slack brand color ────────────────────────────────────────────────────────\nconst SLACK_COLOR = '#4A154B';\n\n// ─── Sync info texts ──────────────────────────────────────────────────────────\nconst SYNC_INFO = {\n title: 'Comment fonctionne la synchronisation ?',\n description:\n 'La synchronisation bidirectionnelle relie ce workspace à un canal externe (Slack, Teams…). Les messages, fichiers et membres sont automatiquement répliqués dans les deux sens.',\n features: [\n 'Messages envoyés depuis le workspace sont répliqués vers Slack',\n 'Messages envoyés depuis Slack sont répliqués vers le workspace',\n 'Fichiers et artefacts sont synchronisés dans les deux sens',\n 'Les nouveaux membres ajoutés au workspace sont invités dans Slack',\n 'Les mentions Slack sont converties en mentions workspace',\n 'Désactiver la synchronisation conserve le canal Slack ouvert (pas d\\'archivage)',\n ],\n limitations: [\n 'Les messages initialement postés par un utilisateur réel dans Slack ne peuvent pas être modifiés/supprimés depuis le workspace (limitation API Slack)',\n 'Le bot Slack doit avoir les scopes nécessaires (channels:*, chat:write, files:read, users:read.email)',\n 'Le listener Socket Mode doit tourner sur une seule instance en production',\n 'Seuls les utilisateurs ayant le même email dans Slack et le workspace sont synchronisés',\n ],\n};\n\ninterface SyncPanelProps {\n workspaceId: string;\n syncWithSlack?: boolean;\n isOwner: boolean;\n /** Whether Slack sync is configured and enabled on the server */\n slackConfigured?: boolean;\n /** Called after a sync toggle — the parent page will get the updated workspace via real-time. */\n onToggleSync?: (provider: string, enabled: boolean) => Promise<void>;\n}\n\nexport const SyncPanel: React.FC<SyncPanelProps> = ({\n workspaceId,\n syncWithSlack,\n isOwner,\n slackConfigured = true,\n onToggleSync,\n}) => {\n const [syncStatus, setSyncStatus] = useState<SyncStatus | null>(null);\n const [loading, setLoading] = useState(true);\n const [toggling, setToggling] = useState(false);\n const [infoOpen, setInfoOpen] = useState(false);\n const apis = useWorkspaceApi();\n\n const fetchSyncStatus = useCallback(async () => {\n try {\n const status = await apis.syncApi.getStatus(workspaceId);\n setSyncStatus(status);\n } catch (err) {\n console.error('Failed to fetch sync status:', err);\n } finally {\n setLoading(false);\n }\n }, [workspaceId]);\n\n useEffect(() => {\n fetchSyncStatus();\n }, [fetchSyncStatus]);\n\n // Also re-sync state when workspace.syncWithSlack changes (via real-time)\n useEffect(() => {\n if (syncStatus) {\n setSyncStatus((prev) =>\n prev ? { ...prev, syncWithSlack: syncWithSlack ?? false } : prev,\n );\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [syncWithSlack]);\n\n const handleToggle = async (provider: string, enabled: boolean) => {\n setToggling(true);\n try {\n await onToggleSync?.(provider, enabled);\n // Refresh the sync links after toggle\n await fetchSyncStatus();\n } catch (err) {\n console.error('Failed to toggle sync:', err);\n } finally {\n setToggling(false);\n }\n };\n\n const slackLink = syncStatus?.links?.find((l) => l.provider === 'slack');\n const isSlackActive = syncStatus?.syncWithSlack ?? syncWithSlack ?? false;\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 size={20} className=\"text-primary animate-spin\" />\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n {/* Section header */}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-muted text-xs font-semibold tracking-wider uppercase\">\n Synchronisation\n </span>\n <button\n className=\"text-text-muted hover:text-primary flex items-center gap-1 text-xs transition-colors\"\n onClick={() => fetchSyncStatus()}\n title=\"Rafraîchir\"\n >\n <RefreshCw size={11} /> Rafraîchir\n </button>\n </div>\n\n {/* ── Slack sync card ─────────────────────────────────────────────── */}\n <div className={cn('bg-bg border-border rounded-lg border', !slackConfigured && 'opacity-60')}>\n <div className=\"flex items-center justify-between p-3\">\n <div className=\"flex items-center gap-2.5\">\n {/* Slack icon */}\n <div\n className=\"flex h-8 w-8 items-center justify-center rounded-lg\"\n style={{ backgroundColor: SLACK_COLOR }}\n >\n <Hash size={16} className=\"text-white\" />\n </div>\n <div>\n <div className=\"text-text flex items-center gap-1.5 text-sm font-medium\">\n Slack\n {!slackConfigured ? (\n <XCircle size={14} className=\"text-text-muted\" />\n ) : isSlackActive ? (\n <CheckCircle2 size={14} className=\"text-success\" />\n ) : (\n <XCircle size={14} className=\"text-text-muted\" />\n )}\n </div>\n <span className=\"text-text-muted text-[10px]\">\n {!slackConfigured\n ? 'Non configuré'\n : isSlackActive\n ? 'Synchronisation active'\n : 'Non synchronisé'}\n </span>\n </div>\n </div>\n\n {slackConfigured && isOwner && (\n <button\n className={`rounded-lg px-3 py-1.5 text-xs font-medium transition-colors ${\n isSlackActive\n ? 'bg-danger-light text-danger hover:bg-danger/20'\n : 'bg-success-light text-success hover:bg-success/20'\n }`}\n onClick={() => handleToggle('slack', !isSlackActive)}\n disabled={toggling}\n >\n {toggling ? (\n <Loader2 size={12} className=\"animate-spin\" />\n ) : isSlackActive ? (\n 'Désactiver'\n ) : (\n 'Activer'\n )}\n </button>\n )}\n\n {!slackConfigured && (\n <span className=\"bg-bg border-border rounded border px-2 py-1 text-[10px] font-medium text-text-muted\">\n Non disponible\n </span>\n )}\n </div>\n\n {!slackConfigured && (\n <div className=\"border-border border-t px-3 py-2.5\">\n <div className=\"text-text-muted flex items-center gap-2 text-xs\">\n <AlertTriangle size={14} className=\"flex-shrink-0 text-warning\" />\n <span>\n La synchronisation Slack n&apos;est pas configurée sur le serveur.\n Contactez un administrateur pour l&apos;activer.\n </span>\n </div>\n </div>\n )}\n\n {/* Slack link details (always show when link exists) */}\n {slackConfigured && slackLink && (\n <div className=\"border-border border-t px-3 py-2.5\">\n <div className=\"flex flex-col gap-1.5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-muted text-[10px] font-medium uppercase tracking-wider\">\n Canal externe\n </span>\n <ExternalLink size={10} className=\"text-text-muted\" />\n </div>\n <div className=\"bg-surface border-border rounded border p-2\">\n <div className=\"flex items-center gap-2 text-xs\">\n <Hash size={12} className=\"text-text-muted flex-shrink-0\" />\n <span className=\"text-text font-medium\">\n {slackLink.externalName || slackLink.externalId}\n </span>\n </div>\n <div className=\"text-text-muted mt-1 flex items-center gap-2 text-[10px]\">\n <span>ID: {slackLink.externalId}</span>\n {slackLink.externalTeamId && (\n <>\n <span>•</span>\n <span>Team: {slackLink.externalTeamId}</span>\n </>\n )}\n </div>\n <div className=\"text-text-muted mt-1 flex items-center gap-2 text-[10px]\">\n <span\n className={`inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[9px] font-medium ${\n isSlackActive\n ? 'bg-success-light text-success'\n : 'bg-warning-light text-warning'\n }`}\n >\n {isSlackActive ? 'Sync active' : 'Sync en pause'}\n </span>\n <span>\n Créé le{' '}\n {new Date(slackLink.createdAt).toLocaleDateString('fr-FR')}\n </span>\n </div>\n {!isSlackActive && (\n <div className=\"text-text-muted mt-1.5 text-[10px] italic\">\n Le canal Slack reste ouvert — seule la synchronisation est en pause.\n </div>\n )}\n </div>\n </div>\n </div>\n )}\n\n {slackConfigured && isSlackActive && !slackLink && (\n <div className=\"border-border border-t px-3 py-2.5\">\n <div className=\"text-warning bg-warning-light flex items-center gap-2 rounded-lg p-2 text-xs\">\n <AlertTriangle size={14} className=\"flex-shrink-0\" />\n <span>\n La synchronisation est activée mais aucun canal Slack n&apos;est\n encore lié. Le canal sera créé automatiquement.\n </span>\n </div>\n </div>\n )}\n </div>\n\n {/* ── Teams sync card (future) ────────────────────────────────────── */}\n <div className=\"bg-bg border-border rounded-lg border opacity-50\">\n <div className=\"flex items-center justify-between p-3\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"bg-info flex h-8 w-8 items-center justify-center rounded-lg\">\n <span className=\"text-xs font-bold text-white\">T</span>\n </div>\n <div>\n <div className=\"text-text flex items-center gap-1.5 text-sm font-medium\">\n Microsoft Teams\n <XCircle size={14} className=\"text-text-muted\" />\n </div>\n <span className=\"text-text-muted text-[10px]\">\n Bientôt disponible\n </span>\n </div>\n </div>\n <span className=\"bg-bg border-border rounded border px-2 py-1 text-[10px] font-medium text-text-muted\">\n Prochainement\n </span>\n </div>\n </div>\n\n {/* ── Info section ────────────────────────────────────────────────── */}\n <div className=\"bg-bg border-border rounded-lg border\">\n <button\n className=\"flex w-full items-center gap-2 p-3 text-left\"\n onClick={() => setInfoOpen(!infoOpen)}\n >\n <Info size={14} className=\"text-info flex-shrink-0\" />\n <span className=\"text-text text-xs font-medium\">\n {SYNC_INFO.title}\n </span>\n <span\n className={`text-text-muted ml-auto text-[10px] transition-transform ${\n infoOpen ? 'rotate-180' : ''\n }`}\n >\n ▾\n </span>\n </button>\n\n {infoOpen && (\n <div className=\"border-border border-t px-3 pb-3 pt-2\">\n <p className=\"text-text-muted mb-3 text-xs leading-relaxed\">\n {SYNC_INFO.description}\n </p>\n\n <div className=\"mb-3\">\n <span className=\"text-text mb-1.5 block text-[10px] font-semibold uppercase tracking-wider\">\n Fonctionnalités\n </span>\n <ul className=\"flex flex-col gap-1\">\n {SYNC_INFO.features.map((f, i) => (\n <li\n key={i}\n className=\"text-text-muted flex items-start gap-1.5 text-xs\"\n >\n <CheckCircle2\n size={12}\n className=\"text-success mt-0.5 flex-shrink-0\"\n />\n {f}\n </li>\n ))}\n </ul>\n </div>\n\n <div>\n <span className=\"text-text mb-1.5 block text-[10px] font-semibold uppercase tracking-wider\">\n Limitations connues\n </span>\n <ul className=\"flex flex-col gap-1\">\n {SYNC_INFO.limitations.map((l, i) => (\n <li\n key={i}\n className=\"text-text-muted flex items-start gap-1.5 text-xs\"\n >\n <AlertTriangle\n size={12}\n className=\"text-warning mt-0.5 flex-shrink-0\"\n />\n {l}\n </li>\n ))}\n </ul>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n","\n\nimport React from 'react';\nimport {\n ChevronsLeft,\n ChevronLeft,\n ChevronRight,\n ChevronsRight,\n} from 'lucide-react';\nimport { cn } from './ui/cn';\n\ninterface NavButtonProps {\n onClick: () => void;\n disabled: boolean;\n children: React.ReactNode;\n title: string;\n}\n\nconst NavButton: React.FC<NavButtonProps> = ({\n onClick,\n disabled,\n children,\n title,\n}) => (\n <button\n onClick={onClick}\n disabled={disabled}\n title={title}\n className={cn(\n 'flex h-9 w-9 items-center justify-center rounded-lg border text-sm transition-all duration-200',\n disabled\n ? 'border-border-light text-text-placeholder cursor-not-allowed opacity-40'\n : 'border-border bg-surface text-text-secondary hover:bg-primary/8 hover:border-primary/30 hover:text-primary active:scale-95',\n )}\n >\n {children}\n </button>\n);\n\ninterface PaginationProps {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n /** Show a subtle loading indicator when fetching */\n loading?: boolean;\n}\n\nexport const Pagination: React.FC<PaginationProps> = ({\n currentPage,\n totalPages,\n onPageChange,\n loading = false,\n}) => {\n if (totalPages <= 1) return null;\n\n // Build a window of page numbers to display\n const getVisiblePages = (): (number | 'ellipsis')[] => {\n const pages: (number | 'ellipsis')[] = [];\n const maxVisible = 5;\n\n if (totalPages <= maxVisible + 2) {\n for (let i = 1; i <= totalPages; i++) pages.push(i);\n return pages;\n }\n\n // Always show first page\n pages.push(1);\n\n const start = Math.max(2, currentPage - 1);\n const end = Math.min(totalPages - 1, currentPage + 1);\n\n if (start > 2) pages.push('ellipsis');\n\n for (let i = start; i <= end; i++) pages.push(i);\n\n if (end < totalPages - 1) pages.push('ellipsis');\n\n // Always show last page\n pages.push(totalPages);\n\n return pages;\n };\n\n const pages = getVisiblePages();\n\n return (\n <div className=\"mt-6 flex items-center justify-center gap-1.5\">\n {/* First page */}\n <NavButton\n onClick={() => onPageChange(1)}\n disabled={currentPage === 1 || loading}\n title=\"Première page\"\n >\n <ChevronsLeft size={16} />\n </NavButton>\n\n {/* Previous */}\n <NavButton\n onClick={() => onPageChange(currentPage - 1)}\n disabled={currentPage === 1 || loading}\n title=\"Page précédente\"\n >\n <ChevronLeft size={16} />\n </NavButton>\n\n {/* Page numbers */}\n {pages.map((p, idx) =>\n p === 'ellipsis' ? (\n <span\n key={`ellipsis-${idx}`}\n className=\"text-text-muted flex h-9 w-9 items-center justify-center text-sm\"\n >\n …\n </span>\n ) : (\n <button\n key={p}\n onClick={() => onPageChange(p)}\n disabled={loading}\n className={cn(\n 'flex h-9 w-9 items-center justify-center rounded-lg text-sm font-medium transition-all duration-200',\n p === currentPage\n ? 'bg-primary text-white shadow-sm shadow-primary/30'\n : 'border-border bg-surface text-text-secondary hover:bg-primary/8 hover:border-primary/30 hover:text-primary border active:scale-95',\n )}\n >\n {p}\n </button>\n ),\n )}\n\n {/* Next */}\n <NavButton\n onClick={() => onPageChange(currentPage + 1)}\n disabled={currentPage === totalPages || loading}\n title=\"Page suivante\"\n >\n <ChevronRight size={16} />\n </NavButton>\n\n {/* Last page */}\n <NavButton\n onClick={() => onPageChange(totalPages)}\n disabled={currentPage === totalPages || loading}\n title=\"Dernière page\"\n >\n <ChevronsRight size={16} />\n </NavButton>\n </div>\n );\n};\n"],"mappings":"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","names":["WorkspaceEvent","import_react","ROLE_LABELS","import_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","pages"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/api/client.ts","../src/socket/client.ts","../src/types/index.ts","../src/types/activity.ts","../src/api/index.ts","../src/store/useWorkspaceListStore.ts","../src/hooks/useWorkspaceApi.ts","../src/utils/constants.ts","../src/utils/formatExport.ts","../src/components/ui/Modal.tsx","../src/components/ui/cn.ts","../src/components/ui/Badge.tsx","../src/components/ui/Tooltip.tsx","../src/components/ui/ConfirmModal.tsx","../src/components/MemberAvatar.tsx","../src/components/Pagination.tsx","../src/components/WorkspaceCard.tsx","../src/components/WorkspaceRow.tsx","../src/components/WorkspaceList.tsx","../src/components/CreateWorkspaceModal.tsx","../src/components/CreatePrivateWorkspaceModal.tsx","../src/components/ContextPanel.tsx","../src/components/MembersPanel.tsx","../src/components/SyncPanel.tsx","../src/components/MessageFeed.tsx","../src/components/MessageItem.tsx","../src/components/ArtefactViewerDialog.tsx","../src/components/streamdownCustomComponents.tsx","../src/components/ChartRenderer.tsx","../src/components/TableRenderer.tsx","../src/components/MessageFilterDialog.tsx"],"sourcesContent":["// ─── @workspace-platform/ui ───────────────────────────────────────────────────\n// Main barrel export\n\n// Provider\nexport { WorkspaceProvider, useWorkspaceContext } from './provider';\nexport type { WorkspaceConfig, WorkspaceContextValue, UserSearchResult } from './provider';\n\n// Types\nexport * from './types';\nexport type { SyncLink, SyncStatus, SyncProviderInfo, ToggleReactionResponse, WorkspaceApis } from './api';\n\n// Activity types\nexport * from './types/activity';\n\n// API\nexport { createWorkspaceApis } from './api';\nexport { createWorkspaceClient } from './api/client';\nexport type { WorkspaceClient } from './api/client';\n\n// Socket\nexport { createWorkspaceSocket } from './socket/client';\nexport type { WorkspaceSocketManager } from './socket/client';\n\n// Store\nexport { createWorkspaceListStore } from './store/useWorkspaceListStore';\nexport type { WorkspaceListState, WorkspaceListFilters, WorkspaceTab } from './store/useWorkspaceListStore';\n\n// Hooks\nexport { useWorkspaceApi } from './hooks/useWorkspaceApi';\n\n// Utils\nexport { getInitials, ROLE_LABELS, STATUS_LABELS, AVAILABLE_AGENTS, fixMojibake } from './utils/constants';\nexport { formatWorkspaceExport } from './utils/formatExport';\nexport type { WorkspaceExportData } from './utils/formatExport';\n\n// ── UI Primitives ─────────────────────────────────────────────────────────────\nexport { Modal } from './components/ui/Modal';\nexport type { ModalProps, ModalSize } from './components/ui/Modal';\nexport { cn } from './components/ui/cn';\nexport { Badge } from './components/ui/Badge';\nexport type { BadgeProps } from './components/ui/Badge';\nexport { Tooltip } from './components/ui/Tooltip';\nexport type { TooltipProps } from './components/ui/Tooltip';\nexport { ConfirmModal } from './components/ui/ConfirmModal';\nexport type { ConfirmModalProps } from './components/ui/ConfirmModal';\n\n// ── Core components ────────────────────────────────────────────────────────────\nexport { MemberAvatar } from './components/MemberAvatar';\nexport type { MemberAvatarProps } from './components/MemberAvatar';\nexport { Pagination } from './components/Pagination';\n\n// ── Workspace listing ─────────────────────────────────────────────────────────\nexport { WorkspaceCard } from './components/WorkspaceCard';\nexport type { WorkspaceCardProps } from './components/WorkspaceCard';\nexport { WorkspaceRow } from './components/WorkspaceRow';\nexport type { WorkspaceRowProps } from './components/WorkspaceRow';\nexport { WorkspaceList } from './components/WorkspaceList';\nexport type { WorkspaceListProps } from './components/WorkspaceList';\n\n// ── Workspace creation modals ─────────────────────────────────────────────────\nexport { CreateWorkspaceModal } from './components/CreateWorkspaceModal';\nexport { CreatePrivateWorkspaceModal } from './components/CreatePrivateWorkspaceModal';\n\n// ── Workspace detail — panels ─────────────────────────────────────────────────\nexport { ContextPanel } from './components/ContextPanel';\nexport type { ContextPanelProps } from './components/ContextPanel';\nexport { MembersPanel } from './components/MembersPanel';\nexport { SyncPanel } from './components/SyncPanel';\n\n// ── Workspace detail — chat ────────────────────────────────────────────────────\nexport { MessageFeed } from './components/MessageFeed';\nexport type { MessageFeedProps } from './components/MessageFeed';\nexport { MessageItem } from './components/MessageItem';\nexport type { MessageItemProps, MessageRole } from './components/MessageItem';\nexport { MessageFilterDialog, EMPTY_FILTERS } from './components/MessageFilterDialog';\nexport type { MessageFilterDialogProps, MessageFilters } from './components/MessageFilterDialog';\n\n// ── Artefact viewers ──────────────────────────────────────────────────────────\nexport { ArtefactViewerDialog } from './components/ArtefactViewerDialog';\nexport { ChartRenderer } from './components/ChartRenderer';\nexport { TableRenderer } from './components/TableRenderer';\nexport { workspaceStreamdownComponents } from './components/streamdownCustomComponents';\n","import React, { createContext, useContext, useMemo } from 'react';\nimport { createWorkspaceClient, type WorkspaceClient } from './api/client';\nimport { createWorkspaceSocket, type WorkspaceSocketManager } from './socket/client';\n\n// ─── Config types ─────────────────────────────────────────────────────────────\n\nexport interface UserSearchResult {\n id: string;\n email: string;\n displayName: string;\n avatarUrl?: string;\n}\n\nexport interface WorkspaceConfig {\n /** Base URL of the workspace-platform server (e.g. http://localhost:3100) */\n baseUrl: string;\n /** Function that returns the current Bearer token (JWT) */\n getAuthToken: () => string | null;\n /** Current user identifier (email or ID) — used for socket auth & UI */\n currentUserId: string | null;\n /** Current user display name */\n currentUserName?: string | null;\n /** Optional: additional headers for API requests (e.g. { 'x-auth-mode': 'keycloak' }) */\n extraHeaders?: Record<string, string>;\n /** Optional: function to search users for member invitation */\n searchUsers?: (query: string) => Promise<UserSearchResult[]>;\n /** Optional: function to resolve user avatar URLs by email */\n resolveAvatars?: (memberIds: string[]) => Promise<Record<string, string>>;\n /** Optional: callback when navigating to a workspace */\n onNavigateToWorkspace?: (workspaceId: string) => void;\n}\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport interface WorkspaceContextValue {\n config: WorkspaceConfig;\n apiClient: WorkspaceClient;\n socket: WorkspaceSocketManager;\n}\n\nconst WorkspaceContext = createContext<WorkspaceContextValue | null>(null);\n\nexport function WorkspaceProvider({\n config,\n children,\n}: {\n config: WorkspaceConfig;\n children: React.ReactNode;\n}) {\n const value = useMemo(() => {\n const apiClient = createWorkspaceClient(config);\n const socket = createWorkspaceSocket(config);\n return { config, apiClient, socket };\n }, [config.baseUrl, config.currentUserId]);\n\n return (\n <WorkspaceContext.Provider value={value}>\n {children}\n </WorkspaceContext.Provider>\n );\n}\n\nexport function useWorkspaceContext(): WorkspaceContextValue {\n const ctx = useContext(WorkspaceContext);\n if (!ctx)\n throw new Error(\n 'useWorkspaceContext must be used within <WorkspaceProvider>'\n );\n return ctx;\n}\n","import type { WorkspaceConfig } from '../provider';\n\n// ─── Decoupled Workspace API HTTP Client ──────────────────────────────────────\n// Uses config from WorkspaceProvider instead of localStorage.\n\nexport interface WorkspaceClient {\n get: <T>(path: string) => Promise<T>;\n post: <T>(path: string, body: unknown) => Promise<T>;\n patch: <T>(path: string, body: unknown) => Promise<T>;\n delete: <T>(path: string) => Promise<T>;\n upload: <T>(path: string, formData: FormData) => Promise<T>;\n getBlob: (path: string) => Promise<Blob>;\n}\n\nexport function createWorkspaceClient(config: WorkspaceConfig): WorkspaceClient {\n function buildHeaders(extra?: HeadersInit): Record<string, string> {\n const base: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(extra as Record<string, string> | undefined),\n };\n const token = config.getAuthToken();\n if (token) base['Authorization'] = `Bearer ${token}`;\n if (config.extraHeaders) Object.assign(base, config.extraHeaders);\n return base;\n }\n\n async function req<T>(path: string, options?: RequestInit): Promise<T> {\n const res = await fetch(`${config.baseUrl}${path}`, {\n ...options,\n headers: buildHeaders(options?.headers),\n });\n if (res.status === 204) return undefined as T;\n const json = await res.json();\n if (!res.ok) {\n const rawMessage = json?.message ?? `Error ${res.status}`;\n const errorMessage = Array.isArray(rawMessage)\n ? rawMessage.join(', ')\n : typeof rawMessage === 'string'\n ? rawMessage\n : JSON.stringify(rawMessage);\n throw new Error(errorMessage);\n }\n return json as T;\n }\n\n async function reqBlob(path: string): Promise<Blob> {\n const res = await fetch(`${config.baseUrl}${path}`, {\n headers: buildHeaders(),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`Error ${res.status}: ${text}`);\n }\n return res.blob();\n }\n\n async function upload<T>(path: string, formData: FormData): Promise<T> {\n const headers: Record<string, string> = {};\n const token = config.getAuthToken();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n if (config.extraHeaders) Object.assign(headers, config.extraHeaders);\n // Do NOT set Content-Type — browser handles multipart boundary\n const res = await fetch(`${config.baseUrl}${path}`, {\n method: 'POST',\n headers,\n body: formData,\n });\n if (!res.ok) {\n const json = await res.json().catch(() => ({}));\n throw new Error(\n (json as { message?: string })?.message ??\n `Upload failed (${res.status})`\n );\n }\n return res.json();\n }\n\n return {\n get: <T>(path: string) => req<T>(path),\n post: <T>(path: string, body: unknown) =>\n req<T>(path, { method: 'POST', body: JSON.stringify(body) }),\n patch: <T>(path: string, body: unknown) =>\n req<T>(path, { method: 'PATCH', body: JSON.stringify(body) }),\n delete: <T>(path: string) => req<T>(path, { method: 'DELETE' }),\n upload: <T>(path: string, formData: FormData) => upload<T>(path, formData),\n getBlob: (path: string) => reqBlob(path),\n };\n}\n","import { io, Socket } from 'socket.io-client';\nimport type { WorkspaceConfig } from '../provider';\n\n// ─── Decoupled Workspace Socket.IO Client ─────────────────────────────────────\n\nexport interface WorkspaceSocketManager {\n getSocket: () => Socket;\n connect: (userId?: string) => Socket;\n disconnect: () => void;\n}\n\nexport function createWorkspaceSocket(\n config: WorkspaceConfig\n): WorkspaceSocketManager {\n let socket: Socket | null = null;\n\n function getSocket(): Socket {\n if (!socket) {\n const token = config.getAuthToken();\n socket = io(`${config.baseUrl}/workspaces`, {\n autoConnect: false,\n auth: { token: token ?? '' },\n });\n }\n return socket;\n }\n\n function connect(userId?: string): Socket {\n const s = getSocket();\n if (!s.connected) s.connect();\n const uid = userId ?? config.currentUserId;\n if (uid) {\n if (s.connected) {\n s.emit('authenticate', { userId: uid });\n } else {\n s.once('connect', () => {\n s.emit('authenticate', { userId: uid });\n });\n }\n }\n return s;\n }\n\n function disconnect() {\n socket?.disconnect();\n socket = null;\n }\n\n return { getSocket, connect, disconnect };\n}\n","// ─── Workspace Platform Types ─────────────────────────────────────────────────\n// Mirrors workspace-platform server schemas.\n\nexport type WorkspaceStatus = 'ACTIVE' | 'CLOSED' | 'ARCHIVED';\nexport type ArtefactType = 'NOTE' | 'EXPORT' | 'DECISION' | 'FILE' | 'TASK';\nexport type MemberType = 'user' | 'agent';\nexport type MemberRole = 'owner' | 'participant' | 'viewer';\n\n// ─── Socket / Webhook Event Enum ──────────────────────────────────────────────\n// Must stay synchronised with WebhookEvent in workspace-platform server\n// (webhook-dispatcher.service.ts).\n\nexport enum WorkspaceEvent {\n // ── Workspace lifecycle ──────────────────────────────────────────────────\n WORKSPACE_CREATED = 'workspace.created',\n WORKSPACE_UPDATED = 'workspace.updated',\n WORKSPACE_DELETED = 'workspace.deleted',\n WORKSPACE_STATUS_CHANGED = 'workspace.statusChanged',\n\n // ── Personal-room events (list-level) ────────────────────────────────────\n /** Sent to user's personal room when they are added as a member */\n WORKSPACE_ADDED = 'workspace.added',\n /** Sent to user's personal room when they are removed as a member */\n WORKSPACE_REMOVED = 'workspace.removed',\n\n // ── Workspace room events (detail-level) ─────────────────────────────────\n WORKSPACE_MEMBER_ADDED = 'workspace.member.added',\n WORKSPACE_MEMBER_UPDATED = 'workspace.member.updated',\n WORKSPACE_MEMBER_REMOVED = 'workspace.member.removed',\n WORKSPACE_MESSAGE_CREATED = 'workspace.message.created',\n WORKSPACE_MESSAGE_UPDATED = 'workspace.message.updated',\n WORKSPACE_MESSAGE_DELETED = 'workspace.message.deleted',\n WORKSPACE_MEMBER_USER_MENTIONED = 'workspace.member.user.mentioned',\n WORKSPACE_MEMBER_AGENT_MENTIONED = 'workspace.member.agent.mentioned',\n WORKSPACE_ARTEFACT_CREATED = 'workspace.artefact.created',\n WORKSPACE_TYPING_STARTED = 'workspace.typing.started',\n WORKSPACE_TYPING_STOPPED = 'workspace.typing.stopped',\n WORKSPACE_MESSAGE_REACTION_CREATED = 'workspace.message.reaction.created',\n WORKSPACE_MESSAGE_REACTION_DELETED = 'workspace.message.reaction.deleted',\n WORKSPACE_MESSAGE_PINNED = 'workspace.message.pinned',\n\n // ── Private workspace events ────────────────────────────────────────────\n PRIVATE_WORKSPACE_CREATED = 'private.workspace.created',\n PRIVATE_WORKSPACE_MESSAGE_CREATED = 'private.workspace.message.created',\n PRIVATE_WORKSPACE_MEMBER_ADDED = 'private.workspace.member.added',\n}\n\n// ─── API Response Wrapper ─────────────────────────────────────────────────────\n\nexport interface PaginatedResponse<T> {\n data: T[];\n total: number;\n offset: number;\n limit: number;\n}\n\n// ─── Domain Models ────────────────────────────────────────────────────────────\n\nexport interface EntityWithSecret {\n key: string;\n value: string;\n isSecret: boolean;\n}\n\nexport interface WorkspaceType {\n _id: string;\n name: string;\n entitiesWithSecrets?: EntityWithSecret[];\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface Workspace {\n _id: string;\n name: string;\n isPrivate?: boolean;\n type?: WorkspaceType | string;\n scope?: string;\n entitiesWithSecrets?: EntityWithSecret[];\n status: WorkspaceStatus;\n syncWithSlack?: boolean;\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface WorkspaceMember {\n _id: string;\n workspace: string;\n memberId: string;\n memberName: string;\n memberType: MemberType;\n role: MemberRole;\n createdBy?: string;\n updatedBy?: string;\n joinedAt: string;\n createdAt?: string;\n}\n\n/** Subset of WorkspaceMessage returned when populated as a reply reference */\nexport interface ReplyMessage {\n _id: string;\n senderId: string;\n senderName: string;\n senderType: MemberType;\n content: string;\n createdAt: string;\n /** Set locally when the replied-to message is soft-deleted */\n deleted?: boolean;\n}\n\nexport interface WorkspaceMessage {\n _id: string;\n workspace: string;\n senderId: string;\n senderName: string;\n senderType: MemberType;\n sender?: WorkspaceMessageSender;\n content: string;\n mentionedUsers?: string[];\n mentionedAgents?: string[];\n replyToMessage?: ReplyMessage | null;\n metadata?: Record<string, unknown>;\n deleted?: boolean;\n editedAt?: string;\n pinned?: boolean;\n pinnedAt?: string;\n pinnedBy?: string;\n createdBy?: string;\n createdAt: string;\n}\n\nexport interface WorkspaceMessageSender {\n _id: string;\n memberId: string;\n memberName: string;\n memberType: MemberType;\n role: MemberRole;\n}\n\nexport interface FileRecord {\n _id: string;\n filename: string;\n originalName: string;\n mimetype: string;\n size: number;\n bucket: string;\n key: string;\n storageProvider: string;\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface WorkspaceArtefact {\n _id: string;\n workspace: string;\n message?: string;\n file: FileRecord;\n type: ArtefactType;\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface WorkspaceMessageReaction {\n _id: string;\n reaction: string;\n message: string;\n member?: string;\n memberId?: string;\n memberName?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface MessageWithArtefacts extends WorkspaceMessage {\n artefacts: WorkspaceArtefact[];\n reactions: WorkspaceMessageReaction[];\n}\n\nexport interface WorkspaceAgent {\n _id: string;\n agentId: string;\n agentName: string;\n webhookCount: number;\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface AgentDeleteInfo {\n webhookCount: number;\n memberCount: number;\n}\n\nexport interface WebhookSubscription {\n _id: string;\n name: string;\n targetUrl: string;\n secretKey: string;\n secretValue: string;\n eventTypes: string[];\n active: boolean;\n isAgent: boolean;\n agentId?: string;\n metadata?: Record<string, unknown>;\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface WorkspaceSummary {\n _id: string;\n workspace: string;\n keyPoints: string[];\n keyTasks: string[];\n keyDecisions: string[];\n messageCount: number;\n lastMessage?: {\n _id: string;\n senderId: string;\n senderName: string;\n senderType: MemberType;\n content: string;\n createdAt: string;\n } | null;\n wasTruncated: boolean;\n generatedAt: string;\n threadId?: string;\n threadState?: 'queued' | 'running' | 'succeeded' | 'failed';\n createdBy?: string;\n updatedBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface LatestSummaryResponse {\n summary: WorkspaceSummary | null;\n messagesAfterCount: number;\n}\n\n// ─── API Payload Types ────────────────────────────────────────────────────────\n\nexport interface CreateWorkspacePayload {\n name: string;\n isPrivate?: boolean;\n type?: string;\n scope?: string;\n entitiesWithSecrets?: EntityWithSecret[];\n members?: {\n memberId: string;\n memberName: string;\n memberType?: MemberType;\n role?: string;\n }[];\n syncWithSlack?: boolean;\n}\n\nexport interface SendMessagePayload {\n senderType?: MemberType;\n content: string;\n metadata?: Record<string, unknown>;\n replyToMessageId?: string;\n}\n\nexport interface UpdateMessagePayload {\n content: string;\n}\n\n// ─── Socket Event Payload Types ───────────────────────────────────────────────\n// These mirror exactly what workspace.gateway.ts emits over Socket.IO.\n\n/** workspace.created → emitted to each member's personal room */\nexport interface WsPayloadWorkspaceCreated {\n workspace: Workspace;\n}\n\n/** workspace.added → emitted to the new member's personal room */\nexport interface WsPayloadWorkspaceAdded {\n workspaceId: string;\n workspace?: Workspace;\n}\n\n/** workspace.removed → emitted to the removed member's personal room */\nexport interface WsPayloadWorkspaceRemoved {\n workspaceId: string;\n}\n\n/** workspace.updated → emitted to workspace room */\nexport interface WsPayloadWorkspaceUpdated {\n workspace: Workspace;\n}\n\n/** workspace.statusChanged → emitted to workspace room */\nexport interface WsPayloadWorkspaceStatusChanged {\n workspace: Workspace;\n}\n\n/** workspace.member.added → emitted to workspace room */\nexport interface WsPayloadMemberAdded {\n workspaceId: string;\n member: WorkspaceMember;\n}\n\n/** workspace.member.updated → emitted to workspace room */\nexport interface WsPayloadMemberUpdated {\n workspaceId: string;\n member: WorkspaceMember;\n}\n\n/**\n * workspace.member.removed → emitted to workspace room.\n * `memberId` = the WorkspaceMember document _id (ObjectId string)\n * `memberId_field` = the actual userId/email of the removed member\n */\nexport interface WsPayloadMemberRemoved {\n workspaceId: string;\n memberId: string;\n memberId_field: string;\n}\n\n/** workspace.message.created → emitted to workspace room */\nexport interface WsPayloadMessageCreated {\n workspaceId: string;\n message: WorkspaceMessage;\n}\n\n/** workspace.artefact.created → emitted to workspace room */\nexport interface WsPayloadArtefactCreated {\n workspaceId: string;\n artefacts: WorkspaceArtefact[];\n}\n\n/** workspace.typing.started / workspace.typing.stopped */\nexport interface WsPayloadTyping {\n workspaceId: string;\n member: {\n memberId: string;\n memberName: string;\n memberType?: 'user' | 'agent' | string;\n };\n}\n\n/** workspace.message.updated → emitted to workspace room */\nexport interface WsPayloadMessageUpdated {\n workspaceId: string;\n message: WorkspaceMessage;\n}\n\n/** workspace.message.deleted → emitted to workspace room */\nexport interface WsPayloadMessageDeleted {\n workspaceId: string;\n messageId: string;\n}\n\n/** workspace.message.reaction.created → emitted to workspace room */\nexport interface WsPayloadReactionCreated {\n workspaceId: string;\n messageId: string;\n reaction: WorkspaceMessageReaction;\n}\n\n/** workspace.message.reaction.deleted → emitted to workspace room */\nexport interface WsPayloadReactionDeleted {\n workspaceId: string;\n messageId: string;\n reaction: string;\n memberId: string;\n memberName: string;\n}\n\n/** workspace.message.pinned → emitted to workspace room */\nexport interface WsPayloadMessagePinned {\n workspaceId: string;\n message: WorkspaceMessage;\n action: 'pinned' | 'unpinned';\n author: string;\n}\n\n// ─── UI Helpers ───────────────────────────────────────────────────────────────\n\n/** User with an optional avatar photo URL, for member avatar display. */\nexport interface AvatarUser {\n email: string;\n avatarUrl?: string;\n}\n","// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Payload shape sent by the backend Atlas Change Stream trigger */\nexport interface ChangeLogData {\n /** Full document snapshot (insert / replace events) */\n fullDocument?: Record<string, unknown>;\n /** Flat fields sent directly on data (legacy / simplified events) */\n updatedFields?: Record<string, unknown>;\n name?: string;\n memberName?: string;\n role?: string;\n originalName?: string;\n filename?: string;\n /** MongoDB update description (update events) */\n updateDescription?: {\n updatedFields?: Record<string, unknown>;\n removedFields?: string[];\n };\n}\n\n/** Matches the backend ChangeLog schema */\nexport interface ChangeLog {\n _id: string;\n event: string;\n timestamp: number;\n type: string;\n entityId: string;\n data?: ChangeLogData;\n createdBy?: string;\n updatedBy?: string;\n}\n\nexport type ActivityIcon =\n | 'created'\n | 'updated'\n | 'deleted'\n | 'member_added'\n | 'member_removed'\n | 'member_role'\n | 'artefact_added'\n | 'artefact_deleted'\n | 'archived'\n | 'generic';\n\nexport type EntityCategory = 'context' | 'members' | 'artefacts' | 'other';\n\nexport interface ActivityEntry {\n _id: string;\n title: string;\n description: string;\n date: string;\n author: string;\n icon: ActivityIcon;\n category: EntityCategory;\n}\n\nexport interface FilterPill {\n label: string;\n value: string | undefined; // undefined = Tout\n entityType: string | undefined; // sent to backend\n category: EntityCategory | undefined;\n}\n\n// ─── Filtre pills ─────────────────────────────────────────────────────────────\n\nexport const FILTER_PILLS: FilterPill[] = [\n {\n label: 'Tout',\n value: undefined,\n entityType: undefined,\n category: undefined,\n },\n {\n label: 'Contexte',\n value: 'context',\n entityType: 'workspaces',\n category: 'context',\n },\n {\n label: 'Membres',\n value: 'members',\n entityType: 'workspace_members',\n category: 'members',\n },\n {\n label: 'Artefacts',\n value: 'artefacts',\n entityType: 'workspace_artefacts',\n category: 'artefacts',\n },\n];\n\n// ─── Mapping helpers ──────────────────────────────────────────────────────────\n\nexport const WORKSPACE_FIELD_LABELS: Record<string, string> = {\n name: 'Nom',\n type: 'Type',\n scope: 'Périmètre',\n entities: 'Entités',\n entitiesWithSecrets: 'Entités',\n status: 'Statut',\n description: 'Description',\n};\n\nexport const WORKSPACE_STATUS_LABELS: Record<string, string> = {\n ACTIVE: 'Actif',\n ARCHIVED: 'Archivé',\n DRAFT: 'Brouillon',\n CLOSED: 'Clôturé',\n};\n\nexport const MEMBER_ROLE_LABELS: Record<string, string> = {\n owner: 'Propriétaire',\n participant: 'Participant',\n viewer: 'Lecteur',\n};\n\nexport const IGNORED_FIELDS = [\n '_id',\n '__v',\n 'updatedAt',\n 'createdAt',\n 'createdBy',\n 'updatedBy',\n 'workspace',\n];\n\n// ─── Icon / category style maps ───────────────────────────────────────────────\n\nexport const CATEGORY_STYLES: Record<\n EntityCategory,\n { dot: string; badge: string; label: string }\n> = {\n context: {\n dot: 'bg-primary/15 border-primary/30',\n badge: 'bg-primary/10 text-primary',\n label: 'Contexte',\n },\n members: {\n dot: 'bg-info/15 border-info/30',\n badge: 'bg-info/10 text-info',\n label: 'Membre',\n },\n artefacts: {\n dot: 'bg-success/15 border-success/30',\n badge: 'bg-success/10 text-success',\n label: 'Artefact',\n },\n other: {\n dot: 'bg-border',\n badge: 'bg-border text-text-muted',\n label: 'Autre',\n },\n};\n\nexport const ICON_COLOR: Record<ActivityIcon, string> = {\n created: 'text-primary',\n updated: 'text-primary',\n deleted: 'text-danger',\n member_added: 'text-info',\n member_removed: 'text-danger',\n member_role: 'text-info',\n artefact_added: 'text-success',\n artefact_deleted: 'text-danger',\n archived: 'text-text-muted',\n generic: 'text-text-muted',\n};\n","import type { WorkspaceClient } from './client';\nimport type {\n Workspace,\n WorkspaceType,\n WorkspaceMember,\n WorkspaceMessage,\n WorkspaceArtefact,\n WorkspaceMessageReaction,\n MessageWithArtefacts,\n PaginatedResponse,\n CreateWorkspacePayload,\n SendMessagePayload,\n UpdateMessagePayload,\n WebhookSubscription,\n WorkspaceStatus,\n MemberRole,\n MemberType,\n ArtefactType,\n WorkspaceAgent,\n AgentDeleteInfo,\n EntityWithSecret,\n WorkspaceSummary,\n LatestSummaryResponse,\n} from '../types';\n\n// ─── Sync types (co-located with API for convenience) ─────────────────────────\n\nexport interface SyncLink {\n provider: string;\n externalId: string;\n externalName?: string;\n externalTeamId?: string;\n active: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface SyncStatus {\n syncWithSlack: boolean;\n syncProviders?: string[];\n links: SyncLink[];\n}\n\nexport interface SyncProviderInfo {\n id: string;\n enabled: boolean;\n}\n\nexport interface ToggleReactionResponse {\n action: 'created' | 'deleted';\n reaction: WorkspaceMessageReaction | null;\n}\n\n// ─── API factory ──────────────────────────────────────────────────────────────\n// Each API object uses the injected client (from WorkspaceProvider).\n\nexport function createWorkspaceApis(client: WorkspaceClient) {\n // ── Workspace Types ──\n const workspaceTypeApi = {\n list: () => client.get<WorkspaceType[]>('/workspace-types'),\n get: (id: string) => client.get<WorkspaceType>(`/workspace-types/${id}`),\n create: (payload: { name: string; entitiesWithSecrets?: EntityWithSecret[] }) =>\n client.post<WorkspaceType>('/workspace-types', payload),\n update: (id: string, payload: { name?: string; entitiesWithSecrets?: EntityWithSecret[] }) =>\n client.patch<WorkspaceType>(`/workspace-types/${id}`, payload),\n delete: (id: string) => client.delete<void>(`/workspace-types/${id}`),\n };\n\n // ── Workspaces ──\n const workspaceApi = {\n list: (params?: {\n search?: string;\n status?: string;\n type?: string;\n isPrivate?: boolean;\n limit?: number;\n skip?: number;\n }) => {\n const cleanParams = Object.fromEntries(\n Object.entries(params || {})\n .filter(([, v]) => v != null && v !== '' && v !== 'all')\n .map(([k, v]) => [k, String(v)])\n );\n const qs =\n Object.keys(cleanParams).length > 0\n ? '?' + new URLSearchParams(cleanParams as Record<string, string>).toString()\n : '';\n return client.get<PaginatedResponse<Workspace>>(`/workspaces${qs}`);\n },\n get: (id: string) => client.get<Workspace>(`/workspaces/${id}`),\n create: (payload: CreateWorkspacePayload) =>\n client.post<Workspace>('/workspaces', payload),\n update: (id: string, payload: Partial<Omit<CreateWorkspacePayload, 'members'>>) =>\n client.patch<Workspace>(`/workspaces/${id}`, payload),\n updateStatus: (id: string, status: WorkspaceStatus) =>\n client.patch<Workspace>(`/workspaces/${id}/status`, { status }),\n delete: (id: string) => client.delete<void>(`/workspaces/${id}`),\n startTyping: (id: string) => client.post<void>(`/workspaces/${id}/writing/start`, {}),\n stopTyping: (id: string) => client.post<void>(`/workspaces/${id}/writing/stop`, {}),\n timeline: (\n workspaceId: string,\n params?: { limit?: number; offset?: number; entityType?: string }\n ) => {\n const qs = params\n ? '?' +\n new URLSearchParams(\n Object.fromEntries(\n Object.entries(params)\n .filter(([, v]) => v != null)\n .map(([k, v]) => [k, String(v)])\n )\n ).toString()\n : '';\n return client.get<PaginatedResponse<any>>(`/workspaces/${workspaceId}/timeline${qs}`);\n },\n };\n\n // ── Members ──\n const memberApi = {\n list: (workspaceId: string) =>\n client.get<WorkspaceMember[]>(`/workspaces/${workspaceId}/members`),\n add: (\n workspaceId: string,\n payload: { memberId: string; memberName: string; memberType?: MemberType; role?: MemberRole }\n ) => client.post<WorkspaceMember>(`/workspaces/${workspaceId}/members`, payload),\n updateRole: (workspaceId: string, memberId: string, role: MemberRole) =>\n client.patch<WorkspaceMember>(`/workspaces/${workspaceId}/members/${memberId}`, { role }),\n remove: (workspaceId: string, memberId: string) =>\n client.delete<void>(`/workspaces/${workspaceId}/members/${memberId}`),\n };\n\n // ── Messages ──\n const messageApi = {\n list: (\n workspaceId: string,\n params?: { limit?: number; offset?: number; sort?: 'asc' | 'desc' }\n ) => {\n const qs = params\n ? '?' +\n new URLSearchParams(\n Object.fromEntries(\n Object.entries(params)\n .filter(([, v]) => v != null)\n .map(([k, v]) => [k, String(v)])\n )\n ).toString()\n : '';\n return client.get<PaginatedResponse<WorkspaceMessage>>(`/workspaces/${workspaceId}/messages${qs}`);\n },\n send: (workspaceId: string, payload: SendMessagePayload) =>\n client.post<WorkspaceMessage>(`/workspaces/${workspaceId}/messages`, payload),\n update: (workspaceId: string, messageId: string, payload: UpdateMessagePayload) =>\n client.patch<WorkspaceMessage>(`/workspaces/${workspaceId}/messages/${messageId}`, payload),\n delete: (workspaceId: string, messageId: string) =>\n client.delete<WorkspaceMessage>(`/workspaces/${workspaceId}/messages/${messageId}`),\n togglePin: (workspaceId: string, messageId: string) =>\n client.patch<WorkspaceMessage>(`/workspaces/${workspaceId}/messages/${messageId}/pin`, {}),\n };\n\n // ── Artefacts ──\n const artefactApi = {\n upload: async (\n workspaceId: string,\n files: File[],\n messageId?: string,\n artefactType?: string\n ): Promise<{ success: boolean; count: number; results: WorkspaceArtefact[] }> => {\n const formData = new FormData();\n files.forEach((f) => formData.append('files', f));\n if (messageId) formData.append('messageId', messageId);\n if (artefactType) formData.append('type', artefactType);\n return client.upload(`/workspaces/${workspaceId}/artefacts`, formData);\n },\n list: (workspaceId: string, artefactType?: ArtefactType) => {\n const query = artefactType ? `?type=${artefactType}` : '';\n return client.get<{ data: WorkspaceArtefact[]; total: number }>(\n `/workspaces/${workspaceId}/artefacts${query}`\n );\n },\n listPaginated: (\n workspaceId: string,\n params?: { type?: ArtefactType; limit?: number; offset?: number }\n ) => {\n const entries: [string, string][] = [];\n if (params) {\n if (params.type) entries.push(['type', params.type]);\n if (params.limit != null) entries.push(['limit', String(params.limit)]);\n if (params.offset != null) entries.push(['offset', String(params.offset)]);\n }\n const qs = entries.length > 0 ? '?' + new URLSearchParams(entries).toString() : '';\n return client.get<PaginatedResponse<WorkspaceArtefact>>(\n `/workspaces/${workspaceId}/artefacts${qs}`\n );\n },\n delete: (workspaceId: string, artefactId: string) =>\n client.delete(`/workspaces/${workspaceId}/artefacts/${artefactId}`),\n getSignedUrl: (fileId: string) =>\n client.get<{ url: string }>(`/files/${fileId}/signed-url`),\n getDownloadBlob: (fileId: string) => client.getBlob(`/files/${fileId}/download`),\n messagesWithArtefacts: (\n workspaceId: string,\n params?: {\n limit?: number;\n offset?: number;\n sort?: 'asc' | 'desc';\n members?: string[];\n concernsMe?: boolean;\n pinned?: boolean;\n }\n ) => {\n const entries: [string, string][] = [];\n if (params) {\n if (params.limit != null) entries.push(['limit', String(params.limit)]);\n if (params.offset != null) entries.push(['offset', String(params.offset)]);\n if (params.sort) entries.push(['sort', params.sort]);\n if (params.members && params.members.length > 0)\n entries.push(['members', params.members.join(',')]);\n if (params.concernsMe) entries.push(['concernsMe', 'true']);\n if (params.pinned) entries.push(['pinned', 'true']);\n }\n const qs = entries.length > 0 ? '?' + new URLSearchParams(entries).toString() : '';\n return client.get<PaginatedResponse<MessageWithArtefacts>>(\n `/workspaces/${workspaceId}/messages/with-artefacts${qs}`\n );\n },\n };\n\n // ── Reactions ──\n const reactionApi = {\n toggle: (workspaceId: string, messageId: string, reaction: string) =>\n client.post<ToggleReactionResponse>(\n `/workspaces/${workspaceId}/messages/${messageId}/reactions/toggle`,\n { reaction }\n ),\n };\n\n // ── Agents ──\n const agentApi = {\n list: (search?: string) => {\n const qs = search ? `?search=${encodeURIComponent(search)}` : '';\n return client.get<WorkspaceAgent[]>(`/workspace-agents${qs}`);\n },\n create: (body: { agentId: string; agentName: string }) =>\n client.post<WorkspaceAgent>('/workspace-agents', body),\n update: (id: string, body: { agentName: string }) =>\n client.patch<WorkspaceAgent>(`/workspace-agents/${id}`, body),\n delete: (id: string) => client.delete<void>(`/workspace-agents/${id}`),\n getDeleteInfo: (id: string) =>\n client.get<AgentDeleteInfo>(`/workspace-agents/${id}/delete-info`),\n };\n\n // ── Summaries ──\n const summaryApi = {\n generate: (workspaceId: string) =>\n client.post<WorkspaceSummary>(`/workspaces/${workspaceId}/summaries/generate`, {}),\n getLatest: (workspaceId: string) =>\n client.get<LatestSummaryResponse>(`/workspaces/${workspaceId}/summaries/latest`),\n getHistory: (workspaceId: string) =>\n client.get<WorkspaceSummary[]>(`/workspaces/${workspaceId}/summaries`),\n create: (\n workspaceId: string,\n payload: {\n keyPoints: string[];\n keyTasks: string[];\n keyDecisions: string[];\n messageCount: number;\n lastMessage?: string;\n wasTruncated?: boolean;\n generatedAt?: string;\n }\n ) => client.post<WorkspaceSummary>(`/workspaces/${workspaceId}/summaries`, payload),\n update: (\n workspaceId: string,\n summaryId: string,\n payload: Partial<{\n keyPoints: string[];\n keyTasks: string[];\n keyDecisions: string[];\n messageCount: number;\n wasTruncated: boolean;\n }>\n ) =>\n client.patch<WorkspaceSummary>(\n `/workspaces/${workspaceId}/summaries/${summaryId}`,\n payload\n ),\n };\n\n // ── Webhooks ──\n const webhookApi = {\n list: (params?: { search?: string; isAgent?: string; agentId?: string }) => {\n const cleanParams = Object.fromEntries(\n Object.entries(params || {}).filter(([, v]) => v !== undefined && v !== '')\n );\n const qs =\n Object.keys(cleanParams).length > 0\n ? '?' + new URLSearchParams(cleanParams as Record<string, string>).toString()\n : '';\n return client.get<WebhookSubscription[]>(`/webhook-subscriptions${qs}`);\n },\n create: (data: {\n name: string;\n targetUrl: string;\n secretKey: string;\n secretValue: string;\n eventTypes?: string[];\n active?: boolean;\n isAgent?: boolean;\n agentId?: string;\n metadata?: Record<string, unknown>;\n }) => client.post<WebhookSubscription>('/webhook-subscriptions', data),\n update: (\n id: string,\n data: Partial<{\n name: string;\n targetUrl: string;\n secretKey: string;\n secretValue: string;\n eventTypes: string[];\n active: boolean;\n isAgent: boolean;\n agentId: string;\n metadata: Record<string, unknown>;\n }>\n ) => client.patch<WebhookSubscription>(`/webhook-subscriptions/${id}`, data),\n delete: (id: string) => client.delete(`/webhook-subscriptions/${id}`),\n };\n\n // ── Sync ──\n const syncApi = {\n getAvailableProviders: () =>\n client\n .get<{ providers: SyncProviderInfo[] }>('/workspaces/sync/providers')\n .then((res) => res.providers),\n getStatus: (workspaceId: string) =>\n client.get<SyncStatus>(`/workspaces/${workspaceId}/sync-status`),\n toggleSync: (workspaceId: string, provider: string, enabled: boolean) =>\n client.patch<Workspace>(`/workspaces/${workspaceId}/sync`, { provider, enabled }),\n };\n\n return {\n workspaceTypeApi,\n workspaceApi,\n memberApi,\n messageApi,\n artefactApi,\n reactionApi,\n agentApi,\n summaryApi,\n webhookApi,\n syncApi,\n };\n}\n\nexport type WorkspaceApis = ReturnType<typeof createWorkspaceApis>;\n","import { create, type StoreApi, type UseBoundStore } from 'zustand';\nimport type { Workspace, WorkspaceMember, WorkspaceType } from '../types';\nimport type { WorkspaceApis } from '../api';\n\n// ─── Workspace List Store ─────────────────────────────────────────────────────\n// Zustand store for workspace list with in-memory cache, pagination,\n// group/private tabs, and real-time prepend/remove.\n\nconst PAGE_SIZE = 12;\n\nexport type WorkspaceTab = 'group' | 'private';\n\nexport interface WorkspaceListFilters {\n search: string;\n status: string;\n type: string;\n}\n\nexport interface WorkspaceListState {\n workspaces: Workspace[];\n total: number;\n membersMap: Record<string, WorkspaceMember[]>;\n types: WorkspaceType[];\n tab: WorkspaceTab;\n page: number;\n pageSize: number;\n totalPages: number;\n filters: WorkspaceListFilters;\n initialLoading: boolean;\n fetching: boolean;\n hydrated: boolean;\n\n setTab: (tab: WorkspaceTab) => void;\n setFilters: (filters: WorkspaceListFilters) => void;\n setPage: (page: number) => void;\n fetchWorkspaces: () => Promise<void>;\n fetchTypes: () => Promise<void>;\n prependWorkspace: (ws: Workspace, members?: WorkspaceMember[]) => void;\n removeWorkspace: (workspaceId: string) => void;\n refresh: () => Promise<void>;\n}\n\n/**\n * Factory that creates a Zustand store bound to the injected API client.\n * Call this inside your WorkspaceProvider or in a hook.\n */\nexport function createWorkspaceListStore(\n apis: WorkspaceApis\n): UseBoundStore<StoreApi<WorkspaceListState>> {\n return create<WorkspaceListState>()((set, get) => ({\n workspaces: [],\n total: 0,\n membersMap: {},\n types: [],\n tab: 'group',\n page: 1,\n pageSize: PAGE_SIZE,\n totalPages: 0,\n filters: { search: '', status: 'ACTIVE', type: 'all' },\n initialLoading: true,\n fetching: false,\n hydrated: false,\n\n setTab: (tab) => {\n const prev = get().tab;\n if (prev === tab) return;\n set({\n tab,\n page: 1,\n workspaces: [],\n total: 0,\n totalPages: 0,\n membersMap: {},\n });\n get().fetchWorkspaces();\n },\n\n setFilters: (filters) => {\n set({ filters, page: 1 });\n },\n\n setPage: (page) => {\n set({ page });\n },\n\n fetchTypes: async () => {\n try {\n const types = await apis.workspaceTypeApi.list();\n set({ types });\n } catch (err) {\n console.error('Failed to load workspace types:', err);\n }\n },\n\n fetchWorkspaces: async () => {\n const { filters, page, pageSize, hydrated, tab } = get();\n if (!hydrated) set({ initialLoading: true });\n set({ fetching: true });\n\n try {\n const skip = (page - 1) * pageSize;\n const result = await apis.workspaceApi.list({\n ...filters,\n isPrivate: tab === 'private',\n limit: pageSize,\n skip,\n });\n\n const wsList = result.data;\n const totalPages = Math.ceil(result.total / pageSize);\n\n const map: Record<string, WorkspaceMember[]> = {};\n await Promise.all(\n wsList.map(async (ws) => {\n try {\n map[ws._id] = await apis.memberApi.list(ws._id);\n } catch {\n map[ws._id] = [];\n }\n })\n );\n\n set({\n workspaces: wsList,\n total: result.total,\n totalPages,\n membersMap: map,\n hydrated: true,\n initialLoading: false,\n fetching: false,\n });\n } catch (err) {\n console.error('Failed to load workspaces:', err);\n set({ initialLoading: false, fetching: false });\n }\n },\n\n prependWorkspace: (ws, members = []) => {\n set((state) => {\n if (state.workspaces.some((w) => w._id === ws._id)) return state;\n return {\n workspaces: [ws, ...state.workspaces],\n total: state.total + 1,\n totalPages: Math.ceil((state.total + 1) / state.pageSize),\n membersMap: { ...state.membersMap, [ws._id]: members },\n };\n });\n },\n\n removeWorkspace: (workspaceId) => {\n set((state) => {\n const next = { ...state.membersMap };\n delete next[workspaceId];\n const newTotal = Math.max(0, state.total - 1);\n return {\n workspaces: state.workspaces.filter((w) => w._id !== workspaceId),\n total: newTotal,\n totalPages: Math.ceil(newTotal / state.pageSize),\n membersMap: next,\n };\n });\n },\n\n refresh: async () => {\n const { fetchWorkspaces } = get();\n await fetchWorkspaces();\n },\n }));\n}\n","import { useMemo } from 'react';\nimport { createWorkspaceApis, type WorkspaceApis } from '../api';\nimport { useWorkspaceContext } from '../provider';\n\n/**\n * Hook to access all workspace API modules within a WorkspaceProvider.\n * The APIs are memoized and only recreated when the client changes.\n */\nexport function useWorkspaceApi(): WorkspaceApis {\n const { apiClient } = useWorkspaceContext();\n return useMemo(() => createWorkspaceApis(apiClient), [apiClient]);\n}\n","import type { MemberType } from '../types';\n\n// ─── Static Agent Members ─────────────────────────────────────────────────────\n\nexport const AVAILABLE_AGENTS: {\n memberId: string;\n memberName: string;\n memberType: MemberType;\n}[] = [\n { memberId: 'james-agent', memberName: 'James', memberType: 'agent' },\n { memberId: 'eclaireur-agent', memberName: 'Éclaireur IA', memberType: 'agent' },\n { memberId: 'sentinelle-agent', memberName: 'Sentinelle', memberType: 'agent' },\n { memberId: 'archiviste-agent', memberName: 'Archiviste', memberType: 'agent' },\n { memberId: 'stratege-agent', memberName: 'Stratège', memberType: 'agent' },\n];\n\n// ─── Role Labels (French) ─────────────────────────────────────────────────────\n\nexport const ROLE_LABELS: Record<string, string> = {\n owner: 'Propriétaire',\n participant: 'Participant',\n viewer: 'Observateur',\n};\n\n// ─── Status Labels (French) ───────────────────────────────────────────────────\n\nexport const STATUS_LABELS: Record<string, string> = {\n ACTIVE: 'Actif',\n CLOSED: 'Fermé',\n ARCHIVED: 'Archivé',\n};\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nexport function getInitials(name: string): string {\n return name\n .split(/\\s+/)\n .map((w) => w[0])\n .join('')\n .toUpperCase()\n .slice(0, 2);\n}\n\n/**\n * Fix mojibake: corrects filenames that were incorrectly decoded as Latin-1\n * when they are actually UTF-8 (common with some multipart upload implementations).\n */\nexport function fixMojibake(str: string): string {\n try {\n // Attempt to re-encode as Latin-1 bytes then decode as UTF-8\n const bytes = new Uint8Array(str.split('').map((c) => c.charCodeAt(0)));\n return new TextDecoder('utf-8').decode(bytes);\n } catch {\n return str;\n }\n}\n","import type {\n Workspace,\n WorkspaceType,\n WorkspaceMember,\n MessageWithArtefacts,\n} from '../types';\n\n// ─── Role labels ──────────────────────────────────────────────────────────────\n\nconst ROLE_LABELS: Record<string, string> = {\n owner: 'Propriétaire',\n participant: 'Participant',\n viewer: 'Observateur',\n};\n\nconst MEMBER_TYPE_LABELS: Record<string, string> = {\n user: 'Utilisateur',\n agent: 'Agent IA',\n};\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction formatDate(iso: string): string {\n return new Date(iso).toLocaleDateString('fr-FR', {\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n}\n\nfunction formatDateTime(iso: string): string {\n return new Date(iso).toLocaleString('fr-FR', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nfunction getTypeName(workspace: Workspace): string {\n if (!workspace.type) return '—';\n if (typeof workspace.type === 'object') return (workspace.type as WorkspaceType).name;\n return workspace.type;\n}\n\n/**\n * Attempt to fix common mojibake patterns (UTF-8 decoded as Latin-1).\n * Simplified version — consumers can override with their own implementation.\n */\nfunction fixMojibake(text: string): string {\n return text\n .replace(/é/g, 'é')\n .replace(/è/g, 'è')\n .replace(/à /g, 'à')\n .replace(/ç/g, 'ç')\n .replace(/ô/g, 'ô')\n .replace(/î/g, 'î')\n .replace(/â/g, 'â')\n .replace(/ë/g, 'ë')\n .replace(/ü/g, 'ü');\n}\n\n// ─── Main export function ─────────────────────────────────────────────────────\n\nexport interface WorkspaceExportData {\n workspace: Workspace;\n members: WorkspaceMember[];\n messages: MessageWithArtefacts[];\n}\n\n/**\n * Generates a formatted Markdown string representing the full workspace export.\n * Includes context, members, and the complete discussion thread.\n */\nexport function formatWorkspaceExport(data: WorkspaceExportData): string {\n const { workspace, members, messages } = data;\n const lines: string[] = [];\n\n lines.push(`# 📋 Export — ${workspace.name}`);\n lines.push('');\n lines.push(`> Export généré le **${formatDateTime(new Date().toISOString())}**`);\n lines.push('');\n lines.push('---');\n lines.push('');\n\n lines.push('## 📌 Contexte');\n lines.push('');\n lines.push(`| Champ | Valeur |`);\n lines.push(`| ----- | ------ |`);\n lines.push(`| **Nom** | ${workspace.name} |`);\n lines.push(`| **Type** | ${getTypeName(workspace)} |`);\n lines.push(`| **Scope** | ${workspace.scope || '—'} |`);\n lines.push(`| **Statut** | ${workspace.status} |`);\n lines.push(`| **Créé le** | ${formatDate(workspace.createdAt)} |`);\n lines.push(`| **Mis à jour le** | ${formatDate(workspace.updatedAt)} |`);\n\n const displayEntities = workspace.entitiesWithSecrets ?? [];\n if (displayEntities.length > 0) {\n lines.push('');\n lines.push('### Entités');\n lines.push('');\n lines.push('| Clé | Valeur | Secret |');\n lines.push('| --- | ------ | ------ |');\n for (const ent of displayEntities) {\n lines.push(\n `| ${ent.key} | ${ent.isSecret ? '••••••' : ent.value} | ${ent.isSecret ? '🔒 Oui' : 'Non'} |`\n );\n }\n }\n\n lines.push('');\n lines.push('---');\n lines.push('');\n\n lines.push(`## 👥 Membres (${members.length})`);\n lines.push('');\n lines.push('| Nom | Type | Rôle | Rejoint le |');\n lines.push('| --- | ---- | ---- | ---------- |');\n for (const m of members) {\n lines.push(\n `| ${m.memberName} | ${MEMBER_TYPE_LABELS[m.memberType] || m.memberType} | ${ROLE_LABELS[m.role] || m.role} | ${m.joinedAt || m.createdAt ? formatDate(m.joinedAt || m.createdAt!) : '—'} |`\n );\n }\n\n lines.push('');\n lines.push('---');\n lines.push('');\n\n lines.push(`## 💬 Discussion (${messages.length} messages)`);\n lines.push('');\n\n if (messages.length === 0) {\n lines.push('_Aucun message dans ce workspace._');\n } else {\n let currentDay = '';\n for (const msg of messages) {\n const day = formatDate(msg.createdAt);\n if (day !== currentDay) {\n currentDay = day;\n lines.push(`### 📅 ${day}`);\n lines.push('');\n }\n const timeStr = new Date(msg.createdAt).toLocaleTimeString('fr-FR', {\n hour: '2-digit',\n minute: '2-digit',\n });\n const senderIcon = msg.senderType === 'agent' ? '🤖' : '👤';\n lines.push(`**${senderIcon} ${msg.senderName}** — _${timeStr}_`);\n lines.push('');\n lines.push(msg.content);\n lines.push('');\n if (msg.artefacts && msg.artefacts.length > 0) {\n lines.push('> 📎 Pièces jointes :');\n for (const art of msg.artefacts) {\n lines.push(`> - \\`${fixMojibake(art.file.originalName)}\\` (${art.type})`);\n }\n lines.push('');\n }\n lines.push('---');\n lines.push('');\n }\n }\n\n lines.push('');\n lines.push(`_Fin de l'export — ${workspace.name}_`);\n\n return lines.join('\\n');\n}\n","import React, { useEffect, useId, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X } from 'lucide-react';\nimport { cn } from './cn';\n\n/** Preset width for the centered panel */\nexport type ModalSize =\n | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | '7xl' | 'full';\n\nexport type ModalHeaderVariant = 'strip' | 'plain';\n\nconst MODAL_SIZE_CLASS: Record<ModalSize, string> = {\n sm: 'w-full min-w-0 max-w-sm',\n md: 'w-full min-w-0 max-w-md',\n lg: 'w-full min-w-0 max-w-lg',\n xl: 'w-full min-w-0 max-w-xl',\n '2xl': 'w-full min-w-0 max-w-2xl',\n '3xl': 'w-full min-w-0 max-w-3xl',\n '4xl': 'w-full min-w-0 max-w-4xl',\n '5xl': 'w-full min-w-0 max-w-5xl',\n '6xl': 'w-full min-w-0 max-w-6xl',\n '7xl': 'w-full min-w-0 max-w-7xl',\n full: 'w-full min-w-0 max-w-[calc(100vw-2rem)] sm:max-w-[min(96vw,90rem)]',\n};\n\nexport interface ModalProps {\n open: boolean;\n onClose: () => void;\n children: React.ReactNode;\n zIndexClass?: string;\n backdropClassName?: string;\n size?: ModalSize;\n panelClassName?: string;\n className?: string;\n closeOnBackdropClick?: boolean;\n closeOnEscape?: boolean;\n ariaLabelledBy?: string;\n ariaDescribedBy?: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n titleIcon?: React.ReactNode;\n headingId?: string;\n modalHeaderVariant?: ModalHeaderVariant;\n hideCloseButton?: boolean;\n headerTrailing?: React.ReactNode;\n closeButtonAriaLabel?: string;\n closeButtonDisabled?: boolean;\n closeButtonClassName?: string;\n closeIconSize?: number;\n headerClassName?: string;\n titleClassName?: string;\n descriptionClassName?: string;\n}\n\nexport function Modal({\n open,\n onClose,\n children,\n zIndexClass = 'z-[100]',\n backdropClassName = 'bg-black/40 backdrop-blur-sm',\n size,\n panelClassName,\n className,\n closeOnBackdropClick = false,\n closeOnEscape = true,\n ariaLabelledBy: ariaLabelledByProp,\n ariaDescribedBy: ariaDescribedByProp,\n title,\n description,\n titleIcon,\n headingId,\n modalHeaderVariant = 'strip',\n hideCloseButton = false,\n headerTrailing,\n closeButtonAriaLabel = 'Fermer',\n closeButtonDisabled = false,\n closeButtonClassName,\n closeIconSize = 20,\n headerClassName,\n titleClassName,\n descriptionClassName = 'text-text-secondary mt-1 text-sm',\n}: ModalProps) {\n const [mounted, setMounted] = useState(false);\n const autoHeadingId = useId();\n const autoDescIdByModal = useId();\n\n const hasHeader = title != null;\n const resolvedHeadingId = headingId ?? ariaLabelledByProp ?? autoHeadingId;\n\n const assignAutoDescriptionId =\n hasHeader &&\n description != null &&\n ariaDescribedByProp === undefined &&\n (typeof description === 'string' || typeof description === 'number');\n\n const resolvedAriaDescribedBy = assignAutoDescriptionId\n ? autoDescIdByModal\n : ariaDescribedByProp;\n\n const resolvedAriaLabelledBy = hasHeader\n ? ariaLabelledByProp ?? resolvedHeadingId\n : ariaLabelledByProp;\n\n useEffect(() => { setMounted(true); }, []);\n\n useEffect(() => {\n if (!open) return;\n const prevOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => { document.body.style.overflow = prevOverflow; };\n }, [open]);\n\n useEffect(() => {\n if (!open || !closeOnEscape) return;\n const onKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [open, closeOnEscape, onClose]);\n\n const defaultCloseClasses =\n closeButtonClassName ?? 'text-text-secondary hover:text-text rounded p-1 transition-colors';\n\n const trailing =\n headerTrailing ??\n (!hideCloseButton ? (\n <button\n type=\"button\"\n disabled={closeButtonDisabled}\n onClick={onClose}\n className={cn(defaultCloseClasses, closeButtonDisabled && 'opacity-40')}\n aria-label={closeButtonAriaLabel}\n >\n <X size={closeIconSize} />\n </button>\n ) : null);\n\n const descriptionSlot =\n description == null ? null : typeof description === 'string' ||\n typeof description === 'number' ? (\n <p\n id={assignAutoDescriptionId ? autoDescIdByModal : undefined}\n className={descriptionClassName}\n >\n {description}\n </p>\n ) : (\n description\n );\n\n const headerShellClass =\n modalHeaderVariant === 'strip'\n ? 'border-border flex shrink-0 items-start justify-between gap-3 border-b px-6 py-4'\n : 'mb-4 flex shrink-0 items-start justify-between gap-3';\n\n const modalHeaderMarkup = hasHeader ? (\n <div className={cn(headerShellClass, headerClassName)}>\n <div className=\"flex min-w-0 flex-1 items-start gap-3\">\n {titleIcon != null ? <div className=\"mt-0.5 shrink-0\">{titleIcon}</div> : null}\n <div className=\"min-w-0 flex-1\">\n <h2\n id={resolvedHeadingId}\n className={cn('text-text text-lg font-semibold', titleClassName)}\n >\n {title}\n </h2>\n {descriptionSlot}\n </div>\n </div>\n {trailing ? <div className=\"flex shrink-0 items-start\">{trailing}</div> : null}\n </div>\n ) : null;\n\n if (!mounted || !open) return null;\n\n return createPortal(\n <div\n className={cn(\n 'fixed inset-0 flex items-center justify-center p-4',\n zIndexClass,\n backdropClassName,\n className,\n )}\n onClick={closeOnBackdropClick ? onClose : undefined}\n aria-hidden={false}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={resolvedAriaLabelledBy}\n aria-describedby={resolvedAriaDescribedBy}\n className={cn(size ? MODAL_SIZE_CLASS[size] : undefined, panelClassName)}\n onClick={(e) => e.stopPropagation()}\n >\n {modalHeaderMarkup}\n {children}\n </div>\n </div>,\n document.body,\n );\n}\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","'use client';\n\nimport React from 'react';\nimport { cn } from './cn';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface BadgeProps {\n variant?: 'default' | 'success' | 'warning' | 'danger' | 'info' | 'primary';\n size?: 'xs' | 'sm' | 'md';\n className?: string;\n children: React.ReactNode;\n title?: string;\n}\n\n// ── Variant & size maps ───────────────────────────────────────────────────────\n\nconst VARIANT_CLASSES: Record<NonNullable<BadgeProps['variant']>, string> = {\n default: 'bg-[var(--color-bg,#f1f5f9)] text-[var(--color-text-muted,#64748b)] border-[var(--color-border,#e2e8f0)]',\n primary: 'bg-[var(--color-primary-light,#eff6ff)] text-[var(--color-primary,#3b82f6)] border-[var(--color-primary,#3b82f6)]/30',\n success: 'bg-emerald-50 text-emerald-700 border-emerald-200 dark:bg-emerald-500/10 dark:text-emerald-400 dark:border-emerald-500/20',\n warning: 'bg-amber-50 text-amber-700 border-amber-200 dark:bg-amber-500/10 dark:text-amber-400 dark:border-amber-500/20',\n danger: 'bg-red-50 text-red-700 border-red-200 dark:bg-red-500/10 dark:text-red-400 dark:border-red-500/20',\n info: 'bg-sky-50 text-sky-700 border-sky-200 dark:bg-sky-500/10 dark:text-sky-400 dark:border-sky-500/20',\n};\n\nconst SIZE_CLASSES: Record<NonNullable<BadgeProps['size']>, string> = {\n xs: 'px-1.5 py-0.5 text-[10px] font-medium',\n sm: 'px-2 py-0.5 text-[11px] font-medium',\n md: 'px-2.5 py-1 text-xs font-semibold',\n};\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport const Badge: React.FC<BadgeProps> = ({\n variant = 'default',\n size = 'sm',\n className,\n children,\n title,\n}) => (\n <span\n title={title}\n className={cn(\n 'inline-flex items-center rounded-full border leading-none',\n VARIANT_CLASSES[variant],\n SIZE_CLASSES[size],\n className,\n )}\n >\n {children}\n </span>\n);\n","'use client';\n\nimport React, { useState, useRef, useEffect } from 'react';\nimport { cn } from './cn';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface TooltipProps {\n text: string;\n children: React.ReactNode;\n position?: 'top' | 'bottom' | 'left' | 'right';\n className?: string;\n /** Delay before showing (ms). Default 400. */\n delay?: number;\n}\n\n// ── Position classes ──────────────────────────────────────────────────────────\n\nconst POSITION: Record<NonNullable<TooltipProps['position']>, string> = {\n top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',\n bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',\n left: 'right-full top-1/2 -translate-y-1/2 mr-2',\n right: 'left-full top-1/2 -translate-y-1/2 ml-2',\n};\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport const Tooltip: React.FC<TooltipProps> = ({\n text,\n children,\n position = 'top',\n className,\n delay = 400,\n}) => {\n const [visible, setVisible] = useState(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const show = () => {\n timerRef.current = setTimeout(() => setVisible(true), delay);\n };\n const hide = () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n setVisible(false);\n };\n\n // Clean up on unmount\n useEffect(() => () => { if (timerRef.current) clearTimeout(timerRef.current); }, []);\n\n return (\n <div\n className=\"relative inline-flex\"\n onMouseEnter={show}\n onMouseLeave={hide}\n onFocus={show}\n onBlur={hide}\n >\n {children}\n {visible && text && (\n <div\n role=\"tooltip\"\n className={cn(\n 'pointer-events-none absolute z-50 max-w-xs rounded-lg px-2.5 py-1.5',\n 'bg-[#1e293b] text-white text-[11px] leading-snug whitespace-nowrap shadow-lg',\n POSITION[position],\n className,\n )}\n >\n {text}\n </div>\n )}\n </div>\n );\n};\n","'use client';\n\nimport React, { useEffect } from 'react';\nimport { AlertTriangle, Loader2, X } from 'lucide-react';\nimport { cn } from './cn';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface ConfirmModalProps {\n open: boolean;\n onClose: () => void;\n onConfirm: () => void | Promise<void>;\n title: string;\n description?: React.ReactNode;\n confirmText?: string;\n cancelText?: string;\n danger?: boolean;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport const ConfirmModal: React.FC<ConfirmModalProps> = ({\n open,\n onClose,\n onConfirm,\n title,\n description,\n confirmText = 'Confirmer',\n cancelText = 'Annuler',\n danger = false,\n}) => {\n const [loading, setLoading] = React.useState(false);\n\n // Close on Escape\n useEffect(() => {\n if (!open) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && !loading) onClose();\n };\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n }, [open, loading, onClose]);\n\n if (!open) return null;\n\n const handleConfirm = async () => {\n setLoading(true);\n try { await onConfirm(); }\n finally { setLoading(false); onClose(); }\n };\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center p-4\"\n style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}\n onClick={(e) => { if (e.target === e.currentTarget && !loading) onClose(); }}\n >\n <div\n className={cn(\n 'relative flex w-full max-w-sm flex-col gap-4 rounded-2xl border p-6 shadow-2xl',\n 'bg-[var(--color-surface,#fff)] border-[var(--color-border,#e2e8f0)]',\n )}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"confirm-title\"\n >\n {/* Close */}\n <button\n onClick={onClose}\n disabled={loading}\n className=\"absolute top-4 right-4 rounded-full p-1 text-[var(--color-text-muted,#94a3b8)] hover:text-[var(--color-text,#0f172a)] transition-colors\"\n >\n <X size={16} />\n </button>\n\n {/* Icon + title */}\n <div className=\"flex items-start gap-3\">\n <div className={cn(\n 'flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full',\n danger ? 'bg-red-100 dark:bg-red-500/10' : 'bg-[var(--color-bg,#f1f5f9)]',\n )}>\n <AlertTriangle size={18} className={danger ? 'text-red-500' : 'text-[var(--color-text-muted,#94a3b8)]'} />\n </div>\n <div className=\"min-w-0 flex-1 pt-0.5\">\n <h3 id=\"confirm-title\" className=\"text-sm font-semibold text-[var(--color-text,#0f172a)]\">\n {title}\n </h3>\n {description && (\n <div className=\"mt-1 text-xs text-[var(--color-text-secondary,#64748b)] leading-relaxed\">\n {description}\n </div>\n )}\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex justify-end gap-2\">\n <button\n onClick={onClose}\n disabled={loading}\n className=\"rounded-lg border border-[var(--color-border,#e2e8f0)] px-4 py-1.5 text-xs font-medium text-[var(--color-text-muted,#64748b)] hover:text-[var(--color-text,#0f172a)] transition-colors disabled:opacity-50\"\n >\n {cancelText}\n </button>\n <button\n onClick={handleConfirm}\n disabled={loading}\n className={cn(\n 'flex items-center gap-1.5 rounded-lg px-4 py-1.5 text-xs font-medium text-white transition-colors disabled:opacity-70',\n danger\n ? 'bg-red-500 hover:bg-red-600'\n : 'bg-[var(--color-primary,#3b82f6)] hover:bg-[var(--color-primary-hover,#2563eb)]',\n )}\n >\n {loading && <Loader2 size={12} className=\"animate-spin\" />}\n {confirmText}\n </button>\n </div>\n </div>\n </div>\n );\n};\n","import React from 'react';\nimport { Brain } from 'lucide-react';\nimport { cn } from './ui/cn';\nimport { getInitials } from '../utils/constants';\n\ntype AvatarSize = 'xs' | 'sm' | 'md' | 'lg';\n\nconst SIZES: Record<AvatarSize, { container: string; text: string; icon: number }> = {\n xs: { container: 'h-6 w-6', text: 'text-[9px]', icon: 10 },\n sm: { container: 'h-7 w-7', text: 'text-[10px]', icon: 12 },\n md: { container: 'h-9 w-9', text: 'text-xs', icon: 16 },\n lg: { container: 'h-10 w-10', text: 'text-sm', icon: 18 },\n};\n\nexport interface MemberAvatarProps {\n memberName: string;\n memberType: 'user' | 'agent';\n avatarUrl?: string | null;\n size?: AvatarSize;\n className?: string;\n variant?: 'primary' | 'owner' | 'currentUser';\n}\n\nexport const MemberAvatar: React.FC<MemberAvatarProps> = ({\n memberName, memberType, avatarUrl, size = 'md', className, variant = 'primary',\n}) => {\n const s = SIZES[size];\n if (memberType === 'agent') {\n return (\n <span className={cn('flex flex-shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-violet-100 to-indigo-100 ring-1 ring-indigo-200/60', s.container, className)}>\n <Brain size={s.icon} className=\"text-indigo-600\" />\n </span>\n );\n }\n if (avatarUrl) {\n return <img src={avatarUrl} alt={memberName} className={cn('flex-shrink-0 rounded-full object-cover ring-2 ring-white', s.container, className)} />;\n }\n return (\n <span className={cn('flex flex-shrink-0 items-center justify-center rounded-full font-semibold', s.container, s.text, variant === 'currentUser' ? 'bg-primary text-white shadow-md' : variant === 'owner' ? 'bg-warning-light text-warning' : 'bg-primary-light text-primary', className)}>\n {getInitials(memberName)}\n </span>\n );\n};\n","\n\nimport React from 'react';\nimport {\n ChevronsLeft,\n ChevronLeft,\n ChevronRight,\n ChevronsRight,\n} from 'lucide-react';\nimport { cn } from './ui/cn';\n\ninterface NavButtonProps {\n onClick: () => void;\n disabled: boolean;\n children: React.ReactNode;\n title: string;\n}\n\nconst NavButton: React.FC<NavButtonProps> = ({\n onClick,\n disabled,\n children,\n title,\n}) => (\n <button\n onClick={onClick}\n disabled={disabled}\n title={title}\n className={cn(\n 'flex h-9 w-9 items-center justify-center rounded-lg border text-sm transition-all duration-200',\n disabled\n ? 'border-border-light text-text-placeholder cursor-not-allowed opacity-40'\n : 'border-border bg-surface text-text-secondary hover:bg-primary/8 hover:border-primary/30 hover:text-primary active:scale-95',\n )}\n >\n {children}\n </button>\n);\n\ninterface PaginationProps {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n /** Show a subtle loading indicator when fetching */\n loading?: boolean;\n}\n\nexport const Pagination: React.FC<PaginationProps> = ({\n currentPage,\n totalPages,\n onPageChange,\n loading = false,\n}) => {\n if (totalPages <= 1) return null;\n\n // Build a window of page numbers to display\n const getVisiblePages = (): (number | 'ellipsis')[] => {\n const pages: (number | 'ellipsis')[] = [];\n const maxVisible = 5;\n\n if (totalPages <= maxVisible + 2) {\n for (let i = 1; i <= totalPages; i++) pages.push(i);\n return pages;\n }\n\n // Always show first page\n pages.push(1);\n\n const start = Math.max(2, currentPage - 1);\n const end = Math.min(totalPages - 1, currentPage + 1);\n\n if (start > 2) pages.push('ellipsis');\n\n for (let i = start; i <= end; i++) pages.push(i);\n\n if (end < totalPages - 1) pages.push('ellipsis');\n\n // Always show last page\n pages.push(totalPages);\n\n return pages;\n };\n\n const pages = getVisiblePages();\n\n return (\n <div className=\"mt-6 flex items-center justify-center gap-1.5\">\n {/* First page */}\n <NavButton\n onClick={() => onPageChange(1)}\n disabled={currentPage === 1 || loading}\n title=\"Première page\"\n >\n <ChevronsLeft size={16} />\n </NavButton>\n\n {/* Previous */}\n <NavButton\n onClick={() => onPageChange(currentPage - 1)}\n disabled={currentPage === 1 || loading}\n title=\"Page précédente\"\n >\n <ChevronLeft size={16} />\n </NavButton>\n\n {/* Page numbers */}\n {pages.map((p, idx) =>\n p === 'ellipsis' ? (\n <span\n key={`ellipsis-${idx}`}\n className=\"text-text-muted flex h-9 w-9 items-center justify-center text-sm\"\n >\n …\n </span>\n ) : (\n <button\n key={p}\n onClick={() => onPageChange(p)}\n disabled={loading}\n className={cn(\n 'flex h-9 w-9 items-center justify-center rounded-lg text-sm font-medium transition-all duration-200',\n p === currentPage\n ? 'bg-primary text-white shadow-sm shadow-primary/30'\n : 'border-border bg-surface text-text-secondary hover:bg-primary/8 hover:border-primary/30 hover:text-primary border active:scale-95',\n )}\n >\n {p}\n </button>\n ),\n )}\n\n {/* Next */}\n <NavButton\n onClick={() => onPageChange(currentPage + 1)}\n disabled={currentPage === totalPages || loading}\n title=\"Page suivante\"\n >\n <ChevronRight size={16} />\n </NavButton>\n\n {/* Last page */}\n <NavButton\n onClick={() => onPageChange(totalPages)}\n disabled={currentPage === totalPages || loading}\n title=\"Dernière page\"\n >\n <ChevronsRight size={16} />\n </NavButton>\n </div>\n );\n};\n","'use client';\n\nimport React from 'react';\nimport { Brain, Lock, Calendar, ArrowUpRight, MessageSquare } from 'lucide-react';\nimport { cn } from './ui/cn';\nimport type { Workspace, WorkspaceMember, WorkspaceType, AvatarUser } from '../types';\nimport { STATUS_LABELS, ROLE_LABELS } from '../utils/constants';\nimport { MemberAvatar } from './MemberAvatar';\nimport { Badge } from './ui/Badge';\nimport { Tooltip } from './ui/Tooltip';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface WorkspaceCardProps {\n workspace: Workspace;\n members?: WorkspaceMember[];\n avatarUsers?: AvatarUser[];\n onClick?: () => void;\n currentUserId?: string;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport const WorkspaceCard: React.FC<WorkspaceCardProps> = ({\n workspace, members = [], avatarUsers, onClick, currentUserId,\n}) => {\n const isPrivate = workspace.isPrivate === true;\n\n const typeName =\n typeof workspace.type === 'object' && workspace.type !== null\n ? (workspace.type as WorkspaceType).name\n : (workspace.type as string | undefined);\n\n const userRole = currentUserId\n ? members.find((m) => m.memberId === currentUserId)?.role\n : undefined;\n\n const userMembers = members.filter((m) => m.memberType === 'user');\n const agentMembers = members.filter((m) => m.memberType === 'agent');\n\n const otherMember = isPrivate ? members.find((m) => m.memberId !== currentUserId) : null;\n const otherAvatarUrl = otherMember\n ? avatarUsers?.find((u) => u.email.toLowerCase() === otherMember.memberId.toLowerCase())?.avatarUrl\n : undefined;\n\n const displayEntities = workspace.entitiesWithSecrets ?? [];\n const isActive = workspace.status === 'ACTIVE';\n\n const cardClass = cn(\n 'group bg-[var(--color-surface,#fff)] border-[var(--color-border,#e2e8f0)] relative flex cursor-pointer flex-col rounded-2xl border p-5 transition-all duration-300',\n 'shadow-sm hover:shadow-md hover:-translate-y-1 overflow-hidden',\n );\n\n // ── Private ──\n if (isPrivate) {\n return (\n <div className={cardClass} onClick={onClick}>\n <div className=\"mb-4 flex items-center justify-between\">\n <span className=\"bg-[var(--color-primary-light,#eff6ff)] text-[var(--color-primary,#3b82f6)] flex items-center gap-1.5 rounded-lg px-2.5 py-1 text-[11px] font-semibold tracking-wide uppercase\">\n <MessageSquare size={11} /> Privé\n </span>\n <ArrowUpRight size={14} className=\"text-[var(--color-text-muted,#94a3b8)] group-hover:text-[var(--color-primary,#3b82f6)] transition-all duration-200 group-hover:translate-x-0.5 group-hover:-translate-y-0.5\" />\n </div>\n <div className=\"mb-4 flex items-center gap-3\">\n <MemberAvatar memberName={otherMember?.memberName ?? 'Inconnu'} memberType=\"user\" avatarUrl={otherAvatarUrl} size=\"lg\" />\n <div className=\"min-w-0 flex-1\">\n <h4 className=\"text-[var(--color-text,#0f172a)] group-hover:text-[var(--color-primary,#3b82f6)] text-[15px] leading-snug font-bold transition-colors duration-200\">\n {otherMember?.memberName ?? 'Utilisateur inconnu'}\n </h4>\n <p className=\"text-[var(--color-text-muted,#94a3b8)] truncate text-xs\">{otherMember?.memberId ?? ''}</p>\n </div>\n </div>\n <div className=\"mt-auto\">\n <div className=\"border-[var(--color-border,#e2e8f0)] mb-3 border-t\" />\n <div className=\"flex items-center justify-end\">\n <span className=\"text-[var(--color-text-muted,#94a3b8)] flex items-center gap-1 text-[11px]\">\n <Calendar size={11} className=\"opacity-50\" />\n {new Date(workspace.updatedAt).toLocaleDateString('fr-FR')}\n </span>\n </div>\n </div>\n </div>\n );\n }\n\n // ── Public ──\n return (\n <div className={cardClass} onClick={onClick}>\n {/* Header */}\n <div className=\"mb-3 flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n {typeName && (\n <span className=\"bg-[var(--color-primary-light,#eff6ff)] text-[var(--color-primary,#3b82f6)] rounded-lg px-2.5 py-1 text-[11px] font-semibold tracking-wide uppercase\">\n {typeName}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-1.5\">\n {userRole && (\n <span className={cn('rounded-lg px-2 py-0.5 text-[10px] font-semibold',\n userRole === 'owner' ? 'bg-amber-50 text-amber-600 dark:bg-amber-500/10 dark:text-amber-400'\n : userRole === 'participant' ? 'bg-[var(--color-primary-light,#eff6ff)] text-[var(--color-primary,#3b82f6)]'\n : 'bg-[var(--color-bg,#f8fafc)] text-[var(--color-text-muted,#94a3b8)]',\n )}>\n {ROLE_LABELS[userRole] ?? userRole}\n </span>\n )}\n <Badge variant={isActive ? 'success' : 'default'} size=\"xs\">\n {STATUS_LABELS[workspace.status] ?? workspace.status}\n </Badge>\n </div>\n </div>\n\n {/* Name & scope */}\n <div className=\"mb-3\">\n <h4 className=\"text-[var(--color-text,#0f172a)] group-hover:text-[var(--color-primary,#3b82f6)] mb-1 text-[15px] leading-snug font-bold transition-colors duration-200\">\n {workspace.name}\n </h4>\n {workspace.scope && (\n <p className=\"text-[var(--color-text-secondary,#475569)] line-clamp-2 text-[13px] leading-relaxed\">{workspace.scope}</p>\n )}\n </div>\n\n {/* Entities */}\n {displayEntities.length > 0 && (\n <div className=\"mb-3 flex flex-wrap gap-1.5\">\n {displayEntities.slice(0, 3).map((ent) => (\n <span key={ent.key} className=\"bg-[var(--color-bg,#f8fafc)] border-[var(--color-border,#e2e8f0)] inline-flex items-center gap-1 rounded-lg border px-2 py-1 text-[10px]\">\n {ent.isSecret && <Lock size={9} className=\"text-amber-500 shrink-0\" />}\n <span className=\"text-[var(--color-text-muted,#94a3b8)] font-medium\">{ent.key}:</span>\n <span className=\"text-[var(--color-text,#0f172a)]\">{ent.isSecret ? '••••••' : ent.value}</span>\n </span>\n ))}\n {displayEntities.length > 3 && (\n <span className=\"text-[var(--color-text-muted,#94a3b8)] self-center text-[10px]\">+{displayEntities.length - 3}</span>\n )}\n </div>\n )}\n\n {/* Footer */}\n <div className=\"mt-auto\">\n <div className=\"border-[var(--color-border,#e2e8f0)] mb-3 border-t\" />\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center\">\n <div className=\"flex -space-x-2\">\n {userMembers.slice(0, 4).map((m) => (\n <Tooltip key={m._id} text={`${m.memberName} (${ROLE_LABELS[m.role] ?? m.role})`}>\n <MemberAvatar memberName={m.memberName} memberType={m.memberType}\n avatarUrl={avatarUsers?.find((u) => u.email.toLowerCase() === m.memberId.toLowerCase())?.avatarUrl}\n size=\"xs\" />\n </Tooltip>\n ))}\n </div>\n {userMembers.length > 4 && (\n <span className=\"text-[var(--color-text-muted,#94a3b8)] ml-1.5 text-[11px] font-medium\">+{userMembers.length - 4}</span>\n )}\n </div>\n {agentMembers.length > 0 && (\n <Tooltip text={`${agentMembers.length} agent(s): ${agentMembers.map((a) => a.memberName).join(', ')}`}>\n <span className=\"bg-[var(--color-primary-light,#eff6ff)] text-[var(--color-primary,#3b82f6)] flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] font-medium\">\n <Brain size={12} /> {agentMembers.length}\n </span>\n </Tooltip>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-[var(--color-text-muted,#94a3b8)] flex items-center gap-1 text-[11px]\">\n <Calendar size={11} className=\"opacity-50\" />\n {new Date(workspace.updatedAt).toLocaleDateString('fr-FR')}\n </span>\n <ArrowUpRight size={14} className=\"text-[var(--color-text-muted,#94a3b8)] group-hover:text-[var(--color-primary,#3b82f6)] transition-all duration-200 group-hover:translate-x-0.5 group-hover:-translate-y-0.5\" />\n </div>\n </div>\n </div>\n </div>\n );\n};\n","'use client';\n\nimport React from 'react';\nimport { Brain } from 'lucide-react';\nimport { cn } from './ui/cn';\nimport type { Workspace, WorkspaceMember, WorkspaceType, AvatarUser } from '../types';\nimport { STATUS_LABELS, ROLE_LABELS } from '../utils/constants';\nimport { MemberAvatar } from './MemberAvatar';\nimport { Badge } from './ui/Badge';\nimport { Tooltip } from './ui/Tooltip';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface WorkspaceRowProps {\n workspace: Workspace;\n members?: WorkspaceMember[];\n avatarUsers?: AvatarUser[];\n onClick?: () => void;\n currentUserId?: string;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport const WorkspaceRow: React.FC<WorkspaceRowProps> = ({\n workspace, members = [], avatarUsers, onClick, currentUserId,\n}) => {\n const typeName =\n typeof workspace.type === 'object' && workspace.type !== null\n ? (workspace.type as WorkspaceType).name\n : (workspace.type as string | undefined);\n\n const userRole = currentUserId\n ? members.find((m) => m.memberId === currentUserId)?.role\n : undefined;\n\n const userMembers = members.filter((m) => m.memberType === 'user');\n const agentMembers = members.filter((m) => m.memberType === 'agent');\n\n return (\n <div\n className=\"bg-[var(--color-surface,#fff)] border-[var(--color-border,#e2e8f0)] hover:bg-[var(--color-primary-light,#eff6ff)]/30 flex cursor-pointer items-center gap-4 rounded-lg border px-4 py-3 transition-colors\"\n onClick={onClick}\n >\n {/* Name + type */}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-[var(--color-text,#0f172a)] truncate font-semibold\">{workspace.name}</span>\n {typeName && <Badge size=\"xs\" title={typeName}>{typeName}</Badge>}\n </div>\n {workspace.scope && (\n <p className=\"text-[var(--color-text-muted,#94a3b8)] mt-0.5 truncate text-xs\">{workspace.scope}</p>\n )}\n </div>\n\n {/* Members */}\n <div className=\"flex items-center gap-2\">\n <div className=\"flex -space-x-1.5\">\n {userMembers.slice(0, 3).map((m) => (\n <Tooltip key={m._id} text={m.memberName}>\n <MemberAvatar memberName={m.memberName} memberType={m.memberType}\n avatarUrl={avatarUsers?.find((u) => u.email.toLowerCase() === m.memberId.toLowerCase())?.avatarUrl}\n size=\"xs\" />\n </Tooltip>\n ))}\n </div>\n {agentMembers.length > 0 && (\n <span className=\"text-[var(--color-text-muted,#94a3b8)] flex items-center gap-0.5 text-[10px]\">\n <Brain size={10} /> {agentMembers.length}\n </span>\n )}\n </div>\n\n {/* Role */}\n {userRole && (\n <span className={cn(\n 'rounded-full px-2 py-0.5 text-[10px] font-medium',\n userRole === 'owner' ? 'bg-amber-50 text-amber-600 dark:bg-amber-500/10 dark:text-amber-400'\n : 'bg-[var(--color-primary-light,#eff6ff)] text-[var(--color-primary,#3b82f6)]',\n )}>\n {ROLE_LABELS[userRole] ?? userRole}\n </span>\n )}\n\n {/* Status */}\n <Badge variant={workspace.status === 'ACTIVE' ? 'success' : 'default'} size=\"xs\">\n {STATUS_LABELS[workspace.status] ?? workspace.status}\n </Badge>\n\n {/* Date */}\n <span className=\"text-[var(--color-text-muted,#94a3b8)] text-[10px] whitespace-nowrap\">\n {new Date(workspace.updatedAt).toLocaleDateString('fr-FR')}\n </span>\n </div>\n );\n};\n","'use client';\n\nimport React from 'react';\nimport { Search, Filter, LayoutGrid, List, Layers } from 'lucide-react';\nimport { cn } from './ui/cn';\nimport type { Workspace, WorkspaceMember, WorkspaceType, AvatarUser } from '../types';\nimport { WorkspaceCard } from './WorkspaceCard';\nimport { WorkspaceRow } from './WorkspaceRow';\nimport { Pagination } from './Pagination';\n\nexport interface WorkspaceListProps {\n workspaces: Workspace[];\n total?: number;\n membersMap?: Record<string, WorkspaceMember[]>;\n avatarUsers?: AvatarUser[];\n types?: WorkspaceType[];\n loading?: boolean;\n fetching?: boolean;\n onOpen: (workspaceId: string) => void;\n title?: string;\n showViewToggle?: boolean;\n currentUserId?: string;\n headerActions?: React.ReactNode;\n hideHeader?: boolean;\n hideFilters?: boolean;\n filters?: { search: string; status: string; type: string };\n onFiltersChange?: (filters: { search: string; status: string; type: string }) => void;\n currentPage?: number;\n totalPages?: number;\n onPageChange?: (page: number) => void;\n}\n\nconst SkeletonCard = () => (\n <div className=\"bg-[var(--color-surface,#fff)] border-[var(--color-border,#e2e8f0)] animate-pulse rounded-2xl border p-5\">\n <div className=\"mb-3 flex items-center justify-between\">\n <div className=\"bg-[var(--color-border,#e2e8f0)] h-5 w-20 rounded-lg\" />\n <div className=\"bg-[var(--color-border,#e2e8f0)] h-4 w-14 rounded-lg\" />\n </div>\n <div className=\"mb-3\">\n <div className=\"bg-[var(--color-border,#e2e8f0)] mb-2 h-4 w-3/4 rounded\" />\n <div className=\"bg-[var(--color-border,#e2e8f0)] h-3 w-1/2 rounded\" />\n </div>\n <div className=\"mt-auto\">\n <div className=\"border-[var(--color-border,#e2e8f0)] mb-3 border-t\" />\n <div className=\"flex items-center justify-between\">\n <div className=\"flex -space-x-2\">\n {[0, 1, 2].map((i) => <div key={i} className=\"bg-[var(--color-border,#e2e8f0)] h-6 w-6 rounded-full\" />)}\n </div>\n <div className=\"bg-[var(--color-border,#e2e8f0)] h-3 w-16 rounded\" />\n </div>\n </div>\n </div>\n);\n\nexport const WorkspaceList: React.FC<WorkspaceListProps> = ({\n workspaces, total, membersMap = {}, avatarUsers, types = [], loading = false, fetching = false,\n onOpen, title = 'Workspaces', showViewToggle = true, currentUserId, headerActions,\n hideHeader = false, hideFilters = false, filters, onFiltersChange,\n currentPage = 1, totalPages = 1, onPageChange,\n}) => {\n const [viewMode, setViewMode] = React.useState<'grid' | 'list'>('grid');\n\n const search = filters?.search ?? '';\n const statusFilter = filters?.status ?? 'ACTIVE';\n const typeFilter = filters?.type ?? 'all';\n\n const statusOptions = [\n { value: 'all', label: 'Tous' },\n { value: 'ACTIVE', label: 'Actifs' },\n { value: 'ARCHIVED', label: 'Archivés' },\n ] as const;\n\n const showSkeletons = loading || (fetching && workspaces.length === 0);\n\n const Header = () => (\n <div className=\"mb-5 flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"bg-[var(--color-primary-light,#eff6ff)] flex h-9 w-9 items-center justify-center rounded-xl\">\n <Layers size={18} className=\"text-[var(--color-primary,#3b82f6)]\" />\n </div>\n <div>\n <h2 className=\"text-[var(--color-text,#0f172a)] text-lg font-bold tracking-tight\">{title}</h2>\n {total != null && !showSkeletons && (\n <p className=\"text-[var(--color-text-muted,#94a3b8)] text-xs\">{total} workspace{total !== 1 ? 's' : ''}</p>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {showViewToggle && (\n <div className=\"bg-[var(--color-bg,#f8fafc)] border-[var(--color-border,#e2e8f0)] flex rounded-lg border p-0.5\">\n <button className={cn('rounded-md p-1.5 transition-all duration-200',\n viewMode === 'grid' ? 'bg-[var(--color-primary,#3b82f6)] text-white shadow-sm' : 'text-[var(--color-text-muted,#94a3b8)] hover:text-[var(--color-text,#0f172a)]')}\n onClick={() => setViewMode('grid')} title=\"Vue grille\">\n <LayoutGrid size={14} />\n </button>\n <button className={cn('rounded-md p-1.5 transition-all duration-200',\n viewMode === 'list' ? 'bg-[var(--color-primary,#3b82f6)] text-white shadow-sm' : 'text-[var(--color-text-muted,#94a3b8)] hover:text-[var(--color-text,#0f172a)]')}\n onClick={() => setViewMode('list')} title=\"Vue liste\">\n <List size={14} />\n </button>\n </div>\n )}\n {headerActions}\n </div>\n </div>\n );\n\n if (showSkeletons) {\n return (\n <div>\n {!hideHeader && <Header />}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {Array.from({ length: 6 }).map((_, i) => <SkeletonCard key={i} />)}\n </div>\n </div>\n );\n }\n\n return (\n <div>\n {!hideHeader && <Header />}\n\n {/* Filters */}\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <div className=\"relative min-w-[220px] flex-1\">\n <Search size={15} className=\"text-[var(--color-text-muted,#94a3b8)] absolute top-1/2 left-3.5 -translate-y-1/2\" />\n <input\n className=\"border-[var(--color-border,#e2e8f0)] bg-[var(--color-surface,#fff)] text-[var(--color-text,#0f172a)] w-full rounded-xl border py-2.5 pr-3 pl-10 text-sm transition-all duration-200 focus:border-[var(--color-primary,#3b82f6)]/50 focus:outline-none focus:ring-2 focus:ring-[var(--color-primary,#3b82f6)]/10 placeholder:text-[var(--color-text-muted,#94a3b8)]\"\n placeholder=\"Rechercher un workspace…\"\n value={search}\n onChange={(e) => onFiltersChange?.({ search: e.target.value, status: statusFilter, type: typeFilter })}\n />\n </div>\n\n {!hideFilters && (\n <>\n <div className=\"flex items-center gap-1.5\">\n <Filter size={13} className=\"text-[var(--color-text-muted,#94a3b8)] mr-0.5\" />\n {statusOptions.map(({ value, label }) => (\n <button key={value}\n className={cn('rounded-full px-3 py-1.5 text-xs font-medium transition-all duration-200',\n statusFilter === value\n ? 'bg-[var(--color-primary,#3b82f6)] text-white shadow-sm'\n : 'bg-[var(--color-surface,#fff)] border-[var(--color-border,#e2e8f0)] text-[var(--color-text-muted,#94a3b8)] hover:bg-[var(--color-primary-light,#eff6ff)] hover:text-[var(--color-primary,#3b82f6)] border')}\n onClick={() => onFiltersChange?.({ search, status: value, type: typeFilter })}>\n {label}\n </button>\n ))}\n </div>\n {types.length > 0 && (\n <select className=\"border-[var(--color-border,#e2e8f0)] bg-[var(--color-surface,#fff)] text-[var(--color-text,#0f172a)] rounded-xl border px-3 py-2 text-xs transition-all duration-200 focus:border-[var(--color-primary,#3b82f6)]/50 focus:outline-none focus:ring-2 focus:ring-[var(--color-primary,#3b82f6)]/10\"\n value={typeFilter} onChange={(e) => onFiltersChange?.({ search, status: statusFilter, type: e.target.value })}>\n <option value=\"all\">Tous les types</option>\n {types.map((t) => <option key={t._id} value={t._id}>{t.name}</option>)}\n </select>\n )}\n </>\n )}\n </div>\n\n {/* Content */}\n <div className={cn('transition-opacity duration-300', fetching ? 'opacity-60' : 'opacity-100')}>\n {workspaces.length === 0 ? (\n <div className=\"text-[var(--color-text-muted,#94a3b8)] border-[var(--color-border,#e2e8f0)] flex flex-col items-center justify-center rounded-2xl border border-dashed py-12 text-center\">\n <div className=\"bg-[var(--color-bg,#f8fafc)] mb-3 flex h-12 w-12 items-center justify-center rounded-full\">\n <Layers size={22} className=\"opacity-40\" />\n </div>\n <p className=\"mb-1 text-sm font-medium\">Aucun workspace trouvé</p>\n <p className=\"text-xs\">\n {search || statusFilter !== 'all' || typeFilter !== 'all'\n ? 'Modifiez vos filtres pour voir plus de résultats'\n : 'Créez un workspace pour commencer à collaborer'}\n </p>\n </div>\n ) : viewMode === 'grid' ? (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {workspaces.map((ws) => (\n <WorkspaceCard key={ws._id} workspace={ws} members={membersMap[ws._id]}\n avatarUsers={avatarUsers} onClick={() => onOpen(ws._id)} currentUserId={currentUserId} />\n ))}\n </div>\n ) : (\n <div className=\"flex flex-col gap-2\">\n {workspaces.map((ws) => (\n <WorkspaceRow key={ws._id} workspace={ws} members={membersMap[ws._id]}\n avatarUsers={avatarUsers} onClick={() => onOpen(ws._id)} currentUserId={currentUserId} />\n ))}\n </div>\n )}\n\n {onPageChange && totalPages > 1 && (\n <Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={onPageChange} loading={fetching} />\n )}\n </div>\n </div>\n );\n};\n","import React, { useState, useEffect, useMemo, useId, useRef } from 'react';\nimport { X, ArrowRight, ArrowLeft, Plus, Trash2, Check, Users, Brain, Loader2, Lock, Unlock, Slack } from 'lucide-react';\nimport { cn } from './ui/cn';\nimport { useWorkspaceContext } from '../provider';\nimport { useWorkspaceApi } from '../hooks/useWorkspaceApi';\nimport type { WorkspaceType, CreateWorkspacePayload, MemberType, WorkspaceAgent, EntityWithSecret } from '../types';\nimport { getInitials } from '../utils/constants';\nimport { Modal } from './ui/Modal';\nimport { MemberAvatar } from './MemberAvatar';\n\ninterface CreateWorkspaceModalProps {\n open: boolean;\n onClose: () => void;\n onCreated?: (workspace: unknown) => void;\n}\n\ninterface MemberEntry {\n memberId: string;\n memberName: string;\n memberType: MemberType;\n role: string;\n}\n\nconst STEP_TITLES = ['Type de workspace', 'Contexte', 'Membres', 'Confirmation'];\n\nexport const CreateWorkspaceModal: React.FC<CreateWorkspaceModalProps> = ({ open, onClose, onCreated }) => {\n const titleId = useId();\n const stepDescriptionId = useId();\n const { config } = useWorkspaceContext();\n const apis = useWorkspaceApi();\n\n const [step, setStep] = useState(0);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Step 0: Type\n const [types, setTypes] = useState<WorkspaceType[]>([]);\n const [typesLoading, setTypesLoading] = useState(false);\n const [selectedTypeId, setSelectedTypeId] = useState<string | null>(null);\n\n // Step 1: Context\n const [name, setName] = useState('');\n const [scope, setScope] = useState('');\n const [entities, setEntities] = useState<{ key: string; value: string; isSecret: boolean }[]>([]);\n const [syncWithSlack, setSyncWithSlack] = useState(false);\n const [slackAvailable, setSlackAvailable] = useState(false);\n\n // Step 2: Members\n const [memberSearch, setMemberSearch] = useState('');\n const [members, setMembers] = useState<MemberEntry[]>([]);\n const [agents, setAgents] = useState<WorkspaceAgent[]>([]);\n const [searchResults, setSearchResults] = useState<{ id: string; email: string; displayName: string; avatarUrl?: string }[]>([]);\n const [searchingUsers, setSearchingUsers] = useState(false);\n const [avatarMap, setAvatarMap] = useState<Record<string, string>>({});\n\n // Agent autocomplete\n const [agentSearch, setAgentSearch] = useState('');\n const [showAgentDropdown, setShowAgentDropdown] = useState(false);\n const [agentSearchFocused, setAgentSearchFocused] = useState(false);\n const agentSearchInputRef = useRef<HTMLInputElement>(null);\n\n const invitedUsers = useMemo(() => members.filter((m) => m.memberType === 'user'), [members]);\n const invitedAgents = useMemo(() => members.filter((m) => m.memberType === 'agent'), [members]);\n const unselectedAgents = useMemo(() => agents.filter((a) => !members.some((m) => m.memberId === a.agentId) && (agentSearch.trim() === '' || a.agentName.toLowerCase().includes(agentSearch.toLowerCase()))), [agents, members, agentSearch]);\n\n // Resolve avatars when members change\n useEffect(() => {\n if (!config.resolveAvatars || invitedUsers.length === 0) return;\n config.resolveAvatars(invitedUsers.map((m) => m.memberId)).then(setAvatarMap).catch(() => {});\n }, [invitedUsers.length]);\n\n // User search via injected searchUsers\n useEffect(() => {\n if (memberSearch.length < 2 || !config.searchUsers) { setSearchResults([]); return; }\n let cancelled = false;\n setSearchingUsers(true);\n config.searchUsers(memberSearch).then((r) => { if (!cancelled) setSearchResults(r); }).catch(() => { if (!cancelled) setSearchResults([]); }).finally(() => { if (!cancelled) setSearchingUsers(false); });\n return () => { cancelled = true; };\n }, [memberSearch]);\n\n const filteredUsers = useMemo(() => searchResults.filter((u) => u.email !== config.currentUserId && !members.some((m) => m.memberId === u.email)), [searchResults, members, config.currentUserId]);\n\n // Load types on mount\n useEffect(() => {\n if (!open) return;\n setTypesLoading(true);\n Promise.all([apis.workspaceTypeApi.list(), apis.agentApi.list()])\n .then(([wt, ag]) => { setTypes(wt); setAgents(ag); })\n .catch(() => { setTypes([]); setAgents([]); })\n .finally(() => setTypesLoading(false));\n apis.syncApi.getAvailableProviders().then((providers) => setSlackAvailable(providers.some((p) => p.id === 'slack' && p.enabled))).catch(() => setSlackAvailable(false));\n }, [open]);\n\n // Pre-fill entities when type changes\n useEffect(() => {\n if (!selectedTypeId) return;\n const t = types.find((tp) => tp._id === selectedTypeId);\n if (t?.entitiesWithSecrets && t.entitiesWithSecrets.length > 0) {\n setEntities(t.entitiesWithSecrets.map((e) => ({ key: e.key, value: e.value, isSecret: e.isSecret })));\n }\n }, [selectedTypeId, types]);\n\n // Reset on close\n useEffect(() => {\n if (!open) { setStep(0); setSelectedTypeId(null); setName(''); setScope(''); setEntities([]); setSyncWithSlack(false); setMembers([]); setMemberSearch(''); setError(null); }\n }, [open]);\n\n const selectedType = types.find((t) => t._id === selectedTypeId);\n const canAdvance = () => { switch (step) { case 0: return !!selectedTypeId; case 1: return name.trim().length > 0; default: return true; } };\n\n const addMember = (memberId: string, memberName: string, memberType: MemberType) => {\n if (members.some((m) => m.memberId === memberId)) return;\n setMembers((prev) => [...prev, { memberId, memberName, memberType, role: 'participant' }]);\n setMemberSearch('');\n };\n\n const removeMember = (memberId: string) => setMembers((prev) => prev.filter((m) => m.memberId !== memberId));\n\n const handleCreate = async () => {\n setLoading(true); setError(null);\n try {\n const entitiesWithSecrets: EntityWithSecret[] = entities.filter((e) => e.key.trim()).map((e) => ({ key: e.key.trim(), value: e.value, isSecret: e.isSecret }));\n const payload: CreateWorkspacePayload = {\n name: name.trim(), type: selectedTypeId || undefined, scope: scope.trim() || undefined,\n entitiesWithSecrets: entitiesWithSecrets.length > 0 ? entitiesWithSecrets : undefined,\n members: members.length > 0 ? members.map((m) => ({ memberId: m.memberId, memberName: m.memberName, memberType: m.memberType, role: m.role })) : undefined,\n syncWithSlack: syncWithSlack || undefined,\n };\n const ws = await apis.workspaceApi.create(payload);\n onCreated?.(ws); onClose();\n } catch (err) { setError((err as Error).message); }\n finally { setLoading(false); }\n };\n\n return (\n <Modal open={open} onClose={onClose} zIndexClass=\"z-50\" size=\"md\" closeOnBackdropClick={false} backdropClassName=\"bg-black/40\" panelClassName=\"bg-surface border-border flex h-[600px] max-h-[min(90dvh,100vh)] flex-col overflow-hidden rounded-2xl border shadow-xl\" headingId={titleId} ariaLabelledBy={titleId} ariaDescribedBy={stepDescriptionId} title=\"Nouveau Workspace\" description={<p id={stepDescriptionId} className=\"text-text-muted text-xs\">Étape {step + 1}/4 — {STEP_TITLES[step]}</p>} headerClassName=\"items-center\" closeButtonClassName=\"text-text-muted hover:text-text transition-colors\">\n {/* Step progress bar */}\n <div className=\"flex shrink-0 gap-1 px-6 pt-4\">\n {[0, 1, 2, 3].map((s) => (<div key={s} className={cn('h-1 flex-1 rounded-full transition-colors', s <= step ? 'bg-primary' : 'bg-border-light')} />))}\n </div>\n\n {/* Content */}\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n {/* Step 0: Type */}\n {step === 0 && (typesLoading ? (<div className=\"flex h-[220px] items-center justify-center\"><Loader2 size={20} className=\"text-primary animate-spin\" /></div>) : types.length === 0 ? (<p className=\"text-text-muted py-8 text-center text-sm\">Aucun type disponible</p>) : (\n <div className=\"grid grid-cols-2 gap-2\">\n {types.map((t) => (<button key={t._id} className={cn('flex flex-col items-start gap-1 rounded-xl border p-3 text-left transition-all', selectedTypeId === t._id ? 'border-primary bg-primary-light shadow-sm' : 'border-border hover:border-primary/50 hover:bg-bg')} onClick={() => setSelectedTypeId(t._id)}><span className=\"text-text text-sm font-medium\">{t.name}</span></button>))}\n </div>\n ))}\n\n {/* Step 1: Context */}\n {step === 1 && (\n <div className=\"flex flex-col gap-4\">\n <div>\n <label className=\"text-text-muted mb-1 block text-xs font-medium\">Nom du workspace</label>\n <input className=\"border-border bg-bg text-text focus:border-primary w-full rounded-lg border px-3 py-2 text-sm focus:outline-none\" placeholder={`Ex: ${selectedType?.name ?? 'Workspace'} - ...`} value={name} onChange={(e) => setName(e.target.value)} autoFocus />\n </div>\n <div>\n <label className=\"text-text-muted mb-1 block text-xs font-medium\">Scope</label>\n <input className=\"border-border bg-bg text-text focus:border-primary w-full rounded-lg border px-3 py-2 text-sm focus:outline-none\" placeholder=\"Ex: production, engineering...\" value={scope} onChange={(e) => setScope(e.target.value)} />\n </div>\n <div>\n <label className=\"text-text-muted mb-1 block text-xs font-medium\">Entités</label>\n <div className=\"flex flex-col gap-2\">\n {entities.map((e, idx) => (\n <div key={idx} className=\"flex items-center gap-2\">\n <input className=\"border-border bg-bg text-text focus:border-primary w-28 rounded border px-2 py-1 text-xs focus:outline-none\" value={e.key} onChange={(ev) => { const arr = [...entities]; arr[idx].key = ev.target.value; setEntities(arr); }} placeholder=\"Clé\" />\n <input className=\"border-border bg-bg text-text focus:border-primary flex-1 rounded border px-2 py-1 text-xs focus:outline-none\" value={e.value} onChange={(ev) => { const arr = [...entities]; arr[idx].value = ev.target.value; setEntities(arr); }} placeholder=\"Valeur\" />\n <button type=\"button\" className={`rounded p-1 transition-colors ${e.isSecret ? 'bg-warning/15 text-warning' : 'text-text-muted hover:text-text hover:bg-bg'}`} onClick={() => { const arr = [...entities]; arr[idx].isSecret = !arr[idx].isSecret; setEntities(arr); }}>{e.isSecret ? <Lock size={12} /> : <Unlock size={12} />}</button>\n <button className=\"text-text-muted hover:text-danger\" onClick={() => setEntities(entities.filter((_, i) => i !== idx))}><Trash2 size={14} /></button>\n </div>\n ))}\n <button className=\"text-primary hover:bg-primary-light flex items-center gap-1 rounded px-2 py-1 text-xs transition-colors\" onClick={() => setEntities([...entities, { key: '', value: '', isSecret: false }])}><Plus size={12} /> Ajouter une entité</button>\n </div>\n </div>\n {slackAvailable && (\n <label className={cn('border-border bg-bg hover:border-primary/50 flex cursor-pointer items-start gap-3 rounded-xl border p-3 transition-colors', syncWithSlack && 'border-primary bg-primary-light/40')}>\n <input type=\"checkbox\" className=\"accent-primary mt-0.5 h-4 w-4 shrink-0 cursor-pointer\" checked={syncWithSlack} onChange={(e) => setSyncWithSlack(e.target.checked)} />\n <div className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span className=\"text-text flex items-center gap-1.5 text-sm font-medium\"><Slack size={14} className=\"text-primary\" /> Synchroniser avec Slack</span>\n <span className=\"text-text-muted text-[11px] leading-snug\">Un canal Slack privé sera créé et les membres utilisateurs y seront invités automatiquement.</span>\n </div>\n </label>\n )}\n </div>\n )}\n\n {/* Step 2: Members */}\n {step === 2 && (\n <div className=\"flex flex-col gap-5\">\n {/* USER INVITATIONS */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <label className=\"text-text-muted flex items-center gap-1.5 text-xs font-semibold tracking-wider uppercase\"><Users size={14} className=\"text-primary\" /> Membres Utilisateurs</label>\n {invitedUsers.length > 0 && <span className=\"bg-primary-light text-primary rounded-full px-2 py-0.5 text-[10px] font-bold\">{invitedUsers.length} invité{invitedUsers.length > 1 ? 's' : ''}</span>}\n </div>\n <div className=\"relative\">\n <input type=\"search\" name=\"workspace-member-search\" autoComplete=\"off\" data-lpignore=\"true\" data-1p-ignore=\"true\" className=\"border-border bg-bg text-text focus:border-primary focus:ring-primary/10 placeholder:text-text-muted/65 w-full rounded-xl border px-3.5 py-2.5 text-sm transition-all focus:ring-2 focus:outline-none\" placeholder=\"Rechercher un membre par nom ou identifiant...\" value={memberSearch} onChange={(e) => setMemberSearch(e.target.value)} />\n {memberSearch.length >= 2 && searchingUsers && (<div className=\"absolute top-1/2 right-3.5 flex -translate-y-1/2 items-center justify-center py-3\"><Loader2 size={16} className=\"text-primary animate-spin\" /></div>)}\n {filteredUsers.length > 0 && memberSearch.length >= 2 && !searchingUsers && (\n <div className=\"border-border bg-surface divide-border/30 absolute top-full left-0 z-20 mt-1 flex max-h-48 w-full flex-col divide-y overflow-y-auto rounded-xl border shadow-md\">\n {filteredUsers.slice(0, 5).map((u) => (\n <div key={u.id} className=\"hover:bg-primary-light/50 flex cursor-pointer items-center justify-between px-3.5 py-2.5 text-xs transition-colors\" onClick={() => addMember(u.email, u.displayName, 'user')}>\n <div className=\"flex items-center gap-2.5\">\n <span className=\"bg-primary-light text-primary ring-primary/10 flex h-7 w-7 items-center justify-center rounded-full text-[10px] font-semibold ring-1\">{getInitials(u.displayName)}</span>\n <div className=\"flex flex-col\"><span className=\"text-text font-medium\">{u.displayName}</span><span className=\"text-text-muted text-[10px]\">{u.email}</span></div>\n </div>\n <Plus size={14} className=\"text-primary/75\" />\n </div>\n ))}\n </div>\n )}\n </div>\n <div className=\"mt-1 flex flex-col gap-1.5\">\n {invitedUsers.length === 0 ? (\n <div className=\"bg-bg/40 border-border/40 flex items-center justify-center rounded-xl border border-dashed py-4 text-center\"><p className=\"text-text-muted text-xs italic\">Aucun utilisateur invité pour le moment.</p></div>\n ) : invitedUsers.map((m) => (\n <div key={m.memberId} className=\"bg-bg-subtle hover:bg-bg border-border/30 flex items-center gap-3 rounded-xl border p-2.5 transition-all duration-200\">\n <MemberAvatar memberName={m.memberName} memberType=\"user\" avatarUrl={avatarMap[m.memberId.toLowerCase()]} size=\"sm\" variant={m.role === 'owner' ? 'owner' : 'primary'} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-text truncate text-xs font-semibold\">{m.memberName}</div>\n <div className=\"text-text-muted truncate text-[10px]\">{m.memberId}</div>\n </div>\n <div className=\"flex items-center gap-2\">\n <select className=\"border-border bg-surface text-text focus:border-primary rounded-lg border px-2 py-1 text-[10px] font-medium focus:outline-none\" value={m.role} onChange={(e) => setMembers(members.map((x) => x.memberId === m.memberId ? { ...x, role: e.target.value } : x))}>\n <option value=\"owner\">Propriétaire</option><option value=\"participant\">Participant</option><option value=\"viewer\">Observateur</option>\n </select>\n <button type=\"button\" className=\"text-text-muted hover:text-danger hover:bg-danger-light/20 rounded-lg p-1.5 transition-colors\" onClick={() => removeMember(m.memberId)}><X size={14} /></button>\n </div>\n </div>\n ))}\n </div>\n </div>\n {/* AGENT INVITATIONS */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <label className=\"text-text-muted flex items-center gap-1.5 text-xs font-semibold tracking-wider uppercase\"><Brain size={14} className=\"text-primary\" /> Agents IA</label>\n <span className=\"bg-primary-light text-primary rounded-full px-2 py-0.5 text-[10px] font-bold\">{invitedAgents.length}/{agents.length}</span>\n </div>\n <div className=\"relative\">\n <div className={cn('border-border bg-bg focus-within:border-primary focus-within:ring-primary/10 flex min-h-[44px] cursor-text flex-wrap items-center gap-1.5 rounded-xl border px-3 py-1.5 text-sm transition-all focus-within:ring-2', agentSearchFocused && 'border-primary ring-primary/10 ring-2')} onClick={() => agentSearchInputRef.current?.focus()}>\n {invitedAgents.map((m) => (\n <span key={m.memberId} className=\"bg-primary-light/50 border-primary/20 text-primary flex items-center gap-1 rounded-lg border py-1 pr-1.5 pl-2 text-xs font-medium\">\n <Brain size={10} className=\"text-primary/80\" />{m.memberName}\n <button type=\"button\" className=\"hover:bg-primary-light text-primary rounded-md p-0.5 transition-colors\" onClick={(e) => { e.stopPropagation(); removeMember(m.memberId); }}><X size={10} /></button>\n </span>\n ))}\n <input ref={agentSearchInputRef} type=\"search\" name=\"workspace-agent-search\" autoComplete=\"off\" data-lpignore=\"true\" data-1p-ignore=\"true\" className=\"text-text placeholder:text-text-muted/65 min-w-[100px] flex-1 border-none bg-transparent p-0.5 text-xs focus:ring-0 focus:outline-none\" placeholder={invitedAgents.length === 0 ? 'Rechercher et inviter des agents...' : ''} value={agentSearch} onChange={(e) => { setAgentSearch(e.target.value); setShowAgentDropdown(true); }} onFocus={() => { setAgentSearchFocused(true); setShowAgentDropdown(true); }} onBlur={() => setTimeout(() => { setAgentSearchFocused(false); setShowAgentDropdown(false); }, 200)} />\n </div>\n {showAgentDropdown && (\n <div className=\"border-border bg-surface divide-border/30 absolute z-20 mt-1.5 flex max-h-48 w-full flex-col divide-y overflow-y-auto rounded-xl border shadow-lg\">\n {unselectedAgents.length === 0 ? (<p className=\"text-text-muted p-3 text-center text-xs italic\">{agentSearch.trim().length > 0 ? 'Aucun agent ne correspond.' : 'Tous les agents ont été invités.'}</p>) : unselectedAgents.map((agent) => (\n <div key={agent.agentId} className=\"hover:bg-primary-light/50 flex cursor-pointer items-center justify-between px-3.5 py-2.5 text-xs transition-colors\" onClick={() => { addMember(agent.agentId, agent.agentName, 'agent'); setAgentSearch(''); }}>\n <div className=\"flex items-center gap-2.5\"><span className=\"bg-surface border-border flex h-7 w-7 items-center justify-center rounded-full border\"><Brain size={12} className=\"text-primary\" /></span><span className=\"text-text font-medium\">{agent.agentName}</span></div>\n <Plus size={14} className=\"text-primary/75\" />\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n )}\n\n {/* Step 3: Confirmation */}\n {step === 3 && (\n <div className=\"flex flex-col gap-3\">\n <div className=\"bg-bg rounded-xl p-4\">\n <div className=\"mb-3 flex items-center gap-2\"><div><div className=\"text-text text-sm font-semibold\">{name || 'Sans nom'}</div><div className=\"text-text-muted text-xs\">{selectedType?.name ?? '—'} • {scope || 'Sans scope'}</div></div></div>\n {entities.filter((e) => e.key.trim() && e.value.trim()).length > 0 && (\n <div className=\"mb-2 flex flex-wrap gap-1\">\n {entities.filter((e) => e.key.trim() && e.value.trim()).map((e, i) => (\n <span key={i} className=\"border-border inline-flex items-center gap-1 rounded border px-2 py-0.5 text-xs\">\n {e.isSecret && <Lock size={10} className=\"text-warning shrink-0\" />}\n <span className=\"text-text-muted mr-1 font-medium\">{e.key}:</span>\n <span className=\"text-text\">{e.isSecret ? '••••••' : e.value}</span>\n </span>\n ))}\n </div>\n )}\n <div className=\"text-text-muted flex items-center gap-3 text-xs\">\n <span className=\"flex items-center gap-1\"><Users size={12} /> {members.length} membre{members.length > 1 ? 's' : ''}</span>\n {syncWithSlack && <span className=\"text-primary flex items-center gap-1 font-medium\"><Slack size={12} /> Synchronisé avec Slack</span>}\n </div>\n {members.length > 0 && (\n <div className=\"border-border/30 mt-3 border-t pt-3\">\n <span className=\"text-text-muted mb-2 block text-[10px] font-bold tracking-wider uppercase\">Membres et Agents invités ({members.length})</span>\n <div className=\"flex max-h-40 flex-col gap-1.5 overflow-y-auto pr-1\">\n {members.map((m) => (\n <div key={m.memberId} className=\"bg-bg-subtle/50 flex items-center gap-2.5 rounded-lg p-2 text-xs\">\n <MemberAvatar memberName={m.memberName} memberType={m.memberType} avatarUrl={m.memberType === 'user' ? avatarMap[m.memberId.toLowerCase()] : undefined} size=\"xs\" variant={m.role === 'owner' ? 'owner' : 'primary'} />\n <div className=\"min-w-0 flex-1\"><span className=\"text-text truncate font-medium\">{m.memberName}</span><span className=\"text-text-muted ml-2 text-[10px]\">({m.memberType === 'agent' ? 'Agent' : m.role === 'owner' ? 'Propriétaire' : m.role === 'viewer' ? 'Observateur' : 'Participant'})</span></div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n {error && <div className=\"bg-danger-light text-danger rounded-lg px-3 py-2 text-xs\">{error}</div>}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"border-border flex shrink-0 items-center justify-between border-t px-6 py-4\">\n <button type=\"button\" className={cn('text-text-muted hover:text-text flex items-center gap-1 text-sm transition-colors', step === 0 && 'invisible')} onClick={() => setStep((s) => s - 1)} disabled={loading}><ArrowLeft size={14} /> Précédent</button>\n {step < 3 ? (\n <button type=\"button\" className={cn('flex items-center gap-1 rounded-lg px-4 py-2 text-sm font-medium text-white transition-colors', canAdvance() ? 'bg-primary hover:bg-primary-hover' : 'bg-border cursor-not-allowed')} onClick={() => setStep((s) => s + 1)} disabled={!canAdvance()}>Suivant <ArrowRight size={14} /></button>\n ) : (\n <button type=\"button\" className=\"bg-primary hover:bg-primary-hover flex items-center gap-1 rounded-lg px-4 py-2 text-sm font-medium text-white transition-colors disabled:opacity-50\" onClick={handleCreate} disabled={loading}>{loading ? <Loader2 size={14} className=\"animate-spin\" /> : <Check size={14} />} Créer le workspace</button>\n )}\n </div>\n </Modal>\n );\n};\n","import React, { useState, useEffect, useMemo, useId, useRef } from 'react';\nimport { X, Loader2, Lock, MessageSquare, Search } from 'lucide-react';\nimport { cn } from './ui/cn';\nimport { useWorkspaceContext } from '../provider';\nimport { useWorkspaceApi } from '../hooks/useWorkspaceApi';\nimport type { CreateWorkspacePayload } from '../types';\nimport { getInitials } from '../utils/constants';\nimport { Modal } from './ui/Modal';\nimport { MemberAvatar } from './MemberAvatar';\n\ninterface CreatePrivateWorkspaceModalProps {\n open: boolean;\n onClose: () => void;\n onCreated?: (workspace: unknown) => void;\n}\n\nexport const CreatePrivateWorkspaceModal: React.FC<CreatePrivateWorkspaceModalProps> = ({ open, onClose, onCreated }) => {\n const titleId = useId();\n const { config } = useWorkspaceContext();\n const apis = useWorkspaceApi();\n\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [search, setSearch] = useState('');\n const [searchResults, setSearchResults] = useState<{ id: string; email: string; displayName: string; avatarUrl?: string }[]>([]);\n const [searchingUsers, setSearchingUsers] = useState(false);\n const [selectedUser, setSelectedUser] = useState<{ id: string; email: string; displayName: string; avatarUrl?: string } | null>(null);\n const searchInputRef = useRef<HTMLInputElement>(null);\n\n // User search via injected searchUsers\n useEffect(() => {\n if (search.length < 2 || !config.searchUsers) { setSearchResults([]); return; }\n let cancelled = false;\n setSearchingUsers(true);\n config.searchUsers(search).then((r) => { if (!cancelled) setSearchResults(r); }).catch(() => { if (!cancelled) setSearchResults([]); }).finally(() => { if (!cancelled) setSearchingUsers(false); });\n return () => { cancelled = true; };\n }, [search]);\n\n const filteredUsers = useMemo(() => searchResults.filter((u) => u.email !== config.currentUserId), [searchResults, config.currentUserId]);\n\n // Reset on close\n useEffect(() => {\n if (!open) { setSearch(''); setSelectedUser(null); setError(null); setLoading(false); }\n else { setTimeout(() => searchInputRef.current?.focus(), 100); }\n }, [open]);\n\n const handleCreate = async () => {\n if (!selectedUser || !config.currentUserId) return;\n setLoading(true); setError(null);\n try {\n const payload: CreateWorkspacePayload = {\n name: `${config.currentUserName ?? config.currentUserId} ↔ ${selectedUser.displayName}`,\n isPrivate: true,\n members: [{ memberId: selectedUser.email, memberName: selectedUser.displayName, memberType: 'user', role: 'participant' }],\n };\n const ws = await apis.workspaceApi.create(payload);\n onCreated?.(ws); onClose();\n } catch (err) { setError((err as Error).message); }\n finally { setLoading(false); }\n };\n\n return (\n <Modal open={open} onClose={onClose} zIndexClass=\"z-50\" size=\"sm\" closeOnBackdropClick={false} backdropClassName=\"bg-black/40\" panelClassName=\"bg-surface border-border flex max-h-[min(70dvh,500px)] flex-col overflow-hidden rounded-2xl border shadow-xl\" headingId={titleId} ariaLabelledBy={titleId} title=\"Conversation Privée\" description={<p className=\"text-text-muted text-xs\">Choisissez un utilisateur pour démarrer une conversation privée.</p>} headerClassName=\"items-center\" closeButtonClassName=\"text-text-muted hover:text-text transition-colors\" titleIcon={<span className=\"bg-primary-light text-primary flex h-8 w-8 items-center justify-center rounded-lg\"><Lock size={16} /></span>}>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n {/* Selected user */}\n {selectedUser ? (\n <div className=\"mb-4\">\n <div className=\"bg-primary-light/30 border-primary/20 flex items-center gap-3 rounded-xl border p-3\">\n <MemberAvatar memberName={selectedUser.displayName} memberType=\"user\" avatarUrl={selectedUser.avatarUrl} size=\"md\" variant=\"primary\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-text text-sm font-semibold\">{selectedUser.displayName}</div>\n <div className=\"text-text-muted text-xs\">{selectedUser.email}</div>\n </div>\n <button type=\"button\" className=\"text-text-muted hover:text-danger rounded p-1 transition-colors\" onClick={() => setSelectedUser(null)}><X size={16} /></button>\n </div>\n </div>\n ) : (\n <div>\n <div className=\"relative\">\n <Search size={14} className=\"text-text-muted absolute top-1/2 left-3 -translate-y-1/2\" />\n <input ref={searchInputRef} type=\"search\" autoComplete=\"off\" data-lpignore=\"true\" data-1p-ignore=\"true\" className=\"border-border bg-bg text-text focus:border-primary focus:ring-primary/10 placeholder:text-text-muted/65 w-full rounded-xl border py-2.5 pr-3 pl-9 text-sm transition-all focus:ring-2 focus:outline-none\" placeholder=\"Rechercher un utilisateur...\" value={search} onChange={(e) => setSearch(e.target.value)} />\n {search.length >= 2 && searchingUsers && <div className=\"absolute top-1/2 right-3 -translate-y-1/2\"><Loader2 size={16} className=\"text-primary animate-spin\" /></div>}\n </div>\n {search.length >= 2 && !searchingUsers && filteredUsers.length > 0 && (\n <div className=\"border-border bg-surface mt-2 flex max-h-48 flex-col overflow-y-auto rounded-xl border shadow-sm\">\n {filteredUsers.slice(0, 8).map((u) => (\n <button key={u.id} type=\"button\" className=\"hover:bg-primary-light/50 flex items-center gap-3 px-3.5 py-2.5 text-left transition-colors first:rounded-t-xl last:rounded-b-xl\" onClick={() => { setSelectedUser(u); setSearch(''); }}>\n <span className=\"bg-primary-light text-primary flex h-8 w-8 items-center justify-center rounded-full text-xs font-semibold\">{getInitials(u.displayName)}</span>\n <div className=\"min-w-0 flex-1\"><div className=\"text-text text-sm font-medium\">{u.displayName}</div><div className=\"text-text-muted text-[11px]\">{u.email}</div></div>\n </button>\n ))}\n </div>\n )}\n {search.length >= 2 && !searchingUsers && filteredUsers.length === 0 && <p className=\"text-text-muted mt-3 text-center text-xs italic\">Aucun utilisateur trouvé.</p>}\n {search.length < 2 && <p className=\"text-text-muted mt-4 text-center text-xs\">Saisissez au moins 2 caractères pour rechercher.</p>}\n </div>\n )}\n {error && <div className=\"bg-danger-light text-danger mt-3 rounded-lg px-3 py-2 text-xs\">{error}</div>}\n </div>\n <div className=\"border-border flex shrink-0 items-center justify-end gap-2 border-t px-6 py-4\">\n <button type=\"button\" className=\"text-text-muted hover:text-text text-sm transition-colors\" onClick={onClose} disabled={loading}>Annuler</button>\n <button type=\"button\" className={cn('flex items-center gap-1.5 rounded-lg px-4 py-2 text-sm font-medium text-white transition-colors disabled:opacity-50', selectedUser ? 'bg-primary hover:bg-primary-hover' : 'bg-border cursor-not-allowed')} onClick={handleCreate} disabled={!selectedUser || loading}>\n {loading ? <Loader2 size={14} className=\"animate-spin\" /> : <MessageSquare size={14} />} Démarrer\n </button>\n </div>\n </Modal>\n );\n};\n","'use client';\n\nimport React, { useState } from 'react';\nimport { Edit2, Check, X, Brain, Plus, Trash2, Lock, Unlock } from 'lucide-react';\nimport type { Workspace, WorkspaceType, EntityWithSecret } from '../types';\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction toEditableEntities(ws: Workspace) {\n return (ws.entitiesWithSecrets ?? []).map((e) => ({ key: e.key, value: e.value, isSecret: e.isSecret }));\n}\n\nfunction getDisplayEntities(ws: Workspace) {\n return ws.entitiesWithSecrets ?? [];\n}\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface ContextPanelProps {\n workspace: Workspace;\n types?: WorkspaceType[];\n onUpdateContext?: (updates: Partial<{\n name: string; type: string; scope: string; entitiesWithSecrets: EntityWithSecret[];\n }>) => void;\n readonly?: boolean;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport const ContextPanel: React.FC<ContextPanelProps> = ({\n workspace, types = [], onUpdateContext, readonly,\n}) => {\n const [editing, setEditing] = useState(false);\n const [editName, setEditName] = useState(workspace.name ?? '');\n const [editType, setEditType] = useState('');\n const [editScope, setEditScope] = useState(workspace.scope ?? '');\n const [editEntities, setEditEntities] = useState(toEditableEntities(workspace));\n\n const currentTypeId =\n typeof workspace.type === 'object' && workspace.type !== null\n ? (workspace.type as WorkspaceType)._id\n : (workspace.type as string | undefined);\n\n const typeName =\n typeof workspace.type === 'object' && workspace.type !== null\n ? (workspace.type as WorkspaceType).name\n : (workspace.type as string | undefined);\n\n const handleEdit = () => {\n setEditName(workspace.name ?? '');\n setEditType(currentTypeId ?? '');\n setEditScope(workspace.scope ?? '');\n setEditEntities(toEditableEntities(workspace));\n setEditing(true);\n };\n\n const handleSave = () => {\n const entitiesWithSecrets: EntityWithSecret[] = editEntities\n .filter((e) => e.key.trim())\n .map((e) => ({ key: e.key.trim(), value: e.value, isSecret: e.isSecret }));\n onUpdateContext?.({ name: editName.trim() || undefined, type: editType || undefined, scope: editScope, entitiesWithSecrets });\n setEditing(false);\n };\n\n const handleCancel = () => {\n setEditName(workspace.name ?? '');\n setEditType(currentTypeId ?? '');\n setEditScope(workspace.scope ?? '');\n setEditEntities(toEditableEntities(workspace));\n setEditing(false);\n };\n\n const handleTypeChange = (id: string) => {\n setEditType(id);\n const sel = types.find((t) => t._id === id);\n if (sel?.entitiesWithSecrets?.length) {\n setEditEntities(sel.entitiesWithSecrets.map((e) => ({ key: e.key, value: e.value, isSecret: e.isSecret })));\n }\n };\n\n const displayEntities = getDisplayEntities(workspace);\n\n return (\n <div className=\"flex flex-col gap-3\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[var(--color-text-muted,#94a3b8)] text-xs font-semibold tracking-wider uppercase\">Contexte</span>\n {!editing && !readonly && (\n <button className=\"text-[var(--color-text-muted,#94a3b8)] hover:text-[var(--color-primary,#3b82f6)] flex items-center gap-1 text-xs transition-colors\" onClick={handleEdit}>\n <Edit2 size={11} /> Modifier\n </button>\n )}\n </div>\n\n {/* Name */}\n <div className=\"bg-[var(--color-bg,#f8fafc)] flex items-center gap-2 rounded-lg p-2\">\n <span className=\"text-[var(--color-text-muted,#94a3b8)] text-xs\">Nom :</span>\n {editing ? (\n <input className=\"border-[var(--color-border,#e2e8f0)] bg-[var(--color-surface,#fff)] text-[var(--color-text,#0f172a)] focus:border-[var(--color-primary,#3b82f6)] w-48 rounded border px-2 py-1 text-xs focus:outline-none\"\n value={editName} onChange={(e) => setEditName(e.target.value)} placeholder=\"Nom du workspace\" />\n ) : (\n <span className=\"text-[var(--color-text,#0f172a)] text-sm font-medium\">{workspace.name ?? '—'}</span>\n )}\n </div>\n\n {/* Type */}\n <div className=\"bg-[var(--color-bg,#f8fafc)] flex items-center gap-2 rounded-lg p-2\">\n <span className=\"text-[var(--color-text-muted,#94a3b8)] text-xs\">Type :</span>\n {editing && types.length > 0 ? (\n <select className=\"border-[var(--color-border,#e2e8f0)] bg-[var(--color-surface,#fff)] text-[var(--color-text,#0f172a)] focus:border-[var(--color-primary,#3b82f6)] rounded border px-2 py-1 text-xs focus:outline-none\"\n value={editType} onChange={(e) => handleTypeChange(e.target.value)}>\n <option value=\"\">— Aucun —</option>\n {types.map((t) => <option key={t._id} value={t._id}>{t.name}</option>)}\n </select>\n ) : (\n <span className=\"text-[var(--color-text,#0f172a)] text-sm font-medium\">{typeName ?? '—'}</span>\n )}\n </div>\n\n {/* Scope */}\n <div className=\"bg-[var(--color-bg,#f8fafc)] flex items-center gap-2 rounded-lg p-2\">\n <span className=\"text-[var(--color-text-muted,#94a3b8)] text-xs\">Scope :</span>\n {editing ? (\n <input className=\"border-[var(--color-border,#e2e8f0)] bg-[var(--color-surface,#fff)] text-[var(--color-text,#0f172a)] focus:border-[var(--color-primary,#3b82f6)] w-36 rounded border px-2 py-1 text-xs focus:outline-none\"\n value={editScope} onChange={(e) => setEditScope(e.target.value)} placeholder=\"Saisir...\" />\n ) : (\n <span className=\"text-[var(--color-text,#0f172a)] text-sm font-medium\">{workspace.scope ?? '—'}</span>\n )}\n </div>\n\n {/* Entities */}\n <div>\n <span className=\"text-[var(--color-text-muted,#94a3b8)] text-xs\">Entités</span>\n {editing ? (\n <div className=\"mt-1 flex flex-col gap-1\">\n {editEntities.map((e, idx) => (\n <div key={idx} className=\"flex items-center gap-1\">\n <input className=\"border-[var(--color-border,#e2e8f0)] bg-[var(--color-surface,#fff)] text-[var(--color-text,#0f172a)] focus:border-[var(--color-primary,#3b82f6)] w-20 rounded border px-2 py-1 text-xs focus:outline-none\"\n value={e.key} onChange={(ev) => { const arr = [...editEntities]; arr[idx].key = ev.target.value; setEditEntities(arr); }} placeholder=\"Clé\" />\n <input className=\"border-[var(--color-border,#e2e8f0)] bg-[var(--color-surface,#fff)] text-[var(--color-text,#0f172a)] focus:border-[var(--color-primary,#3b82f6)] flex-1 rounded border px-2 py-1 text-xs focus:outline-none\"\n value={e.value} onChange={(ev) => { const arr = [...editEntities]; arr[idx].value = ev.target.value; setEditEntities(arr); }} placeholder=\"Valeur\" />\n <button type=\"button\"\n className={`rounded p-0.5 transition-colors ${e.isSecret ? 'bg-amber-100 text-amber-600 dark:bg-amber-500/10 dark:text-amber-400' : 'text-[var(--color-text-muted,#94a3b8)] hover:text-[var(--color-text,#0f172a)] hover:bg-[var(--color-bg,#f8fafc)]'}`}\n onClick={() => { const arr = [...editEntities]; arr[idx].isSecret = !arr[idx].isSecret; setEditEntities(arr); }}\n title={e.isSecret ? 'Secret (cliquer pour rendre public)' : 'Public (cliquer pour rendre secret)'}>\n {e.isSecret ? <Lock size={12} /> : <Unlock size={12} />}\n </button>\n <button className=\"text-red-500 hover:bg-red-50 dark:hover:bg-red-500/10 rounded p-0.5 transition-colors\"\n onClick={() => setEditEntities(editEntities.filter((_, i) => i !== idx))}>\n <Trash2 size={12} />\n </button>\n </div>\n ))}\n <button className=\"text-[var(--color-primary,#3b82f6)] hover:bg-[var(--color-primary-light,#eff6ff)] mt-1 flex items-center gap-1 rounded px-2 py-1 text-xs transition-colors\"\n onClick={() => setEditEntities([...editEntities, { key: '', value: '', isSecret: false }])}>\n <Plus size={12} /> Ajouter\n </button>\n </div>\n ) : (\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {displayEntities.map((ent) => (\n <span key={ent.key} className=\"bg-[var(--color-bg,#f8fafc)] border-[var(--color-border,#e2e8f0)] inline-flex items-center gap-1 rounded border px-2 py-0.5 text-xs\">\n {ent.isSecret && <Lock size={10} className=\"text-amber-500 shrink-0\" />}\n <span className=\"text-[var(--color-text-muted,#94a3b8)] mr-1 font-medium\">{ent.key}:</span>\n <span className=\"text-[var(--color-text,#0f172a)]\">{ent.isSecret ? '••••••' : ent.value}</span>\n </span>\n ))}\n {displayEntities.length === 0 && <span className=\"text-[var(--color-text-muted,#94a3b8)] text-xs\">Aucune entité</span>}\n </div>\n )}\n </div>\n\n {editing && (\n <div className=\"flex justify-end gap-2\">\n <button className=\"text-[var(--color-text-muted,#94a3b8)] hover:text-[var(--color-text,#0f172a)] flex items-center gap-1 text-xs transition-colors\" onClick={handleCancel}>\n <X size={11} /> Annuler\n </button>\n <button className=\"text-emerald-600 hover:bg-emerald-50 dark:hover:bg-emerald-500/10 flex items-center gap-1 rounded px-2 py-1 text-xs font-medium transition-colors\" onClick={handleSave}>\n <Check size={11} /> Enregistrer\n </button>\n </div>\n )}\n\n {/* RAG note */}\n <div className=\"text-[var(--color-text-muted,#94a3b8)] bg-[var(--color-bg,#f8fafc)] mt-2 flex items-center gap-2 rounded-lg p-2 text-xs italic\">\n <Brain size={14} /> Ce contexte est injecté dans les requêtes IA (RAG)\n </div>\n </div>\n );\n};\n","import React, { useState, useEffect, useMemo } from 'react';\nimport { UserPlus, Crown, Eye, Users, X, Search, Plus, Brain, Loader2, Check } from 'lucide-react';\nimport type { WorkspaceMember, MemberRole, MemberType, WorkspaceAgent, AvatarUser } from '../types';\nimport { useWorkspaceContext } from '../provider';\nimport { useWorkspaceApi } from '../hooks/useWorkspaceApi';\nimport { getInitials, ROLE_LABELS } from '../utils/constants';\nimport { MemberAvatar } from './MemberAvatar';\n\ninterface MembersPanelProps {\n members: WorkspaceMember[];\n avatarUsers?: AvatarUser[];\n onAddMember?: (payload: { memberId: string; memberName: string; memberType: MemberType; role?: MemberRole }) => void;\n onRemoveMember?: (memberId: string) => void;\n onUpdateRole?: (memberId: string, role: MemberRole) => void;\n readonly?: boolean;\n /** Hide the agents section entirely (e.g. for private workspaces between two users) */\n hideAgents?: boolean;\n}\n\nconst roleIcon = (role: MemberRole) => {\n switch (role) {\n case 'owner': return <Crown size={11} className=\"text-warning\" />;\n case 'viewer': return <Eye size={11} className=\"text-text-muted\" />;\n default: return <Users size={11} className=\"text-primary\" />;\n }\n};\n\nexport const MembersPanel: React.FC<MembersPanelProps> = ({\n members, avatarUsers, onAddMember, onRemoveMember, onUpdateRole, readonly, hideAgents = false,\n}) => {\n const { config } = useWorkspaceContext();\n const apis = useWorkspaceApi();\n const [showUserSearch, setShowUserSearch] = useState(false);\n const [search, setSearch] = useState('');\n const [searchResults, setSearchResults] = useState<{ id: string; email: string; displayName: string; avatarUrl?: string }[]>([]);\n const [searchingUsers, setSearchingUsers] = useState(false);\n const [allAgents, setAllAgents] = useState<WorkspaceAgent[]>([]);\n\n useEffect(() => {\n apis.agentApi.list().then(setAllAgents).catch(() => setAllAgents([]));\n }, []);\n\n // User search via injected searchUsers callback\n useEffect(() => {\n if (search.length < 2 || !showUserSearch || !config.searchUsers) {\n setSearchResults([]);\n return;\n }\n let cancelled = false;\n setSearchingUsers(true);\n config.searchUsers(search).then((results) => {\n if (!cancelled) setSearchResults(results);\n }).catch(() => {\n if (!cancelled) setSearchResults([]);\n }).finally(() => {\n if (!cancelled) setSearchingUsers(false);\n });\n return () => { cancelled = true; };\n }, [search, showUserSearch, config.searchUsers]);\n\n const filteredUsers = useMemo(() => {\n return searchResults.filter(\n (u) => u.email !== config.currentUserId && !members.some((m) => m.memberId === u.email)\n );\n }, [searchResults, members, config.currentUserId]);\n\n const userMembers = members.filter((m) => m.memberType === 'user');\n const agentMembers = members.filter((m) => m.memberType === 'agent');\n const agentMemberIds = useMemo(() => new Set(agentMembers.map((m) => m.memberId)), [agentMembers]);\n const agentMemberIdMap = useMemo(() => new Map(agentMembers.map((m) => [m.memberId, m._id])), [agentMembers]);\n\n const handleAddUser = (user: { email: string; displayName: string }) => {\n onAddMember?.({ memberId: user.email, memberName: user.displayName, memberType: 'user', role: 'participant' });\n setSearch('');\n setShowUserSearch(false);\n };\n\n const handleAddAgent = (agent: WorkspaceAgent) => {\n onAddMember?.({ memberId: agent.agentId, memberName: agent.agentName, memberType: 'agent', role: 'participant' });\n };\n\n return (\n <div className=\"flex flex-col gap-4\">\n {/* Users section */}\n <div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-muted flex items-center gap-1.5 text-xs font-semibold tracking-wider uppercase\">\n <Users size={14} className=\"text-primary\" /> Utilisateurs\n </span>\n <span className=\"flex items-center gap-1\">\n <span className=\"bg-primary-light text-primary rounded-full px-2 py-0.5 text-[10px] font-bold\">{userMembers.length}</span>\n {!readonly && (\n <button className=\"text-primary hover:bg-primary-light flex items-center gap-1 rounded px-2 py-1 text-xs transition-colors\" onClick={() => setShowUserSearch(!showUserSearch)}>\n <UserPlus size={12} /> Inviter\n </button>\n )}\n </span>\n </div>\n {showUserSearch && (\n <>\n <div className=\"relative mt-2\">\n <Search size={12} className=\"text-text-muted absolute top-1/2 left-2 -translate-y-1/2\" />\n <input className=\"border-border bg-surface text-text focus:border-primary w-full rounded-lg border py-1.5 pr-2 pl-7 text-xs focus:outline-none\" placeholder=\"Rechercher par nom ou email...\" value={search} onChange={(e) => setSearch(e.target.value)} autoFocus />\n </div>\n {search.length >= 2 && searchingUsers && (\n <div className=\"flex items-center justify-center py-3\"><Loader2 size={14} className=\"text-primary animate-spin\" /></div>\n )}\n {filteredUsers.length > 0 && !searchingUsers && (\n <div className=\"bg-surface border-border mt-1 flex flex-col rounded-lg border shadow-sm\">\n {filteredUsers.map((u) => (\n <div key={u.id} className=\"hover:bg-primary-light flex cursor-pointer items-center gap-2 px-3 py-2 text-xs transition-colors first:rounded-t-lg last:rounded-b-lg\" onClick={() => handleAddUser(u)}>\n <span className=\"bg-primary-light text-primary flex h-6 w-6 items-center justify-center rounded-full text-[10px] font-semibold\">{getInitials(u.displayName)}</span>\n <span className=\"text-text\">{u.displayName}</span>\n <Plus size={12} className=\"text-primary ml-auto\" />\n </div>\n ))}\n </div>\n )}\n </>\n )}\n <div className=\"mt-2 flex flex-col gap-1\">\n {userMembers.map((m) => (\n <div key={m._id} className=\"bg-bg group flex items-center gap-2 rounded-lg p-2\">\n <MemberAvatar memberName={m.memberName} memberType={m.memberType} avatarUrl={avatarUsers?.find((u) => u.email.toLowerCase() === m.memberId.toLowerCase())?.avatarUrl} size=\"sm\" variant={m.role === 'owner' ? 'owner' : 'primary'} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-text truncate text-xs font-medium\">{m.memberName}</div>\n <div className=\"text-text-muted flex items-center gap-1 text-[10px]\">{roleIcon(m.role)} {ROLE_LABELS[m.role] ?? m.role}</div>\n </div>\n {!(readonly || (m.role === 'owner' && members.filter((x) => x.role === 'owner').length === 1)) && (\n <select className=\"border-border bg-surface text-text-muted rounded border px-1 py-0.5 text-[10px] opacity-0 transition-opacity group-hover:opacity-100 focus:opacity-100\" value={m.role} onChange={(e) => { e.stopPropagation(); onUpdateRole?.(m._id, e.target.value as MemberRole); }} disabled={readonly || (m.role === 'owner' && members.filter((x) => x.role === 'owner').length === 1)}>\n <option value=\"owner\">Propriétaire</option>\n <option value=\"participant\">Participant</option>\n <option value=\"viewer\">Observateur</option>\n </select>\n )}\n {m.role !== 'owner' && !readonly && (\n <button className=\"text-text-muted hover:text-danger rounded p-0.5 opacity-0 transition-all group-hover:opacity-100\" onClick={(e) => { e.stopPropagation(); onRemoveMember?.(m._id); }}>\n <X size={14} />\n </button>\n )}\n </div>\n ))}\n </div>\n </div>\n {/* Agents section */}\n {!hideAgents && (\n <div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-muted flex items-center gap-1.5 text-xs font-semibold tracking-wider uppercase\">\n <Brain size={14} className=\"text-primary\" /> Agents IA\n </span>\n <span className=\"bg-primary-light text-primary rounded-full px-2 py-0.5 text-[10px] font-bold\">{agentMembers.length}/{allAgents.length}</span>\n </div>\n <div className=\"mt-2 flex flex-col gap-1\">\n {allAgents.map((agent) => {\n const isMember = agentMemberIds.has(agent.agentId);\n const memberId = agentMemberIdMap.get(agent.agentId);\n return (\n <div key={agent.agentId} className=\"bg-bg group flex items-center gap-2 rounded-lg p-2\">\n <span className=\"bg-surface border-border flex h-7 w-7 items-center justify-center rounded-full border\"><Brain size={14} className=\"text-primary\" /></span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-text truncate text-xs font-medium\">{agent.agentName}</div>\n <div className=\"text-text-muted text-[10px]\">Agent IA</div>\n </div>\n {!readonly && (\n isMember ? (\n <button className=\"relative flex h-6 w-6 items-center justify-center rounded-full transition-colors\" onClick={(e) => { e.stopPropagation(); if (memberId) onRemoveMember?.(memberId); }}>\n <Check size={14} className=\"text-success absolute transition-opacity group-hover:opacity-0\" />\n <X size={14} className=\"text-danger absolute opacity-0 transition-opacity group-hover:opacity-100\" />\n </button>\n ) : (\n <button className=\"text-text-muted hover:text-primary hover:bg-primary-light flex h-6 w-6 items-center justify-center rounded-full transition-colors\" onClick={(e) => { e.stopPropagation(); handleAddAgent(agent); }}>\n <Plus size={14} />\n </button>\n )\n )}\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n};\n","\n\nimport React, { useState, useEffect, useCallback } from 'react';\nimport {\n RefreshCw,\n ExternalLink,\n Info,\n CheckCircle2,\n XCircle,\n Loader2,\n Hash,\n AlertTriangle,\n} from 'lucide-react';\nimport { type SyncLink, type SyncStatus } from '../api';\nimport { useWorkspaceApi } from '../hooks/useWorkspaceApi';\nimport { cn } from './ui/cn';\n\n// ─── Slack brand color ────────────────────────────────────────────────────────\nconst SLACK_COLOR = '#4A154B';\n\n// ─── Sync info texts ──────────────────────────────────────────────────────────\nconst SYNC_INFO = {\n title: 'Comment fonctionne la synchronisation ?',\n description:\n 'La synchronisation bidirectionnelle relie ce workspace à un canal externe (Slack, Teams…). Les messages, fichiers et membres sont automatiquement répliqués dans les deux sens.',\n features: [\n 'Messages envoyés depuis le workspace sont répliqués vers Slack',\n 'Messages envoyés depuis Slack sont répliqués vers le workspace',\n 'Fichiers et artefacts sont synchronisés dans les deux sens',\n 'Les nouveaux membres ajoutés au workspace sont invités dans Slack',\n 'Les mentions Slack sont converties en mentions workspace',\n 'Désactiver la synchronisation conserve le canal Slack ouvert (pas d\\'archivage)',\n ],\n limitations: [\n 'Les messages initialement postés par un utilisateur réel dans Slack ne peuvent pas être modifiés/supprimés depuis le workspace (limitation API Slack)',\n 'Le bot Slack doit avoir les scopes nécessaires (channels:*, chat:write, files:read, users:read.email)',\n 'Le listener Socket Mode doit tourner sur une seule instance en production',\n 'Seuls les utilisateurs ayant le même email dans Slack et le workspace sont synchronisés',\n ],\n};\n\ninterface SyncPanelProps {\n workspaceId: string;\n syncWithSlack?: boolean;\n isOwner: boolean;\n /** Whether Slack sync is configured and enabled on the server */\n slackConfigured?: boolean;\n /** Called after a sync toggle — the parent page will get the updated workspace via real-time. */\n onToggleSync?: (provider: string, enabled: boolean) => Promise<void>;\n}\n\nexport const SyncPanel: React.FC<SyncPanelProps> = ({\n workspaceId,\n syncWithSlack,\n isOwner,\n slackConfigured = true,\n onToggleSync,\n}) => {\n const [syncStatus, setSyncStatus] = useState<SyncStatus | null>(null);\n const [loading, setLoading] = useState(true);\n const [toggling, setToggling] = useState(false);\n const [infoOpen, setInfoOpen] = useState(false);\n const apis = useWorkspaceApi();\n\n const fetchSyncStatus = useCallback(async () => {\n try {\n const status = await apis.syncApi.getStatus(workspaceId);\n setSyncStatus(status);\n } catch (err) {\n console.error('Failed to fetch sync status:', err);\n } finally {\n setLoading(false);\n }\n }, [workspaceId]);\n\n useEffect(() => {\n fetchSyncStatus();\n }, [fetchSyncStatus]);\n\n // Also re-sync state when workspace.syncWithSlack changes (via real-time)\n useEffect(() => {\n if (syncStatus) {\n setSyncStatus((prev) =>\n prev ? { ...prev, syncWithSlack: syncWithSlack ?? false } : prev,\n );\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [syncWithSlack]);\n\n const handleToggle = async (provider: string, enabled: boolean) => {\n setToggling(true);\n try {\n await onToggleSync?.(provider, enabled);\n // Refresh the sync links after toggle\n await fetchSyncStatus();\n } catch (err) {\n console.error('Failed to toggle sync:', err);\n } finally {\n setToggling(false);\n }\n };\n\n const slackLink = syncStatus?.links?.find((l) => l.provider === 'slack');\n const isSlackActive = syncStatus?.syncWithSlack ?? syncWithSlack ?? false;\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 size={20} className=\"text-primary animate-spin\" />\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n {/* Section header */}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-muted text-xs font-semibold tracking-wider uppercase\">\n Synchronisation\n </span>\n <button\n className=\"text-text-muted hover:text-primary flex items-center gap-1 text-xs transition-colors\"\n onClick={() => fetchSyncStatus()}\n title=\"Rafraîchir\"\n >\n <RefreshCw size={11} /> Rafraîchir\n </button>\n </div>\n\n {/* ── Slack sync card ─────────────────────────────────────────────── */}\n <div className={cn('bg-bg border-border rounded-lg border', !slackConfigured && 'opacity-60')}>\n <div className=\"flex items-center justify-between p-3\">\n <div className=\"flex items-center gap-2.5\">\n {/* Slack icon */}\n <div\n className=\"flex h-8 w-8 items-center justify-center rounded-lg\"\n style={{ backgroundColor: SLACK_COLOR }}\n >\n <Hash size={16} className=\"text-white\" />\n </div>\n <div>\n <div className=\"text-text flex items-center gap-1.5 text-sm font-medium\">\n Slack\n {!slackConfigured ? (\n <XCircle size={14} className=\"text-text-muted\" />\n ) : isSlackActive ? (\n <CheckCircle2 size={14} className=\"text-success\" />\n ) : (\n <XCircle size={14} className=\"text-text-muted\" />\n )}\n </div>\n <span className=\"text-text-muted text-[10px]\">\n {!slackConfigured\n ? 'Non configuré'\n : isSlackActive\n ? 'Synchronisation active'\n : 'Non synchronisé'}\n </span>\n </div>\n </div>\n\n {slackConfigured && isOwner && (\n <button\n className={`rounded-lg px-3 py-1.5 text-xs font-medium transition-colors ${\n isSlackActive\n ? 'bg-danger-light text-danger hover:bg-danger/20'\n : 'bg-success-light text-success hover:bg-success/20'\n }`}\n onClick={() => handleToggle('slack', !isSlackActive)}\n disabled={toggling}\n >\n {toggling ? (\n <Loader2 size={12} className=\"animate-spin\" />\n ) : isSlackActive ? (\n 'Désactiver'\n ) : (\n 'Activer'\n )}\n </button>\n )}\n\n {!slackConfigured && (\n <span className=\"bg-bg border-border rounded border px-2 py-1 text-[10px] font-medium text-text-muted\">\n Non disponible\n </span>\n )}\n </div>\n\n {!slackConfigured && (\n <div className=\"border-border border-t px-3 py-2.5\">\n <div className=\"text-text-muted flex items-center gap-2 text-xs\">\n <AlertTriangle size={14} className=\"flex-shrink-0 text-warning\" />\n <span>\n La synchronisation Slack n&apos;est pas configurée sur le serveur.\n Contactez un administrateur pour l&apos;activer.\n </span>\n </div>\n </div>\n )}\n\n {/* Slack link details (always show when link exists) */}\n {slackConfigured && slackLink && (\n <div className=\"border-border border-t px-3 py-2.5\">\n <div className=\"flex flex-col gap-1.5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-muted text-[10px] font-medium uppercase tracking-wider\">\n Canal externe\n </span>\n <ExternalLink size={10} className=\"text-text-muted\" />\n </div>\n <div className=\"bg-surface border-border rounded border p-2\">\n <div className=\"flex items-center gap-2 text-xs\">\n <Hash size={12} className=\"text-text-muted flex-shrink-0\" />\n <span className=\"text-text font-medium\">\n {slackLink.externalName || slackLink.externalId}\n </span>\n </div>\n <div className=\"text-text-muted mt-1 flex items-center gap-2 text-[10px]\">\n <span>ID: {slackLink.externalId}</span>\n {slackLink.externalTeamId && (\n <>\n <span>•</span>\n <span>Team: {slackLink.externalTeamId}</span>\n </>\n )}\n </div>\n <div className=\"text-text-muted mt-1 flex items-center gap-2 text-[10px]\">\n <span\n className={`inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[9px] font-medium ${\n isSlackActive\n ? 'bg-success-light text-success'\n : 'bg-warning-light text-warning'\n }`}\n >\n {isSlackActive ? 'Sync active' : 'Sync en pause'}\n </span>\n <span>\n Créé le{' '}\n {new Date(slackLink.createdAt).toLocaleDateString('fr-FR')}\n </span>\n </div>\n {!isSlackActive && (\n <div className=\"text-text-muted mt-1.5 text-[10px] italic\">\n Le canal Slack reste ouvert — seule la synchronisation est en pause.\n </div>\n )}\n </div>\n </div>\n </div>\n )}\n\n {slackConfigured && isSlackActive && !slackLink && (\n <div className=\"border-border border-t px-3 py-2.5\">\n <div className=\"text-warning bg-warning-light flex items-center gap-2 rounded-lg p-2 text-xs\">\n <AlertTriangle size={14} className=\"flex-shrink-0\" />\n <span>\n La synchronisation est activée mais aucun canal Slack n&apos;est\n encore lié. Le canal sera créé automatiquement.\n </span>\n </div>\n </div>\n )}\n </div>\n\n {/* ── Teams sync card (future) ────────────────────────────────────── */}\n <div className=\"bg-bg border-border rounded-lg border opacity-50\">\n <div className=\"flex items-center justify-between p-3\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"bg-info flex h-8 w-8 items-center justify-center rounded-lg\">\n <span className=\"text-xs font-bold text-white\">T</span>\n </div>\n <div>\n <div className=\"text-text flex items-center gap-1.5 text-sm font-medium\">\n Microsoft Teams\n <XCircle size={14} className=\"text-text-muted\" />\n </div>\n <span className=\"text-text-muted text-[10px]\">\n Bientôt disponible\n </span>\n </div>\n </div>\n <span className=\"bg-bg border-border rounded border px-2 py-1 text-[10px] font-medium text-text-muted\">\n Prochainement\n </span>\n </div>\n </div>\n\n {/* ── Info section ────────────────────────────────────────────────── */}\n <div className=\"bg-bg border-border rounded-lg border\">\n <button\n className=\"flex w-full items-center gap-2 p-3 text-left\"\n onClick={() => setInfoOpen(!infoOpen)}\n >\n <Info size={14} className=\"text-info flex-shrink-0\" />\n <span className=\"text-text text-xs font-medium\">\n {SYNC_INFO.title}\n </span>\n <span\n className={`text-text-muted ml-auto text-[10px] transition-transform ${\n infoOpen ? 'rotate-180' : ''\n }`}\n >\n ▾\n </span>\n </button>\n\n {infoOpen && (\n <div className=\"border-border border-t px-3 pb-3 pt-2\">\n <p className=\"text-text-muted mb-3 text-xs leading-relaxed\">\n {SYNC_INFO.description}\n </p>\n\n <div className=\"mb-3\">\n <span className=\"text-text mb-1.5 block text-[10px] font-semibold uppercase tracking-wider\">\n Fonctionnalités\n </span>\n <ul className=\"flex flex-col gap-1\">\n {SYNC_INFO.features.map((f, i) => (\n <li\n key={i}\n className=\"text-text-muted flex items-start gap-1.5 text-xs\"\n >\n <CheckCircle2\n size={12}\n className=\"text-success mt-0.5 flex-shrink-0\"\n />\n {f}\n </li>\n ))}\n </ul>\n </div>\n\n <div>\n <span className=\"text-text mb-1.5 block text-[10px] font-semibold uppercase tracking-wider\">\n Limitations connues\n </span>\n <ul className=\"flex flex-col gap-1\">\n {SYNC_INFO.limitations.map((l, i) => (\n <li\n key={i}\n className=\"text-text-muted flex items-start gap-1.5 text-xs\"\n >\n <AlertTriangle\n size={12}\n className=\"text-warning mt-0.5 flex-shrink-0\"\n />\n {l}\n </li>\n ))}\n </ul>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n","'use client';\n\nimport React, { useRef, useEffect, useCallback, useState, useMemo } from 'react';\nimport { Brain, Loader2, ArrowDown, ChevronDown, ChevronRight } from 'lucide-react';\nimport { format, isToday, isYesterday, parseISO } from 'date-fns';\nimport { fr } from 'date-fns/locale';\nimport type { WorkspaceMessage, MessageWithArtefacts, WorkspaceMember, AvatarUser } from '../types';\nimport { MessageItem, type MessageRole } from './MessageItem';\n\n// ── Helpers ────────────────────────────────────────────────────────────────────\n\nfunction getRole(msg: WorkspaceMessage, currentUserId?: string): MessageRole {\n if (msg.senderType === 'agent') return 'assistant';\n if (currentUserId && msg.senderId === currentUserId) return 'user';\n return 'participant';\n}\n\nfunction getDateKey(dateStr: string): string {\n const d = typeof dateStr === 'string' ? parseISO(dateStr) : new Date(dateStr);\n return format(d, 'yyyy-MM-dd');\n}\n\nfunction formatDateLabel(dateStr: string): string {\n const d = typeof dateStr === 'string' ? parseISO(dateStr) : new Date(dateStr);\n if (isToday(d)) return \"Aujourd'hui\";\n if (isYesterday(d)) return 'Hier';\n return format(d, 'EEEE d MMMM yyyy', { locale: fr });\n}\n\n// ── DateSeparator ─────────────────────────────────────────────────────────────\n\nfunction DateSeparator({ date, isCollapsed, onToggle, messageCount }: {\n date: string; isCollapsed: boolean; onToggle: () => void; messageCount: number;\n}) {\n return (\n <div className=\"flex items-center gap-3 py-2 select-none\" role=\"separator\">\n <div className=\"bg-[var(--color-border,#e2e8f0)] h-px flex-1\" />\n <button onClick={onToggle}\n className=\"bg-[var(--color-surface,#fff)] border-[var(--color-border,#e2e8f0)] text-[var(--color-text-muted,#94a3b8)] hover:text-[var(--color-text,#0f172a)] hover:bg-[var(--color-bg,#f8fafc)] flex cursor-pointer items-center gap-1.5 rounded-full border px-3 py-1 text-[11px] font-medium capitalize shadow-sm transition-colors\"\n type=\"button\">\n <span>{formatDateLabel(date)}</span>\n {isCollapsed && (\n <span className=\"bg-[var(--color-primary,#3b82f6)] flex h-4 min-w-[16px] items-center justify-center rounded-full px-1 text-[9px] leading-none font-bold text-white\">{messageCount}</span>\n )}\n {isCollapsed ? <ChevronRight size={12} className=\"text-[var(--color-text-muted,#94a3b8)] shrink-0\" /> : <ChevronDown size={12} className=\"text-[var(--color-text-muted,#94a3b8)] shrink-0\" />}\n </button>\n <div className=\"bg-[var(--color-border,#e2e8f0)] h-px flex-1\" />\n </div>\n );\n}\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface MessageFeedProps {\n messages: (WorkspaceMessage | MessageWithArtefacts)[];\n members?: WorkspaceMember[];\n currentUserId?: string;\n workspaceId?: string;\n avatarUsers?: AvatarUser[];\n isTyping?: boolean;\n typingText?: string;\n hasMore?: boolean;\n loadingMore?: boolean;\n onLoadMore?: () => void;\n onArtefactDeleted?: (artefactId: string) => void;\n onReply?: (message: WorkspaceMessage | MessageWithArtefacts) => void;\n onEditMessage?: (message: WorkspaceMessage | MessageWithArtefacts) => void;\n onDeleteMessage?: (messageId: string) => void;\n onToggleReaction?: (messageId: string, reaction: string) => void;\n onTogglePin?: (messageId: string) => void;\n isOwner?: boolean;\n}\n\nconst BOTTOM_THRESHOLD = 80;\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport const MessageFeed: React.FC<MessageFeedProps> = ({\n messages, members = [], currentUserId, workspaceId, avatarUsers,\n isTyping, typingText, hasMore = false, loadingMore = false, onLoadMore,\n onArtefactDeleted, onReply, onEditMessage, onDeleteMessage, onToggleReaction, onTogglePin, isOwner = false,\n}) => {\n const feedRef = useRef<HTMLDivElement>(null);\n const initialScrollDone = useRef(false);\n const prevScrollHeight = useRef(0);\n const prevMessageCount = useRef(0);\n const isAtBottom = useRef(true);\n const [newMessageCount, setNewMessageCount] = useState(0);\n const [collapsedDates, setCollapsedDates] = useState<Record<string, boolean>>({});\n\n const toggleDateCollapse = useCallback((dateKey: string) => {\n setCollapsedDates((prev) => ({ ...prev, [dateKey]: !prev[dateKey] }));\n }, []);\n\n const checkIsAtBottom = useCallback(() => {\n const el = feedRef.current;\n if (!el) return true;\n return el.scrollHeight - el.scrollTop - el.clientHeight < BOTTOM_THRESHOLD;\n }, []);\n\n const scrollToBottom = useCallback(() => {\n const el = feedRef.current;\n if (!el) return;\n el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });\n isAtBottom.current = true;\n setNewMessageCount(0);\n }, []);\n\n type FeedItem =\n | { type: 'separator'; dateKey: string; date: string; messageCount: number }\n | { type: 'message'; dateKey: string; msg: WorkspaceMessage | MessageWithArtefacts };\n\n const feedItems: FeedItem[] = useMemo(() => {\n const counts: Record<string, number> = {};\n for (const msg of messages) { const k = getDateKey(msg.createdAt); counts[k] = (counts[k] || 0) + 1; }\n const items: FeedItem[] = [];\n let lastDateKey = '';\n for (const msg of messages) {\n const dateKey = getDateKey(msg.createdAt);\n if (dateKey !== lastDateKey) {\n items.push({ type: 'separator', dateKey, date: msg.createdAt, messageCount: counts[dateKey] || 0 });\n lastDateKey = dateKey;\n }\n items.push({ type: 'message', dateKey, msg });\n }\n return items;\n }, [messages]);\n\n useEffect(() => {\n const el = feedRef.current;\n if (!el) return;\n const messageCountGrew = messages.length > prevMessageCount.current;\n const prependedOlder = messageCountGrew && prevScrollHeight.current > 0 && initialScrollDone.current;\n if (!initialScrollDone.current) {\n el.scrollTop = el.scrollHeight;\n initialScrollDone.current = true;\n } else if (prependedOlder) {\n el.scrollTop = el.scrollHeight - prevScrollHeight.current;\n } else if (messageCountGrew) {\n if (isAtBottom.current) { el.scrollTop = el.scrollHeight; }\n else { setNewMessageCount((prev) => prev + messages.length - prevMessageCount.current); }\n }\n prevMessageCount.current = messages.length;\n prevScrollHeight.current = 0;\n }, [messages]);\n\n useEffect(() => {\n if (isTyping && feedRef.current && isAtBottom.current) feedRef.current.scrollTop = feedRef.current.scrollHeight;\n }, [isTyping]);\n\n const handleScroll = useCallback(() => {\n const el = feedRef.current;\n if (!el) return;\n const atBottom = checkIsAtBottom();\n isAtBottom.current = atBottom;\n if (atBottom && newMessageCount > 0) setNewMessageCount(0);\n if (!hasMore || loadingMore || !onLoadMore) return;\n if (el.scrollTop <= 50) { prevScrollHeight.current = el.scrollHeight; onLoadMore(); }\n }, [hasMore, loadingMore, onLoadMore, checkIsAtBottom, newMessageCount]);\n\n if (messages.length === 0) return (\n <div className=\"flex flex-1 flex-col items-center justify-center gap-2 text-center\" ref={feedRef}>\n <Brain size={32} className=\"text-[var(--color-text-muted,#94a3b8)]\" />\n <p className=\"text-[var(--color-text-muted,#94a3b8)] text-sm\">Aucun message pour le moment.</p>\n <p className=\"text-[var(--color-text-muted,#94a3b8)] text-xs\">Commencez par envoyer un message pour démarrer la conversation.</p>\n </div>\n );\n\n return (\n <div className=\"relative flex flex-1 flex-col overflow-hidden\">\n <div className=\"flex flex-1 flex-col gap-4 overflow-y-auto p-4\" ref={feedRef} onScroll={handleScroll}>\n {loadingMore && (\n <div className=\"flex items-center justify-center gap-2 py-3\">\n <Loader2 size={16} className=\"text-[var(--color-primary,#3b82f6)] animate-spin\" />\n <span className=\"text-[var(--color-text-muted,#94a3b8)] text-xs\">Chargement des messages précédents…</span>\n </div>\n )}\n {!hasMore && messages.length > 0 && (\n <div className=\"flex items-center justify-center py-2\">\n <span className=\"text-[var(--color-text-muted,#94a3b8)] text-[10px] italic\">Début de la conversation</span>\n </div>\n )}\n {feedItems.map((item) =>\n item.type === 'separator' ? (\n <DateSeparator key={`sep-${item.dateKey}`} date={item.date}\n isCollapsed={!!collapsedDates[item.dateKey]}\n onToggle={() => toggleDateCollapse(item.dateKey)}\n messageCount={item.messageCount} />\n ) : !collapsedDates[item.dateKey] ? (\n <MessageItem key={item.msg._id} message={item.msg} role={getRole(item.msg, currentUserId)}\n members={members} workspaceId={workspaceId} currentUserId={currentUserId} isOwner={isOwner}\n avatarUsers={avatarUsers} onArtefactDeleted={onArtefactDeleted} onReply={onReply}\n onEditMessage={onEditMessage} onDeleteMessage={onDeleteMessage}\n onToggleReaction={onToggleReaction} onTogglePin={onTogglePin} />\n ) : null\n )}\n {isTyping && (\n <div className=\"text-[var(--color-text-muted,#94a3b8)] flex items-center gap-2 self-start text-xs\">\n <div className=\"flex gap-0.5\">\n {[0, 150, 300].map((delay) => (\n <div key={delay} className=\"bg-[var(--color-primary,#3b82f6)] h-1.5 w-1.5 animate-bounce rounded-full\" style={{ animationDelay: `${delay}ms`}} />\n ))}\n </div>\n <span>{typingText || \"Assistant IA est en train d'écrire…\"}</span>\n </div>\n )}\n </div>\n {newMessageCount > 0 && (\n <button onClick={scrollToBottom}\n className=\"bg-[var(--color-primary,#3b82f6)] hover:bg-[var(--color-primary-hover,#2563eb)] absolute bottom-4 left-1/2 z-10 flex -translate-x-1/2 items-center gap-2 rounded-full px-4 py-2 text-xs font-medium text-white shadow-lg transition-all hover:scale-105 active:scale-95\">\n <ArrowDown size={14} />\n <span>{newMessageCount} nouveau{newMessageCount > 1 ? 'x' : ''} message{newMessageCount > 1 ? 's' : ''}</span>\n </button>\n )}\n </div>\n );\n};\n","'use client';\n\nimport React, { useState, useEffect, useRef } from 'react';\nimport {\n Paperclip, Eye, Download, Trash2, Loader2, FileIcon, ImageIcon,\n Reply, MoreVertical, Pencil, SmilePlus, ThumbsUp, ThumbsDown,\n Heart, Laugh, Frown, CheckCircle2, Pin, PinOff, ChevronDown, ChevronUp,\n} from 'lucide-react';\nimport { cn } from './ui/cn';\nimport { fixMojibake } from '../utils/constants';\nimport type {\n WorkspaceMessage, MessageWithArtefacts, WorkspaceMember,\n WorkspaceArtefact, WorkspaceMessageReaction, AvatarUser,\n} from '../types';\nimport { useWorkspaceApi } from '../hooks/useWorkspaceApi';\nimport { ArtefactViewerDialog } from './ArtefactViewerDialog';\nimport { MemberAvatar } from './MemberAvatar';\nimport { ConfirmModal } from './ui/ConfirmModal';\nimport { Streamdown } from 'streamdown';\nimport { cjk } from '@streamdown/cjk';\nimport { createCodePlugin } from '@streamdown/code';\nimport { math } from '@streamdown/math';\nimport { mermaid } from '@streamdown/mermaid';\nimport 'katex/dist/katex.min.css';\nimport 'streamdown/styles.css';\nimport { workspaceStreamdownComponents } from './streamdownCustomComponents';\n\n// ─── Constants ────────────────────────────────────────────────────────────────\nconst MAX_LINES = 12;\n// Dynamically compute collapsed max height based on the line limit (approx 23px per line + 20px padding)\nconst COLLAPSED_MAX_HEIGHT = MAX_LINES * 23 + 20;\n/** Maximum number of artefacts shown before collapsing */\nconst MAX_VISIBLE_ARTEFACTS = 3;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type MessageRole = 'user' | 'assistant' | 'participant';\n\nexport interface MessageItemProps {\n message: WorkspaceMessage | MessageWithArtefacts;\n role: MessageRole;\n members?: WorkspaceMember[];\n workspaceId?: string;\n currentUserId?: string;\n isOwner?: boolean;\n avatarUsers?: AvatarUser[];\n onArtefactDeleted?: (artefactId: string) => void;\n onReply?: (message: WorkspaceMessage | MessageWithArtefacts) => void;\n onEditMessage?: (message: WorkspaceMessage | MessageWithArtefacts) => void;\n onDeleteMessage?: (messageId: string) => void;\n onToggleReaction?: (messageId: string, reaction: string) => void;\n onTogglePin?: (messageId: string) => void;\n}\n\n// ─── Reaction Definitions ─────────────────────────────────────────────────────\n\nconst REACTION_OPTIONS = [\n { key: 'like', emoji: '👍', label: 'J\\u2019aime', icon: ThumbsUp },\n { key: 'dislike', emoji: '👎', label: 'Pas d\\u2019accord', icon: ThumbsDown },\n { key: 'heart', emoji: '❤️', label: 'J\\u2019adore', icon: Heart },\n { key: 'laugh', emoji: '😂', label: 'Drôle', icon: Laugh },\n { key: 'sad', emoji: '😢', label: 'Triste', icon: Frown },\n { key: 'check', emoji: '✅', label: 'Fait', icon: CheckCircle2 },\n] as const;\n\nconst REACTION_EMOJI_MAP: Record<string, string> = Object.fromEntries(\n REACTION_OPTIONS.map((r) => [r.key, r.emoji]),\n);\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\n/** Pre-process content to wrap @mentions in bold markdown so Streamdown highlights them */\nfunction preprocessMentions(\n content: string,\n members: WorkspaceMember[],\n): string {\n let result = content;\n\n // ─── Global mentions (longest first to avoid partial matches) ──────\n const globalMentions = ['@Tous le monde et agents', '@Tous le monde'];\n for (const token of globalMentions) {\n const escaped = token.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(`(${escaped})`, 'gi');\n result = result.replace(regex, '**$1**');\n }\n\n if (!members.length) return result;\n\n // ─── Individual mentions ──────────────────────────────────────────\n // Sort by name length (longest first) so longer names match before shorter substrings\n const sorted = [...members].sort(\n (a, b) => b.memberName.length - a.memberName.length,\n );\n\n for (const member of sorted) {\n const mentionByName = `@${member.memberName}`;\n const mentionById = `@${member.memberId}`;\n const escapedName = mentionByName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const escapedId = mentionById.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(`(${escapedName}|${escapedId})`, 'gi');\n result = result.replace(regex, '**$1**');\n }\n return result;\n}\n\nfunction formatTime(iso: string): string {\n return new Date(iso).toLocaleTimeString('fr-FR', {\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\n// ─── Inline Image Preview ─────────────────────────────────────────────────────\n\nfunction InlineImagePreview({ artefact }: { artefact: WorkspaceArtefact }) {\n const { artefactApi } = useWorkspaceApi();\n const [url, setUrl] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n artefactApi\n .getSignedUrl(artefact.file._id)\n .then(({ url: signedUrl }) => {\n if (!cancelled) setUrl(signedUrl);\n })\n .catch(() => {})\n .finally(() => {\n if (!cancelled) setLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [artefact.file._id, artefactApi]);\n\n if (loading) {\n return (\n <div className=\"bg-bg flex h-32 w-full items-center justify-center rounded-lg\">\n <Loader2 size={16} className=\"text-text-muted animate-spin\" />\n </div>\n );\n }\n\n if (!url) {\n return (\n <div className=\"bg-bg flex h-24 w-full items-center justify-center gap-2 rounded-lg\">\n <ImageIcon size={16} className=\"text-text-muted\" />\n <span className=\"text-text-muted text-xs\">Image indisponible</span>\n </div>\n );\n }\n\n return (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={url}\n alt={fixMojibake(artefact.file.originalName)}\n className=\"max-h-48 w-full rounded-lg object-contain\"\n />\n );\n}\n\n// ─── Artefact Card ────────────────────────────────────────────────────────────\n\nfunction ArtefactCard({\n artefact,\n isUserMessage,\n workspaceId,\n onView,\n onDeleted,\n canDelete = false,\n}: {\n artefact: WorkspaceArtefact;\n isUserMessage: boolean;\n workspaceId?: string;\n onView: () => void;\n onDeleted?: (artefactId: string) => void;\n canDelete?: boolean;\n}) {\n const { artefactApi } = useWorkspaceApi();\n const isImage = artefact.file.mimetype.startsWith('image/');\n const [confirmOpen, setConfirmOpen] = useState(false);\n\n const handleDownload = async (e: React.MouseEvent) => {\n e.stopPropagation();\n try {\n const blob = await artefactApi.getDownloadBlob(artefact.file._id);\n const blobUrl = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = blobUrl;\n a.download = fixMojibake(artefact.file.originalName);\n document.body.appendChild(a);\n a.click();\n a.remove();\n URL.revokeObjectURL(blobUrl);\n } catch (err) {\n console.error('Download failed:', err);\n }\n };\n\n const handleDeleteConfirmed = async () => {\n if (!workspaceId) return;\n try {\n await artefactApi.delete(workspaceId, artefact._id);\n onDeleted?.(artefact._id);\n } catch (err) {\n console.error('Delete failed:', err);\n }\n };\n\n return (\n <>\n <div\n className={cn(\n 'group/art flex flex-col overflow-hidden rounded-xl border transition-shadow hover:shadow-md',\n isUserMessage ? 'border-white/20 bg-white/10' : 'border-border bg-bg',\n )}\n >\n {/* Inline image preview */}\n {isImage && (\n <div className=\"cursor-pointer\" onClick={onView}>\n <InlineImagePreview artefact={artefact} />\n </div>\n )}\n\n {/* File info + action buttons */}\n <div className=\"flex items-center gap-2 px-3 py-2\">\n {/* Icon */}\n <div\n className={cn(\n 'flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg',\n isUserMessage ? 'bg-white/15' : 'bg-primary-light',\n )}\n >\n {isImage ? (\n <ImageIcon\n size={14}\n className={isUserMessage ? 'text-white/80' : 'text-primary'}\n />\n ) : (\n <FileIcon\n size={14}\n className={isUserMessage ? 'text-white/80' : 'text-primary'}\n />\n )}\n </div>\n\n {/* File name */}\n <div className=\"min-w-0 flex-1\">\n <div\n className={cn(\n 'truncate text-xs font-medium',\n isUserMessage ? 'text-white' : 'text-text',\n )}\n >\n {fixMojibake(artefact.file.originalName)}\n </div>\n {artefact.file.size > 0 && (\n <div\n className={cn(\n 'text-[10px]',\n isUserMessage ? 'text-white/60' : 'text-text-muted',\n )}\n >\n {artefact.file.size > 1024 * 1024\n ? `${(artefact.file.size / (1024 * 1024)).toFixed(1)} MB`\n : `${(artefact.file.size / 1024).toFixed(0)} KB`}\n </div>\n )}\n </div>\n\n {/* Action buttons */}\n <div className=\"flex items-center gap-0.5 opacity-0 transition-opacity group-hover/art:opacity-100\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n onView();\n }}\n className={cn(\n 'rounded-md p-1.5 transition-colors',\n isUserMessage\n ? 'text-white/70 hover:bg-white/15 hover:text-white'\n : 'text-info hover:bg-info-light',\n )}\n title=\"Visualiser\"\n >\n <Eye size={13} />\n </button>\n <button\n onClick={handleDownload}\n className={cn(\n 'rounded-md p-1.5 transition-colors',\n isUserMessage\n ? 'text-white/70 hover:bg-white/15 hover:text-white'\n : 'text-primary hover:bg-primary-light',\n )}\n title=\"Télécharger\"\n >\n <Download size={13} />\n </button>\n {workspaceId && canDelete && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n setConfirmOpen(true);\n }}\n className={cn(\n 'rounded-md p-1.5 transition-colors',\n isUserMessage\n ? 'text-white/70 hover:bg-white/15 hover:text-white'\n : 'text-danger hover:bg-danger-light',\n )}\n title=\"Supprimer\"\n >\n <Trash2 size={13} />\n </button>\n )}\n </div>\n </div>\n </div>\n\n <ConfirmModal\n open={confirmOpen}\n onClose={() => setConfirmOpen(false)}\n onConfirm={handleDeleteConfirmed}\n title=\"Supprimer l'artefact\"\n description={\n <>\n Voulez-vous vraiment supprimer{' '}\n <strong>{fixMojibake(artefact.file.originalName)}</strong> ? Cette action est\n irréversible.\n </>\n }\n confirmText=\"Supprimer\"\n danger\n />\n </>\n );\n}\n\n// ─── Message Actions Popover ──────────────────────────────────────────────────\n\nfunction MessageActionsMenu({\n isUser,\n onEdit,\n onDelete,\n}: {\n isUser: boolean;\n onEdit: () => void;\n onDelete: () => void;\n}) {\n const [open, setOpen] = useState(false);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Close on outside click\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [open]);\n\n return (\n <div className=\"relative\" ref={menuRef}>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setOpen((v) => !v);\n }}\n className={cn(\n 'rounded-full p-1 shadow-sm transition-all',\n 'bg-surface border-border text-text-muted hover:text-text border',\n )}\n title=\"Actions\"\n >\n <MoreVertical size={14} />\n </button>\n\n {open && (\n <div\n className={cn(\n 'bg-surface border-border absolute z-30 min-w-[140px] overflow-hidden rounded-lg border shadow-lg',\n isUser ? 'right-0 bottom-full mb-1' : 'bottom-full left-0 mb-1',\n )}\n >\n <button\n onClick={(e) => {\n e.stopPropagation();\n setOpen(false);\n onEdit();\n }}\n className=\"text-text hover:bg-primary-light hover:text-primary flex w-full items-center gap-2 px-3 py-2 text-xs transition-colors\"\n >\n <Pencil size={13} />\n Modifier\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setOpen(false);\n onDelete();\n }}\n className=\"text-danger hover:bg-danger-light flex w-full items-center gap-2 px-3 py-2 text-xs transition-colors\"\n >\n <Trash2 size={13} />\n Supprimer\n </button>\n </div>\n )}\n </div>\n );\n}\n\n// ─── Reaction Picker Popover ───────────────────────────────────────────────────\n\nfunction ReactionPicker({\n isUser,\n onSelect,\n}: {\n isUser: boolean;\n onSelect: (reaction: string) => void;\n}) {\n const [open, setOpen] = useState(false);\n const pickerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n if (pickerRef.current && !pickerRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [open]);\n\n return (\n <div className=\"relative\" ref={pickerRef}>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setOpen((v) => !v);\n }}\n className={cn(\n 'rounded-full p-1 shadow-sm transition-all',\n 'bg-surface border-border text-text-muted hover:text-text border',\n )}\n title=\"Réagir\"\n >\n <SmilePlus size={14} />\n </button>\n\n {open && (\n <div\n className={cn(\n 'bg-surface border-border absolute z-30 flex items-center gap-0.5 rounded-full border px-1.5 py-1 shadow-lg',\n isUser ? 'right-0 bottom-full mb-1' : 'bottom-full left-0 mb-1',\n )}\n >\n {REACTION_OPTIONS.map((opt) => (\n <button\n key={opt.key}\n onClick={(e) => {\n e.stopPropagation();\n setOpen(false);\n onSelect(opt.key);\n }}\n className=\"hover:bg-bg flex h-7 w-7 items-center justify-center rounded-full text-base transition-all hover:scale-125\"\n title={opt.label}\n >\n {opt.emoji}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ─── Reaction Bar (below the message bubble) ──────────────────────────────\n\ninterface GroupedReaction {\n reaction: string;\n emoji: string;\n count: number;\n members: string[];\n hasMine: boolean;\n}\n\nfunction groupReactions(\n reactions: WorkspaceMessageReaction[],\n currentUserId?: string,\n): GroupedReaction[] {\n const map = new Map<\n string,\n { count: number; members: string[]; hasMine: boolean }\n >();\n for (const r of reactions) {\n if (!map.has(r.reaction)) {\n map.set(r.reaction, { count: 0, members: [], hasMine: false });\n }\n const group = map.get(r.reaction)!;\n group.count++;\n if (r.memberName) group.members.push(r.memberName);\n if (r.memberId === currentUserId) group.hasMine = true;\n }\n\n return Array.from(map.entries()).map(([key, val]) => ({\n reaction: key,\n emoji: REACTION_EMOJI_MAP[key] ?? key,\n count: val.count,\n members: val.members,\n hasMine: val.hasMine,\n }));\n}\n\nfunction ReactionBar({\n reactions,\n currentUserId,\n isUser,\n onToggle,\n}: {\n reactions: WorkspaceMessageReaction[];\n currentUserId?: string;\n isUser: boolean;\n onToggle: (reaction: string) => void;\n}) {\n const grouped = groupReactions(reactions, currentUserId);\n if (grouped.length === 0) return null;\n\n return (\n <div\n className={cn(\n 'mt-1 flex flex-wrap gap-1 px-1',\n isUser ? 'justify-end' : 'justify-start',\n )}\n >\n {grouped.map((g) => (\n <button\n key={g.reaction}\n onClick={() => onToggle(g.reaction)}\n className={cn(\n 'group/reaction relative flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs transition-all hover:shadow-sm',\n g.hasMine\n ? 'border-primary bg-primary-light text-primary font-medium'\n : 'border-border bg-surface text-text-secondary hover:border-primary/40 hover:bg-primary-light/50',\n )}\n title={g.members.join(', ')}\n >\n <span className=\"text-sm\">{g.emoji}</span>\n <span>{g.count}</span>\n {/* Tooltip showing who reacted */}\n <div\n className={cn(\n 'pointer-events-none absolute z-40 min-w-max rounded-lg px-2.5 py-1.5 text-[11px] leading-relaxed opacity-0 shadow-lg transition-opacity group-hover/reaction:opacity-100',\n 'bg-[#1e293b] text-white',\n isUser ? 'right-0 bottom-full mb-2' : 'bottom-full left-0 mb-2',\n )}\n >\n {g.members.length > 0 ? g.members.join(', ') : 'Réaction anonyme'}\n </div>\n </button>\n ))}\n </div>\n );\n}\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport const MessageItem: React.FC<MessageItemProps> = ({\n message,\n role,\n members = [],\n workspaceId,\n currentUserId,\n isOwner = false,\n avatarUsers,\n onArtefactDeleted,\n onReply,\n onEditMessage,\n onDeleteMessage,\n onToggleReaction,\n onTogglePin,\n}) => {\n const isAgent = message.senderType === 'agent';\n const isUser = role === 'user';\n const isDeleted = message.deleted === true;\n const processedContent = isDeleted\n ? ''\n : preprocessMentions(message.content, members);\n const artefacts = isDeleted\n ? []\n : 'artefacts' in message\n ? (message as MessageWithArtefacts).artefacts\n : [];\n const reactions: WorkspaceMessageReaction[] = isDeleted\n ? []\n : 'reactions' in message\n ? ((message as MessageWithArtefacts).reactions ?? [])\n : [];\n const time = formatTime(message.createdAt);\n const isPinned = !isDeleted && message.pinned === true;\n\n const [isExpanded, setIsExpanded] = useState(false);\n const [artefactsExpanded, setArtefactsExpanded] = useState(false);\n const [isLong, setIsLong] = useState(false);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (isDeleted) return;\n const el = contentRef.current;\n if (!el) return;\n\n const checkHeight = () => {\n if (el.scrollHeight > COLLAPSED_MAX_HEIGHT) {\n setIsLong(true);\n } else {\n setIsLong(false);\n }\n };\n\n // Initial check\n checkHeight();\n\n // Secondary checks for dynamic elements like Mermaid that load or compile asynchronously\n const timer1 = setTimeout(checkHeight, 100);\n const timer2 = setTimeout(checkHeight, 500);\n\n let observer: ResizeObserver | null = null;\n if (typeof ResizeObserver !== 'undefined') {\n observer = new ResizeObserver(checkHeight);\n observer.observe(el);\n }\n\n return () => {\n clearTimeout(timer1);\n clearTimeout(timer2);\n if (observer) observer.disconnect();\n };\n }, [message.content, isDeleted]);\n\n const isDark =\n typeof document !== 'undefined' &&\n document.documentElement.getAttribute('data-theme') === 'dark';\n\n const codePlugin = React.useMemo(\n () =>\n createCodePlugin({\n themes: isDark ? ['min-dark', 'min-dark'] : ['min-light', 'min-light'],\n }),\n [isDark],\n );\n\n const [viewingArtefact, setViewingArtefact] =\n useState<WorkspaceArtefact | null>(null);\n const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);\n\n const memberName = message.sender?.memberName || message.senderName;\n\n // Soft-deleted message rendering\n if (isDeleted) {\n return (\n <div\n className={cn(\n 'group flex max-w-[85%] gap-3',\n isUser ? 'flex-row-reverse self-end' : 'self-start',\n )}\n >\n <MemberAvatar\n memberName={memberName}\n memberType={message.senderType as 'user' | 'agent'}\n avatarUrl={\n avatarUsers?.find(\n (u) => u.email.toLowerCase() === message.senderId.toLowerCase(),\n )?.avatarUrl\n }\n size=\"md\"\n variant={isUser ? 'currentUser' : 'primary'}\n className=\"opacity-50 shadow-sm\"\n />\n <div className=\"flex min-w-0 flex-col gap-0.5\">\n {!isUser && (\n <div className=\"flex items-center gap-2 px-1\">\n <span className=\"text-text-muted text-[11px] font-semibold\">\n {memberName}\n </span>\n <span className=\"text-text-placeholder text-[10px]\">{time}</span>\n </div>\n )}\n <div\n className={cn(\n 'rounded-2xl px-4 py-2.5 italic',\n isUser\n ? 'bg-primary/80 rounded-tr-sm text-white/80'\n : 'bg-surface border-border text-text-muted rounded-tl-sm border',\n )}\n >\n <span className=\"text-xs\">🗑️ Ce message a été supprimé</span>\n </div>\n {isUser && (\n <div className=\"flex items-center gap-1 self-end px-1\">\n <span className=\"text-text-placeholder text-[10px]\">{time}</span>\n </div>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <>\n <div\n className={cn(\n 'group flex max-w-[85%] gap-3',\n isUser ? 'flex-row-reverse self-end' : 'self-start',\n )}\n >\n {/* ── Avatar ── */}\n <MemberAvatar\n memberName={memberName}\n memberType={message.senderType as 'user' | 'agent'}\n avatarUrl={\n avatarUsers?.find(\n (u) => u.email.toLowerCase() === message.senderId.toLowerCase(),\n )?.avatarUrl\n }\n size=\"md\"\n variant={isUser ? 'currentUser' : 'primary'}\n className=\"mt-1 flex-shrink-0 self-start shadow-sm\"\n />\n\n {/* ── Bubble ── */}\n <div className=\"flex min-w-0 flex-col gap-0.5\">\n {/* Sender name + timestamp + reply button */}\n {!isUser && (\n <div className=\"flex items-center gap-2 px-1\">\n <span\n className={cn(\n 'text-[11px] font-semibold',\n isAgent ? 'text-indigo-600' : 'text-text-secondary',\n )}\n >\n {memberName}\n </span>\n <span className=\"text-text-placeholder text-[10px]\">{time}</span>\n {message.editedAt && (\n <span className=\"text-text-placeholder text-[10px] italic\">\n (modifié)\n </span>\n )}\n {onReply && (\n <button\n onClick={() => onReply(message)}\n className=\"text-text-muted hover:text-primary ml-auto rounded p-0.5 opacity-0 transition-all group-hover:opacity-100\"\n title=\"Répondre\"\n >\n <Reply size={13} />\n </button>\n )}\n </div>\n )}\n\n {/* Pinned indicator */}\n {isPinned && (\n <div\n className={cn(\n 'flex items-center gap-1 px-2 py-0.5 text-[10px] font-medium',\n isUser\n ? 'self-end text-amber-200'\n : 'text-amber-600 dark:text-amber-400',\n )}\n >\n <Pin size={10} className=\"rotate-45\" />\n <span>Épinglé</span>\n </div>\n )}\n\n <div className=\"flex items-start gap-1.5\">\n {/* Actions menu — to the left of user messages */}\n {isUser && (\n <div className=\"flex flex-shrink-0 items-center gap-0.5 self-center opacity-0 transition-opacity group-hover:opacity-100\">\n {onTogglePin && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onTogglePin(message._id);\n }}\n className={cn(\n 'rounded-full p-1 shadow-sm transition-all',\n 'bg-surface border-border border',\n isPinned\n ? 'text-amber-500 hover:text-amber-600'\n : 'text-text-muted hover:text-text',\n )}\n title={isPinned ? 'Désépingler' : 'Épingler'}\n >\n {isPinned ? <PinOff size={14} /> : <Pin size={14} />}\n </button>\n )}\n {onToggleReaction && (\n <ReactionPicker\n isUser={isUser}\n onSelect={(r) => onToggleReaction(message._id, r)}\n />\n )}\n {onEditMessage && onDeleteMessage && (\n <MessageActionsMenu\n isUser={isUser}\n onEdit={() => onEditMessage(message)}\n onDelete={() => setConfirmDeleteOpen(true)}\n />\n )}\n </div>\n )}\n\n <div\n className={cn(\n 'relative rounded-2xl px-4 py-2.5 shadow-sm transition-shadow group-hover:shadow-md',\n isUser\n ? 'bg-primary rounded-tr-sm text-white'\n : isAgent\n ? 'rounded-tl-sm border border-indigo-100 bg-gradient-to-br from-white to-indigo-50/40 dark:border-indigo-800/60 dark:from-indigo-900/20 dark:to-indigo-800/10'\n : 'bg-surface border-border rounded-tl-sm border',\n )}\n >\n {/* Reply preview (when this message is a reply) */}\n {message.replyToMessage &&\n typeof message.replyToMessage === 'object' &&\n 'content' in message.replyToMessage && (\n <div\n className={cn(\n 'mb-2 rounded-lg border-l-3 px-3 py-1.5',\n isUser\n ? 'border-l-white/50 bg-white/15'\n : 'border-l-[var(--color-primary)] bg-[var(--color-primary-light)]/60',\n )}\n >\n <div\n className={cn(\n 'text-[10px] font-semibold',\n isUser ? 'text-white/80' : 'text-primary',\n )}\n >\n {message.replyToMessage.senderName}\n </div>\n <div\n className={cn(\n 'truncate text-[11px]',\n isUser ? 'text-white/60' : 'text-text-muted',\n message.replyToMessage.deleted && 'italic',\n )}\n >\n {message.replyToMessage.deleted\n ? '🗑️ Ce message a été supprimé'\n : message.replyToMessage.content.length > 100\n ? message.replyToMessage.content.slice(0, 100) + '…'\n : message.replyToMessage.content}\n </div>\n </div>\n )}\n\n {/* Message content rendered via Streamdown */}\n <div\n ref={contentRef}\n className={cn(\n 'streamdown-message overflow-hidden text-sm leading-relaxed transition-all duration-300 ease-in-out',\n isUser &&\n 'text-white [&_a]:text-white/80 [&_a]:underline [&_code]:bg-white/15 [&_code]:text-white [&_strong]:text-white/90',\n )}\n style={\n !isExpanded && isLong\n ? {\n maxHeight: `${COLLAPSED_MAX_HEIGHT}px`,\n maskImage:\n 'linear-gradient(to bottom, black 70%, transparent 100%)',\n WebkitMaskImage:\n 'linear-gradient(to bottom, black 70%, transparent 100%)',\n }\n : undefined\n }\n >\n <Streamdown\n mode=\"static\"\n plugins={{ code: codePlugin, mermaid, math, cjk }}\n components={workspaceStreamdownComponents}\n >\n {processedContent}\n </Streamdown>\n </div>\n\n {isLong && (\n <button\n onClick={() => setIsExpanded((prev) => !prev)}\n className={cn(\n 'mt-2 flex cursor-pointer items-center gap-0.5 self-start text-[10px] font-semibold transition-colors select-none',\n isUser\n ? 'text-white/85 hover:text-white'\n : 'text-primary hover:text-primary-hover',\n )}\n type=\"button\"\n >\n {isExpanded ? (\n <>\n <ChevronUp size={12} />\n Voir moins\n </>\n ) : (\n <>\n <ChevronDown size={12} />\n Voir plus\n </>\n )}\n </button>\n )}\n\n {/* Artefacts / attachments */}\n {artefacts.length > 0 &&\n (() => {\n const hasMany = artefacts.length > MAX_VISIBLE_ARTEFACTS;\n const visibleArtefacts =\n artefactsExpanded || !hasMany\n ? artefacts\n : artefacts.slice(0, MAX_VISIBLE_ARTEFACTS);\n const hiddenCount = artefacts.length - MAX_VISIBLE_ARTEFACTS;\n\n return (\n <div\n className={cn(\n 'mt-3 flex flex-col gap-2 border-t pt-2.5',\n isUser ? 'border-white/20' : 'border-border-light',\n )}\n >\n <div\n className={cn(\n 'flex items-center gap-1 text-[10px] font-medium',\n isUser ? 'text-white/60' : 'text-text-muted',\n )}\n >\n <Paperclip size={10} />\n {artefacts.length} pièce\n {artefacts.length > 1 ? 's' : ''} jointe\n {artefacts.length > 1 ? 's' : ''}\n </div>\n {visibleArtefacts.map((art) => (\n <ArtefactCard\n key={art._id}\n artefact={art}\n isUserMessage={isUser}\n workspaceId={workspaceId}\n onView={() => setViewingArtefact(art)}\n onDeleted={onArtefactDeleted}\n canDelete={isOwner || art.createdBy === currentUserId}\n />\n ))}\n\n {hasMany && (\n <button\n onClick={() => setArtefactsExpanded((prev) => !prev)}\n className={cn(\n 'mt-0.5 flex cursor-pointer items-center gap-1 self-start rounded-md px-2 py-1 text-[10px] font-semibold transition-all select-none',\n isUser\n ? 'text-white/80 hover:bg-white/10 hover:text-white'\n : 'text-primary hover:bg-primary-light hover:text-primary-hover',\n )}\n type=\"button\"\n >\n {artefactsExpanded ? (\n <>\n <ChevronUp size={12} />\n Voir moins\n </>\n ) : (\n <>\n <ChevronDown size={12} />+{hiddenCount} autre\n {hiddenCount > 1 ? 's' : ''} pièce\n {hiddenCount > 1 ? 's' : ''} jointe\n {hiddenCount > 1 ? 's' : ''}\n </>\n )}\n </button>\n )}\n </div>\n );\n })()}\n </div>\n\n {/* Reaction picker + Pin for non-user messages — to the right */}\n {!isUser && (\n <div className=\"flex flex-shrink-0 items-center gap-0.5 self-center opacity-0 transition-opacity group-hover:opacity-100\">\n {onToggleReaction && (\n <ReactionPicker\n isUser={isUser}\n onSelect={(r) => onToggleReaction(message._id, r)}\n />\n )}\n {onTogglePin && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onTogglePin(message._id);\n }}\n className={cn(\n 'rounded-full p-1 shadow-sm transition-all',\n 'bg-surface border-border border',\n isPinned\n ? 'text-amber-500 hover:text-amber-600'\n : 'text-text-muted hover:text-text',\n )}\n title={isPinned ? 'Désépingler' : 'Épingler'}\n >\n {isPinned ? <PinOff size={14} /> : <Pin size={14} />}\n </button>\n )}\n </div>\n )}\n </div>\n\n {/* Reaction bar */}\n {onToggleReaction && reactions.length > 0 && (\n <ReactionBar\n reactions={reactions}\n currentUserId={currentUserId}\n isUser={isUser}\n onToggle={(r) => onToggleReaction(message._id, r)}\n />\n )}\n\n {/* Timestamp + reply button + edited for user messages (shown below, right-aligned) */}\n {isUser && (\n <div className=\"flex items-center gap-1 self-end px-1\">\n {message.editedAt && (\n <span className=\"text-text-placeholder text-[10px] italic\">\n (modifié)\n </span>\n )}\n {onReply && (\n <button\n onClick={() => onReply(message)}\n className=\"text-text-muted hover:text-primary rounded p-0.5 opacity-0 transition-all group-hover:opacity-100\"\n title=\"Répondre\"\n >\n <Reply size={13} />\n </button>\n )}\n <span className=\"text-text-placeholder text-[10px]\">{time}</span>\n </div>\n )}\n </div>\n </div>\n\n {/* Delete confirm modal */}\n <ConfirmModal\n open={confirmDeleteOpen}\n onClose={() => setConfirmDeleteOpen(false)}\n onConfirm={() => {\n onDeleteMessage?.(message._id);\n setConfirmDeleteOpen(false);\n }}\n title=\"Supprimer le message\"\n description=\"Voulez-vous vraiment supprimer ce message ? Cette action est irréversible.\"\n confirmText=\"Supprimer\"\n danger\n />\n\n {/* Artefact viewer dialog */}\n {viewingArtefact && (\n <ArtefactViewerDialog\n artefact={viewingArtefact}\n onClose={() => setViewingArtefact(null)}\n />\n )}\n </>\n );\n};\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { Loader2, FileIcon } from 'lucide-react';\nimport type { WorkspaceArtefact } from '../types';\nimport { useWorkspaceApi } from '../hooks/useWorkspaceApi';\nimport { fixMojibake } from '../utils/constants';\nimport { Modal } from './ui/Modal';\nimport { Streamdown } from 'streamdown';\nimport 'streamdown/styles.css';\n\ninterface ArtefactViewerDialogProps {\n artefact: WorkspaceArtefact;\n onClose: () => void;\n}\n\nexport function ArtefactViewerDialog({ artefact, onClose }: ArtefactViewerDialogProps) {\n const { artefactApi } = useWorkspaceApi();\n const [url, setUrl] = useState<string | null>(null);\n const [textContent, setTextContent] = useState<string | null>(null);\n const [htmlContent, setHtmlContent] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n\n const mimetype = artefact.file?.mimetype ?? '';\n const fileName = fixMojibake(artefact.file?.originalName ?? '');\n const isImage = mimetype.startsWith('image/');\n const isMarkdown = fileName.endsWith('.md') || mimetype === 'text/markdown';\n const isJson = fileName.endsWith('.json') || mimetype === 'application/json';\n const isDocx = fileName.endsWith('.docx') || mimetype === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';\n const isText = !isMarkdown && !isJson && !isDocx && (mimetype === 'text/plain' || mimetype.startsWith('text/'));\n\n useEffect(() => {\n if (!artefact.file?._id) { setLoading(false); return; }\n let cancelled = false;\n setLoading(true);\n (async () => {\n try {\n if (isImage) {\n const { url: signedUrl } = await artefactApi.getSignedUrl(artefact.file._id);\n if (!cancelled) setUrl(signedUrl);\n } else if (isText || isMarkdown || isJson) {\n const blob = await artefactApi.getDownloadBlob(artefact.file._id);\n const text = await blob.text();\n if (!cancelled) setTextContent(text);\n } else if (isDocx) {\n const blob = await artefactApi.getDownloadBlob(artefact.file._id);\n const arrayBuffer = await blob.arrayBuffer();\n const mammoth = await import('mammoth');\n const result = await mammoth.convertToHtml({ arrayBuffer });\n if (!cancelled) setHtmlContent(result.value);\n }\n } catch (err) { console.error('Failed to load artefact preview:', err); }\n finally { if (!cancelled) setLoading(false); }\n })();\n return () => { cancelled = true; };\n }, [artefact.file?._id, isImage, isText, isMarkdown, isJson, isDocx, artefactApi]);\n\n return (\n <Modal open onClose={onClose} size=\"full\"\n panelClassName=\"bg-[var(--color-surface,#fff)] border-[var(--color-border,#e2e8f0)] flex max-h-[95vh] h-[95vh] w-full flex-col overflow-hidden rounded-2xl border shadow-2xl\"\n className=\"p-2 sm:p-4\" closeOnBackdropClick\n title={fileName} titleClassName=\"truncate text-sm font-semibold\"\n headerClassName=\"items-center px-5 py-3\" closeIconSize={18}>\n <div className=\"flex min-h-0 flex-1 flex-col overflow-auto p-4 sm:p-6\">\n {loading ? (\n <div className=\"flex w-full flex-1 items-center justify-center\">\n <Loader2 size={28} className=\"text-[var(--color-primary,#3b82f6)] animate-spin\" />\n </div>\n ) : isImage && url ? (\n <div className=\"flex h-full w-full flex-1 items-center justify-center\">\n <img src={url} alt={fileName} className=\"max-h-full max-w-full rounded-lg object-contain\" />\n </div>\n ) : isMarkdown && textContent !== null ? (\n <div className=\"w-full overflow-auto\">\n <Streamdown mode=\"static\">{textContent}</Streamdown>\n </div>\n ) : isJson && textContent !== null ? (\n <pre className=\"bg-[var(--color-bg,#f8fafc)] text-[var(--color-text,#0f172a)] w-full flex-1 overflow-auto rounded-lg p-6 text-sm leading-relaxed whitespace-pre-wrap\">\n {(() => { try { return JSON.stringify(JSON.parse(textContent), null, 2); } catch { return textContent; } })()}\n </pre>\n ) : isDocx && htmlContent !== null ? (\n <div className=\"bg-[var(--color-bg,#f8fafc)] text-[var(--color-text,#0f172a)] w-full flex-1 overflow-auto rounded-lg p-6 text-sm leading-relaxed\"\n dangerouslySetInnerHTML={{ __html: htmlContent }} />\n ) : isText && textContent !== null ? (\n <pre className=\"bg-[var(--color-bg,#f8fafc)] text-[var(--color-text,#0f172a)] w-full flex-1 overflow-auto rounded-lg p-6 text-sm leading-relaxed whitespace-pre-wrap\">{textContent}</pre>\n ) : (\n <div className=\"text-[var(--color-text-muted,#94a3b8)] flex w-full flex-1 flex-col items-center justify-center gap-2 py-12 text-center\">\n <FileIcon size={48} className=\"opacity-30\" />\n <p className=\"text-sm\">Aperçu non disponible pour ce type de fichier</p>\n <p className=\"text-[10px]\">{mimetype}</p>\n </div>\n )}\n </div>\n </Modal>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport { ChartRenderer } from './ChartRenderer';\nimport { TableRenderer } from './TableRenderer';\n\nconst CUSTOM_LANGUAGES = new Set(['chart', 'tabledata', 'optionsblock', 'table']);\n\n/**\n * Custom Streamdown components for workspace messages.\n * Intercepts chart and tabledata fenced blocks.\n */\nexport const workspaceStreamdownComponents = {\n pre: ({ children }: any) => {\n const codeChild = React.Children.toArray(children)[0];\n if (codeChild && typeof codeChild === 'object' && 'props' in codeChild) {\n const codeProps = (codeChild as any).props || {};\n const className = codeProps.className || '';\n const match = /language-(\\w+)/.exec(className);\n const language = match ? match[1] : '';\n const codeContent = codeProps.children;\n\n if (language === 'chart' && codeContent) {\n try {\n const cfg = JSON.parse(String(codeContent).replace(/\\n$/, ''));\n if (cfg.type === 'chartjs' && cfg.chartConfig) return <ChartRenderer chartConfig={cfg} />;\n } catch { return <pre>{children}</pre>; }\n }\n\n if (language === 'tabledata' && codeContent) {\n try {\n const cfg = JSON.parse(String(codeContent).replace(/\\n$/, ''));\n return <TableRenderer tableConfig={cfg} />;\n } catch { return <pre>{children}</pre>; }\n }\n\n if (CUSTOM_LANGUAGES.has(language)) return <pre>{children}</pre>;\n\n if (React.isValidElement(codeChild)) {\n return React.cloneElement(codeChild as React.ReactElement, { 'data-block': true } as any);\n }\n }\n return children;\n },\n};\n","'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\n\nlet ChartJS: any = null;\nconst loadChartJS = async () => {\n if (ChartJS) return ChartJS;\n const mod = await import('chart.js');\n ChartJS = mod.Chart;\n ChartJS.register(...mod.registerables);\n return ChartJS;\n};\n\nexport const ChartRenderer: React.FC<{ chartConfig: any }> = React.memo(({ chartConfig }) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const chartInstanceRef = useRef<any>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [canvasKey, setCanvasKey] = useState(() => `canvas-${Date.now()}-${Math.random().toString(16).slice(2)}`);\n\n const chartData = useMemo(() => chartConfig.chartConfig.data, [chartConfig]);\n const chartOptions = useMemo(() => ({\n ...chartConfig.chartConfig.options, responsive: true, maintainAspectRatio: false,\n animation: { duration: 0 }, interaction: { intersect: false, mode: 'index' },\n plugins: {\n ...chartConfig.chartConfig.options?.plugins,\n legend: { ...chartConfig.chartConfig.options?.plugins?.legend, labels: { usePointStyle: true, padding: 15, font: { size: 12 } } },\n },\n }), [chartConfig]);\n\n useEffect(() => {\n const timer = setTimeout(async () => {\n try {\n setIsLoading(true); setError(null);\n if (chartInstanceRef.current) { try { chartInstanceRef.current.destroy(); } catch {} chartInstanceRef.current = null; }\n setCanvasKey(`canvas-${Date.now()}-${Math.random().toString(16).slice(2)}`);\n await new Promise((r) => setTimeout(r, 50));\n const CJS = await loadChartJS();\n if (containerRef.current) {\n const canvas = containerRef.current.querySelector('canvas') as HTMLCanvasElement;\n if (canvas) {\n const existing = CJS.getChart(canvas);\n if (existing) existing.destroy();\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n chartInstanceRef.current = new CJS(ctx, { type: chartConfig.chartConfig.type, data: chartData, options: chartOptions });\n setIsLoading(false);\n }\n }\n }\n } catch (err: any) { setError('Échec du graphique : ' + (err.message || 'Erreur inconnue')); setIsLoading(false); }\n }, 10);\n return () => { clearTimeout(timer); if (chartInstanceRef.current) { try { chartInstanceRef.current.destroy(); } catch {} chartInstanceRef.current = null; } };\n }, [chartConfig, chartData, chartOptions]);\n\n if (error) return (\n <div className=\"my-4 rounded-lg border px-4 py-3 text-sm\" style={{ borderColor: '#ef4444', backgroundColor: 'rgba(239,68,68,0.08)', color: '#b91c1c' }}>\n <strong className=\"mb-1 block\">Erreur de graphique</strong>{error}\n </div>\n );\n\n return (\n <div className=\"my-4 w-full\" style={{ height: 500, position: 'relative' }}>\n <div ref={containerRef} className=\"relative h-[calc(100%-40px)] p-2\">\n {isLoading && <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-sm\" style={{ color: 'var(--color-text-secondary,#64748b)' }}>Chargement du graphique...</div>}\n <canvas key={canvasKey} style={{ width: '100%', height: '100%', display: isLoading ? 'none' : 'block' }} />\n </div>\n </div>\n );\n});\n\nChartRenderer.displayName = 'ChartRenderer';\n","'use client';\n\nimport React, { useEffect, useState } from 'react';\n\nexport const TableRenderer: React.FC<{ tableConfig: any }> = React.memo(({ tableConfig }) => {\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n try {\n if (!tableConfig.headers || !Array.isArray(tableConfig.headers)) throw new Error('Headers must be an array');\n if (!tableConfig.rows || !Array.isArray(tableConfig.rows)) throw new Error('Rows must be an array');\n setError(null);\n } catch (err: any) { setError(err.message || 'Configuration de tableau invalide'); }\n }, [tableConfig]);\n\n if (error) return (\n <div className=\"my-4 rounded-lg border px-4 py-3 text-sm\" style={{ borderColor: '#ef4444', backgroundColor: 'rgba(239,68,68,0.08)', color: '#b91c1c' }}>\n <strong className=\"mb-1 block\">Erreur de tableau</strong>{error}\n </div>\n );\n\n return (\n <div className=\"my-4 w-full overflow-x-auto rounded-lg border\" style={{ backgroundColor: 'var(--color-surface,#fff)', borderColor: 'var(--color-border,#e2e8f0)' }}>\n {tableConfig.caption && <p className=\"mb-3 text-center text-sm font-semibold\" style={{ color: 'var(--color-text,#0f172a)' }}>{tableConfig.caption}</p>}\n <table className=\"min-w-full border-collapse text-sm\">\n <thead>\n <tr>\n {tableConfig.headers.map((header: string, i: number) => (\n <th key={i} className=\"border-b px-3 py-2 text-left text-xs font-semibold tracking-wide uppercase\"\n style={{ backgroundColor: 'var(--color-bg,#f8fafc)', borderColor: 'var(--color-border,#e2e8f0)', color: 'var(--color-text-secondary,#475569)', whiteSpace: 'nowrap' }}>\n {header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {tableConfig.rows.map((row: any[], rowIdx: number) => (\n <tr key={rowIdx} style={{ backgroundColor: rowIdx % 2 === 1 ? 'var(--color-bg,#f8fafc)' : undefined }}>\n {row.map((cell: any, cellIdx: number) => (\n <td key={cellIdx} className=\"border-b px-3 py-2 align-top\"\n style={{ borderColor: 'var(--color-border,#e2e8f0)', maxWidth: '260px', wordBreak: 'break-word', color: 'var(--color-text,#0f172a)' }}>\n {String(cell)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n});\n\nTableRenderer.displayName = 'TableRenderer';\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { RotateCcw, Loader2, Filter } from 'lucide-react';\nimport { cn } from './ui/cn';\nimport { Modal } from './ui/Modal';\nimport type { WorkspaceMember, AvatarUser } from '../types';\nimport { getInitials } from '../utils/constants';\n\nexport interface MessageFilters {\n concernsMe: boolean;\n members: string[];\n}\n\nexport const EMPTY_FILTERS: MessageFilters = { concernsMe: false, members: [] };\n\nexport interface MessageFilterDialogProps {\n open: boolean;\n onClose: () => void;\n onApply: (filters: MessageFilters) => Promise<void>;\n currentFilters: MessageFilters;\n members: WorkspaceMember[];\n avatarUsers?: AvatarUser[];\n hideAgents?: boolean;\n}\n\nexport const MessageFilterDialog: React.FC<MessageFilterDialogProps> = ({\n open, onClose, onApply, currentFilters, members, avatarUsers = [], hideAgents = false,\n}) => {\n const displayedMembers = hideAgents ? members.filter((m) => m.memberType !== 'agent') : members;\n const [draft, setDraft] = useState<MessageFilters>({ ...currentFilters });\n const [applying, setApplying] = useState(false);\n\n useEffect(() => { if (open) setDraft({ ...currentFilters }); }, [open, currentFilters]);\n\n const handleToggleConcernsMe = () => setDraft((prev) => ({\n concernsMe: !prev.concernsMe,\n members: !prev.concernsMe ? [] : prev.members,\n }));\n\n const handleToggleMember = (memberId: string) => setDraft((prev) => {\n const isSelected = prev.members.includes(memberId);\n return { ...prev, members: isSelected ? prev.members.filter((id) => id !== memberId) : [...prev.members, memberId] };\n });\n\n const handleApply = async () => {\n setApplying(true);\n try { await onApply(draft); } finally { setApplying(false); onClose(); }\n };\n\n const getAvatarForMember = (m: WorkspaceMember) => avatarUsers.find((u) => u.email === m.memberId);\n\n return (\n <Modal open={open} onClose={onClose} size=\"md\" title=\"Filtrer les messages\"\n description=\"Affinez les messages affichés dans la discussion.\"\n titleIcon={\n <div className=\"bg-[var(--color-primary-light,#eff6ff)] text-[var(--color-primary,#3b82f6)] flex h-8 w-8 items-center justify-center rounded-lg\">\n <Filter size={16} />\n </div>\n }\n closeOnBackdropClick closeOnEscape={!applying} closeButtonDisabled={applying}>\n <div className=\"flex flex-col gap-5 px-6 py-5\">\n {/* ConcernsMe toggle */}\n <button type=\"button\" disabled={applying} onClick={handleToggleConcernsMe}\n className={cn('flex items-center justify-between rounded-xl border px-4 py-3 text-left transition-all',\n draft.concernsMe ? 'border-[var(--color-primary,#3b82f6)] bg-[var(--color-primary-light,#eff6ff)]'\n : 'border-[var(--color-border,#e2e8f0)] hover:border-[var(--color-primary,#3b82f6)]/40')}>\n <div className=\"flex flex-col\">\n <span className={cn('text-sm font-medium', draft.concernsMe ? 'text-[var(--color-primary,#3b82f6)]' : 'text-[var(--color-text,#0f172a)]')}>\n Messages qui me concernent\n </span>\n <span className=\"text-[var(--color-text-muted,#94a3b8)] text-[11px]\">\n Messages envoyés par moi ou dans lesquels je suis mentionné\n </span>\n </div>\n <div className={cn('relative h-6 w-11 flex-shrink-0 rounded-full transition-colors',\n draft.concernsMe ? 'bg-[var(--color-primary,#3b82f6)]' : 'bg-[var(--color-border,#e2e8f0)]')}>\n <div className={cn('absolute top-0.5 h-5 w-5 rounded-full bg-white shadow-sm transition-transform',\n draft.concernsMe ? 'translate-x-[22px]' : 'translate-x-0.5')} />\n </div>\n </button>\n\n {/* Members filter */}\n <div className=\"flex flex-col gap-2\">\n <span className=\"text-[var(--color-text-muted,#94a3b8)] text-xs font-semibold tracking-wider uppercase\">Filtrer par membres</span>\n <div className={cn('flex max-h-52 flex-col gap-1 overflow-y-auto rounded-xl border p-2 transition-opacity',\n draft.concernsMe ? 'pointer-events-none border-[var(--color-border,#e2e8f0)]/50 opacity-50' : 'border-[var(--color-border,#e2e8f0)]')}>\n {displayedMembers.map((member) => {\n const isSelected = draft.members.includes(member.memberId);\n const avatar = getAvatarForMember(member);\n return (\n <button key={member._id} type=\"button\" disabled={draft.concernsMe || applying}\n onClick={() => handleToggleMember(member.memberId)}\n className={cn('flex items-center gap-2.5 rounded-lg px-3 py-2 text-left transition-all',\n isSelected ? 'border-[var(--color-primary,#3b82f6)] bg-[var(--color-primary-light,#eff6ff)] border'\n : 'border border-transparent hover:bg-[var(--color-bg,#f8fafc)]')}>\n <div className={cn('flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full text-[10px] font-semibold overflow-hidden',\n isSelected ? 'bg-[var(--color-primary,#3b82f6)] text-white' : 'bg-[var(--color-bg,#f8fafc)] text-[var(--color-text-muted,#94a3b8)]')}>\n {avatar?.avatarUrl ? <img src={avatar.avatarUrl} alt={member.memberName} className=\"h-full w-full object-cover\" /> : getInitials(member.memberName)}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className={cn('truncate text-xs font-medium', isSelected ? 'text-[var(--color-primary,#3b82f6)]' : 'text-[var(--color-text,#0f172a)]')}>\n {member.memberName}\n </div>\n <div className=\"text-[var(--color-text-muted,#94a3b8)] text-[10px]\">\n {member.memberType === 'agent' ? 'Agent IA' : 'Utilisateur'}\n </div>\n </div>\n {isSelected && (\n <svg className=\"text-[var(--color-primary,#3b82f6)] flex-shrink-0\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M3 8.5L6 11.5L13 4.5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </button>\n );\n })}\n {displayedMembers.length === 0 && (\n <div className=\"text-[var(--color-text-muted,#94a3b8)] py-4 text-center text-xs italic\">Aucun membre dans ce workspace</div>\n )}\n </div>\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"border-[var(--color-border,#e2e8f0)] flex items-center justify-between border-t px-6 py-3\">\n <button type=\"button\" onClick={() => setDraft({ ...EMPTY_FILTERS })} disabled={applying}\n className=\"text-[var(--color-text-muted,#94a3b8)] hover:text-[var(--color-text,#0f172a)] flex items-center gap-1.5 text-xs transition-colors disabled:opacity-50\">\n <RotateCcw size={12} /> Réinitialiser\n </button>\n <div className=\"flex gap-2\">\n <button type=\"button\" onClick={onClose} disabled={applying}\n className=\"border-[var(--color-border,#e2e8f0)] text-[var(--color-text-muted,#94a3b8)] hover:text-[var(--color-text,#0f172a)] rounded-lg border px-4 py-1.5 text-xs font-medium transition-colors disabled:opacity-50\">\n Annuler\n </button>\n <button type=\"button\" onClick={handleApply} disabled={applying}\n className=\"bg-[var(--color-primary,#3b82f6)] hover:bg-[var(--color-primary-hover,#2563eb)] flex items-center gap-1.5 rounded-lg px-4 py-1.5 text-xs font-medium text-white transition-colors disabled:opacity-70\">\n {applying && <Loader2 size={12} className=\"animate-spin\" />}\n {applying ? 'Application...' : 'Appliquer'}\n </button>\n </div>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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","names":["WorkspaceEvent","import_react","ROLE_LABELS","fixMojibake","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","React","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","pages","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","React","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_react","import_lucide_react","import_react","import_lucide_react","import_jsx_runtime","import_streamdown","import_styles","import_react","import_react","import_jsx_runtime","React","import_react","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime"]}