import React, { useState, useRef, useEffect } from 'react';
import {
Upload, Scissors, Download, Image as ImageIcon, Trash2,
Layers, RefreshCw, ArrowRight, ArrowDown, Grid, Share2,
Zap, Shield, Smartphone, ChevronRight, Menu, X, Layout
} from 'lucide-react';
/* =========================================
PART 1: THE LANDING PAGE COMPONENT
=========================================
*/
const LandingPage = ({ onNavigate }) => {
const [isMenuOpen, setIsMenuOpen] = useState(false);
return (
{/* Navigation */}
{/* Hero Section */}
v1.0 Now Live
Simple tools for
creative people.
Free, fast, and privacy-focused web tools to help you create better content for social media and the web. No sign-up required.
{/* Abstract Background Decoration */}
{/* Tools Grid */}
{/* Features / Why Us */}
Privacy First
All image processing happens locally in your browser. Your photos are never uploaded to our servers.
Lightning Fast
No waiting for uploads or downloads. The heavy lifting is done instantly by your device.
Mobile Optimized
Designed for touchscreens. Split and save images directly from your phone to social media.
{/* Footer */}
);
};
/* =========================================
PART 2: THE IMAGE SPLITTER APP (Your Code)
=========================================
*/
const ImageSplitterApp = ({ onBack }) => {
const [selectedImage, setSelectedImage] = useState(null);
const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 });
const [splitCount, setSplitCount] = useState(3);
const [gridRows, setGridRows] = useState(3);
const [gridCols, setGridCols] = useState(3);
const [scale, setScale] = useState(100);
const [splitDirection, setSplitDirection] = useState('horizontal');
const [processedImages, setProcessedImages] = useState([]);
const [isProcessing, setIsProcessing] = useState(false);
const [fileName, setFileName] = useState("image");
const resultsRef = useRef(null);
const handleImageUpload = (event) => {
const file = event.target.files[0];
if (file) {
setFileName(file.name.split('.')[0]);
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
setImageDimensions({ width: img.width, height: img.height });
setSelectedImage(img);
setProcessedImages([]);
if (navigator.vibrate) navigator.vibrate(20);
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
}
};
const handleReset = () => {
if (navigator.vibrate) navigator.vibrate(20);
setSelectedImage(null);
setProcessedImages([]);
setSplitCount(3);
setGridRows(3);
setGridCols(3);
setScale(100);
};
const handleShare = async (dataUrl, index) => {
if (navigator.vibrate) navigator.vibrate(20);
try {
const res = await fetch(dataUrl);
const blob = await res.blob();
const file = new File([blob], `${fileName}_${index}.png`, { type: 'image/png' });
if (navigator.canShare && navigator.canShare({ files: [file] })) {
await navigator.share({
files: [file],
title: 'Split Image Part',
text: `Here is part ${index + 1} of my split image.`
});
} else {
downloadImage(dataUrl, index);
}
} catch (error) {
console.log("Error sharing:", error);
downloadImage(dataUrl, index);
}
};
const processImage = async () => {
if (!selectedImage) return;
if (navigator.vibrate) navigator.vibrate(20);
setIsProcessing(true);
setTimeout(() => {
const chunks = [];
const { width, height } = imageDimensions;
const totalScaledWidth = width * (scale / 100);
const totalScaledHeight = height * (scale / 100);
let rows, cols;
if (splitDirection === 'grid') {
rows = gridRows;
cols = gridCols;
} else if (splitDirection === 'horizontal') {
rows = 1;
cols = splitCount;
} else {
rows = splitCount;
cols = 1;
}
const chunkWidthOriginal = width / cols;
const chunkHeightOriginal = height / rows;
const chunkWidthScaled = totalScaledWidth / cols;
const chunkHeightScaled = totalScaledHeight / rows;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
canvas.width = chunkWidthScaled;
canvas.height = chunkHeightScaled;
const srcX = c * chunkWidthOriginal;
const srcY = r * chunkHeightOriginal;
ctx.drawImage(
selectedImage,
srcX, srcY,
chunkWidthOriginal, chunkHeightOriginal,
0, 0,
chunkWidthScaled, chunkHeightScaled
);
chunks.push(canvas.toDataURL('image/png'));
}
}
setProcessedImages(chunks);
setIsProcessing(false);
setTimeout(() => {
if (resultsRef.current) {
resultsRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
if (navigator.vibrate) navigator.vibrate([50, 50, 50]);
}
}, 100);
}, 100);
};
const getPostNumber = (index) => {
return processedImages.length - index;
};
const downloadImage = (dataUrl, index) => {
if (navigator.vibrate) navigator.vibrate(20);
const postNum = getPostNumber(index);
const link = document.createElement('a');
link.href = dataUrl;
link.download = `${fileName}_post_${postNum}.png`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
const getResultGridClass = () => {
if (splitDirection === 'grid') {
if (gridCols === 2) return 'grid-cols-2';
if (gridCols === 3) return 'grid-cols-3';
if (gridCols >= 4) return 'grid-cols-4';
return 'grid-cols-1';
}
if (splitDirection === 'vertical') return 'grid-cols-1 max-w-sm mx-auto';
return 'grid-cols-1 md:grid-cols-2';
};
return (
{/* Navigation for Tool View */}
Image Splitter
Grid • Carousel • Webtoon
{!selectedImage ? (
Tap to upload
Open Camera Roll or Files
) : (
{fileName}
{imageDimensions.width} × {imageDimensions.height}
{[
{ id: 'horizontal', icon: ArrowRight, label: 'Panorama' },
{ id: 'vertical', icon: ArrowDown, label: 'Vertical' },
{ id: 'grid', icon: Grid, label: 'Grid' }
].map(mode => (
))}
{splitDirection === 'grid' ? (
) : (
{splitCount}
setSplitCount(parseInt(e.target.value))}
className="w-full h-8 accent-blue-600 touch-pan-x"
/>
1
10
)}
)}
{selectedImage && (
Note: Splits are numbered backward (e.g., upload Post #1 first) so they align correctly on your Instagram profile.
)}
{processedImages.length > 0 ? (
Results ({processedImages.length})
{processedImages.map((src, idx) => (
{splitDirection === 'horizontal'
? `Slide ${idx + 1}/${processedImages.length}`
: `Post #${getPostNumber(idx)}`
}
{navigator.share && (
)}
))}
) : (
!selectedImage && (
Select an image to start splitting
)
)}
);
};
/* =========================================
PART 3: MAIN APP (ROUTER)
=========================================
*/
const App = () => {
const [currentView, setCurrentView] = useState('landing');
useEffect(() => {
// Add Favicon
const link = document.createElement('link');
link.rel = 'icon';
// Blue Scissors SVG Data URI
link.href = `data:image/svg+xml,`;
document.head.appendChild(link);
// Update Title
document.title = "CoolWebTools - Image Splitter & More";
return () => {
document.head.removeChild(link);
};
}, []);
return (
<>
{currentView === 'landing' ? (
) : (
setCurrentView('landing')} />
)}
>
);
};
export default App;