UNPKG

aura-glass

Version:

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

402 lines (399 loc) 17.9 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { useState, useEffect, useCallback } from 'react'; import { cn } from '../../lib/utilsComprehensive.js'; import '../../primitives/GlassCore.js'; import '../../primitives/glass/GlassAdvanced.js'; import { OptimizedGlassCore } from '../../primitives/OptimizedGlassCore.js'; import '../../primitives/glass/OptimizedGlassAdvanced.js'; import '../../primitives/MotionNative.js'; import { MotionFramer } from '../../primitives/motion/MotionFramer.js'; import { usePredictiveEngine, useInteractionRecorder } from '../advanced/GlassPredictiveEngine.js'; import { useAchievements } from '../advanced/GlassAchievementSystem.js'; import { useBiometricAdaptation } from '../advanced/GlassBiometricAdaptation.js'; import { useEyeTracking } from '../advanced/GlassEyeTracking.js'; import { useSpatialAudio } from '../advanced/GlassSpatialAudio.js'; import { GlassButton } from '../button/GlassButton.js'; import '../button/GlassFab.js'; import '../button/GlassMagneticButton.js'; import { Target, Brain, Eye, Plus, MoreHorizontal } from 'lucide-react'; /** * GlassKanban component * A comprehensive Kanban board with consciousness interface features */ function GlassKanban({ // TODO: Integrate ContrastGuard for table cells, list items, badges, card titles, and other text content for WCAG AA compliance columns, className, enableDragDrop = true, showLimits = true, showMetrics = false, onCardClick, onColumnClick, onCardMove, // Consciousness features consciousness = false, predictive = false, adaptive = false, eyeTracking = false, spatialAudio = false, trackAchievements = false }) { // Consciousness state const [cardInteractionCounts, setCardInteractionCounts] = useState({}); const [columnInteractionCounts, setColumnInteractionCounts] = useState({}); const [focusedCard, setFocusedCard] = useState(null); const [focusedColumn, setFocusedColumn] = useState(null); const [workflowSuggestions, setWorkflowSuggestions] = useState([]); const [boardMetrics, setBoardMetrics] = useState(null); // Consciousness hooks const predictiveEngine = predictive ? usePredictiveEngine() : null; const eyeTracker = eyeTracking ? useEyeTracking() : null; adaptive ? useBiometricAdaptation() : null; const spatialAudioEngine = spatialAudio ? useSpatialAudio() : null; const interactionRecorder = consciousness ? useInteractionRecorder() : null; const achievementTracker = trackAchievements ? useAchievements() : null; // Consciousness effects // Eye tracking for card and column focus useEffect(() => { if (!eyeTracking || !eyeTracker) return; // Eye tracking functionality temporarily disabled // eyeTracker.startTracking(handleGazeData); // return () => eyeTracker.stopTracking(); }, [eyeTracking, eyeTracker, achievementTracker, trackAchievements]); // Predictive workflow suggestions useEffect(() => { if (!predictive || !predictiveEngine) return; const generateWorkflowSuggestions = async () => { try { const boardContext = { columns: columns.map(col => ({ id: col.id, title: col.title, cardCount: col.cards.length, limit: col.limit, cards: col.cards.map(card => ({ id: card.id, title: card.title, priority: card.priority, interactionCount: cardInteractionCounts[card.id] || 0 })) })), interactions: cardInteractionCounts }; const suggestions = (await predictiveEngine.engine?.generateWorkflowSuggestions(boardContext)) || []; setWorkflowSuggestions(suggestions.slice(0, 3)); // Generate board metrics const metrics = (await predictiveEngine.engine?.analyzeBoardPerformance(boardContext)) || {}; setBoardMetrics(metrics); } catch (error) { console.warn("Predictive workflow generation failed:", error); } }; if (columns.length > 0) { const timeoutId = setTimeout(generateWorkflowSuggestions, 1000); return () => clearTimeout(timeoutId); } }, [columns, predictive, predictiveEngine, cardInteractionCounts]); // Spatial audio for card interactions useEffect(() => { if (!spatialAudio || !spatialAudioEngine) return; const playInteractionSound = type => { const soundMap = { "card-click": { sound: "card-select", volume: 0.4, position: { x: 0, y: 0, z: 0 } }, "column-click": { sound: "column-focus", volume: 0.3, position: { x: -0.5, y: 0, z: 0 } }, "card-move": { sound: "card-move", volume: 0.5, position: { x: 0.5, y: 0, z: 0 } } }; const config = soundMap[type]; spatialAudioEngine.playGlassSound(config.sound, config.position, { volume: config.volume, reverb: 0.2 }); }; // Store sound function for use in handlers window._kanbanSpatialAudio = playInteractionSound; return () => { delete window._kanbanSpatialAudio; }; }, [spatialAudio, spatialAudioEngine]); // Enhanced card click handler const handleCardClick = useCallback((cardId, columnId) => { // Update interaction counts setCardInteractionCounts(prev => ({ ...prev, [cardId]: (prev[cardId] || 0) + 1 })); // Record interaction for consciousness tracking if (consciousness && interactionRecorder) { const mockEvent = { currentTarget: { id: `card-${cardId}` }, clientX: 0, clientY: 0, button: 0, ctrlKey: false, altKey: false, shiftKey: false, metaKey: false, preventDefault: () => {}, stopPropagation: () => {} }; interactionRecorder.recordClick(mockEvent); } // Track achievement if (trackAchievements && achievementTracker) { achievementTracker.recordAction("kanban_card_interaction", { cardId, columnId, timestamp: Date.now() }); } // Play spatial audio if (spatialAudio && window._kanbanSpatialAudio) { window._kanbanSpatialAudio("card-click"); } onCardClick?.(cardId, columnId); }, [consciousness, interactionRecorder, trackAchievements, achievementTracker, spatialAudio, onCardClick, cardInteractionCounts]); // Enhanced column click handler const handleColumnClick = useCallback(columnId => { // Update interaction counts setColumnInteractionCounts(prev => ({ ...prev, [columnId]: (prev[columnId] || 0) + 1 })); // Record interaction for consciousness tracking if (consciousness && interactionRecorder) { const mockEvent = { currentTarget: { id: `column-${columnId}` }, clientX: 0, clientY: 0, button: 0, ctrlKey: false, altKey: false, shiftKey: false, metaKey: false, preventDefault: () => {}, stopPropagation: () => {} }; interactionRecorder.recordClick(mockEvent); } // Play spatial audio if (spatialAudio && window._kanbanSpatialAudio) { window._kanbanSpatialAudio("column-click"); } onColumnClick?.(columnId); }, [consciousness, interactionRecorder, spatialAudio, onColumnClick, columnInteractionCounts]); return jsx(MotionFramer, { "data-glass-component": true, preset: "fadeIn", className: "glass-w-full glass-h-full", children: jsxs("div", { className: cn("grid glass-gap-4 glass-p-4", consciousness && "consciousness-kanban-board", predictive && workflowSuggestions.length > 0 && "consciousness-predictive-board", adaptive && "consciousness-adaptive-board", eyeTracking && "consciousness-eye-trackable", className), style: { gridTemplateColumns: `repeat(${columns.length}, minmax(280px, 1fr))` }, "data-consciousness-kanban": "true", "data-consciousness-active": String(!!consciousness), "data-predictive": String(!!predictive), "data-adaptive": String(!!adaptive), "data-eye-tracking": String(!!eyeTracking), "data-spatial-audio": String(!!spatialAudio), children: [showMetrics && boardMetrics && jsx("div", { className: 'col-span-full mb-4 glass-p-3 glass-surface-subtle/5 glass-radius-lg glass-border glass-border-white/10', children: jsxs("div", { className: "glass-flex glass-items-center glass-justify-between glass-text-sm", children: [jsxs("div", { className: "glass-flex glass-items-center glass-gap-4", children: [jsxs("span", { className: 'text-primary/80', children: ["Total Cards: ", boardMetrics.totalCards] }), jsxs("span", { className: 'text-primary/80', children: ["Productivity: ", Math.round(boardMetrics.productivity * 100), "%"] }), jsxs("span", { className: 'text-primary/80', children: ["Completion Rate:", " ", Math.round(boardMetrics.completionRate * 100), "%"] })] }), boardMetrics.bottlenecks.length > 0 && jsxs("div", { className: "glass-flex glass-items-center glass-gap-2", children: [jsx(Target, { className: 'w-4 h-4 text-primary' }), jsxs("span", { className: 'text-primary glass-text-xs', children: ["Bottlenecks: ", boardMetrics.bottlenecks.join(", ")] })] })] }) }), predictive && workflowSuggestions.length > 0 && jsxs("div", { className: 'col-span-full mb-4 glass-p-3 glass-surface-primary/10 glass-radius-lg glass-border glass-border-primary/20', children: [jsxs("div", { className: 'glass-flex glass-items-center glass-gap-2 mb-2', children: [jsx(Brain, { className: 'w-4 h-4 text-primary' }), jsx("span", { className: 'text-primary glass-text-sm font-medium', children: "Workflow Suggestions" })] }), jsx("div", { className: "glass-gap-2", children: workflowSuggestions.map((suggestion, index) => jsxs("div", { className: 'glass-text-xs text-primary/70 glass-flex glass-items-center glass-justify-between', children: [jsxs("span", { children: ["Move \"", suggestion.cardId, "\" to \"", suggestion.suggestedColumn, "\""] }), jsx("span", { className: 'text-primary/80', children: suggestion.reason })] }, index)) })] }), columns.map(column => { const isOverLimit = column.limit && column.cards.length > column.limit; const isFocused = eyeTracking && focusedColumn === column.id; const interactionCount = columnInteractionCounts[column.id] || 0; return jsxs("div", { className: cn("glass-gap-3 min-h-[200px] glass-p-3 glass-radius-xl", "bg-white/5 border border-white/10", isFocused && "consciousness-column-focused", isOverLimit && "consciousness-column-overlimit", interactionCount > 0 && "consciousness-column-interacted", consciousness && "consciousness-enhanced-column"), "data-consciousness-column": "true", "data-column-id": column.id, "data-interaction-count": interactionCount, "data-gaze-focused": isFocused, "data-over-limit": isOverLimit, onClick: () => handleColumnClick(column.id), children: [jsxs("div", { className: "glass-flex glass-items-center glass-justify-between", children: [jsxs("div", { className: 'glass-text-sm text-primary font-medium glass-flex glass-items-center glass-gap-2', style: { color: column.color || "white" }, children: [column.title, jsxs("span", { className: 'glass-text-xs text-primary/60', children: ["(", column.cards.length, ")"] }), isFocused && jsx(Eye, { className: 'w-3 h-3 text-primary' })] }), jsxs("div", { className: "glass-flex glass-items-center glass-gap-2", children: [showLimits && column.limit && jsxs("span", { className: cn("glass-text-xs glass-px-2 glass-py-1 glass-radius-md", isOverLimit ? "bg-red-500/20 text-red-300" : "bg-white/10 glass-text-primary/60"), children: [column.cards.length, "/", column.limit] }), jsx(GlassButton, { variant: "ghost", size: "sm", className: "glass-p-1", consciousness: consciousness, adaptive: adaptive, spatialAudio: spatialAudio, trackAchievements: trackAchievements, children: jsx(Plus, { className: 'w-3 h-3' }) }), jsx(GlassButton, { variant: "ghost", size: "sm", className: "glass-p-1", consciousness: consciousness, adaptive: adaptive, spatialAudio: spatialAudio, trackAchievements: trackAchievements, children: jsx(MoreHorizontal, { className: 'w-3 h-3' }) })] })] }), jsx("div", { className: "glass-gap-2", children: column.cards.map((card, cardIndex) => { const isCardFocused = eyeTracking && focusedCard === card.id; const cardInteractionCount = cardInteractionCounts[card.id] || 0; const hasSuggestion = workflowSuggestions.some(s => s.cardId === card.id); return jsxs(OptimizedGlassCore, { elevation: "level1", className: cn("glass-radius-lg glass-p-3 border cursor-pointer transition-all duration-200", "hover:border-white/30 hover:bg-white/10", isCardFocused && "consciousness-card-focused border-primary", cardInteractionCount > 0 && "consciousness-card-interacted", hasSuggestion && "consciousness-card-suggested border-yellow-400/50", card.priority === "high" && "border-red-400/50", card.priority === "medium" && "border-yellow-400/50", card.priority === "low" && "border-green-400/50", consciousness && "consciousness-enhanced-card"), style: { animationDelay: `${cardIndex * 50}ms`, animationFillMode: "both" }, "data-consciousness-card": "true", "data-card-id": card.id, "data-column-id": column.id, "data-interaction-count": cardInteractionCount, "data-gaze-focused": isCardFocused, "data-priority": card.priority, "data-has-suggestion": hasSuggestion, onClick: () => handleCardClick(card.id, column.id), children: [jsxs("div", { className: 'glass-flex glass-items-start glass-justify-between mb-2', children: [jsxs("div", { className: 'glass-text-sm text-primary font-medium glass-flex-1', children: [card.title, isCardFocused && jsx(Eye, { className: 'inline-block w-3 h-3 text-primary glass-ml-2' })] }), hasSuggestion && jsx("div", { className: 'glass-text-xs text-primary glass-surface-yellow/20 glass-px-2 glass-py-1 glass-radius-md', children: "Suggested" })] }), card.description && jsx("div", { className: 'glass-text-xs text-primary/70 mb-2', children: card.description }), jsxs("div", { className: "glass-flex glass-items-center glass-justify-between", children: [jsxs("div", { className: "glass-flex glass-items-center glass-gap-2", children: [card.priority && jsx("span", { className: cn("glass-text-xs glass-px-2 glass-py-1 glass-radius-md", card.priority === "high" && "bg-red-500/20 text-red-300", card.priority === "medium" && "bg-yellow-500/20 text-yellow-300", card.priority === "low" && "bg-green-500/20 text-green-300"), children: card.priority }), card.tags && card.tags.length > 0 && jsx("div", { className: "glass-flex glass-gap-1", children: card.tags.slice(0, 2).map((tag, index) => jsx("span", { className: 'glass-text-xs text-primary glass-surface-primary/20 glass-px-1 glass-radius-md', children: tag }, index)) })] }), cardInteractionCount > 0 && jsxs("span", { className: 'glass-text-xs text-primary/50', children: [cardInteractionCount, " interactions"] })] }), card.assignee && jsxs("div", { className: 'glass-text-xs text-primary/60 glass-mt-2', children: ["Assigned: ", card.assignee] }), card.dueDate && jsxs("div", { className: 'glass-text-xs text-primary/60 glass-mt-1', children: ["Due: ", card.dueDate.toLocaleDateString()] })] }, card.id); }) })] }, column.id); })] }) }); } export { GlassKanban, GlassKanban as default }; //# sourceMappingURL=GlassKanban.js.map