UNPKG

aura-glass

Version:

A comprehensive glassmorphism design system for React applications with 142+ production-ready components

356 lines (353 loc) 14 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { useState } from 'react'; import { GlassCore } from '../../primitives/GlassCore.js'; import '../../primitives/glass/GlassAdvanced.js'; import '../../primitives/OptimizedGlassCore.js'; import '../../primitives/glass/OptimizedGlassAdvanced.js'; import '../../primitives/MotionNative.js'; import '../../primitives/motion/MotionFramer.js'; import { useCollaboration } from './GlassCollaborationProvider.js'; import { cn } from '../../lib/utilsComprehensive.js'; const UserAvatar = ({ user, size = "md", showStatus = true }) => { const sizeClasses = { sm: "w-6 h-6 text-xs", md: "w-8 h-8 text-sm", lg: "w-10 h-10 text-base" }; const isActive = Date.now() - user.lastActive < 60000; // Active within last minute return jsxs("div", { "data-glass-component": true, className: 'relative', children: [user.avatar ? jsx("img", { src: user.avatar, alt: user.name, className: cn("rounded-full object-cover border-2", sizeClasses[size], isActive ? "border-green-400" : "border-gray-300") }) : jsx("div", { className: cn("rounded-full flex items-center justify-center text-white font-medium border-2", sizeClasses[size], isActive ? "border-green-400" : "border-gray-300"), style: { backgroundColor: user.color }, children: user.name[0]?.toUpperCase() }), showStatus && jsx("div", { className: cn("absolute -bottom-0.5 -right-0.5 w-3 h-3 rounded-full border-2 border-white", isActive ? "bg-green-400" : "bg-gray-400") })] }); }; const ActivityItem = ({ activity, user }) => { const formatTime = timestamp => { const now = Date.now(); const diff = now - timestamp; const minutes = Math.floor(diff / 60000); const hours = Math.floor(diff / 3600000); if (minutes < 1) return "now"; if (minutes < 60) return `${minutes}m`; if (hours < 24) return `${hours}h`; return new Date(timestamp).toLocaleDateString(); }; const getActivityIcon = () => { switch (activity.type) { case "join": return "🟢"; case "leave": return "🔴"; case "edit": return "✏️"; case "comment": return "💬"; case "cursor_move": return "👆"; default: return "•"; } }; const getActivityColor = () => { switch (activity.type) { case "join": return "text-green-600"; case "leave": return "text-red-600"; case "edit": return "text-blue-600"; case "comment": return "text-purple-600"; default: return "text-gray-600"; } }; return jsxs("div", { className: 'glass-flex glass-items-center glass-gap-3 glass-p-2 glass-radius hover:glass-surface-subtle transition-colors', children: [jsxs("div", { className: "glass-flex glass-items-center glass-gap-2", children: [user && jsx(UserAvatar, { user: user, size: "sm", showStatus: false }), jsx("span", { className: "glass-text-lg", children: getActivityIcon() })] }), jsx("div", { className: 'glass-flex-1 min-glass-w-0', children: jsx("p", { className: cn("text-sm", getActivityColor()), children: activity.description }) }), jsx("span", { className: 'glass-text-xs glass-text-secondary whitespace-nowrap', children: formatTime(activity.timestamp) })] }); }; const ConnectionStatus = () => { const { connectionStatus, isConnected } = useCollaboration(); const getStatusColor = () => { switch (connectionStatus) { case "connected": return "text-green-600"; case "connecting": case "reconnecting": return "text-yellow-600"; case "disconnected": return "text-red-600"; default: return "text-gray-600"; } }; const getStatusIcon = () => { switch (connectionStatus) { case "connected": return "🟢"; case "connecting": case "reconnecting": return "🟡"; case "disconnected": return "🔴"; default: return "⚫"; } }; const getStatusText = () => { switch (connectionStatus) { case "connected": return "Connected"; case "connecting": return "Connecting..."; case "reconnecting": return "Reconnecting..."; case "disconnected": return "Disconnected"; default: return "Unknown"; } }; return jsxs("div", { className: cn("flex items-center gap-2 text-sm", getStatusColor()), children: [jsx("span", { children: getStatusIcon() }), jsx("span", { children: getStatusText() })] }); }; const GlassCollaborationDashboard = ({ className, position = "top-right", showUserList = true, showActivityFeed = true, showControls = true }) => { const { users, currentUser, activities, comments, showCursors, showComments, showActivity, toggleCursors, toggleComments, toggleActivity } = useCollaboration(); const [isExpanded, setIsExpanded] = useState(false); const [activeTab, setActiveTab] = useState("users"); const positionClasses = { "top-left": "top-4 left-4", "top-right": "top-4 right-4", "bottom-left": "bottom-4 left-4", "bottom-right": "bottom-4 right-4" }; const activeUsers = users.filter(user => Date.now() - user.lastActive < 300000); // Active within 5 minutes const recentActivities = activities.slice(0, 20); const unresolvedComments = comments.filter(c => !c.resolved); return jsx("div", { className: cn("fixed z-40", positionClasses[position], className), children: !isExpanded ? // Collapsed state jsx(GlassCore, { className: "glass-p-3 glass-contrast-guard", children: jsxs("button", { onClick: () => setIsExpanded(true), className: 'glass-flex glass-items-center glass-gap-3 hover:glass-surface-subtle glass-radius glass-p-2 transition-colors glass-focus glass-touch-target glass-contrast-guard', children: [jsxs("div", { className: 'glass-flex -space-x-2', children: [activeUsers.slice(0, 3).map(user => jsx(UserAvatar, { user: user, size: "sm" }, user.id)), activeUsers.length > 3 && jsxs("div", { className: 'w-6 h-6 glass-surface-subtle glass-text-secondary glass-radius-full glass-flex glass-items-center glass-justify-center glass-text-xs glass-border-2 glass-border-white', children: ["+", activeUsers.length - 3] })] }), jsxs("div", { className: 'text-left', children: [jsxs("div", { className: 'glass-text-sm font-medium glass-text-secondary', children: [activeUsers.length, " online"] }), jsx(ConnectionStatus, {})] }), unresolvedComments.length > 0 && jsx("div", { className: 'w-5 h-5 glass-surface-red text-primary glass-radius-full glass-flex glass-items-center glass-justify-center glass-text-xs', children: unresolvedComments.length })] }) }) : // Expanded state jsxs(GlassCore, { className: 'w-80 max-h-96 overflow-hidden glass-contrast-guard', children: [jsxs("div", { className: "glass-flex glass-items-center glass-justify-between glass-p-4 glass-border-b glass-border-subtle", children: [jsx("h3", { className: 'font-semibold glass-text-secondary', children: "Collaboration" }), jsx("button", { onClick: () => setIsExpanded(false), className: 'glass-text-secondary hover:glass-text-secondary glass-p-1 glass-focus glass-touch-target glass-contrast-guard', children: "\u2715" })] }), jsx("div", { className: "glass-px-4 glass-py-2 glass-surface-subtle glass-border-b glass-border-subtle", children: jsx(ConnectionStatus, {}) }), showControls && jsx("div", { className: "glass-p-4 glass-border-b glass-border-subtle", children: jsxs("div", { className: "glass-grid glass-grid-cols-3 glass-gap-2", children: [jsxs("button", { onClick: toggleCursors, className: cn("flex flex-col items-center gap-1 p-2 rounded text-xs transition-colors glass-focus glass-touch-target glass-contrast-guard", showCursors ? "bg-blue-100 text-blue-700" : "bg-gray-100 text-gray-600 hover:bg-gray-200"), children: [jsx("span", { children: "\uD83D\uDC46" }), "Cursors"] }), jsxs("button", { onClick: toggleComments, className: cn("flex flex-col items-center gap-1 p-2 rounded text-xs transition-colors relative glass-focus glass-touch-target glass-contrast-guard", showComments ? "bg-purple-100 text-purple-700" : "bg-gray-100 text-gray-600 hover:bg-gray-200"), children: [jsx("span", { children: "\uD83D\uDCAC" }), "Comments", unresolvedComments.length > 0 && jsx("div", { className: 'absolute glass-top-1 -right-1 w-4 h-4 glass-surface-red text-primary glass-radius-full glass-flex glass-items-center glass-justify-center glass-text-xs', children: unresolvedComments.length })] }), jsxs("button", { onClick: toggleActivity, className: cn("flex flex-col items-center gap-1 p-2 rounded text-xs transition-colors glass-focus glass-touch-target glass-contrast-guard", showActivity ? "bg-green-100 text-green-700" : "bg-gray-100 text-gray-600 hover:bg-gray-200"), children: [jsx("span", { children: "\uD83D\uDCCA" }), "Activity"] })] }) }), jsxs("div", { className: "glass-flex glass-border-b glass-border-subtle", children: [jsxs("button", { onClick: () => setActiveTab("users"), className: cn("flex-1 px-4 py-2 text-sm font-medium transition-colors glass-focus glass-touch-target glass-contrast-guard", activeTab === "users" ? "text-blue-600 border-b-2 border-blue-600 bg-blue-50" : "text-gray-600 hover:text-gray-900"), children: ["Users (", activeUsers.length, ")"] }), jsx("button", { onClick: () => setActiveTab("activity"), className: cn("flex-1 px-4 py-2 text-sm font-medium transition-colors glass-focus glass-touch-target glass-contrast-guard", activeTab === "activity" ? "text-blue-600 border-b-2 border-blue-600 bg-blue-50" : "text-gray-600 hover:text-gray-900"), children: "Activity" })] }), jsxs("div", { className: 'glass-max-h-64 overflow-y-auto', children: [activeTab === "users" && showUserList && jsxs("div", { className: 'glass-p-4 space-y-3', children: [activeUsers.map(user => { const isCurrentUser = user.id === currentUser?.id; const isActive = Date.now() - user.lastActive < 60000; return jsxs("div", { className: cn("flex items-center gap-3 p-2 rounded", isCurrentUser ? "bg-blue-50" : "hover:bg-gray-50"), children: [jsx(UserAvatar, { user: user, size: "md" }), jsxs("div", { className: 'glass-flex-1 min-glass-w-0', children: [jsxs("div", { className: "glass-flex glass-items-center glass-gap-2", children: [jsxs("span", { className: 'glass-text-sm font-medium glass-text-secondary truncate', children: [user.name, isCurrentUser && " (You)"] }), !isActive && jsx("span", { className: "glass-text-xs glass-text-secondary", children: "Away" })] }), jsx("span", { className: 'glass-text-xs glass-text-secondary truncate', children: user.email })] }), user.cursor && jsx("span", { className: 'glass-text-xs text-primary', children: "\uD83D\uDCCD" })] }, user.id); }), activeUsers.length === 0 && jsxs("div", { className: 'text-center glass-py-6 glass-text-secondary', children: [jsx("div", { className: 'glass-text-2xl mb-2', children: "\uD83D\uDC65" }), jsx("p", { className: "glass-text-sm", children: "No users online" })] })] }), activeTab === "activity" && showActivityFeed && jsxs("div", { className: 'glass-p-4 space-y-1', children: [recentActivities.map(activity => { const user = users.find(u => u.id === activity.userId); return jsx(ActivityItem, { activity: activity, user: user }, activity.id); }), recentActivities.length === 0 && jsxs("div", { className: 'text-center glass-py-6 glass-text-secondary', children: [jsx("div", { className: 'glass-text-2xl mb-2', children: "\uD83D\uDCCA" }), jsx("p", { className: "glass-text-sm", children: "No recent activity" })] })] })] }), jsx("div", { className: "glass-px-4 glass-py-2 glass-surface-subtle glass-border-t glass-border-subtle glass-text-xs glass-text-secondary", children: jsxs("div", { className: "glass-flex glass-justify-between", children: [jsxs("span", { children: [comments.length, " comments"] }), jsxs("span", { children: [activities.length, " activities"] })] }) })] }) }); }; export { GlassCollaborationDashboard }; //# sourceMappingURL=GlassCollaborationDashboard.js.map