DotSlashGabut commited on
Commit
8917a24
·
verified ·
1 Parent(s): 9056787

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +315 -19
index.html CHANGED
@@ -1,19 +1,315 @@
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
+ <title>Ultra-QR Studio</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <style>
8
+ :root{
9
+ --bg:#f5f7fa;
10
+ --fg:#111;
11
+ --accent:#0066ff;
12
+ --radius:.5rem;
13
+ --shadow:0 2px 8px rgba(0,0,0,.08);
14
+ --font:"Inter",system-ui;
15
+ --transition:.2s ease;
16
+ }
17
+ [data-theme="dark"]{
18
+ --bg:#111;
19
+ --fg:#f5f7fa;
20
+ --accent:#0af;
21
+ }
22
+ *{box-sizing:border-box;font-family:var(--font)}
23
+ body{margin:0;background:var(--bg);color:var(--fg);display:flex;align-items:center;justify-content:center;min-height:100vh;padding:1rem}
24
+ .panel{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;max-width:900px;width:100%}
25
+ .card{background:var(--bg);border-radius:var(--radius);box-shadow:var(--shadow);padding:1.5rem}
26
+ h1{font-size:1.25rem;margin:0 0 1rem;text-align:center}
27
+ .tabs{display:flex;gap:.25rem;margin-bottom:1rem;flex-wrap:wrap}
28
+ .tab{flex:1;padding:.5rem .75rem;border:none;border-radius:var(--radius);background:transparent;cursor:pointer;font-size:.75rem;color:var(--fg);transition:var(--transition)}
29
+ .tab.active{background:var(--accent);color:#fff}
30
+ .field{display:flex;flex-direction:column;margin-bottom:.75rem}
31
+ label{font-size:.75rem;margin-bottom:.25rem}
32
+ input,select,textarea{font-size:.875rem;padding:.5rem;border:1px solid #ccc;border-radius:var(--radius);background:var(--bg);color:var(--fg);transition:var(--transition)}
33
+ input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent)}
34
+ textarea{resize:vertical;min-height:3rem}
35
+ .qr{display:flex;justify-content:center;align-items:center;flex-direction:column}
36
+ .qr canvas{border:1px solid #ccc;border-radius:var(--radius)}
37
+ .controls{display:flex;gap:.5rem;flex-wrap:wrap}
38
+ .btn{flex:1;padding:.5rem;border:none;border-radius:var(--radius);cursor:pointer;background:#eee;color:var(--fg);transition:var(--transition)}
39
+ .btn.primary{background:var(--accent);color:#fff}
40
+ .btn:hover{opacity:.9}
41
+ .hidden{display:none}
42
+ .settings{display:flex;justify-content:space-between;align-items:center;font-size:.75rem;margin-bottom:.75rem}
43
+ .theme-toggle{background:none;border:none;cursor:pointer;font-size:1.2rem}
44
+ .size-slider{width:100%;margin:.5rem 0}
45
+ .size-value{font-size:.75rem;text-align:center}
46
+ @media(max-width:700px){.panel{grid-template-columns:1fr}}
47
+ </style>
48
+ </head>
49
+ <body>
50
+ <div class="panel">
51
+ <!-- ===== LEFT: FORM ===== -->
52
+ <div class="card">
53
+ <div class="settings">
54
+ <h1>Ultra-QR Studio</h1>
55
+ <button class="theme-toggle" title="Toggle dark mode" onclick="toggleTheme()">🌓</button>
56
+ </div>
57
+
58
+ <div class="tabs">
59
+ <button class="tab active" data-type="text">Text</button>
60
+ <button class="tab" data-type="url">URL</button>
61
+ <button class="tab" data-type="wifi">Wi-Fi</button>
62
+ <button class="tab" data-type="vcard">vCard</button>
63
+ <button class="tab" data-type="email">Email</button>
64
+ <button class="tab" data-type="sms">SMS</button>
65
+ <button class="tab" data-type="event">Event</button>
66
+ <button class="tab" data-type="location">Location</button>
67
+ </div>
68
+
69
+ <!-- Text -->
70
+ <div class="field" data-panel="text">
71
+ <label>Plain Text</label>
72
+ <textarea id="textInput" placeholder="Type anything..."></textarea>
73
+ </div>
74
+
75
+ <!-- URL -->
76
+ <div class="field hidden" data-panel="url">
77
+ <label>URL</label>
78
+ <input id="urlInput" type="url" placeholder="https://example.com">
79
+ </div>
80
+
81
+ <!-- Wi-Fi -->
82
+ <div class="hidden" data-panel="wifi">
83
+ <div class="field">
84
+ <label>SSID</label>
85
+ <input id="wifiSSID" placeholder="Network Name">
86
+ </div>
87
+ <div class="field">
88
+ <label>Password</label>
89
+ <input id="wifiPass" type="password" placeholder="Password">
90
+ </div>
91
+ <div class="field">
92
+ <label>Security</label>
93
+ <select id="wifiEnc">
94
+ <option>WPA</option>
95
+ <option>WEP</option>
96
+ <option>None</option>
97
+ </select>
98
+ </div>
99
+ <label><input type="checkbox" id="wifiHidden"> Hidden Network</label>
100
+ </div>
101
+
102
+ <!-- vCard -->
103
+ <div class="hidden" data-panel="vcard">
104
+ <div class="field">
105
+ <label>Name</label>
106
+ <input id="vcName" placeholder="John Doe">
107
+ </div>
108
+ <div class="field">
109
+ <label>Company</label>
110
+ <input id="vcOrg" placeholder="ACME Inc">
111
+ </div>
112
+ <div class="field">
113
+ <label>Phone</label>
114
+ <input id="vcTel" placeholder="+123456789">
115
+ </div>
116
+ <div class="field">
117
+ <label>Email</label>
118
+ <input id="vcEmail" type="email" placeholder="[email protected]">
119
+ </div>
120
+ </div>
121
+
122
+ <!-- Email -->
123
+ <div class="hidden" data-panel="email">
124
+ <div class="field">
125
+ <label>To</label>
126
+ <input id="emailTo" type="email" placeholder="[email protected]">
127
+ </div>
128
+ <div class="field">
129
+ <label>Subject</label>
130
+ <input id="emailSub" placeholder="Subject">
131
+ </div>
132
+ <div class="field">
133
+ <label>Body</label>
134
+ <textarea id="emailBody" placeholder="Message..."></textarea>
135
+ </div>
136
+ </div>
137
+
138
+ <!-- SMS -->
139
+ <div class="hidden" data-panel="sms">
140
+ <div class="field">
141
+ <label>Number</label>
142
+ <input id="smsNum" type="tel" placeholder="+123456789">
143
+ </div>
144
+ <div class="field">
145
+ <label>Message</label>
146
+ <textarea id="smsMsg" placeholder="SMS text..."></textarea>
147
+ </div>
148
+ </div>
149
+
150
+ <!-- Event -->
151
+ <div class="hidden" data-panel="event">
152
+ <div class="field">
153
+ <label>Title</label>
154
+ <input id="evTitle" placeholder="Team Meeting">
155
+ </div>
156
+ <div class="field">
157
+ <label>Start</label>
158
+ <input id="evStart" type="datetime-local">
159
+ </div>
160
+ <div class="field">
161
+ <label>End</label>
162
+ <input id="evEnd" type="datetime-local">
163
+ </div>
164
+ <div class="field">
165
+ <label>Location</label>
166
+ <input id="evLoc" placeholder="Conference Room">
167
+ </div>
168
+ <div class="field">
169
+ <label>Description</label>
170
+ <textarea id="evDesc" placeholder="Details..."></textarea>
171
+ </div>
172
+ </div>
173
+
174
+ <!-- Location -->
175
+ <div class="hidden" data-panel="location">
176
+ <div class="field">
177
+ <label>Latitude</label>
178
+ <input id="locLat" type="number" placeholder="48.8584">
179
+ </div>
180
+ <div class="field">
181
+ <label>Longitude</label>
182
+ <input id="locLng" type="number" placeholder="2.2945">
183
+ </div>
184
+ <div class="field">
185
+ <label>Query (optional)</label>
186
+ <input id="locQuery" placeholder="Eiffel Tower">
187
+ </div>
188
+ </div>
189
+
190
+ <div class="field">
191
+ <label>Size <span class="size-value"><span id="sizeValue">200</span>px</span></label>
192
+ <input class="size-slider" id="sizeRange" type="range" min="100" max="340" value="200">
193
+ </div>
194
+
195
+ <div class="controls">
196
+ <button class="btn primary" onclick="generateQR()">Generate</button>
197
+ <button class="btn" onclick="downloadQR()">PNG</button>
198
+ <button class="btn" onclick="downloadSVG()">SVG</button>
199
+ </div>
200
+ </div>
201
+
202
+ <!-- ===== RIGHT: PREVIEW ===== -->
203
+ <div class="card">
204
+ <div class="qr">
205
+ <canvas id="qrCanvas" width="200" height="200"></canvas>
206
+ </div>
207
+ </div>
208
+ </div>
209
+
210
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/qrcode.min.js"></script>
211
+ <script>
212
+ // ---------- Theme ----------
213
+ const setTheme = t => document.documentElement.setAttribute('data-theme', t);
214
+ const toggleTheme = () => setTheme(localStorage.theme === 'dark' ? (localStorage.theme='light') : (localStorage.theme='dark'));
215
+ if (!localStorage.theme) localStorage.theme = 'light';
216
+ setTheme(localStorage.theme);
217
+
218
+ // ---------- Tab Switch ----------
219
+ const tabs = document.querySelectorAll('.tab');
220
+ const panels = document.querySelectorAll('[data-panel]');
221
+ const switchTab = type => {
222
+ tabs.forEach(t => t.classList.toggle('active', t.dataset.type === type));
223
+ panels.forEach(p => p.classList.toggle('hidden', p.dataset.panel !== type));
224
+ generateQR();
225
+ };
226
+ tabs.forEach(t => t.addEventListener('click', () => switchTab(t.dataset.type)));
227
+
228
+ // ---------- Build Content ----------
229
+ const buildContent = () => {
230
+ const t = document.querySelector('.tab.active').dataset.type;
231
+ switch (t) {
232
+ case 'text': return document.getElementById('textInput').value.trim() || 'Hello World';
233
+ case 'url': return document.getElementById('urlInput').value.trim() || 'https://example.com';
234
+ case 'wifi': {
235
+ const ssid = document.getElementById('wifiSSID').value.trim();
236
+ const pass = document.getElementById('wifiPass').value;
237
+ const enc = document.getElementById('wifiEnc').value;
238
+ const hidden = document.getElementById('wifiHidden').checked;
239
+ return `WIFI:T:${enc};S:${ssid};P:${pass};H:${hidden ? 'true' : 'false'};;`;
240
+ }
241
+ case 'vcard': {
242
+ const n = document.getElementById('vcName').value.trim();
243
+ const o = document.getElementById('vcOrg').value.trim();
244
+ const t = document.getElementById('vcTel').value.trim();
245
+ const e = document.getElementById('vcEmail').value.trim();
246
+ return `BEGIN:VCARD\nVERSION:3.0\nFN:${n}\nORG:${o}\nTEL:${t}\nEMAIL:${e}\nEND:VCARD`;
247
+ }
248
+ case 'email': {
249
+ const to = document.getElementById('emailTo').value.trim();
250
+ const sub = document.getElementById('emailSub').value.trim();
251
+ const body = document.getElementById('emailBody').value.trim();
252
+ return `mailto:${to}?subject=${encodeURIComponent(sub)}&body=${encodeURIComponent(body)}`;
253
+ }
254
+ case 'sms': {
255
+ const num = document.getElementById('smsNum').value.trim();
256
+ const msg = document.getElementById('smsMsg').value.trim();
257
+ return `smsto:${num}:${msg}`;
258
+ }
259
+ case 'event': {
260
+ const title = document.getElementById('evTitle').value.trim();
261
+ const start = new Date(document.getElementById('evStart').value).toISOString().replace(/[-:]/g,'').slice(0,15);
262
+ const end = new Date(document.getElementById('evEnd').value).toISOString().replace(/[-:]/g,'').slice(0,15);
263
+ const loc = document.getElementById('evLoc').value.trim();
264
+ const desc = document.getElementById('evDesc').value.trim();
265
+ return `BEGIN:VEVENT\nSUMMARY:${title}\nDTSTART:${start}\nDTEND:${end}\nLOCATION:${loc}\nDESCRIPTION:${desc}\nEND:VEVENT`;
266
+ }
267
+ case 'location': {
268
+ const lat = document.getElementById('locLat').value || '0';
269
+ const lng = document.getElementById('locLng').value || '0';
270
+ const q = document.getElementById('locQuery').value;
271
+ return `geo:${lat},${lng}?q=${encodeURIComponent(q)}`;
272
+ }
273
+ default: return '';
274
+ }
275
+ };
276
+
277
+ // ---------- Generate ----------
278
+ const generateQR = () => {
279
+ const content = buildContent();
280
+ const size = document.getElementById('sizeRange').value;
281
+ document.getElementById('sizeValue').textContent = size;
282
+ const canvas = document.getElementById('qrCanvas');
283
+ canvas.width = canvas.height = size;
284
+ QRCode.toCanvas(canvas, content, { width: size, margin: 2, color: { dark: '#000', light: '#fff' } });
285
+ };
286
+
287
+ // ---------- Downloads ----------
288
+ const downloadQR = () => {
289
+ const canvas = document.getElementById('qrCanvas');
290
+ const a = document.createElement('a');
291
+ a.href = canvas.toDataURL('image/png');
292
+ a.download = 'qr.png';
293
+ a.click();
294
+ };
295
+ const downloadSVG = () => {
296
+ const content = buildContent();
297
+ const size = document.getElementById('sizeRange').value;
298
+ QRCode.toString(content, { type: 'svg', width: size }, (err, svg) => {
299
+ if (err) return;
300
+ const blob = new Blob([svg], { type: 'image/svg+xml' });
301
+ const a = document.createElement('a');
302
+ a.href = URL.createObjectURL(blob);
303
+ a.download = 'qr.svg';
304
+ a.click();
305
+ });
306
+ };
307
+
308
+ // ---------- Live Update ----------
309
+ document.querySelectorAll('input, textarea, select').forEach(el => el.addEventListener('input', generateQR));
310
+
311
+ // ---------- Init ----------
312
+ generateQR();
313
+ </script>
314
+ </body>
315
+ </html>