@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/README.md +69 -3
- package/declarations.d.ts +28 -1
- package/demo/index.html +1243 -0
- package/demo/main.js +368 -0
- package/demo/style.css +541 -0
- package/dist/js_aide.cjs.js +337 -314
- package/dist/js_aide.cjs.js.map +4 -4
- package/dist/js_aide.esm.js +337 -314
- package/dist/js_aide.esm.js.map +4 -4
- package/dist/js_aide.min.js +337 -314
- package/dist/js_aide.min.js.map +4 -4
- package/package.json +4 -2
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 = `» [${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();
|