| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- 'use client';
- import { useState } from 'react';
- import ImageInput from '../../components/ui/image-input';
- import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../components/ui/card';
- import { Button } from '../../components/ui/button';
- import { Label } from '../../components/ui/label';
- import { Tabs, TabsContent, TabsList, TabsTrigger } from '../../components/ui/tabs';
- import { ImageValidationResult } from '../../lib/image-validation';
- export default function DemoPage() {
- const [input1, setInput1] = useState<File | string | null>(null);
- const [input2, setInput2] = useState<File | string | null>(null);
- const [validation1, setValidation1] = useState<ImageValidationResult | null>(null);
- const [validation2, setValidation2] = useState<ImageValidationResult | null>(null);
- const handleValidation1 = (result: ImageValidationResult) => {
- setValidation1(result);
- console.log('Input 1 validation:', result);
- };
- const handleValidation2 = (result: ImageValidationResult) => {
- setValidation2(result);
- console.log('Input 2 validation:', result);
- };
- const clearAll = () => {
- setInput1(null);
- setInput2(null);
- setValidation1(null);
- setValidation2(null);
- };
- return (
- <div className="min-h-screen bg-gray-50 p-8">
- <div className="max-w-4xl mx-auto space-y-8">
- <div className="text-center space-y-2">
- <h1 className="text-3xl font-bold text-gray-900">ImageInput Component Demo</h1>
- <p className="text-gray-600">Demonstration of the ImageInput component with both file upload and URL input modes</p>
- </div>
- <Tabs defaultValue="demo" className="w-full">
- <TabsList className="grid w-full grid-cols-3">
- <TabsTrigger value="demo">Demo</TabsTrigger>
- <TabsTrigger value="api">API Reference</TabsTrigger>
- <TabsTrigger value="examples">Examples</TabsTrigger>
- </TabsList>
- <TabsContent value="demo" className="space-y-6">
- {/* First ImageInput - Default Configuration */}
- <Card>
- <CardHeader>
- <CardTitle>Image Input 1 - Default Configuration</CardTitle>
- <CardDescription>
- File upload and URL input with default 10MB size limit
- </CardDescription>
- </CardHeader>
- <CardContent className="space-y-4">
- <ImageInput
- value={input1}
- onChange={setInput1}
- onValidation={handleValidation1}
- />
-
- {validation1 && (
- <div className="mt-4 p-4 bg-gray-100 rounded-lg">
- <Label className="font-semibold">Validation Result:</Label>
- <pre className="text-sm mt-2 overflow-auto">
- {JSON.stringify(validation1, null, 2)}
- </pre>
- </div>
- )}
- </CardContent>
- </Card>
- {/* Second ImageInput - Custom Configuration */}
- <Card>
- <CardHeader>
- <CardTitle>Image Input 2 - Custom Configuration</CardTitle>
- <CardDescription>
- Custom size limit (2MB) and without preview
- </CardDescription>
- </CardHeader>
- <CardContent className="space-y-4">
- <ImageInput
- value={input2}
- onChange={setInput2}
- onValidation={handleValidation2}
- maxSize={2 * 1024 * 1024} // 2MB
- showPreview={false}
- accept="image/jpeg,image/png,image/gif"
- placeholder="Enter a valid image URL or select a JPEG/PNG/GIF file"
- />
-
- {validation2 && (
- <div className="mt-4 p-4 bg-gray-100 rounded-lg">
- <Label className="font-semibold">Validation Result:</Label>
- <pre className="text-sm mt-2 overflow-auto">
- {JSON.stringify(validation2, null, 2)}
- </pre>
- </div>
- )}
- </CardContent>
- </Card>
- {/* Control Panel */}
- <Card>
- <CardHeader>
- <CardTitle>Current Values</CardTitle>
- <CardDescription>
- Shows the current state of both inputs
- </CardDescription>
- </CardHeader>
- <CardContent className="space-y-4">
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
- <div>
- <Label>Input 1 Value:</Label>
- <div className="mt-1 p-2 bg-gray-100 rounded text-sm">
- {input1 instanceof File
- ? `File: ${input1.name} (${(input1.size / 1024 / 1024).toFixed(2)} MB)`
- : input1 || 'null'
- }
- </div>
- </div>
- <div>
- <Label>Input 2 Value:</Label>
- <div className="mt-1 p-2 bg-gray-100 rounded text-sm">
- {input2 instanceof File
- ? `File: ${input2.name} (${(input2.size / 1024 / 1024).toFixed(2)} MB)`
- : input2 || 'null'
- }
- </div>
- </div>
- </div>
-
- <Button onClick={clearAll} variant="outline" className="w-full">
- Clear All Inputs
- </Button>
- </CardContent>
- </Card>
- </TabsContent>
- <TabsContent value="api" className="space-y-6">
- <Card>
- <CardHeader>
- <CardTitle>Props</CardTitle>
- <CardDescription>
- Available props for the ImageInput component
- </CardDescription>
- </CardHeader>
- <CardContent>
- <div className="overflow-x-auto">
- <table className="w-full text-sm">
- <thead>
- <tr className="border-b">
- <th className="text-left p-2">Prop</th>
- <th className="text-left p-2">Type</th>
- <th className="text-left p-2">Default</th>
- <th className="text-left p-2">Description</th>
- </tr>
- </thead>
- <tbody className="space-y-2">
- <tr className="border-b">
- <td className="p-2 font-mono">value</td>
- <td className="p-2 font-mono">File | string | null</td>
- <td className="p-2 font-mono">undefined</td>
- <td className="p-2">Current value of the input</td>
- </tr>
- <tr className="border-b">
- <td className="p-2 font-mono">onChange</td>
- <td className="p-2 font-mono">(File | string | null) => void</td>
- <td className="p-2 font-mono">-</td>
- <td className="p-2">Callback when value changes</td>
- </tr>
- <tr className="border-b">
- <td className="p-2 font-mono">onValidation</td>
- <td className="p-2 font-mono">(ImageValidationResult) => void</td>
- <td className="p-2 font-mono">-</td>
- <td className="p-2">Callback for validation results</td>
- </tr>
- <tr className="border-b">
- <td className="p-2 font-mono">disabled</td>
- <td className="p-2 font-mono">boolean</td>
- <td className="p-2 font-mono">false</td>
- <td className="p-2">Disable the input</td>
- </tr>
- <tr className="border-b">
- <td className="p-2 font-mono">maxSize</td>
- <td className="p-2 font-mono">number</td>
- <td className="p-2 font-mono">10MB</td>
- <td className="p-2">Maximum file size in bytes</td>
- </tr>
- <tr className="border-b">
- <td className="p-2 font-mono">accept</td>
- <td className="p-2 font-mono">string</td>
- <td className="p-2 font-mono">image/*</td>
- <td className="p-2">Accepted file types</td>
- </tr>
- <tr className="border-b">
- <td className="p-2 font-mono">placeholder</td>
- <td className="p-2 font-mono">string</td>
- <td className="p-2 font-mono">-</td>
- <td className="p-2">Placeholder for URL input</td>
- </tr>
- <tr className="border-b">
- <td className="p-2 font-mono">showPreview</td>
- <td className="p-2 font-mono">boolean</td>
- <td className="p-2 font-mono">true</td>
- <td className="p-2">Show image preview</td>
- </tr>
- <tr>
- <td className="p-2 font-mono">className</td>
- <td className="p-2 font-mono">string</td>
- <td className="p-2 font-mono">-</td>
- <td className="p-2">Additional CSS classes</td>
- </tr>
- </tbody>
- </table>
- </div>
- </CardContent>
- </Card>
- </TabsContent>
- <TabsContent value="examples" className="space-y-6">
- <Card>
- <CardHeader>
- <CardTitle>Usage Examples</CardTitle>
- <CardDescription>
- Common patterns for using the ImageInput component
- </CardDescription>
- </CardHeader>
- <CardContent className="space-y-6">
- <div>
- <Label className="text-base font-semibold">Basic Usage</Label>
- <pre className="mt-2 p-4 bg-gray-100 rounded-lg text-sm overflow-x-auto">
- {`import ImageInput from './components/ui/image-input';
- const [image, setImage] = useState<File | string | null>(null);
- <ImageInput
- value={image}
- onChange={setImage}
- />`}
- </pre>
- </div>
- <div>
- <Label className="text-base font-semibold">With Validation Callback</Label>
- <pre className="mt-2 p-4 bg-gray-100 rounded-lg text-sm overflow-x-auto">
- {`const [image, setImage] = useState<File | string | null>(null);
- const [validation, setValidation] = useState<ImageValidationResult | null>(null);
- const handleValidation = (result: ImageValidationResult) => {
- setValidation(result);
- console.log('Is valid:', result.isValid);
- console.log('File name:', result.filename);
- };
- <ImageInput
- value={image}
- onChange={setImage}
- onValidation={handleValidation}
- />`}
- </pre>
- </div>
- <div>
- <Label className="text-base font-semibold">Custom Configuration</Label>
- <pre className="mt-2 p-4 bg-gray-100 rounded-lg text-sm overflow-x-auto">
- {`<ImageInput
- value={image}
- onChange={setImage}
- maxSize={5 * 1024 * 1024} // 5MB
- accept="image/jpeg,image/png"
- showPreview={true}
- placeholder="Enter image URL or select JPEG/PNG file"
- className="custom-image-input"
- />`}
- </pre>
- </div>
- <div>
- <Label className="text-base font-semibold">Disabled State</Label>
- <pre className="mt-2 p-4 bg-gray-100 rounded-lg text-sm overflow-x-auto">
- {`const [isUploading, setIsUploading] = useState(false);
- <ImageInput
- value={image}
- onChange={setImage}
- disabled={isUploading}
- />`}
- </pre>
- </div>
- </CardContent>
- </Card>
- </TabsContent>
- </Tabs>
- </div>
- </div>
- );
- }
|