@vicaniddouglas/js_aide 1.11.0 → 1.13.0

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.
package/demo/main.js ADDED
@@ -0,0 +1,368 @@
1
+ import {
2
+ sendRequest,
3
+ popup,
4
+ icons,
5
+ inputHandlers,
6
+ SmartInput,
7
+ getQueueStatus,
8
+ } from "../index.js";
9
+
10
+ /**
11
+ * JS AIDE DASHBOARD & DOCUMENTATION
12
+ * Modernized for v1.12.0 with a new Indigo/Teal theme.
13
+ */
14
+
15
+ // Global State for Demo
16
+ const retryStats = {
17
+ attempts: 0,
18
+ };
19
+
20
+ // =============================================================================
21
+ // I. SETUP SMART COMPONENTS
22
+ // =============================================================================
23
+ const initSmartInputs = () => {
24
+ SmartInput.injectStyles();
25
+
26
+ const si = new SmartInput();
27
+ const showcase = document.getElementById("smart-input-showcase");
28
+
29
+ if (showcase) {
30
+ si.createFormattedNumberInput({
31
+ id: "demo-salary",
32
+ labelText: "Annual Salary (Currency)",
33
+ container: showcase,
34
+ placeholder: "e.g., 50,000.00",
35
+ });
36
+
37
+ si.createLimitedTextInput({
38
+ id: "demo-username",
39
+ labelText: "Restricted Username",
40
+ container: showcase,
41
+ maxLength: 15,
42
+ placeholder: "Alphabets & Numbers Only",
43
+ allowedCharactersString:
44
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
45
+ });
46
+ }
47
+
48
+ ["cfg-retries", "cfg-delay", "cfg-latency"].forEach((id) => {
49
+ const el = document.getElementById(id);
50
+ if (el) {
51
+ inputHandlers.allowOnlyNumbers(el, { allowDecimals: false });
52
+ }
53
+ });
54
+ };
55
+
56
+ // =============================================================================
57
+ // II. DYNAMIC NAVIGATION & ACCORDIONS
58
+ // =============================================================================
59
+ const initNavigation = () => {
60
+ const navItems = document.querySelectorAll(".nav-item, .sub-nav-item");
61
+ const views = document.querySelectorAll(".content-view");
62
+ const viewTitle = document.getElementById("current-view-title");
63
+
64
+ navItems.forEach((item) => {
65
+ item.addEventListener("click", (e) => {
66
+ if (item.classList.contains("github-link")) return;
67
+ e.preventDefault();
68
+
69
+ const targetView = item.getAttribute("data-view");
70
+
71
+ navItems.forEach((n) => n.classList.remove("active"));
72
+ item.classList.add("active");
73
+
74
+ views.forEach((v) => v.classList.remove("active"));
75
+
76
+ const specificView = document.getElementById(`view-${targetView}`);
77
+ if (specificView) {
78
+ specificView.classList.add("active");
79
+ } else if (targetView.startsWith("docs-")) {
80
+ document.getElementById("view-docs-generic").classList.add("active");
81
+ } else {
82
+ document.getElementById("view-about").classList.add("active");
83
+ }
84
+
85
+ viewTitle.innerText = item.innerText.replace(/^\S+\s/, "");
86
+ window.scrollTo(0, 0);
87
+ });
88
+ });
89
+
90
+ const accordionItems = document.querySelectorAll(".accordion-item");
91
+ accordionItems.forEach((item) => {
92
+ const header = item.querySelector(".accordion-header");
93
+ header.addEventListener("click", () => {
94
+ const isActive = item.classList.contains("active");
95
+
96
+ accordionItems.forEach((other) => {
97
+ other.classList.remove("active");
98
+ const arrow = other.querySelector(".accordion-arrow");
99
+ if (arrow) arrow.innerText = "▸";
100
+ });
101
+
102
+ if (!isActive) {
103
+ item.classList.add("active");
104
+ const arrow = item.querySelector(".accordion-arrow");
105
+ if (arrow) arrow.innerText = "▾";
106
+ }
107
+ });
108
+ });
109
+
110
+ document.querySelectorAll(".nav-group-header").forEach((header) => {
111
+ header.addEventListener("click", () => {
112
+ const content = header.nextElementSibling;
113
+ const arrow = header.querySelector(".arrow");
114
+ if (content.style.display === "none") {
115
+ content.style.display = "block";
116
+ arrow.innerText = "▾";
117
+ } else {
118
+ content.style.display = "none";
119
+ arrow.innerText = "▸";
120
+ }
121
+ });
122
+ });
123
+ };
124
+
125
+ // =============================================================================
126
+ // III. ICON INJECTION
127
+ // =============================================================================
128
+ const initIcons = () => {
129
+ const iconMap = {
130
+ "icon-about": icons.homeIcon2(),
131
+ "icon-features": icons.skillsIcon(),
132
+ "icon-demo": icons.playIcon2(),
133
+ "info-icon-light": icons.dashboardIcon2(),
134
+ "info-icon-modular": icons.branchIcon(),
135
+ "info-icon-proactive": icons.notificationsIcon(),
136
+ "icon-config": icons.settingsIcon
137
+ ? icons.settingsIcon()
138
+ : icons.skillsIcon(),
139
+ "icon-smart": icons.checkMarkIcon1(),
140
+ "feat-icon-http": icons.refreshIcon2(),
141
+ "feat-icon-ws": icons.messagesIcon2(),
142
+ "feat-icon-val": icons.checkMarkIcon1(),
143
+ "feat-icon-obs": icons.viewIcon(),
144
+ "feat-icon-pop": icons.notificationsIcon(),
145
+ };
146
+
147
+ Object.entries(iconMap).forEach(([id, svg]) => {
148
+ const el = document.getElementById(id);
149
+ if (el) el.innerHTML = svg;
150
+ });
151
+ };
152
+
153
+ // =============================================================================
154
+ // IV. MOCK BACKEND
155
+ // =============================================================================
156
+ const getMockDelay = () =>
157
+ parseInt(document.getElementById("cfg-latency").value) || 1000;
158
+ const mocks = {
159
+ "/api/save": {
160
+ status: true,
161
+ log: "Profile saved securely",
162
+ data: { id: 101 },
163
+ },
164
+ "/api/settings": {
165
+ status: false,
166
+ log: "500 Internal Server Error",
167
+ data: null,
168
+ },
169
+ "/api/queue": {
170
+ status: true,
171
+ log: "Task Complete",
172
+ data: {},
173
+ },
174
+ };
175
+
176
+ // =============================================================================
177
+ // V. LOADING OVERLAY
178
+ // =============================================================================
179
+ const toggleLoading = async (show) => {
180
+ const bar = document.getElementById("top-loading-bar");
181
+ if (show) {
182
+ bar.className = "loading-bar active";
183
+ } else {
184
+ bar.className = "loading-bar complete";
185
+ setTimeout(() => {
186
+ bar.className = "loading-bar";
187
+ }, 500);
188
+ }
189
+ };
190
+
191
+ // =============================================================================
192
+ // VI. DEMO ACTIONS
193
+ // =============================================================================
194
+ const initDemoActions = () => {
195
+ const getConfig = () => ({
196
+ maxRetries: parseInt(document.getElementById("cfg-retries").value) || 0,
197
+ retryDelay: parseInt(document.getElementById("cfg-delay").value) || 1000,
198
+ silent: document.getElementById("cfg-silent").checked,
199
+ });
200
+
201
+ const updateQueueStatus = () => {
202
+ const status = getQueueStatus();
203
+ const display = document.getElementById("queue-display");
204
+ if (display) {
205
+ display.querySelector(".active-count").innerText =
206
+ `Active: ${status.active}`;
207
+ display.querySelector(".pending-count").innerText =
208
+ `Pending: ${status.pending}`;
209
+ }
210
+ };
211
+
212
+ // SUCCESS ACTION
213
+ document.getElementById("btn-success").addEventListener("click", async () => {
214
+ const log = document.getElementById("log-success");
215
+ log.innerText = "Processing...";
216
+ log.className = "status-pill status-active";
217
+
218
+ await sendRequest({
219
+ endpoint: "/api/save",
220
+ showLoading: toggleLoading,
221
+ ...getConfig(),
222
+ onSuccess: async () => {
223
+ log.innerText = "Success (Popup Blocked)";
224
+ await popup.success("Success! Requests validated.");
225
+ log.innerText = "Flow Complete";
226
+ },
227
+ });
228
+
229
+ log.className = "status-pill status-idle";
230
+ });
231
+
232
+ // ERROR ACTION (With Retry Showcase)
233
+ document.getElementById("btn-error").addEventListener("click", async () => {
234
+ const log = document.getElementById("log-error");
235
+ retryStats.attempts = 0; // Reset
236
+ log.innerText = "Attempting...";
237
+ log.className = "status-pill status-active";
238
+
239
+ await sendRequest({
240
+ endpoint: "/api/settings",
241
+ showLoading: toggleLoading,
242
+ ...getConfig(),
243
+ onError: () => {
244
+ log.innerText = "Failed after retries";
245
+ },
246
+ });
247
+
248
+ log.className = "status-pill status-idle";
249
+ });
250
+
251
+ // QUEUE ACTIONS
252
+ const addToQueue = (priority) => {
253
+ const logArea = document.getElementById("queue-log");
254
+ const item = document.createElement("div");
255
+ const id = Math.random().toString(36).substr(2, 5).toUpperCase();
256
+ item.className = `queue-item ${priority > 0 ? "high" : "low"}`;
257
+ item.innerHTML = `<span><strong>[ID-${id}]</strong> ${priority > 0 ? "High" : "Low"} Priority</span><span class="status">Waiting...</span>`;
258
+ logArea.prepend(item);
259
+
260
+ sendRequest({
261
+ endpoint: "/api/queue",
262
+ useQueue: true,
263
+ priority,
264
+ onSuccess: () => {
265
+ item.classList.add("complete");
266
+ item.querySelector(".status").innerText = "Success";
267
+ updateQueueStatus();
268
+ },
269
+ });
270
+ updateQueueStatus();
271
+ };
272
+
273
+ document
274
+ .getElementById("btn-queue-low")
275
+ .addEventListener("click", () => addToQueue(0));
276
+ document
277
+ .getElementById("btn-queue-high")
278
+ .addEventListener("click", () => addToQueue(10));
279
+ };
280
+
281
+ // =============================================================================
282
+ // VII. BOOTSTRAP INTERCEPTOR MOCK
283
+ // =============================================================================
284
+ XMLHttpRequest.prototype.open = (function (open) {
285
+ return function (_method, url) {
286
+ this._url = url;
287
+ return open.apply(this, arguments);
288
+ };
289
+ })(XMLHttpRequest.prototype.open);
290
+
291
+ XMLHttpRequest.prototype.send = (function (send) {
292
+ return function () {
293
+ const mockMatch = Object.keys(mocks).find((m) => this._url.includes(m));
294
+ if (mockMatch) {
295
+ // Retry Showcase Logic
296
+ if (this._url.includes("/api/settings")) {
297
+ retryStats.attempts++;
298
+ const log = document.getElementById("log-error");
299
+ if (log) {
300
+ log.innerHTML = `<span class="spinner"></span> Retry #${retryStats.attempts - 1}...`;
301
+ }
302
+ }
303
+
304
+ setTimeout(() => {
305
+ const mock = mocks[mockMatch];
306
+ Object.defineProperty(this, "status", {
307
+ writable: true,
308
+ value: mock.status ? 200 : 500,
309
+ });
310
+ Object.defineProperty(this, "responseText", {
311
+ writable: true,
312
+ value: JSON.stringify(mock),
313
+ });
314
+ Object.defineProperty(this, "readyState", { writable: true, value: 4 });
315
+ this.onload();
316
+ }, getMockDelay());
317
+ } else {
318
+ send.apply(this, arguments);
319
+ }
320
+ };
321
+ })(XMLHttpRequest.prototype.send);
322
+
323
+ // =============================================================================
324
+ // VI. POPUP PLAYGROUND
325
+ // =============================================================================
326
+ const initPopups = () => {
327
+ const logResult = (type, result) => {
328
+ const display = document.getElementById("popup-playground-result");
329
+ if (display) {
330
+ display.innerHTML = `&raquo; [${new Date().toLocaleTimeString()}] <span style="color:white">${type}:</span> ${JSON.stringify(result)}`;
331
+ }
332
+ };
333
+
334
+ const getPlaygroundConfig = () => {
335
+ const message =
336
+ document.getElementById("playground-message")?.value || "Default Message";
337
+ const type =
338
+ document.querySelector('input[name="playground-type"]:checked')?.value ||
339
+ "text";
340
+ return { message, type };
341
+ };
342
+
343
+ document
344
+ .getElementById("btn-run-prompt")
345
+ ?.addEventListener("click", async () => {
346
+ const { message, type } = getPlaygroundConfig();
347
+ const res = await popup.prompt(message, {
348
+ inputType: type,
349
+ placeholder: `Enter ${type} here...`,
350
+ });
351
+ logResult(`Prompt (${type})`, res);
352
+ });
353
+
354
+ document
355
+ .getElementById("btn-run-confirm")
356
+ ?.addEventListener("click", async () => {
357
+ const { message } = getPlaygroundConfig();
358
+ const res = await popup.confirm(message);
359
+ logResult("Confirm Result", res);
360
+ });
361
+ };
362
+
363
+ // RUN
364
+ initNavigation();
365
+ initIcons();
366
+ initSmartInputs();
367
+ initDemoActions();
368
+ initPopups();