hrmkmdtv commited on
Commit
a8f4d29
·
verified ·
1 Parent(s): 6e7cf9c

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +449 -19
index.html CHANGED
@@ -1,19 +1,449 @@
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>Arc Project Starter</title>
7
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
8
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
9
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
10
+ <script src="https://cdn.tailwindcss.com"></script>
11
+ <script>
12
+ tailwind.config = {
13
+ content: ["*"],
14
+ theme: {
15
+ extend: {}
16
+ }
17
+ }
18
+ </script>
19
+ </head>
20
+ <body>
21
+ <div id="root"></div>
22
+
23
+ <script type="text/babel">
24
+ const { useState } = React;
25
+
26
+ // Lucide React icons as simple SVG components
27
+ const Copy = ({ className }) => (
28
+ <svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
29
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
30
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
31
+ </svg>
32
+ );
33
+
34
+ const BookOpen = ({ className }) => (
35
+ <svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
36
+ <path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path>
37
+ <path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path>
38
+ </svg>
39
+ );
40
+
41
+ const FileText = ({ className }) => (
42
+ <svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
43
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
44
+ <polyline points="14,2 14,8 20,8"></polyline>
45
+ <line x1="16" y1="13" x2="8" y2="13"></line>
46
+ <line x1="16" y1="17" x2="8" y2="17"></line>
47
+ <polyline points="10,9 9,9 8,9"></polyline>
48
+ </svg>
49
+ );
50
+
51
+ const Grid = ({ className }) => (
52
+ <svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
53
+ <rect x="3" y="3" width="7" height="7"></rect>
54
+ <rect x="14" y="3" width="7" height="7"></rect>
55
+ <rect x="14" y="14" width="7" height="7"></rect>
56
+ <rect x="3" y="14" width="7" height="7"></rect>
57
+ </svg>
58
+ );
59
+
60
+ const Calculator = ({ className }) => (
61
+ <svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
62
+ <rect x="4" y="2" width="16" height="20" rx="2"></rect>
63
+ <line x1="8" y1="6" x2="16" y2="6"></line>
64
+ <line x1="8" y1="10" x2="16" y2="10"></line>
65
+ <line x1="8" y1="14" x2="16" y2="14"></line>
66
+ <line x1="8" y1="18" x2="16" y2="18"></line>
67
+ </svg>
68
+ );
69
+
70
+ const RefreshCw = ({ className }) => (
71
+ <svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
72
+ <polyline points="23 4 23 10 17 10"></polyline>
73
+ <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path>
74
+ </svg>
75
+ );
76
+
77
+ const Download = ({ className }) => (
78
+ <svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
79
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
80
+ <polyline points="7 10 12 15 17 10"></polyline>
81
+ <line x1="12" y1="15" x2="12" y2="3"></line>
82
+ </svg>
83
+ );
84
+
85
+ // Simple Card components
86
+ const Card = ({ children, className = "" }) => (
87
+ <div className={`rounded-lg border bg-card text-card-foreground shadow-sm ${className}`}>
88
+ {children}
89
+ </div>
90
+ );
91
+
92
+ const CardContent = ({ children, className = "" }) => (
93
+ <div className={`p-6 pt-0 ${className}`}>
94
+ {children}
95
+ </div>
96
+ );
97
+
98
+ const CardHeader = ({ children, className = "" }) => (
99
+ <div className={`flex flex-col space-y-1.5 p-6 ${className}`}>
100
+ {children}
101
+ </div>
102
+ );
103
+
104
+ const CardTitle = ({ children, className = "" }) => (
105
+ <h3 className={`text-2xl font-semibold leading-none tracking-tight ${className}`}>
106
+ {children}
107
+ </h3>
108
+ );
109
+
110
+ // Simple Button component
111
+ const Button = ({ children, onClick, variant = "default", className = "" }) => {
112
+ const baseClasses = "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 px-4 py-2";
113
+ const variantClasses = variant === "outline"
114
+ ? "border border-input bg-background hover:bg-accent hover:text-accent-foreground"
115
+ : "bg-primary text-primary-foreground hover:bg-primary/90";
116
+
117
+ return (
118
+ <button
119
+ className={`${baseClasses} ${variantClasses} ${className}`}
120
+ onClick={onClick}
121
+ >
122
+ {children}
123
+ </button>
124
+ );
125
+ };
126
+
127
+ function ArcProjectStarter() {
128
+ const [books, setBooks] = useState(1);
129
+ const [chapters, setChapters] = useState(10);
130
+ const [pagesRange, setPagesRange] = useState([15, 25]);
131
+ const [panelsRange, setPanelsRange] = useState([4, 6]);
132
+ const [excludePagesMin, setExcludePagesMin] = useState(false);
133
+ const [excludePanelsMin, setExcludePanelsMin] = useState(false);
134
+ const [context, setContext] = useState("A fantasy adventure manga about a young mage discovering ancient magic");
135
+ const [outputTitle, setOutputTitle] = useState("My Manga Project");
136
+ const [contextTitle, setContextTitle] = useState("Story Context");
137
+ const [copySuccess, setCopySuccess] = useState(false);
138
+
139
+ // Adjusted ranges based on checkboxes
140
+ const effectivePagesRange = excludePagesMin ? [pagesRange[1], pagesRange[1]] : pagesRange;
141
+ const effectivePanelsRange = excludePanelsMin ? [panelsRange[1], panelsRange[1]] : panelsRange;
142
+
143
+ // Calculation for page and panel estimates
144
+ const totalPagesMin = books * chapters * effectivePagesRange[0];
145
+ const totalPagesMax = books * chapters * effectivePagesRange[1];
146
+ const totalPanelsMin = totalPagesMin * effectivePanelsRange[0];
147
+ const totalPanelsMax = totalPagesMax * effectivePanelsRange[1];
148
+
149
+ // Explicit total pages of book range string
150
+ const totalPagesOfBookRange = `${totalPagesMin}${totalPagesMin !== totalPagesMax ? ` - ${totalPagesMax}` : ''}`;
151
+
152
+ const outputPrompt = `${outputTitle ? `# ${outputTitle}` : ''}
153
+
154
+ ${contextTitle ? `## ${contextTitle}` : ''}
155
+ "${context}"
156
+
157
+ ## Project Specifications
158
+ - **Books:** ${books}
159
+ - **Chapters per Book:** ${chapters}
160
+ - **Pages per Chapter:** ${effectivePagesRange[0]}${effectivePagesRange[0] !== effectivePagesRange[1] ? ` - ${effectivePagesRange[1]}` : ''}
161
+ - **Total Pages Range:** ${totalPagesMin}${totalPagesMin !== totalPagesMax ? ` - ${totalPagesMax}` : ''}
162
+ - **Panels per Page:** ${effectivePanelsRange[0]}${effectivePanelsRange[0] !== effectivePanelsRange[1] ? ` - ${effectivePanelsRange[1]}` : ''}
163
+ - **Total Panels Range:** ${totalPanelsMin}${totalPanelsMin !== totalPanelsMax ? ` - ${totalPanelsMax}` : ''}
164
+ - **Total Pages of Complete Work:** ${totalPagesOfBookRange}`;
165
+
166
+ const copyToClipboard = async () => {
167
+ try {
168
+ await navigator.clipboard.writeText(outputPrompt);
169
+ setCopySuccess(true);
170
+ setTimeout(() => setCopySuccess(false), 2000);
171
+ } catch (err) {
172
+ console.error('Failed to copy text: ', err);
173
+ }
174
+ };
175
+
176
+ const downloadAsFile = () => {
177
+ const blob = new Blob([outputPrompt], { type: 'text/plain' });
178
+ const url = URL.createObjectURL(blob);
179
+ const a = document.createElement('a');
180
+ a.href = url;
181
+ a.download = `${outputTitle.replace(/\s+/g, '_')}_project_specs.txt`;
182
+ document.body.appendChild(a);
183
+ a.click();
184
+ document.body.removeChild(a);
185
+ URL.revokeObjectURL(url);
186
+ };
187
+
188
+ const resetForm = () => {
189
+ setBooks(1);
190
+ setChapters(10);
191
+ setPagesRange([15, 25]);
192
+ setPanelsRange([4, 6]);
193
+ setExcludePagesMin(false);
194
+ setExcludePanelsMin(false);
195
+ setContext("A fantasy adventure manga about a young mage discovering ancient magic");
196
+ setOutputTitle("My Manga Project");
197
+ setContextTitle("Story Context");
198
+ };
199
+
200
+ // Statistics cards data
201
+ const stats = [
202
+ {
203
+ label: "Total Pages",
204
+ value: totalPagesOfBookRange,
205
+ icon: FileText,
206
+ color: "text-blue-600",
207
+ bgColor: "bg-blue-50"
208
+ },
209
+ {
210
+ label: "Total Panels",
211
+ value: `${totalPanelsMin}${totalPanelsMin !== totalPanelsMax ? ` - ${totalPanelsMax}` : ''}`,
212
+ icon: Grid,
213
+ color: "text-purple-600",
214
+ bgColor: "bg-purple-50"
215
+ },
216
+ {
217
+ label: "Avg Pages/Chapter",
218
+ value: `${effectivePagesRange[0]}${effectivePagesRange[0] !== effectivePagesRange[1] ? ` - ${effectivePagesRange[1]}` : ''}`,
219
+ icon: BookOpen,
220
+ color: "text-green-600",
221
+ bgColor: "bg-green-50"
222
+ }
223
+ ];
224
+
225
+ return (
226
+ <div className="min-h-screen bg-gradient-to-br from-indigo-100 via-purple-50 to-pink-100 p-6">
227
+ <div className="max-w-7xl mx-auto">
228
+ {/* Header */}
229
+ <div className="text-center mb-8">
230
+ <h1 className="text-4xl font-bold text-gray-800 mb-2">Arc Project Starter</h1>
231
+ <p className="text-gray-600">Plan and calculate your manga or comic project specifications</p>
232
+ </div>
233
+
234
+ {/* Statistics Cards */}
235
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
236
+ {stats.map((stat, index) => (
237
+ <Card key={index} className={`${stat.bgColor} border-0 shadow-lg`}>
238
+ <CardContent className="p-4">
239
+ <div className="flex items-center justify-between">
240
+ <div>
241
+ <p className="text-sm font-medium text-gray-600">{stat.label}</p>
242
+ <p className={`text-2xl font-bold ${stat.color}`}>{stat.value}</p>
243
+ </div>
244
+ <stat.icon className={`h-8 w-8 ${stat.color}`} />
245
+ </div>
246
+ </CardContent>
247
+ </Card>
248
+ ))}
249
+ </div>
250
+
251
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
252
+ {/* Left Panel - Configuration */}
253
+ <Card className="bg-white/80 backdrop-blur-sm shadow-xl border-0">
254
+ <CardHeader className="bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-t-lg">
255
+ <CardTitle className="flex items-center gap-2">
256
+ <Calculator className="h-5 w-5" />
257
+ Project Configuration
258
+ </CardTitle>
259
+ </CardHeader>
260
+ <CardContent className="p-6 space-y-6">
261
+ {/* Basic Structure */}
262
+ <div className="grid grid-cols-2 gap-4">
263
+ <div>
264
+ <label className="block text-sm font-semibold text-gray-700 mb-2">Books</label>
265
+ <input
266
+ type="number"
267
+ min="1"
268
+ max="100"
269
+ value={books}
270
+ onChange={(e) => setBooks(Math.max(1, parseInt(e.target.value) || 1))}
271
+ className="w-full border-2 border-gray-200 rounded-lg p-3 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all"
272
+ />
273
+ </div>
274
+ <div>
275
+ <label className="block text-sm font-semibold text-gray-700 mb-2">Chapters per Book</label>
276
+ <input
277
+ type="number"
278
+ min="1"
279
+ max="1000"
280
+ value={chapters}
281
+ onChange={(e) => setChapters(Math.max(1, parseInt(e.target.value) || 1))}
282
+ className="w-full border-2 border-gray-200 rounded-lg p-3 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all"
283
+ />
284
+ </div>
285
+ </div>
286
+
287
+ {/* Pages Range */}
288
+ <div>
289
+ <label className="block text-sm font-semibold text-gray-700 mb-2">Pages per Chapter Range</label>
290
+ <div className="flex gap-3 items-center">
291
+ <input
292
+ type="number"
293
+ min="1"
294
+ max="1000"
295
+ value={pagesRange[0]}
296
+ onChange={(e) => setPagesRange([Math.max(1, parseInt(e.target.value) || 1), Math.max(pagesRange[0], pagesRange[1])])}
297
+ className="flex-1 border-2 border-gray-200 rounded-lg p-3 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all"
298
+ placeholder="Min"
299
+ />
300
+ <span className="text-gray-500 font-medium">to</span>
301
+ <input
302
+ type="number"
303
+ min={pagesRange[0]}
304
+ max="1000"
305
+ value={pagesRange[1]}
306
+ onChange={(e) => setPagesRange([pagesRange[0], Math.max(pagesRange[0], parseInt(e.target.value) || pagesRange[0])])}
307
+ className="flex-1 border-2 border-gray-200 rounded-lg p-3 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all"
308
+ placeholder="Max"
309
+ />
310
+ </div>
311
+ <label className="flex items-center mt-2 text-sm">
312
+ <input
313
+ type="checkbox"
314
+ checked={excludePagesMin}
315
+ onChange={(e) => setExcludePagesMin(e.target.checked)}
316
+ className="mr-2 w-4 h-4 text-blue-600"
317
+ />
318
+ <span className="text-gray-600">Use only maximum value</span>
319
+ </label>
320
+ </div>
321
+
322
+ {/* Panels Range */}
323
+ <div>
324
+ <label className="block text-sm font-semibold text-gray-700 mb-2">Panels per Page Range</label>
325
+ <div className="flex gap-3 items-center">
326
+ <input
327
+ type="number"
328
+ min="1"
329
+ max="50"
330
+ value={panelsRange[0]}
331
+ onChange={(e) => setPanelsRange([Math.max(1, parseInt(e.target.value) || 1), Math.max(panelsRange[0], panelsRange[1])])}
332
+ className="flex-1 border-2 border-gray-200 rounded-lg p-3 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all"
333
+ placeholder="Min"
334
+ />
335
+ <span className="text-gray-500 font-medium">to</span>
336
+ <input
337
+ type="number"
338
+ min={panelsRange[0]}
339
+ max="50"
340
+ value={panelsRange[1]}
341
+ onChange={(e) => setPanelsRange([panelsRange[0], Math.max(panelsRange[0], parseInt(e.target.value) || panelsRange[0])])}
342
+ className="flex-1 border-2 border-gray-200 rounded-lg p-3 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all"
343
+ placeholder="Max"
344
+ />
345
+ </div>
346
+ <label className="flex items-center mt-2 text-sm">
347
+ <input
348
+ type="checkbox"
349
+ checked={excludePanelsMin}
350
+ onChange={(e) => setExcludePanelsMin(e.target.checked)}
351
+ className="mr-2 w-4 h-4 text-blue-600"
352
+ />
353
+ <span className="text-gray-600">Use only maximum value</span>
354
+ </label>
355
+ </div>
356
+
357
+ {/* Reset Button */}
358
+ <Button
359
+ onClick={resetForm}
360
+ variant="outline"
361
+ className="w-full border-2 border-gray-300 hover:bg-gray-50"
362
+ >
363
+ <RefreshCw className="h-4 w-4 mr-2" />
364
+ Reset to Defaults
365
+ </Button>
366
+ </CardContent>
367
+ </Card>
368
+
369
+ {/* Right Panel - Output */}
370
+ <Card className="bg-white/80 backdrop-blur-sm shadow-xl border-0">
371
+ <CardHeader className="bg-gradient-to-r from-green-500 to-teal-600 text-white rounded-t-lg">
372
+ <CardTitle className="flex items-center gap-2">
373
+ <FileText className="h-5 w-5" />
374
+ Project Output
375
+ </CardTitle>
376
+ </CardHeader>
377
+ <CardContent className="p-6 space-y-6">
378
+ {/* Title Inputs */}
379
+ <div>
380
+ <label className="block text-sm font-semibold text-gray-700 mb-2">Project Title</label>
381
+ <input
382
+ type="text"
383
+ value={outputTitle}
384
+ onChange={(e) => setOutputTitle(e.target.value)}
385
+ className="w-full border-2 border-gray-200 rounded-lg p-3 focus:border-green-500 focus:ring-2 focus:ring-green-200 transition-all"
386
+ placeholder="Enter project title..."
387
+ />
388
+ </div>
389
+
390
+ <div>
391
+ <label className="block text-sm font-semibold text-gray-700 mb-2">Context Section Title</label>
392
+ <input
393
+ type="text"
394
+ value={contextTitle}
395
+ onChange={(e) => setContextTitle(e.target.value)}
396
+ className="w-full border-2 border-gray-200 rounded-lg p-3 focus:border-green-500 focus:ring-2 focus:ring-green-200 transition-all"
397
+ placeholder="Enter context section title..."
398
+ />
399
+ </div>
400
+
401
+ <div>
402
+ <label className="block text-sm font-semibold text-gray-700 mb-2">Project Context</label>
403
+ <textarea
404
+ value={context}
405
+ onChange={(e) => setContext(e.target.value)}
406
+ className="w-full border-2 border-gray-200 rounded-lg p-3 focus:border-green-500 focus:ring-2 focus:ring-green-200 transition-all resize-none"
407
+ rows={4}
408
+ placeholder="Describe your project context, story, theme..."
409
+ />
410
+ </div>
411
+
412
+ {/* Generated Output */}
413
+ <div className="bg-gradient-to-r from-gray-50 to-gray-100 rounded-xl p-4 border-2 border-gray-200">
414
+ <h3 className="text-lg font-semibold mb-3 text-gray-800">Generated Project Specification</h3>
415
+ <pre className="whitespace-pre-wrap text-sm bg-white p-4 rounded-lg border shadow-inner font-mono text-gray-700 max-h-64 overflow-y-auto">
416
+ {outputPrompt}
417
+ </pre>
418
+
419
+ {/* Action Buttons */}
420
+ <div className="flex gap-3 mt-4">
421
+ <Button
422
+ onClick={copyToClipboard}
423
+ className={`flex-1 transition-all ${copySuccess ? 'bg-green-600 hover:bg-green-700' : 'bg-blue-600 hover:bg-blue-700'} text-white`}
424
+ >
425
+ <Copy className="h-4 w-4 mr-2" />
426
+ {copySuccess ? 'Copied!' : 'Copy to Clipboard'}
427
+ </Button>
428
+ <Button
429
+ onClick={downloadAsFile}
430
+ variant="outline"
431
+ className="border-2 border-gray-300 hover:bg-gray-50"
432
+ >
433
+ <Download className="h-4 w-4 mr-2" />
434
+ Download
435
+ </Button>
436
+ </div>
437
+ </div>
438
+ </CardContent>
439
+ </Card>
440
+ </div>
441
+ </div>
442
+ </div>
443
+ );
444
+ }
445
+
446
+ ReactDOM.render(<ArcProjectStarter />, document.getElementById('root'));
447
+ </script>
448
+ </body>
449
+ </html>