image-input.demo.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import React, { useState } from 'react';
  2. import ImageInput from './image-input';
  3. export function ImageInputDemo() {
  4. const [selectedImage, setSelectedImage] = useState<File | string | null>(null);
  5. const [validationResult, setValidationResult] = useState<any>(null);
  6. const [demoLog, setDemoLog] = useState<string[]>([]);
  7. const log = (message: string) => {
  8. const timestamp = new Date().toLocaleTimeString();
  9. setDemoLog(prev => [`[${timestamp}] ${message}`, ...prev.slice(0, 4)]);
  10. };
  11. const handleImageChange = (value: File | string | null) => {
  12. setSelectedImage(value);
  13. log(`Image ${value ? 'selected' : 'cleared'}: ${value instanceof File ? value.name : value}`);
  14. };
  15. const handleValidation = (result: any) => {
  16. setValidationResult(result);
  17. log(`Validation: ${result.isValid ? 'Valid' : 'Invalid'} - ${result.error || 'OK'}`);
  18. };
  19. const handleUploadToServer = async () => {
  20. if (!selectedImage) return;
  21. log('Uploading to server...');
  22. // Simulate server upload
  23. await new Promise(resolve => setTimeout(resolve, 2000));
  24. log('Upload completed successfully!');
  25. };
  26. return (
  27. <div className="max-w-2xl mx-auto p-6 space-y-6">
  28. <div>
  29. <h1 className="text-2xl font-bold mb-2">ImageInput Component Demo</h1>
  30. <p className="text-gray-600">
  31. This demo showcases the ImageInput component with both file upload and URL input modes.
  32. Try selecting an image file or entering an image URL to see validation and preview in action.
  33. </p>
  34. </div>
  35. {/* ImageInput Component */}
  36. <div className="border rounded-lg p-6">
  37. <ImageInput
  38. value={selectedImage}
  39. onChange={handleImageChange}
  40. onValidation={handleValidation}
  41. disabled={false}
  42. showPreview={true}
  43. className="space-y-4"
  44. />
  45. </div>
  46. {/* Demo Actions */}
  47. {selectedImage && (
  48. <div className="flex gap-4">
  49. <button
  50. onClick={handleUploadToServer}
  51. className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors"
  52. >
  53. Simulate Upload
  54. </button>
  55. <button
  56. onClick={() => {
  57. setSelectedImage(null);
  58. setValidationResult(null);
  59. setDemoLog([]);
  60. }}
  61. className="px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700 transition-colors"
  62. >
  63. Reset Demo
  64. </button>
  65. </div>
  66. )}
  67. {/* Status Display */}
  68. <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
  69. {/* Validation Status */}
  70. <div className="border rounded-lg p-4">
  71. <h3 className="font-semibold mb-2">Validation Status</h3>
  72. {validationResult ? (
  73. <div className="space-y-2 text-sm">
  74. <div>
  75. <span className="font-medium">Valid:</span>{' '}
  76. <span className={validationResult.isValid ? 'text-green-600' : 'text-red-600'}>
  77. {validationResult.isValid ? 'Yes' : 'No'}
  78. </span>
  79. </div>
  80. {validationResult.error && (
  81. <div>
  82. <span className="font-medium">Error:</span>{' '}
  83. <span className="text-red-600">{validationResult.error}</span>
  84. </div>
  85. )}
  86. {validationResult.detectedType && (
  87. <div>
  88. <span className="font-medium">Type:</span> {validationResult.detectedType}
  89. </div>
  90. )}
  91. {validationResult.filename && (
  92. <div>
  93. <span className="font-medium">Filename:</span> {validationResult.filename}
  94. </div>
  95. )}
  96. </div>
  97. ) : (
  98. <p className="text-gray-500 text-sm">No validation performed yet</p>
  99. )}
  100. </div>
  101. {/* Activity Log */}
  102. <div className="border rounded-lg p-4">
  103. <h3 className="font-semibold mb-2">Activity Log</h3>
  104. <div className="space-y-1 text-sm font-mono bg-gray-50 p-2 rounded max-h-32 overflow-y-auto">
  105. {demoLog.length > 0 ? (
  106. demoLog.map((entry, index) => (
  107. <div key={index} className="text-gray-700">
  108. {entry}
  109. </div>
  110. ))
  111. ) : (
  112. <p className="text-gray-500">No activity yet</p>
  113. )}
  114. </div>
  115. </div>
  116. </div>
  117. {/* Code Example */}
  118. <div className="border rounded-lg p-4">
  119. <h3 className="font-semibold mb-2">Usage Example</h3>
  120. <pre className="bg-gray-100 p-3 rounded text-sm overflow-x-auto">
  121. {`import { ImageInput } from './components/ui/image-input';
  122. function MyComponent() {
  123. const [image, setImage] = useState<File | string | null>(null);
  124. return (
  125. <ImageInput
  126. value={image}
  127. onChange={setImage}
  128. onValidation={(result) => {
  129. console.log('Validation:', result);
  130. }}
  131. showPreview={true}
  132. maxSize={5 * 1024 * 1024} // 5MB
  133. />
  134. );
  135. }`}
  136. </pre>
  137. </div>
  138. </div>
  139. );
  140. }
  141. export default ImageInputDemo;