willytpfw commited on
Commit
315a976
·
verified ·
1 Parent(s): ac69c22

crea una página en donde se vea un carrusel de imágenes tomadas aleatoriamente de sitios web, hazlo con react

Browse files
Files changed (2) hide show
  1. README.md +8 -5
  2. index.html +328 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Pixelflow Carousel Magic
3
- emoji: 🏃
4
- colorFrom: red
5
- colorTo: yellow
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: PixelFlow Carousel Magic
3
+ colorFrom: gray
4
+ colorTo: blue
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://deepsite.hf.co).
index.html CHANGED
@@ -1,19 +1,329 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>PixelFlow Carousel</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
9
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
10
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
12
+ <style>
13
+ .zoom-effect {
14
+ transition: transform 0.3s ease;
15
+ }
16
+ .zoom-effect:hover {
17
+ transform: scale(1.03);
18
+ }
19
+ .skeleton {
20
+ background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
21
+ background-size: 200% 100%;
22
+ animation: shimmer 1.5s infinite;
23
+ }
24
+ @keyframes shimmer {
25
+ 0% { background-position: 200% 0; }
26
+ 100% { background-position: -200% 0; }
27
+ }
28
+ .dark .skeleton {
29
+ background: linear-gradient(90deg, #2d3748 25%, #4a5568 50%, #2d3748 75%);
30
+ }
31
+ .carousel-transition {
32
+ transition: opacity 0.5s ease, transform 0.5s ease;
33
+ }
34
+ </style>
35
+ </head>
36
+ <body class="bg-white dark:bg-gray-900 transition-colors duration-300">
37
+ <div id="root"></div>
38
+
39
+ <script type="text/babel">
40
+ const { useState, useEffect, useRef } = React;
41
+
42
+ const ImageCarousel = () => {
43
+ const [images, setImages] = useState([]);
44
+ const [currentIndex, setCurrentIndex] = useState(0);
45
+ const [isLoading, setIsLoading] = useState(true);
46
+ const [error, setError] = useState(null);
47
+ const [isAutoPlaying, setIsAutoPlaying] = useState(true);
48
+ const [apiSource, setApiSource] = useState('unsplash');
49
+ const [darkMode, setDarkMode] = useState(false);
50
+ const timerRef = useRef(null);
51
+ const carouselRef = useRef(null);
52
+
53
+ const API_CONFIG = {
54
+ unsplash: {
55
+ url: 'https://api.unsplash.com/photos/random',
56
+ params: {
57
+ count: 5,
58
+ client_id: 'YOUR_UNSPLASH_ACCESS_KEY'
59
+ },
60
+ transform: (data) => data.map(item => ({
61
+ url: item.urls.regular,
62
+ alt: item.alt_description || 'Unsplash Image',
63
+ author: item.user.name,
64
+ authorUrl: item.user.links.html
65
+ }))
66
+ },
67
+ pexels: {
68
+ url: 'https://api.pexels.com/v1/curated',
69
+ params: {
70
+ per_page: 5
71
+ },
72
+ headers: {
73
+ Authorization: 'YOUR_PEXELS_API_KEY'
74
+ },
75
+ transform: (data) => data.photos.map(photo => ({
76
+ url: photo.src.large,
77
+ alt: photo.photographer || 'Pexels Image',
78
+ author: photo.photographer,
79
+ authorUrl: photo.photographer_url
80
+ }))
81
+ },
82
+ pixabay: {
83
+ url: 'https://pixabay.com/api/',
84
+ params: {
85
+ key: 'YOUR_PIXABAY_API_KEY',
86
+ per_page: 5
87
+ },
88
+ transform: (data) => data.hits.map(hit => ({
89
+ url: hit.webformatURL,
90
+ alt: hit.tags || 'Pixabay Image',
91
+ author: hit.user,
92
+ authorUrl: `https://pixabay.com/users/${hit.user}-${hit.user_id}/`
93
+ }))
94
+ }
95
+ };
96
+
97
+ const fetchImages = async () => {
98
+ setIsLoading(true);
99
+ setError(null);
100
+
101
+ try {
102
+ const config = API_CONFIG[apiSource];
103
+ const params = new URLSearchParams(config.params).toString();
104
+ const url = `${config.url}?${params}`;
105
+
106
+ const options = {
107
+ headers: config.headers || {}
108
+ };
109
+
110
+ const response = await fetch(url, options);
111
+ const data = await response.json();
112
+
113
+ if (!response.ok) throw new Error(data.message || 'Failed to fetch images');
114
+
115
+ setImages(config.transform(data));
116
+ } catch (err) {
117
+ console.error('Error fetching images:', err);
118
+ setError(err.message || 'Failed to load images. Please try again.');
119
+ // Fallback to placeholder images
120
+ setImages(Array(5).fill().map((_, i) => ({
121
+ url: `http://static.photos/nature/1024x576/${i+1}`,
122
+ alt: `Placeholder Image ${i+1}`,
123
+ author: 'Placeholder Author',
124
+ authorUrl: '#'
125
+ })));
126
+ } finally {
127
+ setIsLoading(false);
128
+ }
129
+ };
130
+
131
+ useEffect(() => {
132
+ fetchImages();
133
+ }, [apiSource]);
134
+
135
+ useEffect(() => {
136
+ if (isAutoPlaying && images.length > 0) {
137
+ timerRef.current = setInterval(() => {
138
+ setCurrentIndex(prev => (prev + 1) % images.length);
139
+ }, 5000);
140
+ }
141
+ return () => clearInterval(timerRef.current);
142
+ }, [isAutoPlaying, images.length]);
143
+
144
+ const goToPrev = () => {
145
+ setCurrentIndex(prev => (prev - 1 + images.length) % images.length);
146
+ resetTimer();
147
+ };
148
+
149
+ const goToNext = () => {
150
+ setCurrentIndex(prev => (prev + 1) % images.length);
151
+ resetTimer();
152
+ };
153
+
154
+ const goToIndex = (index) => {
155
+ setCurrentIndex(index);
156
+ resetTimer();
157
+ };
158
+
159
+ const resetTimer = () => {
160
+ if (isAutoPlaying) {
161
+ clearInterval(timerRef.current);
162
+ timerRef.current = setInterval(() => {
163
+ setCurrentIndex(prev => (prev + 1) % images.length);
164
+ }, 5000);
165
+ }
166
+ };
167
+
168
+ const toggleAutoPlay = () => {
169
+ setIsAutoPlaying(prev => !prev);
170
+ };
171
+
172
+ const toggleDarkMode = () => {
173
+ setDarkMode(prev => !prev);
174
+ document.body.classList.toggle('dark');
175
+ };
176
+
177
+ if (error) {
178
+ return (
179
+ <div className="flex flex-col items-center justify-center min-h-screen p-4">
180
+ <div className="bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 p-4 rounded-lg max-w-md">
181
+ <div className="flex items-center">
182
+ <i data-feather="alert-triangle" className="mr-2"></i>
183
+ <h3 className="font-bold">Error Loading Images</h3>
184
+ </div>
185
+ <p className="mt-2">{error}</p>
186
+ <p className="mt-2 text-sm">Using placeholder images instead.</p>
187
+ <button
188
+ onClick={fetchImages}
189
+ className="mt-4 bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-md transition-colors"
190
+ >
191
+ Retry
192
+ </button>
193
+ </div>
194
+ </div>
195
+ );
196
+ }
197
+
198
+ return (
199
+ <div className="min-h-screen flex flex-col items-center justify-center p-4">
200
+ <div className="w-full max-w-4xl">
201
+ <div className="flex justify-between items-center mb-6">
202
+ <h1 className="text-3xl font-bold text-gray-800 dark:text-white">PixelFlow Carousel</h1>
203
+ <div className="flex space-x-4">
204
+ <select
205
+ value={apiSource}
206
+ onChange={(e) => setApiSource(e.target.value)}
207
+ className="bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-white px-3 py-2 rounded-md"
208
+ >
209
+ <option value="unsplash">Unsplash</option>
210
+ <option value="pexels">Pexels</option>
211
+ <option value="pixabay">Pixabay</option>
212
+ </select>
213
+ <button
214
+ onClick={toggleDarkMode}
215
+ className="p-2 rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200"
216
+ >
217
+ <i data-feather={darkMode ? "sun" : "moon"}></i>
218
+ </button>
219
+ </div>
220
+ </div>
221
+
222
+ <div className="relative overflow-hidden rounded-xl shadow-xl">
223
+ {isLoading ? (
224
+ <div className="aspect-video w-full skeleton rounded-xl"></div>
225
+ ) : (
226
+ <div
227
+ ref={carouselRef}
228
+ className="relative aspect-video w-full overflow-hidden"
229
+ >
230
+ {images.map((image, index) => (
231
+ <div
232
+ key={index}
233
+ className={`absolute inset-0 flex items-center justify-center carousel-transition ${index === currentIndex ? 'opacity-100' : 'opacity-0 pointer-events-none'}`}
234
+ >
235
+ <div className="relative w-full h-full group">
236
+ <img
237
+ src={image.url}
238
+ alt={image.alt}
239
+ className="w-full h-full object-cover zoom-effect"
240
+ />
241
+ <div className="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-30 transition-all duration-300 flex items-end p-6">
242
+ <div className="transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300">
243
+ <h3 className="text-white text-xl font-bold">{image.alt}</h3>
244
+ <a
245
+ href={image.authorUrl}
246
+ target="_blank"
247
+ rel="noopener noreferrer"
248
+ className="text-gray-200 hover:text-white text-sm"
249
+ >
250
+ Photo by {image.author}
251
+ </a>
252
+ </div>
253
+ </div>
254
+ </div>
255
+ </div>
256
+ ))}
257
+ </div>
258
+ )}
259
+
260
+ {/* Navigation Arrows */}
261
+ <button
262
+ onClick={goToPrev}
263
+ className="absolute left-4 top-1/2 -translate-y-1/2 bg-white dark:bg-gray-800 bg-opacity-80 dark:bg-opacity-80 p-2 rounded-full shadow-md hover:bg-opacity-100 transition-all"
264
+ disabled={isLoading}
265
+ >
266
+ <i data-feather="chevron-left" className="text-gray-800 dark:text-white"></i>
267
+ </button>
268
+ <button
269
+ onClick={goToNext}
270
+ className="absolute right-4 top-1/2 -translate-y-1/2 bg-white dark:bg-gray-800 bg-opacity-80 dark:bg-opacity-80 p-2 rounded-full shadow-md hover:bg-opacity-100 transition-all"
271
+ disabled={isLoading}
272
+ >
273
+ <i data-feather="chevron-right" className="text-gray-800 dark:text-white"></i>
274
+ </button>
275
+
276
+ {/* Indicators */}
277
+ <div className="absolute bottom-4 left-0 right-0 flex justify-center space-x-2">
278
+ {images.map((_, index) => (
279
+ <button
280
+ key={index}
281
+ onClick={() => goToIndex(index)}
282
+ className={`w-3 h-3 rounded-full ${index === currentIndex ? 'bg-white' : 'bg-white bg-opacity-50'} transition-all`}
283
+ disabled={isLoading}
284
+ ></button>
285
+ ))}
286
+ </div>
287
+
288
+ {/* Play/Pause Button */}
289
+ <button
290
+ onClick={toggleAutoPlay}
291
+ className="absolute top-4 right-4 bg-white dark:bg-gray-800 bg-opacity-80 dark:bg-opacity-80 p-2 rounded-full shadow-md hover:bg-opacity-100 transition-all"
292
+ >
293
+ <i data-feather={isAutoPlaying ? "pause" : "play"} className="text-gray-800 dark:text-white"></i>
294
+ </button>
295
+ </div>
296
+
297
+ <div className="mt-6 text-center text-gray-600 dark:text-gray-400">
298
+ <p>Click on navigation arrows or dots to browse manually</p>
299
+ <div className="mt-2 flex justify-center space-x-4">
300
+ <button
301
+ onClick={fetchImages}
302
+ className="flex items-center text-sm bg-gray-100 dark:bg-gray-700 px-3 py-1 rounded-md"
303
+ >
304
+ <i data-feather="refresh-cw" className="w-4 h-4 mr-1"></i>
305
+ Refresh Images
306
+ </button>
307
+ </div>
308
+ </div>
309
+ </div>
310
+ </div>
311
+ );
312
+ };
313
+
314
+ const App = () => {
315
+ return (
316
+ <div>
317
+ <ImageCarousel />
318
+ </div>
319
+ );
320
+ };
321
+
322
+ const root = ReactDOM.createRoot(document.getElementById('root'));
323
+ root.render(<App />);
324
+
325
+ // Initialize feather icons
326
+ feather.replace();
327
+ </script>
328
+ </body>
329
  </html>