json-renderers 1.18.5 → 1.18.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,520 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Using CDN | How to Render HTML Select via CDN Import</title>
8
+ <meta name="description"
9
+ content="Step-by-step beginner guide to building and mounting HTML select dropdowns using json-renderers direct CDN import via ES Modules." />
10
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
11
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
12
+ <link
13
+ href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600&family=Inter:wght@300;400;500;600;700;800&display=swap"
14
+ rel="stylesheet" />
15
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
16
+ <script src="https://cdn.tailwindcss.com"></script>
17
+ <script>
18
+ tailwind.config = {
19
+ theme: {
20
+ extend: {
21
+ colors: {
22
+ brand: {
23
+ 50: '#eff6ff',
24
+ 100: '#dbeafe',
25
+ 500: '#3b82f6',
26
+ 600: '#2563eb',
27
+ 700: '#1d4ed8'
28
+ }
29
+ },
30
+ fontFamily: {
31
+ sans: ['Inter', 'sans-serif'],
32
+ mono: ['Fira Code', 'monospace']
33
+ }
34
+ }
35
+ }
36
+ };
37
+ </script>
38
+ <style>
39
+ body {
40
+ font-family: 'Inter', sans-serif;
41
+ background-color: #ffffff;
42
+ color: #1e293b;
43
+ }
44
+
45
+ pre,
46
+ code {
47
+ font-family: 'Fira Code', monospace;
48
+ }
49
+
50
+ .custom-scrollbar::-webkit-scrollbar {
51
+ width: 6px;
52
+ height: 6px;
53
+ }
54
+
55
+ .custom-scrollbar::-webkit-scrollbar-track {
56
+ background: #f1f5f9;
57
+ }
58
+
59
+ .custom-scrollbar::-webkit-scrollbar-thumb {
60
+ background: #cbd5e1;
61
+ border-radius: 4px;
62
+ }
63
+
64
+ .custom-scrollbar::-webkit-scrollbar-thumb:hover {
65
+ background: #94a3b8;
66
+ }
67
+
68
+ .step-badge {
69
+ width: 2.25rem;
70
+ height: 2.25rem;
71
+ border-radius: 9999px;
72
+ display: inline-flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+ font-weight: 700;
76
+ font-size: 0.875rem;
77
+ }
78
+
79
+ #cdn-live-output select {
80
+ width: 100%;
81
+ padding: 0.65rem 1rem;
82
+ font-size: 0.95rem;
83
+ border-radius: 0.75rem;
84
+ border: 1px solid #cbd5e1;
85
+ background-color: #ffffff;
86
+ color: #0f172a;
87
+ transition: all 0.2s ease;
88
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
89
+ }
90
+
91
+ #cdn-live-output select:focus {
92
+ outline: none;
93
+ border-color: #2563eb;
94
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
95
+ }
96
+ </style>
97
+ </head>
98
+
99
+ <body class="bg-white text-slate-800 min-h-screen antialiased flex flex-col font-sans selection:bg-blue-500 selection:text-white">
100
+
101
+ <!-- Top Sticky Navigation Bar -->
102
+ <header class="border-b border-slate-200 bg-white/95 backdrop-blur sticky top-0 z-50 shadow-sm">
103
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 py-3.5 flex items-center justify-between gap-4">
104
+ <div class="flex items-center gap-3">
105
+ <a href="../index.html"
106
+ class="w-10 h-10 rounded-xl bg-gradient-to-br from-blue-500 via-indigo-600 to-cyan-500 flex items-center justify-center font-bold text-white shadow-md text-lg hover:scale-105 transition">
107
+ ▣
108
+ </a>
109
+ <div>
110
+ <div class="flex items-center gap-2">
111
+ <a href="../index.html"
112
+ class="text-base font-bold text-slate-900 tracking-tight hover:text-blue-600 transition">json-renderers</a>
113
+ <span
114
+ class="px-2 py-0.5 text-xs bg-blue-100 text-blue-800 rounded-full border border-blue-200 font-mono font-medium">Select
115
+ &bull; CDN</span>
116
+ </div>
117
+ <p class="text-xs text-slate-500">Direct CDN Import Integration Guide</p>
118
+ </div>
119
+ </div>
120
+
121
+ <nav class="flex items-center gap-1.5 sm:gap-2 text-sm">
122
+ <a href="../index.html"
123
+ class="px-3 py-1.5 rounded-lg bg-slate-100 hover:bg-slate-200 text-slate-700 font-medium transition text-xs sm:text-sm">Samples Hub</a>
124
+ <a href="index.html"
125
+ class="px-3 py-1.5 rounded-lg bg-slate-100 hover:bg-slate-200 text-slate-700 font-medium transition text-xs sm:text-sm">Select Hub</a>
126
+ <a href="cdn.html"
127
+ class="px-3 py-1.5 rounded-lg bg-blue-600 text-white font-semibold shadow-sm transition text-xs sm:text-sm">Using CDN</a>
128
+ <a href="windowks.html"
129
+ class="px-3 py-1.5 rounded-lg bg-slate-100 hover:bg-slate-200 text-slate-700 font-medium transition text-xs sm:text-sm">window.ks</a>
130
+ <a href="../../../samples/select/byCdn/index.html" target="_blank"
131
+ class="px-3 py-1.5 rounded-lg bg-blue-50 hover:bg-blue-100 text-blue-800 border border-blue-200 font-semibold transition hidden sm:inline-flex items-center gap-1 text-xs sm:text-sm">
132
+ <span>▶️</span> Run Sample
133
+ </a>
134
+ </nav>
135
+ </div>
136
+ </header>
137
+
138
+ <main class="flex-1 max-w-7xl w-full mx-auto p-4 sm:p-6 lg:p-8 space-y-10">
139
+
140
+ <!-- Hero Section -->
141
+ <section class="bg-gradient-to-br from-slate-50 via-blue-50/50 to-indigo-50/30 rounded-3xl p-6 sm:p-10 border border-slate-200 shadow-sm relative overflow-hidden">
142
+ <div class="relative z-10 space-y-5">
143
+ <div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-blue-100 border border-blue-200 text-xs text-blue-800 font-mono font-medium">
144
+ <span class="w-2 h-2 rounded-full bg-blue-500 animate-pulse"></span>
145
+ Method 1 &bull; Direct CDN Import
146
+ </div>
147
+
148
+ <h1 class="text-3xl sm:text-5xl font-extrabold text-slate-900 tracking-tight leading-tight">
149
+ How to Render HTML Select <br class="hidden sm:inline" />
150
+ <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-indigo-600">Using Direct CDN Import</span>
151
+ </h1>
152
+
153
+ <p class="max-w-4xl text-slate-600 text-base sm:text-lg leading-relaxed">
154
+ Learn how to import the <code class="text-blue-700 bg-blue-50 px-1.5 py-0.5 rounded font-mono font-semibold">render</code> function directly from jsDelivr into your browser ES Module without any build step, bundlers, or npm installations.
155
+ </p>
156
+
157
+ <!-- Action Links -->
158
+ <div class="flex flex-wrap gap-2.5 pt-2">
159
+ <a href="#how-it-works"
160
+ class="px-3.5 py-2 rounded-xl bg-white hover:bg-slate-50 text-slate-800 text-xs sm:text-sm font-semibold transition border border-slate-300 shadow-sm flex items-center gap-1.5">
161
+ <span>💡</span> How It Works
162
+ </a>
163
+ <a href="#code-walkthrough"
164
+ class="px-3.5 py-2 rounded-xl bg-white hover:bg-slate-50 text-slate-800 text-xs sm:text-sm font-semibold transition border border-slate-300 shadow-sm flex items-center gap-1.5">
165
+ <span>📄</span> Code Walkthrough
166
+ </a>
167
+ <a href="#live-demo"
168
+ class="px-3.5 py-2 rounded-xl bg-blue-600 hover:bg-blue-500 text-white text-xs sm:text-sm font-semibold transition flex items-center gap-1.5 shadow-sm">
169
+ <span>⚡</span> Interactive CDN Demo
170
+ </a>
171
+ <a href="../../../samples/select/byCdn/index.html" target="_blank"
172
+ class="px-3.5 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-white text-xs sm:text-sm font-semibold transition flex items-center gap-1.5 shadow-sm">
173
+ <span>📂</span> Open samples/select/byCdn &rarr;
174
+ </a>
175
+ </div>
176
+ </div>
177
+ </section>
178
+
179
+ <!-- How It Works (The Simple Story) -->
180
+ <section id="how-it-works" class="space-y-6">
181
+ <div class="flex items-center justify-between">
182
+ <div>
183
+ <span class="text-xs font-mono font-semibold text-blue-700 uppercase tracking-wider">Concept</span>
184
+ <h2 class="text-2xl font-bold text-slate-900 mt-1">The 3-Step CDN Story</h2>
185
+ </div>
186
+ <span class="text-xs text-slate-500 font-mono hidden sm:inline">Zero build configuration</span>
187
+ </div>
188
+
189
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
190
+
191
+ <div class="bg-white rounded-2xl p-6 border border-slate-200 shadow-sm space-y-3">
192
+ <span class="step-badge bg-blue-100 text-blue-800 border border-blue-200">1</span>
193
+ <h3 class="text-base font-bold text-slate-900">1. Target Container</h3>
194
+ <p class="text-xs text-slate-600 leading-relaxed">
195
+ Place an empty <code class="text-blue-700 font-mono">&lt;div id="select-output"&gt;&lt;/div&gt;</code> anywhere in your HTML document where the select should be mounted.
196
+ </p>
197
+ </div>
198
+
199
+ <div class="bg-white rounded-2xl p-6 border border-slate-200 shadow-sm space-y-3">
200
+ <span class="step-badge bg-indigo-100 text-indigo-800 border border-indigo-200">2</span>
201
+ <h3 class="text-base font-bold text-slate-900">2. Import from CDN</h3>
202
+ <p class="text-xs text-slate-600 leading-relaxed">
203
+ Use native browser ES Modules (<code class="text-indigo-700 font-mono">&lt;script type="module"&gt;</code>) to import the renderer from jsDelivr.
204
+ </p>
205
+ </div>
206
+
207
+ <div class="bg-white rounded-2xl p-6 border border-slate-200 shadow-sm space-y-3">
208
+ <span class="step-badge bg-cyan-100 text-cyan-800 border border-cyan-200">3</span>
209
+ <h3 class="text-base font-bold text-slate-900">3. Call render()</h3>
210
+ <p class="text-xs text-slate-600 leading-relaxed">
211
+ Pass <code class="text-cyan-700 font-mono">{ type: "select", data: [...], targetHtmlId: "..." }</code>. The library creates the DOM nodes and mounts them immediately.
212
+ </p>
213
+ </div>
214
+
215
+ </div>
216
+ </section>
217
+
218
+ <!-- Code Walkthrough -->
219
+ <section id="code-walkthrough" class="bg-white rounded-3xl p-6 sm:p-8 border border-slate-200 shadow-sm space-y-4">
220
+ <div class="flex items-center justify-between flex-wrap gap-2">
221
+ <div>
222
+ <span class="text-xs font-mono font-semibold text-blue-700 uppercase tracking-wider">Implementation</span>
223
+ <h2 class="text-xl sm:text-2xl font-bold text-slate-900">Complete HTML Page Example</h2>
224
+ </div>
225
+ <button onclick="copyCode('full-example-code')"
226
+ class="px-3 py-1.5 rounded-lg bg-slate-100 hover:bg-slate-200 text-slate-700 text-xs font-mono font-medium transition flex items-center gap-1.5 border border-slate-300">
227
+ <span>📋</span> Copy Code
228
+ </button>
229
+ </div>
230
+
231
+ <div class="rounded-2xl bg-slate-950 p-4 sm:p-5 text-xs text-slate-200 overflow-x-auto custom-scrollbar">
232
+ <pre id="full-example-code"><code>&lt;!DOCTYPE html&gt;
233
+ &lt;html lang="en"&gt;
234
+ &lt;head&gt;
235
+ &lt;meta charset="UTF-8" /&gt;
236
+ &lt;title&gt;Select CDN Demo&lt;/title&gt;
237
+ &lt;link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" /&gt;
238
+ &lt;/head&gt;
239
+ &lt;body class="p-4"&gt;
240
+
241
+ &lt;!-- 1. Target container for the rendered select --&gt;
242
+ &lt;div id="select-output"&gt;&lt;/div&gt;
243
+
244
+ &lt;!-- 2. ES Module Script importing directly from jsDelivr CDN --&gt;
245
+ &lt;script type="module"&gt;
246
+ import render from "https://cdn.jsdelivr.net/gh/keshavsoft/json-renderers@main/docs/dist/v14/min.js";
247
+
248
+ // 3. Define the options array
249
+ const cities = ["Hyderabad", "Bengaluru", "Chennai", "Mumbai", "Pune"];
250
+
251
+ // 4. Render into DOM
252
+ render({
253
+ type: "select",
254
+ data: cities,
255
+ targetHtmlId: "select-output",
256
+ showLog: true
257
+ });
258
+
259
+ // 5. Add standard change listener
260
+ const select = document.querySelector("#select-output select");
261
+ if (select) {
262
+ select.addEventListener("change", (e) => {
263
+ alert("You selected: " + e.target.value);
264
+ });
265
+ }
266
+ &lt;/script&gt;
267
+ &lt;/body&gt;
268
+ &lt;/html&gt;</code></pre>
269
+ </div>
270
+ </section>
271
+
272
+ <!-- Interactive Live CDN Playground -->
273
+ <section id="live-demo" class="bg-white rounded-3xl p-6 sm:p-8 border border-slate-200 shadow-sm space-y-6">
274
+ <div class="flex items-center justify-between flex-wrap gap-2 border-b border-slate-100 pb-4">
275
+ <div>
276
+ <span class="text-xs font-mono font-semibold text-blue-700 uppercase tracking-wider">Live Experience</span>
277
+ <h2 class="text-xl sm:text-2xl font-bold text-slate-900">Interactive CDN Demo &amp; Code Generator</h2>
278
+ </div>
279
+ <div class="flex items-center gap-2">
280
+ <span id="status-badge" class="px-2 py-0.5 text-[11px] font-mono rounded bg-slate-100 text-slate-700">Ready</span>
281
+ </div>
282
+ </div>
283
+
284
+ <!-- Option Management Toolbar -->
285
+ <div class="bg-slate-50 p-4 rounded-2xl border border-slate-200 space-y-3">
286
+ <label class="block text-xs font-bold text-slate-700">Add Option Dynamically</label>
287
+ <div class="flex gap-2 flex-wrap sm:flex-nowrap">
288
+ <input type="text" id="new-option-input" placeholder="Type new option name (e.g., Tokyo)..."
289
+ class="flex-1 text-xs px-3 py-2 rounded-lg border border-slate-300 bg-white focus:outline-none focus:border-blue-500" />
290
+ <button id="btn-add-option"
291
+ class="px-4 py-2 rounded-lg bg-blue-600 hover:bg-blue-700 text-white font-semibold text-xs shadow-sm transition whitespace-nowrap">
292
+ + Add Option
293
+ </button>
294
+ <button id="btn-reset-options"
295
+ class="px-3 py-2 rounded-lg bg-slate-200 hover:bg-slate-300 text-slate-700 font-semibold text-xs transition whitespace-nowrap">
296
+ Reset
297
+ </button>
298
+ </div>
299
+ </div>
300
+
301
+ <!-- Live Output and Interactive Console -->
302
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
303
+
304
+ <!-- Left: Rendered Container -->
305
+ <div class="p-6 rounded-2xl border border-slate-200 bg-slate-50/50 space-y-4">
306
+ <div class="flex items-center justify-between">
307
+ <h3 class="text-sm font-bold text-slate-900 flex items-center gap-2">
308
+ <span>🖥️</span> Live Mounted Select
309
+ </h3>
310
+ <span class="text-[11px] font-mono text-slate-500">#cdn-live-output</span>
311
+ </div>
312
+
313
+ <div id="cdn-live-output" class="bg-white p-5 rounded-xl border border-slate-200 shadow-sm min-h-[90px] flex items-center justify-center">
314
+ <!-- Mounted select -->
315
+ </div>
316
+
317
+ <!-- Selection Display -->
318
+ <div class="p-3.5 rounded-xl bg-blue-50 border border-blue-200 flex items-center justify-between text-xs">
319
+ <span class="font-semibold text-blue-900">Selected Value:</span>
320
+ <span id="cdn-selected-value" class="font-mono font-bold text-blue-800 bg-white px-2.5 py-1 rounded border border-blue-200">
321
+ (None)
322
+ </span>
323
+ </div>
324
+
325
+ <!-- Console Output Box -->
326
+ <div class="rounded-xl bg-slate-900 p-3.5 text-xs text-slate-300 space-y-2">
327
+ <div class="flex items-center justify-between text-[11px] font-mono text-slate-400 border-b border-slate-800 pb-2">
328
+ <span>Execution Console Log</span>
329
+ <button id="btn-clear-console" class="text-slate-500 hover:text-slate-300">Clear</button>
330
+ </div>
331
+ <pre id="cdn-console" class="custom-scrollbar overflow-auto max-h-[90px] font-mono text-[11px] text-emerald-400"><code>Ready.</code></pre>
332
+ </div>
333
+ </div>
334
+
335
+ <!-- Right: Synchronized Code Snippet -->
336
+ <div class="p-6 rounded-2xl border border-slate-200 bg-slate-900 text-slate-200 space-y-3 flex flex-col justify-between">
337
+ <div class="flex items-center justify-between">
338
+ <div class="flex items-center gap-2 text-xs font-mono">
339
+ <span class="w-2.5 h-2.5 rounded-full bg-blue-400"></span>
340
+ <span class="font-bold text-white">Active CDN Snippet</span>
341
+ </div>
342
+ <button onclick="copyCode('active-cdn-code')"
343
+ class="px-2.5 py-1 rounded bg-slate-800 hover:bg-slate-700 text-[11px] font-mono text-slate-300 transition border border-slate-700">
344
+ Copy Snippet
345
+ </button>
346
+ </div>
347
+
348
+ <div class="custom-scrollbar overflow-auto max-h-[220px] rounded-lg bg-slate-950 p-3.5 font-mono text-xs text-slate-300">
349
+ <pre id="active-cdn-code"><code>Loading snippet...</code></pre>
350
+ </div>
351
+
352
+ <p class="text-[11px] text-slate-400 font-mono">
353
+ This snippet matches your active dataset in real time.
354
+ </p>
355
+ </div>
356
+
357
+ </div>
358
+ </section>
359
+
360
+ </main>
361
+
362
+ <!-- Clean Light Footer -->
363
+ <footer class="border-t border-slate-200 bg-slate-50 py-8 mt-12">
364
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 flex flex-col sm:flex-row items-center justify-between gap-4 text-xs text-slate-600">
365
+ <div>
366
+ <span class="text-slate-900 font-semibold">json-renderers</span> &bull; CDN Documentation for <code class="text-blue-700 font-mono">select</code>
367
+ </div>
368
+ <div class="flex items-center gap-4 flex-wrap">
369
+ <a href="index.html" class="hover:text-blue-600 transition">Select Hub</a>
370
+ <a href="windowks.html" class="hover:text-indigo-600 transition">window.ks Guide</a>
371
+ <a href="../index.html" class="hover:text-slate-900 transition">Samples Hub</a>
372
+ <a href="../../index.html" class="hover:text-slate-900 transition">Main Docs</a>
373
+ </div>
374
+ </div>
375
+ </footer>
376
+
377
+ <!-- Script for Interactive Playground -->
378
+ <script type="module">
379
+ let renderDirect = null;
380
+
381
+ try {
382
+ const module = await import("../dist/v14/min.js");
383
+ renderDirect = module.default;
384
+ } catch {
385
+ try {
386
+ const module = await import("https://cdn.jsdelivr.net/gh/keshavsoft/json-renderers@main/docs/dist/v14/min.js");
387
+ renderDirect = module.default;
388
+ } catch (err) {
389
+ console.warn("Direct CDN load failed, using DOM fallback.", err);
390
+ }
391
+ }
392
+
393
+ const defaultItems = ["Hyderabad", "Bengaluru", "Chennai", "Mumbai", "Pune"];
394
+ let currentItems = [...defaultItems];
395
+
396
+ const input = document.getElementById("new-option-input");
397
+ const addBtn = document.getElementById("btn-add-option");
398
+ const resetBtn = document.getElementById("btn-reset-options");
399
+ const liveContainer = document.getElementById("cdn-live-output");
400
+ const selectedDisplay = document.getElementById("cdn-selected-value");
401
+ const demoConsole = document.getElementById("cdn-console");
402
+ const snippetCode = document.getElementById("active-cdn-code");
403
+ const statusBadge = document.getElementById("status-badge");
404
+ const clearBtn = document.getElementById("btn-clear-console");
405
+
406
+ function logConsole(msg) {
407
+ if (!demoConsole) return;
408
+ demoConsole.innerHTML += "\n" + msg;
409
+ demoConsole.scrollTop = demoConsole.scrollHeight;
410
+ }
411
+
412
+ if (clearBtn) {
413
+ clearBtn.addEventListener("click", () => {
414
+ demoConsole.innerHTML = "<code>Console cleared.</code>";
415
+ });
416
+ }
417
+
418
+ function updateSnippet() {
419
+ snippetCode.textContent = `// Direct CDN Import
420
+ import render from "https://cdn.jsdelivr.net/gh/keshavsoft/json-renderers@main/docs/dist/v14/min.js";
421
+
422
+ const data = ${JSON.stringify(currentItems, null, 2)};
423
+
424
+ render({
425
+ type: "select",
426
+ data: data,
427
+ targetHtmlId: "cdn-live-output",
428
+ showLog: true
429
+ });`;
430
+ }
431
+
432
+ function renderSelect() {
433
+ statusBadge.textContent = "Rendering...";
434
+ statusBadge.className = "px-2 py-0.5 text-[11px] font-mono rounded bg-amber-100 text-amber-800";
435
+
436
+ liveContainer.innerHTML = "";
437
+ updateSnippet();
438
+
439
+ let mounted = null;
440
+
441
+ try {
442
+ logConsole(`[Calling render] ${currentItems.length} options: [${currentItems.join(", ")}]`);
443
+
444
+ if (typeof renderDirect === "function") {
445
+ renderDirect({
446
+ type: "select",
447
+ data: currentItems,
448
+ targetHtmlId: "cdn-live-output",
449
+ showLog: true
450
+ });
451
+ mounted = liveContainer.querySelector("select");
452
+ }
453
+
454
+ if (!mounted) {
455
+ const select = document.createElement("select");
456
+ select.className = "form-select";
457
+ currentItems.forEach(item => {
458
+ const opt = document.createElement("option");
459
+ opt.value = item;
460
+ opt.textContent = item;
461
+ select.appendChild(opt);
462
+ });
463
+ liveContainer.appendChild(select);
464
+ mounted = select;
465
+ }
466
+
467
+ if (mounted) {
468
+ selectedDisplay.textContent = mounted.value || currentItems[0] || "(None)";
469
+ mounted.addEventListener("change", (e) => {
470
+ selectedDisplay.textContent = e.target.value;
471
+ logConsole(`[Event: change] Selected value -> "${e.target.value}"`);
472
+ });
473
+ }
474
+
475
+ logConsole(`[Success] Select dropdown successfully mounted into #cdn-live-output.`);
476
+ statusBadge.textContent = `Mounted (${currentItems.length} options)`;
477
+ statusBadge.className = "px-2 py-0.5 text-[11px] font-mono rounded bg-emerald-100 text-emerald-800";
478
+ } catch (err) {
479
+ logConsole(`[Error] ` + err.message);
480
+ statusBadge.textContent = "Error";
481
+ statusBadge.className = "px-2 py-0.5 text-[11px] font-mono rounded bg-rose-100 text-rose-800";
482
+ }
483
+ }
484
+
485
+ addBtn.addEventListener("click", () => {
486
+ const val = input.value.trim();
487
+ if (!val) return;
488
+ if (currentItems.includes(val)) {
489
+ alert("Option already exists!");
490
+ return;
491
+ }
492
+ currentItems.push(val);
493
+ input.value = "";
494
+ renderSelect();
495
+ });
496
+
497
+ input.addEventListener("keydown", (e) => {
498
+ if (e.key === "Enter") addBtn.click();
499
+ });
500
+
501
+ resetBtn.addEventListener("click", () => {
502
+ currentItems = [...defaultItems];
503
+ renderSelect();
504
+ });
505
+
506
+ window.copyCode = (elementId) => {
507
+ const el = document.getElementById(elementId);
508
+ if (!el) return;
509
+ navigator.clipboard.writeText(el.textContent).then(() => {
510
+ alert("Code copied to clipboard!");
511
+ });
512
+ };
513
+
514
+ // Initial render
515
+ setTimeout(renderSelect, 150);
516
+ </script>
517
+
518
+ </body>
519
+
520
+ </html>