"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VectorVisualizations = exports.VectorTimeSeries = exports.VectorClusterMap = exports.VectorComparison = exports.VectorProjection = exports.VectorNetwork = exports.VectorHeatmap = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
/**
 * Vector Visualization Components
 *
 * React components for visualizing vector embeddings, similarity networks,
 * and semantic relationships. These components provide intuitive visual
 * interfaces for understanding vector-based operations.
 */
const react_1 = require("react");
/**
 * VectorHeatmap visualizes vector embeddings as a heatmap
 */
const VectorHeatmap = ({ vectors, width = 800, height = 400, colorScale = ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#a50f15', '#67000d'], showLabels = true, onVectorClick, title = 'Vector Embedding Heatmap', maxDimensions = 50 }) => {
    const containerRef = (0, react_1.useRef)(null);
    const [error, setError] = (0, react_1.useState)(null);
    (0, react_1.useEffect)(() => {
        if (!containerRef.current || vectors.length === 0)
            return;
        try {
            // Check if all vectors have the same dimensions
            const dimensions = vectors[0].vector.length;
            for (const vector of vectors) {
                if (vector.vector.length !== dimensions) {
                    throw new Error('All vectors must have the same dimensions');
                }
            }
            // In a real implementation, we would use D3.js to create the heatmap
            // For this example, we're just creating a simple canvas-based implementation
            // Clear previous content
            containerRef.current.innerHTML = '';
            // Create canvas element
            const canvas = document.createElement('canvas');
            canvas.width = width;
            canvas.height = height;
            containerRef.current.appendChild(canvas);
            const ctx = canvas.getContext('2d');
            if (!ctx) {
                throw new Error('Could not get canvas context');
            }
            // Calculate dimensions
            const actualDimensions = Math.min(dimensions, maxDimensions);
            const cellWidth = width / actualDimensions;
            const cellHeight = height / vectors.length;
            // Draw heatmap
            for (let i = 0; i < vectors.length; i++) {
                const vector = vectors[i];
                for (let j = 0; j < actualDimensions; j++) {
                    // Normalize value to 0-1 range
                    const value = (vector.vector[j] + 1) / 2;
                    // Get color based on value
                    const colorIndex = Math.floor(value * (colorScale.length - 1));
                    ctx.fillStyle = colorScale[colorIndex];
                    // Draw cell
                    ctx.fillRect(j * cellWidth, i * cellHeight, cellWidth, cellHeight);
                    // Add border
                    ctx.strokeStyle = '#ccc';
                    ctx.strokeRect(j * cellWidth, i * cellHeight, cellWidth, cellHeight);
                }
                // Add label
                if (showLabels) {
                    ctx.fillStyle = '#000';
                    ctx.font = '10px Arial';
                    ctx.fillText(vector.id, 5, i * cellHeight + cellHeight / 2 + 3);
                }
            }
            // Add click handler
            if (onVectorClick) {
                canvas.addEventListener('click', (event) => {
                    const rect = canvas.getBoundingClientRect();
                    const x = event.clientX - rect.left;
                    const y = event.clientY - rect.top;
                    // Determine which vector was clicked
                    const vectorIndex = Math.floor(y / cellHeight);
                    if (vectorIndex >= 0 && vectorIndex < vectors.length) {
                        onVectorClick(vectors[vectorIndex]);
                    }
                });
            }
        }
        catch (err) {
            setError(err instanceof Error ? err.message : 'Unknown error');
            console.error('Error rendering vector heatmap:', err);
        }
    }, [vectors, width, height, colorScale, showLabels, onVectorClick, maxDimensions]);
    return ((0, jsx_runtime_1.jsxs)("div", { className: "vector-visualization vector-heatmap", children: [(0, jsx_runtime_1.jsx)("h3", { children: title }), error && (0, jsx_runtime_1.jsx)("div", { className: "error", children: error }), (0, jsx_runtime_1.jsx)("div", { ref: containerRef, className: "heatmap-container", style: { width, height } })] }));
};
exports.VectorHeatmap = VectorHeatmap;
/**
 * VectorNetwork visualizes connections between vectors as a network graph
 */
const VectorNetwork = ({ vectors, connections, width = 800, height = 600, minSimilarity = 0.7, maxConnections = 50, colorScale = ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#08519c', '#08306b'], onNodeClick, onConnectionClick, title = 'Vector Similarity Network', layout = 'force', animated = true }) => {
    const containerRef = (0, react_1.useRef)(null);
    const [error, setError] = (0, react_1.useState)(null);
    (0, react_1.useEffect)(() => {
        if (!containerRef.current || vectors.length === 0)
            return;
        try {
            // Clear previous content
            containerRef.current.innerHTML = '';
            // In a real implementation, we would use a graph visualization library
            // such as D3-force or Sigma.js to create an interactive network graph
            // For this example, we'll just create a placeholder with information
            const infoDiv = document.createElement('div');
            infoDiv.className = 'network-info';
            infoDiv.innerHTML = `
        <p>Network graph with ${vectors.length} nodes and ${connections.length} connections</p>
        <p>Layout: ${layout}</p>
        <p>Minimum similarity: ${minSimilarity}</p>
        <p>Animated: ${animated ? 'Yes' : 'No'}</p>
        <p>This is a placeholder. In a real implementation, this would be an interactive network graph.</p>
      `;
            containerRef.current.appendChild(infoDiv);
            // Create SVG element (placeholder for actual implementation)
            const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            svg.setAttribute('width', width.toString());
            svg.setAttribute('height', height.toString());
            svg.style.border = '1px solid #ccc';
            containerRef.current.appendChild(svg);
            // Add a sample node and connection to demonstrate
            const node1 = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
            node1.setAttribute('cx', '200');
            node1.setAttribute('cy', '300');
            node1.setAttribute('r', '20');
            node1.setAttribute('fill', '#4292c6');
            const node2 = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
            node2.setAttribute('cx', '400');
            node2.setAttribute('cy', '300');
            node2.setAttribute('r', '20');
            node2.setAttribute('fill', '#4292c6');
            const link = document.createElementNS('http://www.w3.org/2000/svg', 'line');
            link.setAttribute('x1', '200');
            link.setAttribute('y1', '300');
            link.setAttribute('x2', '400');
            link.setAttribute('y2', '300');
            link.setAttribute('stroke', '#999');
            link.setAttribute('stroke-width', '2');
            svg.appendChild(link);
            svg.appendChild(node1);
            svg.appendChild(node2);
            // Add click handlers for demonstration
            if (onNodeClick) {
                node1.addEventListener('click', () => onNodeClick(vectors[0]));
                node2.addEventListener('click', () => onNodeClick(vectors[1]));
            }
            if (onConnectionClick && connections.length > 0) {
                link.addEventListener('click', () => onConnectionClick(connections[0]));
            }
        }
        catch (err) {
            setError(err instanceof Error ? err.message : 'Unknown error');
            console.error('Error rendering vector network:', err);
        }
    }, [vectors, connections, width, height, minSimilarity, maxConnections, colorScale, onNodeClick, onConnectionClick, layout, animated]);
    return ((0, jsx_runtime_1.jsxs)("div", { className: "vector-visualization vector-network", children: [(0, jsx_runtime_1.jsx)("h3", { children: title }), error && (0, jsx_runtime_1.jsx)("div", { className: "error", children: error }), (0, jsx_runtime_1.jsx)("div", { ref: containerRef, className: "network-container", style: { width, height } })] }));
};
exports.VectorNetwork = VectorNetwork;
/**
 * VectorProjection projects high-dimensional vectors into 2D or 3D space
 */
const VectorProjection = ({ vectors, width = 800, height = 600, method = 'pca', dimensions = 2, colorBy = 'cluster', sizeBy = 'importance', onVectorClick, title = 'Vector Projection', interactive = true }) => {
    const containerRef = (0, react_1.useRef)(null);
    const [error, setError] = (0, react_1.useState)(null);
    (0, react_1.useEffect)(() => {
        if (!containerRef.current || vectors.length === 0)
            return;
        try {
            // Clear previous content
            containerRef.current.innerHTML = '';
            // In a real implementation, we would use dimensionality reduction techniques
            // like PCA, t-SNE, or UMAP to project the vectors into 2D or 3D space
            // For 3D visualization, we would use Three.js or a similar library
            // For this example, we'll just create a placeholder with information
            const infoDiv = document.createElement('div');
            infoDiv.className = 'projection-info';
            infoDiv.innerHTML = `
        <p>Vector projection with ${vectors.length} vectors</p>
        <p>Method: ${method}</p>
        <p>Dimensions: ${dimensions}D</p>
        <p>Color by: ${colorBy}</p>
        <p>Size by: ${sizeBy}</p>
        <p>Interactive: ${interactive ? 'Yes' : 'No'}</p>
        <p>This is a placeholder. In a real implementation, this would be an interactive projection visualization.</p>
      `;
            containerRef.current.appendChild(infoDiv);
            // Create canvas element (placeholder for actual implementation)
            const canvas = document.createElement('canvas');
            canvas.width = width;
            canvas.height = height;
            canvas.style.border = '1px solid #ccc';
            containerRef.current.appendChild(canvas);
            const ctx = canvas.getContext('2d');
            if (!ctx) {
                throw new Error('Could not get canvas context');
            }
            // Draw a simple scatter plot for demonstration
            ctx.fillStyle = '#f0f0f0';
            ctx.fillRect(0, 0, width, height);
            // Generate random positions for demonstration
            const positions = vectors.map(() => ({
                x: 100 + Math.random() * (width - 200),
                y: 100 + Math.random() * (height - 200)
            }));
            // Draw points
            vectors.forEach((vector, i) => {
                const { x, y } = positions[i];
                // Get color based on metadata (for demonstration)
                const cluster = vector.metadata?.cluster || 0;
                const colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2'];
                const color = colors[cluster % colors.length];
                // Get size based on metadata (for demonstration)
                const importance = vector.metadata?.importance || 0.5;
                const size = 5 + importance * 15;
                // Draw point
                ctx.beginPath();
                ctx.arc(x, y, size, 0, 2 * Math.PI);
                ctx.fillStyle = color;
                ctx.fill();
                ctx.strokeStyle = '#fff';
                ctx.lineWidth = 1;
                ctx.stroke();
                // Add label
                ctx.fillStyle = '#000';
                ctx.font = '10px Arial';
                ctx.fillText(vector.id, x + size + 2, y + 4);
            });
            // Add click handler
            if (onVectorClick) {
                canvas.addEventListener('click', (event) => {
                    const rect = canvas.getBoundingClientRect();
                    const clickX = event.clientX - rect.left;
                    const clickY = event.clientY - rect.top;
                    // Find closest vector
                    let closestVector = null;
                    let closestDistance = Infinity;
                    vectors.forEach((vector, i) => {
                        const { x, y } = positions[i];
                        const distance = Math.sqrt((x - clickX) ** 2 + (y - clickY) ** 2);
                        if (distance < closestDistance) {
                            closestDistance = distance;
                            closestVector = vector;
                        }
                    });
                    // If close enough to a vector, trigger click handler
                    if (closestVector && closestDistance < 20) {
                        onVectorClick(closestVector);
                    }
                });
            }
        }
        catch (err) {
            setError(err instanceof Error ? err.message : 'Unknown error');
            console.error('Error rendering vector projection:', err);
        }
    }, [vectors, width, height, method, dimensions, colorBy, sizeBy, onVectorClick, interactive]);
    return ((0, jsx_runtime_1.jsxs)("div", { className: "vector-visualization vector-projection", children: [(0, jsx_runtime_1.jsx)("h3", { children: title }), error && (0, jsx_runtime_1.jsx)("div", { className: "error", children: error }), (0, jsx_runtime_1.jsx)("div", { ref: containerRef, className: "projection-container", style: { width, height } })] }));
};
exports.VectorProjection = VectorProjection;
/**
 * VectorComparison compares two vectors to visualize similarities and differences
 */
const VectorComparison = ({ vector1, vector2, width = 800, height = 400, showDifference = true, title = 'Vector Comparison' }) => {
    const containerRef = (0, react_1.useRef)(null);
    const [error, setError] = (0, react_1.useState)(null);
    (0, react_1.useEffect)(() => {
        if (!containerRef.current)
            return;
        try {
            // Validate vectors
            if (vector1.vector.length !== vector2.vector.length) {
                throw new Error('Vectors must have the same dimensions');
            }
            // Clear previous content
            containerRef.current.innerHTML = '';
            // Create canvas element
            const canvas = document.createElement('canvas');
            canvas.width = width;
            canvas.height = height;
            containerRef.current.appendChild(canvas);
            const ctx = canvas.getContext('2d');
            if (!ctx) {
                throw new Error('Could not get canvas context');
            }
            // Calculate dimensions
            const dimensions = vector1.vector.length;
            const barWidth = width / dimensions;
            const maxBarHeight = height * 0.8;
            // Draw comparison
            for (let i = 0; i < dimensions; i++) {
                const val1 = vector1.vector[i];
                const val2 = vector2.vector[i];
                // Normalize values to 0-1 range for visualization
                const normVal1 = (val1 + 1) / 2;
                const normVal2 = (val2 + 1) / 2;
                // Calculate bar heights
                const height1 = normVal1 * maxBarHeight;
                const height2 = normVal2 * maxBarHeight;
                // Draw bars for each vector
                ctx.fillStyle = 'rgba(31, 119, 180, 0.8)';
                ctx.fillRect(i * barWidth, height - height1, barWidth / 2, height1);
                ctx.fillStyle = 'rgba(255, 127, 14, 0.8)';
                ctx.fillRect(i * barWidth + barWidth / 2, height - height2, barWidth / 2, height2);
                // Draw difference if enabled
                if (showDifference) {
                    const diff = Math.abs(val1 - val2);
                    const normDiff = diff / 2; // Max possible difference is 2 (-1 to 1)
                    ctx.fillStyle = `rgba(214, 39, 40, ${normDiff})`;
                    ctx.fillRect(i * barWidth, height - 10, barWidth, 5);
                }
            }
            // Add legend
            ctx.fillStyle = '#000';
            ctx.font = '12px Arial';
            ctx.fillText(vector1.id, 10, 20);
            ctx.fillStyle = 'rgba(31, 119, 180, 0.8)';
            ctx.fillRect(10, 30, 20, 10);
            ctx.fillStyle = '#000';
            ctx.fillText(vector2.id, 10, 60);
            ctx.fillStyle = 'rgba(255, 127, 14, 0.8)';
            ctx.fillRect(10, 70, 20, 10);
            if (showDifference) {
                ctx.fillStyle = '#000';
                ctx.fillText('Difference', 10, 100);
                ctx.fillStyle = 'rgba(214, 39, 40, 0.8)';
                ctx.fillRect(10, 110, 20, 10);
            }
            // Calculate similarity
            let dotProduct = 0;
            let norm1 = 0;
            let norm2 = 0;
            for (let i = 0; i < dimensions; i++) {
                dotProduct += vector1.vector[i] * vector2.vector[i];
                norm1 += vector1.vector[i] * vector1.vector[i];
                norm2 += vector2.vector[i] * vector2.vector[i];
            }
            const similarity = dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
            // Display similarity
            ctx.fillStyle = '#000';
            ctx.font = 'bold 14px Arial';
            ctx.fillText(`Cosine Similarity: ${similarity.toFixed(4)}`, width - 200, 30);
        }
        catch (err) {
            setError(err instanceof Error ? err.message : 'Unknown error');
            console.error('Error rendering vector comparison:', err);
        }
    }, [vector1, vector2, width, height, showDifference]);
    return ((0, jsx_runtime_1.jsxs)("div", { className: "vector-visualization vector-comparison", children: [(0, jsx_runtime_1.jsx)("h3", { children: title }), error && (0, jsx_runtime_1.jsx)("div", { className: "error", children: error }), (0, jsx_runtime_1.jsx)("div", { ref: containerRef, className: "comparison-container", style: { width, height } })] }));
};
exports.VectorComparison = VectorComparison;
/**
 * VectorClusterMap visualizes clusters of vectors
 */
const VectorClusterMap = ({ clusters, width = 800, height = 600, method = 'kmeans', dimensions = 2, onClusterClick, onVectorClick, title = 'Vector Cluster Map', interactive = true }) => {
    const containerRef = (0, react_1.useRef)(null);
    const [error, setError] = (0, react_1.useState)(null);
    (0, react_1.useEffect)(() => {
        if (!containerRef.current || clusters.length === 0)
            return;
        try {
            // Clear previous content
            containerRef.current.innerHTML = '';
            // In a real implementation, we would use clustering visualization techniques
            // and dimensionality reduction for projection
            // For this example, we'll just create a placeholder with information
            const infoDiv = document.createElement('div');
            infoDiv.className = 'cluster-info';
            infoDiv.innerHTML = `
        <p>Cluster map with ${clusters.length} clusters and ${clusters.reduce((sum, c) => sum + c.vectors.length, 0)} vectors</p>
        <p>Method: ${method}</p>
        <p>Dimensions: ${dimensions}D</p>
        <p>Interactive: ${interactive ? 'Yes' : 'No'}</p>
        <p>This is a placeholder. In a real implementation, this would be an interactive cluster visualization.</p>
      `;
            containerRef.current.appendChild(infoDiv);
            // Create canvas element (placeholder for actual implementation)
            const canvas = document.createElement('canvas');
            canvas.width = width;
            canvas.height = height;
            canvas.style.border = '1px solid #ccc';
            containerRef.current.appendChild(canvas);
            const ctx = canvas.getContext('2d');
            if (!ctx) {
                throw new Error('Could not get canvas context');
            }
            // Draw a simple cluster visualization for demonstration
            ctx.fillStyle = '#f0f0f0';
            ctx.fillRect(0, 0, width, height);
            // Generate cluster positions for demonstration
            const clusterPositions = clusters.map((_, i) => {
                const angle = (i / clusters.length) * 2 * Math.PI;
                const radius = Math.min(width, height) * 0.3;
                return {
                    x: width / 2 + radius * Math.cos(angle),
                    y: height / 2 + radius * Math.sin(angle)
                };
            });
            // Draw clusters
            clusters.forEach((cluster, i) => {
                const { x, y } = clusterPositions[i];
                const colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2'];
                const color = colors[i % colors.length];
                // Draw cluster circle
                ctx.beginPath();
                ctx.arc(x, y, 50, 0, 2 * Math.PI);
                ctx.fillStyle = `${color}33`; // Add transparency
                ctx.fill();
                ctx.strokeStyle = color;
                ctx.lineWidth = 2;
                ctx.stroke();
                // Draw cluster label
                ctx.fillStyle = '#000';
                ctx.font = 'bold 14px Arial';
                ctx.textAlign = 'center';
                ctx.fillText(cluster.label, x, y - 60);
                ctx.font = '12px Arial';
                ctx.fillText(`${cluster.vectors.length} vectors`, x, y - 40);
                // Draw vectors in cluster
                const vectorRadius = 20;
                cluster.vectors.forEach((_, j) => {
                    // Limit to 8 vectors per cluster for demonstration
                    if (j >= 8)
                        return;
                    const angle = (j / Math.min(cluster.vectors.length, 8)) * 2 * Math.PI;
                    const vx = x + vectorRadius * Math.cos(angle);
                    const vy = y + vectorRadius * Math.sin(angle);
                    ctx.beginPath();
                    ctx.arc(vx, vy, 5, 0, 2 * Math.PI);
                    ctx.fillStyle = color;
                    ctx.fill();
                });
            });
            // Add click handlers
            if (interactive && (onClusterClick || onVectorClick)) {
                canvas.addEventListener('click', (event) => {
                    const rect = canvas.getBoundingClientRect();
                    const clickX = event.clientX - rect.left;
                    const clickY = event.clientY - rect.top;
                    // Check if a cluster was clicked
                    for (let i = 0; i < clusters.length; i++) {
                        const { x, y } = clusterPositions[i];
                        const distance = Math.sqrt((x - clickX) ** 2 + (y - clickY) ** 2);
                        if (distance < 50 && onClusterClick) {
                            onClusterClick(clusters[i]);
                            return;
                        }
                    }
                });
            }
        }
        catch (err) {
            setError(err instanceof Error ? err.message : 'Unknown error');
            console.error('Error rendering cluster map:', err);
        }
    }, [clusters, width, height, method, dimensions, onClusterClick, onVectorClick, interactive]);
    return ((0, jsx_runtime_1.jsxs)("div", { className: "vector-visualization vector-cluster-map", children: [(0, jsx_runtime_1.jsx)("h3", { children: title }), error && (0, jsx_runtime_1.jsx)("div", { className: "error", children: error }), (0, jsx_runtime_1.jsx)("div", { ref: containerRef, className: "cluster-map-container", style: { width, height } })] }));
};
exports.VectorClusterMap = VectorClusterMap;
/**
 * VectorTimeSeries visualizes vectors changing over time
 */
const VectorTimeSeries = ({ vectors, timeField, width = 800, height = 400, method = 'trajectory', onTimePointClick, title = 'Vector Time Series', playable = true }) => {
    const containerRef = (0, react_1.useRef)(null);
    const [error, setError] = (0, react_1.useState)(null);
    const [playing, setPlaying] = (0, react_1.useState)(false);
    const [currentTime, setCurrentTime] = (0, react_1.useState)(0);
    (0, react_1.useEffect)(() => {
        if (!containerRef.current || vectors.length === 0)
            return;
        try {
            // Validate vectors
            for (const vector of vectors) {
                if (!vector.metadata?.[timeField]) {
                    throw new Error(`Vector ${vector.id} is missing the time field: ${timeField}`);
                }
            }
            // Sort vectors by time
            const sortedVectors = [...vectors].sort((a, b) => {
                return a.metadata[timeField] - b.metadata[timeField];
            });
            // Get time range
            const minTime = sortedVectors[0].metadata[timeField];
            const maxTime = sortedVectors[sortedVectors.length - 1].metadata[timeField];
            // Clear previous content
            containerRef.current.innerHTML = '';
            // In a real implementation, we would use specialized visualizations for time series data
            // For this example, we'll just create a placeholder with information
            const infoDiv = document.createElement('div');
            infoDiv.className = 'time-series-info';
            infoDiv.innerHTML = `
        <p>Time series with ${vectors.length} vectors</p>
        <p>Time field: ${timeField}</p>
        <p>Method: ${method}</p>
        <p>Time range: ${new Date(minTime).toLocaleString()} - ${new Date(maxTime).toLocaleString()}</p>
        <p>This is a placeholder. In a real implementation, this would be an interactive time series visualization.</p>
      `;
            containerRef.current.appendChild(infoDiv);
            // Create controls if playable
            if (playable) {
                const controlsDiv = document.createElement('div');
                controlsDiv.className = 'time-series-controls';
                // Create slider
                const slider = document.createElement('input');
                slider.type = 'range';
                slider.min = minTime.toString();
                slider.max = maxTime.toString();
                slider.value = minTime.toString();
                slider.style.width = '80%';
                // Create play button
                const playButton = document.createElement('button');
                playButton.innerText = playing ? 'Pause' : 'Play';
                playButton.onclick = () => setPlaying(!playing);
                // Create time display
                const timeDisplay = document.createElement('div');
                timeDisplay.className = 'time-display';
                timeDisplay.innerText = new Date(parseInt(slider.value)).toLocaleString();
                // Add event listener to slider
                slider.addEventListener('input', () => {
                    const time = parseInt(slider.value);
                    setCurrentTime(time);
                    timeDisplay.innerText = new Date(time).toLocaleString();
                });
                // Add controls to container
                controlsDiv.appendChild(playButton);
                controlsDiv.appendChild(slider);
                controlsDiv.appendChild(timeDisplay);
                containerRef.current.appendChild(controlsDiv);
            }
            // Create canvas element (placeholder for actual implementation)
            const canvas = document.createElement('canvas');
            canvas.width = width;
            canvas.height = height - 80; // Make room for controls
            canvas.style.border = '1px solid #ccc';
            containerRef.current.appendChild(canvas);
            const ctx = canvas.getContext('2d');
            if (!ctx) {
                throw new Error('Could not get canvas context');
            }
            // Draw a simple time series visualization for demonstration
            ctx.fillStyle = '#f0f0f0';
            ctx.fillRect(0, 0, width, canvas.height);
            // Draw time axis
            ctx.strokeStyle = '#000';
            ctx.lineWidth = 1;
            ctx.beginPath();
            ctx.moveTo(50, canvas.height - 30);
            ctx.lineTo(width - 50, canvas.height - 30);
            ctx.stroke();
            // Draw time markers
            const timeRange = maxTime - minTime;
            const markerCount = 5;
            for (let i = 0; i <= markerCount; i++) {
                const time = minTime + (timeRange * i) / markerCount;
                const x = 50 + ((width - 100) * i) / markerCount;
                ctx.beginPath();
                ctx.moveTo(x, canvas.height - 35);
                ctx.lineTo(x, canvas.height - 25);
                ctx.stroke();
                ctx.fillStyle = '#000';
                ctx.font = '10px Arial';
                ctx.textAlign = 'center';
                ctx.fillText(new Date(time).toLocaleDateString(), x, canvas.height - 10);
            }
            // Draw time series data points (simple example)
            ctx.strokeStyle = '#1f77b4';
            ctx.lineWidth = 2;
            ctx.beginPath();
            sortedVectors.forEach((vector, i) => {
                const time = vector.metadata[timeField];
                const x = 50 + ((width - 100) * (time - minTime)) / timeRange;
                // Use the first dimension of the vector for demonstration
                const value = vector.vector[0];
                const normalizedValue = (value + 1) / 2; // Normalize to 0-1
                const y = 30 + (canvas.height - 60) * (1 - normalizedValue);
                if (i === 0) {
                    ctx.moveTo(x, y);
                }
                else {
                    ctx.lineTo(x, y);
                }
                // Draw point
                ctx.fillStyle = '#1f77b4';
                ctx.beginPath();
                ctx.arc(x, y, 4, 0, 2 * Math.PI);
                ctx.fill();
            });
            ctx.stroke();
            // Add click handler
            if (onTimePointClick) {
                canvas.addEventListener('click', (event) => {
                    const rect = canvas.getBoundingClientRect();
                    const clickX = event.clientX - rect.left;
                    // Find closest vector by time
                    const clickTime = minTime + (clickX - 50) / (width - 100) * timeRange;
                    let closestVector = null;
                    let closestTimeDiff = Infinity;
                    for (const vector of vectors) {
                        const time = vector.metadata[timeField];
                        const timeDiff = Math.abs(time - clickTime);
                        if (timeDiff < closestTimeDiff) {
                            closestTimeDiff = timeDiff;
                            closestVector = vector;
                        }
                    }
                    // If close enough to a vector, trigger click handler
                    if (closestVector) {
                        onTimePointClick(closestVector, closestVector.metadata[timeField]);
                    }
                });
            }
        }
        catch (err) {
            setError(err instanceof Error ? err.message : 'Unknown error');
            console.error('Error rendering time series:', err);
        }
    }, [vectors, timeField, width, height, method, onTimePointClick, playable, playing, currentTime]);
    return ((0, jsx_runtime_1.jsxs)("div", { className: "vector-visualization vector-time-series", children: [(0, jsx_runtime_1.jsx)("h3", { children: title }), error && (0, jsx_runtime_1.jsx)("div", { className: "error", children: error }), (0, jsx_runtime_1.jsx)("div", { ref: containerRef, className: "time-series-container", style: { width, height } })] }));
};
exports.VectorTimeSeries = VectorTimeSeries;
/**
 * Export visualization components
 */
exports.VectorVisualizations = {
    Heatmap: exports.VectorHeatmap,
    Network: exports.VectorNetwork,
    Projection: exports.VectorProjection,
    Comparison: exports.VectorComparison,
    ClusterMap: exports.VectorClusterMap,
    TimeSeries: exports.VectorTimeSeries
};
//# sourceMappingURL=VectorVisualization.js.map