lyraxis-notification 1.0.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/assets/sound.mp3 +0 -0
- package/index.html +34 -0
- package/package.json +11 -0
- package/script.js +1010 -0
- package/style.css +915 -0
- package/test.html +216 -0
package/script.js
ADDED
|
@@ -0,0 +1,1010 @@
|
|
|
1
|
+
const isBrowser = typeof window !== "undefined";
|
|
2
|
+
const soundUrl = "./assets/sound.mp3";
|
|
3
|
+
|
|
4
|
+
let isSoundAllowed = false;
|
|
5
|
+
let notificationAudio = null;
|
|
6
|
+
|
|
7
|
+
if (isBrowser) {
|
|
8
|
+
const cssUrl = "./style.css";
|
|
9
|
+
|
|
10
|
+
if (!document.querySelector(`link[href="${cssUrl}"]`)) {
|
|
11
|
+
const linkEl = document.createElement("link");
|
|
12
|
+
|
|
13
|
+
linkEl.rel = "stylesheet";
|
|
14
|
+
linkEl.type = "text/css";
|
|
15
|
+
linkEl.href = cssUrl;
|
|
16
|
+
|
|
17
|
+
document.head.appendChild(linkEl);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function setSoundNotification(status) {
|
|
22
|
+
if (typeof status === "string") {
|
|
23
|
+
const val = status.toLowerCase();
|
|
24
|
+
|
|
25
|
+
isSoundAllowed =
|
|
26
|
+
val === "allow" ||
|
|
27
|
+
val === "on" ||
|
|
28
|
+
val === "enable";
|
|
29
|
+
} else {
|
|
30
|
+
isSoundAllowed = Boolean(status);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function playNotificationSound() {
|
|
35
|
+
if (!isBrowser || !isSoundAllowed) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!notificationAudio) {
|
|
40
|
+
notificationAudio = new Audio(soundUrl);
|
|
41
|
+
notificationAudio.preload = "auto";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
notificationAudio.currentTime = 0;
|
|
45
|
+
notificationAudio.play().catch(() => {});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const listBahasa = {
|
|
49
|
+
id: {
|
|
50
|
+
title_info: "Pesan",
|
|
51
|
+
subtitle_info: "Dari ",
|
|
52
|
+
title_confirm: "Konfirmasi",
|
|
53
|
+
subtitle_confirm: "Konfirmasi",
|
|
54
|
+
default_confirm: "Apakah anda yakin ingin melanjutkan?",
|
|
55
|
+
cancel: "Batal",
|
|
56
|
+
continue: "Lanjutkan",
|
|
57
|
+
ok: "OK",
|
|
58
|
+
prompt_title: "Formulir",
|
|
59
|
+
prompt_subtitle: "Isi Formulir Berikut",
|
|
60
|
+
send: "Kirim",
|
|
61
|
+
bye: "Selamat tinggal",
|
|
62
|
+
error: "Terdapat error",
|
|
63
|
+
default_titleqr: "Scan di sini!",
|
|
64
|
+
any_info:
|
|
65
|
+
"Tombol ini menampilkan informasi tambahan mengenai pesan atau tindakan yang tersedia."
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
en: {
|
|
69
|
+
title_info: "Message",
|
|
70
|
+
subtitle_info: "From",
|
|
71
|
+
title_confirm: "Confirmation",
|
|
72
|
+
subtitle_confirm: "Confirmation",
|
|
73
|
+
default_confirm: "Are you sure you want to continue?",
|
|
74
|
+
cancel: "Cancel",
|
|
75
|
+
continue: "Continue",
|
|
76
|
+
ok: "OK",
|
|
77
|
+
prompt_title: "Form",
|
|
78
|
+
prompt_subtitle: "Fill Out This Form",
|
|
79
|
+
send: "Send",
|
|
80
|
+
bye: "Good bye",
|
|
81
|
+
error: "There is an error",
|
|
82
|
+
default_titleqr: "Scan here!",
|
|
83
|
+
any_info:
|
|
84
|
+
"This button displays additional information about the message or available action."
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
let lang = listBahasa.en;
|
|
89
|
+
|
|
90
|
+
function setBahasa(langs) {
|
|
91
|
+
if (listBahasa[langs]) {
|
|
92
|
+
lang = listBahasa[langs];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function showLog({ Mess, Status } = {}) {
|
|
97
|
+
if (!isBrowser) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
playNotificationSound();
|
|
102
|
+
|
|
103
|
+
const el = document.createElement("div");
|
|
104
|
+
|
|
105
|
+
el.className =
|
|
106
|
+
Status === "err" || Status === "error" || Status === "failed"
|
|
107
|
+
? "message-error"
|
|
108
|
+
: "message-log";
|
|
109
|
+
|
|
110
|
+
el.textContent = Mess || "";
|
|
111
|
+
|
|
112
|
+
document.body.appendChild(el);
|
|
113
|
+
|
|
114
|
+
el.offsetWidth;
|
|
115
|
+
el.classList.add("show");
|
|
116
|
+
|
|
117
|
+
setTimeout(() => {
|
|
118
|
+
el.classList.remove("show");
|
|
119
|
+
el.classList.add("hide");
|
|
120
|
+
|
|
121
|
+
setTimeout(() => {
|
|
122
|
+
el.remove();
|
|
123
|
+
}, 500);
|
|
124
|
+
}, 4000);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function createBaseModal(
|
|
128
|
+
headerSubtitle,
|
|
129
|
+
headerTitle,
|
|
130
|
+
messageText,
|
|
131
|
+
closeCallback,
|
|
132
|
+
headerMess,
|
|
133
|
+
type = "close"
|
|
134
|
+
) {
|
|
135
|
+
playNotificationSound();
|
|
136
|
+
|
|
137
|
+
const overlay = document.createElement("div");
|
|
138
|
+
overlay.className = "message-sistem-overlay";
|
|
139
|
+
|
|
140
|
+
const box = document.createElement("div");
|
|
141
|
+
box.className = "message-sistem-boxinfo";
|
|
142
|
+
|
|
143
|
+
const hr = document.createElement("div");
|
|
144
|
+
hr.className = "line";
|
|
145
|
+
|
|
146
|
+
const content = document.createElement("div");
|
|
147
|
+
content.className = "message-sistem-content";
|
|
148
|
+
|
|
149
|
+
const p = document.createElement("p");
|
|
150
|
+
p.className = "message-sistem-message";
|
|
151
|
+
p.innerHTML = (messageText || "").replace(/\n/g, "<br/>");
|
|
152
|
+
|
|
153
|
+
const btnContainer = document.createElement("div");
|
|
154
|
+
btnContainer.className = "container-button";
|
|
155
|
+
|
|
156
|
+
const header = document.createElement("div");
|
|
157
|
+
header.className = "message-sistem-header";
|
|
158
|
+
|
|
159
|
+
const headerText = document.createElement("div");
|
|
160
|
+
headerText.className = "message-sistem-header-text";
|
|
161
|
+
|
|
162
|
+
const subtitle = document.createElement("div");
|
|
163
|
+
subtitle.className = "message-sistem-subtitle";
|
|
164
|
+
subtitle.textContent = headerSubtitle || "";
|
|
165
|
+
|
|
166
|
+
const title = document.createElement("h1");
|
|
167
|
+
title.className = "message-sistem-title";
|
|
168
|
+
title.textContent = headerTitle || "";
|
|
169
|
+
|
|
170
|
+
headerText.append(subtitle, title);
|
|
171
|
+
|
|
172
|
+
let closed = false;
|
|
173
|
+
|
|
174
|
+
const close = () => {
|
|
175
|
+
if (closed) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
closed = true;
|
|
180
|
+
|
|
181
|
+
if (overlay.parentNode) {
|
|
182
|
+
overlay.remove();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (!document.querySelector(".message-sistem-overlay")) {
|
|
186
|
+
document.body.classList.remove("no-scroll");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (closeCallback) {
|
|
190
|
+
closeCallback();
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const about = () => {
|
|
195
|
+
lyn.toast({
|
|
196
|
+
Title: headerMess || headerTitle || lang.title_confirm,
|
|
197
|
+
Mess: lang.any_info,
|
|
198
|
+
Status: "default"
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const btn = document.createElement("button");
|
|
203
|
+
|
|
204
|
+
btn.className = "message-sistem-custom-button";
|
|
205
|
+
btn.type = "button";
|
|
206
|
+
|
|
207
|
+
if (type === "any") {
|
|
208
|
+
btn.innerHTML = `
|
|
209
|
+
<svg
|
|
210
|
+
viewBox="0 0 24 24"
|
|
211
|
+
class="icon-message-sistem-custom-button"
|
|
212
|
+
>
|
|
213
|
+
<path d="M12 0a12 12 0 1 0 0 24 12 12 0 0 0 0-24Zm0 22a10 10 0 1 1 0-20 10 10 0 0 1 0 20Z"/>
|
|
214
|
+
<path d="M12 10h-1a1 1 0 0 0 0 2h1v6a1 1 0 0 0 2 0v-6a2 2 0 0 0-2-2Z"/>
|
|
215
|
+
<circle cx="12" cy="6.5" r="1.5"/>
|
|
216
|
+
</svg>
|
|
217
|
+
`;
|
|
218
|
+
|
|
219
|
+
btn.onclick = about;
|
|
220
|
+
} else {
|
|
221
|
+
btn.innerHTML = `
|
|
222
|
+
<svg
|
|
223
|
+
viewBox="0 0 24 24"
|
|
224
|
+
class="icon-message-sistem-custom-button"
|
|
225
|
+
>
|
|
226
|
+
<path d="m19 6.41-1.41-1.41L12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
|
227
|
+
</svg>
|
|
228
|
+
`;
|
|
229
|
+
|
|
230
|
+
btn.onclick = close;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
header.append(headerText, btn);
|
|
234
|
+
|
|
235
|
+
document.body.classList.add("no-scroll");
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
overlay,
|
|
239
|
+
box,
|
|
240
|
+
hr,
|
|
241
|
+
content,
|
|
242
|
+
p,
|
|
243
|
+
btnContainer,
|
|
244
|
+
close,
|
|
245
|
+
header,
|
|
246
|
+
get closed() {
|
|
247
|
+
return closed;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function showMessageSistemInfo({
|
|
253
|
+
Subtitle = lang.subtitle_info + (isBrowser ? ` ${location.hostname}` : ""),
|
|
254
|
+
Title = lang.title_info,
|
|
255
|
+
Mess
|
|
256
|
+
} = {}) {
|
|
257
|
+
if (!isBrowser) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const modal = createBaseModal(
|
|
262
|
+
Subtitle,
|
|
263
|
+
Title,
|
|
264
|
+
Mess,
|
|
265
|
+
null,
|
|
266
|
+
Title,
|
|
267
|
+
"close"
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
modal.content.append(
|
|
271
|
+
modal.p,
|
|
272
|
+
modal.btnContainer
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
modal.box.append(
|
|
276
|
+
modal.header,
|
|
277
|
+
modal.hr,
|
|
278
|
+
modal.content
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
modal.overlay.appendChild(modal.box);
|
|
282
|
+
document.body.appendChild(modal.overlay);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function showMessageSistemConfirm({ Mess, Event } = {}) {
|
|
286
|
+
if (!isBrowser) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const text =
|
|
291
|
+
Mess === "default"
|
|
292
|
+
? lang.default_confirm
|
|
293
|
+
: Mess;
|
|
294
|
+
|
|
295
|
+
const modal = createBaseModal(
|
|
296
|
+
lang.subtitle_confirm,
|
|
297
|
+
lang.title_confirm,
|
|
298
|
+
text,
|
|
299
|
+
null,
|
|
300
|
+
lang.title_confirm,
|
|
301
|
+
"any"
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
const btnNo = document.createElement("button");
|
|
305
|
+
|
|
306
|
+
btnNo.type = "button";
|
|
307
|
+
btnNo.textContent = lang.cancel;
|
|
308
|
+
btnNo.onclick = modal.close;
|
|
309
|
+
|
|
310
|
+
const btnYes = document.createElement("button");
|
|
311
|
+
|
|
312
|
+
btnYes.type = "button";
|
|
313
|
+
btnYes.textContent = lang.continue;
|
|
314
|
+
|
|
315
|
+
btnYes.onclick = () => {
|
|
316
|
+
modal.close();
|
|
317
|
+
|
|
318
|
+
if (Event) {
|
|
319
|
+
if (typeof Event === "function") {
|
|
320
|
+
Event();
|
|
321
|
+
} else if (typeof Event === "string") {
|
|
322
|
+
showLog({
|
|
323
|
+
Mess: lang.bye
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
location.href = Event;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
modal.btnContainer.append(
|
|
332
|
+
btnNo,
|
|
333
|
+
btnYes
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
modal.content.append(
|
|
337
|
+
modal.p,
|
|
338
|
+
modal.btnContainer
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
modal.box.append(
|
|
342
|
+
modal.header,
|
|
343
|
+
modal.hr,
|
|
344
|
+
modal.content
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
modal.overlay.appendChild(modal.box);
|
|
348
|
+
document.body.appendChild(modal.overlay);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function showMessageSistemPrompt({
|
|
352
|
+
Mess,
|
|
353
|
+
Type = "text"
|
|
354
|
+
} = {}) {
|
|
355
|
+
return new Promise((resolve, reject) => {
|
|
356
|
+
if (!isBrowser) {
|
|
357
|
+
reject("Bukan di lingkungan browser");
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
let submitted = false;
|
|
362
|
+
|
|
363
|
+
const modal = createBaseModal(
|
|
364
|
+
lang.prompt_subtitle,
|
|
365
|
+
lang.prompt_title,
|
|
366
|
+
Mess,
|
|
367
|
+
() => {
|
|
368
|
+
if (!submitted) {
|
|
369
|
+
reject("Dibatalkan");
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
lang.prompt_title,
|
|
373
|
+
"any"
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
const input = document.createElement("input");
|
|
377
|
+
|
|
378
|
+
input.className = "message-sistem-input";
|
|
379
|
+
|
|
380
|
+
const validTypes = [
|
|
381
|
+
"text",
|
|
382
|
+
"number",
|
|
383
|
+
"email",
|
|
384
|
+
"url",
|
|
385
|
+
"date",
|
|
386
|
+
"time",
|
|
387
|
+
"tel",
|
|
388
|
+
"range",
|
|
389
|
+
"password"
|
|
390
|
+
];
|
|
391
|
+
|
|
392
|
+
const finalType =
|
|
393
|
+
Type === "num"
|
|
394
|
+
? "number"
|
|
395
|
+
: Type;
|
|
396
|
+
|
|
397
|
+
input.type =
|
|
398
|
+
validTypes.includes(finalType)
|
|
399
|
+
? finalType
|
|
400
|
+
: "text";
|
|
401
|
+
|
|
402
|
+
const btnNo = document.createElement("button");
|
|
403
|
+
|
|
404
|
+
btnNo.type = "button";
|
|
405
|
+
btnNo.textContent = lang.cancel;
|
|
406
|
+
btnNo.onclick = modal.close;
|
|
407
|
+
|
|
408
|
+
const btnYes = document.createElement("button");
|
|
409
|
+
|
|
410
|
+
btnYes.type = "button";
|
|
411
|
+
btnYes.textContent = lang.send;
|
|
412
|
+
|
|
413
|
+
btnYes.onclick = () => {
|
|
414
|
+
const val = input.value;
|
|
415
|
+
|
|
416
|
+
submitted = true;
|
|
417
|
+
|
|
418
|
+
modal.close();
|
|
419
|
+
|
|
420
|
+
resolve(val);
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
modal.btnContainer.append(
|
|
424
|
+
btnNo,
|
|
425
|
+
btnYes
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
modal.content.append(
|
|
429
|
+
modal.p,
|
|
430
|
+
input,
|
|
431
|
+
modal.btnContainer
|
|
432
|
+
);
|
|
433
|
+
|
|
434
|
+
modal.box.append(
|
|
435
|
+
modal.header,
|
|
436
|
+
modal.hr,
|
|
437
|
+
modal.content
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
modal.overlay.appendChild(modal.box);
|
|
441
|
+
document.body.appendChild(modal.overlay);
|
|
442
|
+
|
|
443
|
+
setTimeout(() => {
|
|
444
|
+
input.focus();
|
|
445
|
+
}, 50);
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function updateToastStack(container) {
|
|
450
|
+
const toasts = Array.from(container.children);
|
|
451
|
+
|
|
452
|
+
toasts.forEach((toast, index) => {
|
|
453
|
+
toast.dataset.index = index;
|
|
454
|
+
|
|
455
|
+
if (index === 0) {
|
|
456
|
+
if (
|
|
457
|
+
toast.dataset.permanent !== "true" &&
|
|
458
|
+
!toast.dataset.timerActive
|
|
459
|
+
) {
|
|
460
|
+
toast.dataset.timerActive = "true";
|
|
461
|
+
|
|
462
|
+
toast.timerId = setTimeout(() => {
|
|
463
|
+
if (typeof toast.removeToast === "function") {
|
|
464
|
+
toast.removeToast();
|
|
465
|
+
}
|
|
466
|
+
}, 5000);
|
|
467
|
+
}
|
|
468
|
+
} else {
|
|
469
|
+
if (toast.timerId) {
|
|
470
|
+
clearTimeout(toast.timerId);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
toast.timerId = null;
|
|
474
|
+
delete toast.dataset.timerActive;
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function showMessageSistemToast({
|
|
480
|
+
Title,
|
|
481
|
+
Mess,
|
|
482
|
+
Status = "default",
|
|
483
|
+
Permanent = false
|
|
484
|
+
} = {}) {
|
|
485
|
+
if (!isBrowser) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
playNotificationSound();
|
|
490
|
+
|
|
491
|
+
let container =
|
|
492
|
+
document.querySelector(
|
|
493
|
+
".lyraxis-toast-container"
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
if (!container) {
|
|
497
|
+
container = document.createElement("div");
|
|
498
|
+
|
|
499
|
+
container.className =
|
|
500
|
+
"lyraxis-toast-container";
|
|
501
|
+
|
|
502
|
+
document.body.appendChild(container);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const toast = document.createElement("div");
|
|
506
|
+
|
|
507
|
+
toast.className = "lyraxis-toast";
|
|
508
|
+
toast.dataset.permanent =
|
|
509
|
+
Permanent ? "true" : "false";
|
|
510
|
+
|
|
511
|
+
let iconSvg = "";
|
|
512
|
+
let statusClass =
|
|
513
|
+
"lyraxis-toast-default";
|
|
514
|
+
|
|
515
|
+
if (
|
|
516
|
+
Status === "success" ||
|
|
517
|
+
Status === "ok"
|
|
518
|
+
) {
|
|
519
|
+
statusClass =
|
|
520
|
+
"lyraxis-toast-success";
|
|
521
|
+
|
|
522
|
+
iconSvg = `
|
|
523
|
+
<svg viewBox="0 0 24 24">
|
|
524
|
+
<path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
|
|
525
|
+
</svg>
|
|
526
|
+
`;
|
|
527
|
+
} else if (
|
|
528
|
+
["err", "error", "failed"].includes(Status)
|
|
529
|
+
) {
|
|
530
|
+
statusClass =
|
|
531
|
+
"lyraxis-toast-error";
|
|
532
|
+
|
|
533
|
+
iconSvg = `
|
|
534
|
+
<svg viewBox="0 0 24 24">
|
|
535
|
+
<path d="m19 6.41-1.41-1.41L12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
|
536
|
+
</svg>
|
|
537
|
+
`;
|
|
538
|
+
} else {
|
|
539
|
+
iconSvg = `
|
|
540
|
+
<svg viewBox="0 0 24 24">
|
|
541
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2Zm1 15h-2v-6h2v6Zm0-8h-2V7h2v2Z"/>
|
|
542
|
+
</svg>
|
|
543
|
+
`;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
toast.classList.add(statusClass);
|
|
547
|
+
|
|
548
|
+
const iconBox = document.createElement("div");
|
|
549
|
+
|
|
550
|
+
iconBox.className =
|
|
551
|
+
"lyraxis-toast-icon";
|
|
552
|
+
|
|
553
|
+
iconBox.innerHTML = iconSvg;
|
|
554
|
+
|
|
555
|
+
const bodyBox = document.createElement("div");
|
|
556
|
+
|
|
557
|
+
bodyBox.className =
|
|
558
|
+
"lyraxis-toast-body";
|
|
559
|
+
|
|
560
|
+
const titleEl = document.createElement("div");
|
|
561
|
+
|
|
562
|
+
titleEl.className =
|
|
563
|
+
"lyraxis-toast-title";
|
|
564
|
+
|
|
565
|
+
titleEl.textContent =
|
|
566
|
+
Title ||
|
|
567
|
+
(
|
|
568
|
+
Status === "success"
|
|
569
|
+
? "Berhasil"
|
|
570
|
+
: Status === "error" ||
|
|
571
|
+
Status === "failed"
|
|
572
|
+
? "Gagal"
|
|
573
|
+
: "Informasi"
|
|
574
|
+
);
|
|
575
|
+
|
|
576
|
+
const msgEl = document.createElement("p");
|
|
577
|
+
|
|
578
|
+
msgEl.className =
|
|
579
|
+
"lyraxis-toast-message";
|
|
580
|
+
|
|
581
|
+
msgEl.innerHTML =
|
|
582
|
+
(Mess || "").replace(
|
|
583
|
+
/\n/g,
|
|
584
|
+
"<br/>"
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
bodyBox.append(
|
|
588
|
+
titleEl,
|
|
589
|
+
msgEl
|
|
590
|
+
);
|
|
591
|
+
|
|
592
|
+
const closeBtn = document.createElement("button");
|
|
593
|
+
|
|
594
|
+
closeBtn.type = "button";
|
|
595
|
+
closeBtn.className =
|
|
596
|
+
"lyraxis-toast-close";
|
|
597
|
+
|
|
598
|
+
closeBtn.innerHTML = `
|
|
599
|
+
<svg viewBox="0 0 24 24">
|
|
600
|
+
<path d="m19 6.41-1.41-1.41L12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
|
601
|
+
</svg>
|
|
602
|
+
`;
|
|
603
|
+
|
|
604
|
+
const removeToast = () => {
|
|
605
|
+
if (toast.timerId) {
|
|
606
|
+
clearTimeout(toast.timerId);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
toast.classList.add("hide");
|
|
610
|
+
|
|
611
|
+
setTimeout(() => {
|
|
612
|
+
toast.remove();
|
|
613
|
+
|
|
614
|
+
updateToastStack(container);
|
|
615
|
+
|
|
616
|
+
if (!container.children.length) {
|
|
617
|
+
container.remove();
|
|
618
|
+
}
|
|
619
|
+
}, 300);
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
toast.removeToast = removeToast;
|
|
623
|
+
closeBtn.onclick = removeToast;
|
|
624
|
+
|
|
625
|
+
toast.append(
|
|
626
|
+
iconBox,
|
|
627
|
+
bodyBox,
|
|
628
|
+
closeBtn
|
|
629
|
+
);
|
|
630
|
+
|
|
631
|
+
container.appendChild(toast);
|
|
632
|
+
|
|
633
|
+
updateToastStack(container);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const dynamicQueue = [];
|
|
637
|
+
let dynamicRunning = false;
|
|
638
|
+
|
|
639
|
+
const dynamicIcons = {
|
|
640
|
+
home: `
|
|
641
|
+
<svg viewBox="0 0 24 24">
|
|
642
|
+
<path d="M12 3 2 12h3v8h6v-6h2v6h6v-8h3L12 3Z"/>
|
|
643
|
+
</svg>
|
|
644
|
+
`,
|
|
645
|
+
|
|
646
|
+
notification: `
|
|
647
|
+
<svg viewBox="0 0 24 24">
|
|
648
|
+
<path d="M12 22a2.5 2.5 0 0 0 2.45-2h-4.9A2.5 2.5 0 0 0 12 22Zm8-5v-5a8 8 0 0 0-6-7.74V3a2 2 0 1 0-4 0v1.26A8 8 0 0 0 4 12v5l-2 2v1h20v-1l-2-2Z"/>
|
|
649
|
+
</svg>
|
|
650
|
+
`,
|
|
651
|
+
|
|
652
|
+
music: `
|
|
653
|
+
<svg viewBox="0 0 24 24">
|
|
654
|
+
<path d="M9 3v12.13A4 4 0 1 0 11 19V8h8V3H9Zm-2 16a2 2 0 1 1 2-2 2 2 0 0 1-2 2Zm4-13h6v1h-6V6Z"/>
|
|
655
|
+
</svg>
|
|
656
|
+
`,
|
|
657
|
+
|
|
658
|
+
info: `
|
|
659
|
+
<svg viewBox="0 0 24 24">
|
|
660
|
+
<path d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm1 15h-2v-6h2v6Zm0-8h-2V7h2v2Z"/>
|
|
661
|
+
</svg>
|
|
662
|
+
`,
|
|
663
|
+
|
|
664
|
+
download: `
|
|
665
|
+
<svg viewBox="0 0 24 24">
|
|
666
|
+
<path d="M11 3h2v10l3.5-3.5 1.4 1.4-5.9 5.9-5.9-5.9 1.4-1.4L11 13V3ZM4 19h16v2H4v-2Z"/>
|
|
667
|
+
</svg>
|
|
668
|
+
`,
|
|
669
|
+
|
|
670
|
+
upload: `
|
|
671
|
+
<svg viewBox="0 0 24 24">
|
|
672
|
+
<path d="M11 21h2V11l3.5 3.5 1.4-1.4-5.9-5.9-5.9 5.9 1.4 1.4L11 11v10ZM4 3h16v2H4V3Z"/>
|
|
673
|
+
</svg>
|
|
674
|
+
`,
|
|
675
|
+
|
|
676
|
+
settings: `
|
|
677
|
+
<svg viewBox="0 0 24 24">
|
|
678
|
+
<path d="m19.43 12.98 2.11-1.65-2-3.46-2.5 1a7.7 7.7 0 0 0-1.73-1L15 5h-4l-.31 2.87a7.7 7.7 0 0 0-1.73 1l-2.5-1-2 3.46 2.11 1.65a7.2 7.2 0 0 0 0 2.04l-2.11 1.65 2 3.46 2.5-1a7.7 7.7 0 0 0 1.73 1L11 22h4l.31-2.87a7.7 7.7 0 0 0 1.73-1l2.5 1 2-3.46-2.11-1.65a7.2 7.2 0 0 0 0-2.04ZM13 15a3 3 0 1 1 0-6 3 3 0 0 1 0 6Z"/>
|
|
679
|
+
</svg>
|
|
680
|
+
`,
|
|
681
|
+
|
|
682
|
+
success: `
|
|
683
|
+
<svg viewBox="0 0 24 24">
|
|
684
|
+
<path d="m9 16.17-3.88-3.88-1.41 1.42L9 19 21 7l-1.41-1.41z"/>
|
|
685
|
+
</svg>
|
|
686
|
+
`,
|
|
687
|
+
|
|
688
|
+
failed: `
|
|
689
|
+
<svg viewBox="0 0 24 24">
|
|
690
|
+
<path d="m19 6.41-1.41-1.41L12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
|
691
|
+
</svg>
|
|
692
|
+
`,
|
|
693
|
+
|
|
694
|
+
warning: `
|
|
695
|
+
<svg viewBox="0 0 24 24">
|
|
696
|
+
<path d="M1 21h22L12 2 1 21Zm12-3h-2v2h2v-2Zm0-2h-2v-5h2v5Z"/>
|
|
697
|
+
</svg>
|
|
698
|
+
`,
|
|
699
|
+
|
|
700
|
+
wait: `
|
|
701
|
+
<svg viewBox="0 0 24 24">
|
|
702
|
+
<path d="M6 2v2h2v4.59L5.17 12 8 15.41V20H6v2h12v-2h-2v-4.59L18.83 12 16 8.59V4h2V2H6Zm4 6V4h4v4l1.5 2H8.5L10 8Zm4 12h-4v-4l-1.5-2h7L14 16v4Z"/>
|
|
703
|
+
</svg>
|
|
704
|
+
`
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
function getDynamicIcon(label, status) {
|
|
708
|
+
const key = String(
|
|
709
|
+
label || ""
|
|
710
|
+
).toLowerCase();
|
|
711
|
+
|
|
712
|
+
const statusKey = String(
|
|
713
|
+
status || ""
|
|
714
|
+
).toLowerCase();
|
|
715
|
+
|
|
716
|
+
if (dynamicIcons[key]) {
|
|
717
|
+
return dynamicIcons[key];
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if (
|
|
721
|
+
["success", "ok"].includes(statusKey)
|
|
722
|
+
) {
|
|
723
|
+
return dynamicIcons.success;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
if (
|
|
727
|
+
["warning", "warn"].includes(statusKey)
|
|
728
|
+
) {
|
|
729
|
+
return dynamicIcons.warning;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
if (
|
|
733
|
+
[
|
|
734
|
+
"failed",
|
|
735
|
+
"fail",
|
|
736
|
+
"error",
|
|
737
|
+
"err"
|
|
738
|
+
].includes(statusKey)
|
|
739
|
+
) {
|
|
740
|
+
return dynamicIcons.failed;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
if (
|
|
744
|
+
["wait", "waiting"].includes(key)
|
|
745
|
+
) {
|
|
746
|
+
return dynamicIcons.wait;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
return dynamicIcons.info;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
function getDynamicWidth(mess, label) {
|
|
753
|
+
const text = String(mess || "");
|
|
754
|
+
const labelText = String(label || "");
|
|
755
|
+
|
|
756
|
+
const estimated =
|
|
757
|
+
90 +
|
|
758
|
+
Math.max(
|
|
759
|
+
text.length,
|
|
760
|
+
labelText.length
|
|
761
|
+
) * 5.7;
|
|
762
|
+
|
|
763
|
+
const maxWidth = Math.min(
|
|
764
|
+
420,
|
|
765
|
+
window.innerWidth - 30
|
|
766
|
+
);
|
|
767
|
+
|
|
768
|
+
return Math.min(
|
|
769
|
+
Math.max(170, estimated),
|
|
770
|
+
maxWidth
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function showDynamicIsland(options = {}) {
|
|
775
|
+
if (!isBrowser) {
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
dynamicQueue.push({
|
|
780
|
+
Status: options.Status || "default",
|
|
781
|
+
Mess: options.Mess || "",
|
|
782
|
+
Label: options.Label || "info",
|
|
783
|
+
|
|
784
|
+
Duration:
|
|
785
|
+
typeof options.Duration === "number"
|
|
786
|
+
? options.Duration
|
|
787
|
+
: 3000,
|
|
788
|
+
|
|
789
|
+
CustomIcon:
|
|
790
|
+
typeof options.CustomIcon === "string"
|
|
791
|
+
? options.CustomIcon
|
|
792
|
+
: null,
|
|
793
|
+
|
|
794
|
+
CustomAnimation:
|
|
795
|
+
typeof options.CustomAnimation === "string"
|
|
796
|
+
? options.CustomAnimation
|
|
797
|
+
: null
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
processDynamicQueue();
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
async function processDynamicQueue() {
|
|
804
|
+
if (
|
|
805
|
+
dynamicRunning ||
|
|
806
|
+
!dynamicQueue.length
|
|
807
|
+
) {
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
dynamicRunning = true;
|
|
812
|
+
|
|
813
|
+
const data = dynamicQueue.shift();
|
|
814
|
+
|
|
815
|
+
const container = document.createElement("div");
|
|
816
|
+
|
|
817
|
+
container.className =
|
|
818
|
+
"lyraxis-dynamic-container";
|
|
819
|
+
|
|
820
|
+
const island = document.createElement("div");
|
|
821
|
+
|
|
822
|
+
island.className =
|
|
823
|
+
`lyraxis-dynamic ${getDynamicStatus(data.Status)} ${String(data.Label).toLowerCase()}`;
|
|
824
|
+
|
|
825
|
+
if (data.CustomAnimation) {
|
|
826
|
+
island.style.setProperty(
|
|
827
|
+
"--dynamic-custom-animation",
|
|
828
|
+
data.CustomAnimation
|
|
829
|
+
);
|
|
830
|
+
|
|
831
|
+
island.classList.add(
|
|
832
|
+
"custom-animation"
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
const icon = document.createElement("div");
|
|
837
|
+
|
|
838
|
+
icon.className =
|
|
839
|
+
"lyraxis-dynamic-icon";
|
|
840
|
+
|
|
841
|
+
icon.innerHTML =
|
|
842
|
+
data.CustomIcon ||
|
|
843
|
+
getDynamicIcon(
|
|
844
|
+
data.Label,
|
|
845
|
+
data.Status
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
const content = document.createElement("div");
|
|
849
|
+
|
|
850
|
+
content.className =
|
|
851
|
+
"lyraxis-dynamic-content";
|
|
852
|
+
|
|
853
|
+
const message = document.createElement("div");
|
|
854
|
+
|
|
855
|
+
message.className =
|
|
856
|
+
"lyraxis-dynamic-message";
|
|
857
|
+
|
|
858
|
+
message.textContent = data.Mess;
|
|
859
|
+
|
|
860
|
+
const status = document.createElement("div");
|
|
861
|
+
|
|
862
|
+
status.className =
|
|
863
|
+
"lyraxis-dynamic-status";
|
|
864
|
+
|
|
865
|
+
status.textContent = data.Label;
|
|
866
|
+
|
|
867
|
+
content.append(
|
|
868
|
+
message,
|
|
869
|
+
status
|
|
870
|
+
);
|
|
871
|
+
|
|
872
|
+
island.append(
|
|
873
|
+
icon,
|
|
874
|
+
content
|
|
875
|
+
);
|
|
876
|
+
|
|
877
|
+
container.appendChild(island);
|
|
878
|
+
|
|
879
|
+
document.body.appendChild(container);
|
|
880
|
+
|
|
881
|
+
playNotificationSound();
|
|
882
|
+
|
|
883
|
+
const width = getDynamicWidth(
|
|
884
|
+
data.Mess,
|
|
885
|
+
data.Label
|
|
886
|
+
);
|
|
887
|
+
|
|
888
|
+
island.style.setProperty(
|
|
889
|
+
"--dynamic-width",
|
|
890
|
+
`${width}px`
|
|
891
|
+
);
|
|
892
|
+
|
|
893
|
+
await nextFrame();
|
|
894
|
+
|
|
895
|
+
island.classList.add(
|
|
896
|
+
"enter-ball"
|
|
897
|
+
);
|
|
898
|
+
|
|
899
|
+
await wait(1000);
|
|
900
|
+
|
|
901
|
+
island.classList.add("open");
|
|
902
|
+
|
|
903
|
+
await wait(
|
|
904
|
+
Math.max(0, data.Duration)
|
|
905
|
+
);
|
|
906
|
+
|
|
907
|
+
island.classList.remove("open");
|
|
908
|
+
island.classList.add("close");
|
|
909
|
+
|
|
910
|
+
await wait(1000);
|
|
911
|
+
|
|
912
|
+
island.classList.remove("close");
|
|
913
|
+
island.classList.add("leave");
|
|
914
|
+
|
|
915
|
+
await wait(1000);
|
|
916
|
+
|
|
917
|
+
container.remove();
|
|
918
|
+
|
|
919
|
+
dynamicRunning = false;
|
|
920
|
+
|
|
921
|
+
processDynamicQueue();
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
function getDynamicStatus(status) {
|
|
925
|
+
const value = String(
|
|
926
|
+
status || "default"
|
|
927
|
+
).toLowerCase();
|
|
928
|
+
|
|
929
|
+
if (
|
|
930
|
+
value === "success" ||
|
|
931
|
+
value === "ok"
|
|
932
|
+
) {
|
|
933
|
+
return "success";
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
if (
|
|
937
|
+
value === "warning" ||
|
|
938
|
+
value === "warn"
|
|
939
|
+
) {
|
|
940
|
+
return "warning";
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
if (
|
|
944
|
+
[
|
|
945
|
+
"failed",
|
|
946
|
+
"fail",
|
|
947
|
+
"error",
|
|
948
|
+
"err"
|
|
949
|
+
].includes(value)
|
|
950
|
+
) {
|
|
951
|
+
return "failed";
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
if (
|
|
955
|
+
value === "active" ||
|
|
956
|
+
value === "info"
|
|
957
|
+
) {
|
|
958
|
+
return "active";
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
if (
|
|
962
|
+
value === "wait" ||
|
|
963
|
+
value === "waiting"
|
|
964
|
+
) {
|
|
965
|
+
return "waiting";
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
return "default";
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
function wait(ms) {
|
|
972
|
+
return new Promise(resolve => {
|
|
973
|
+
setTimeout(resolve, ms);
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
function nextFrame() {
|
|
978
|
+
return new Promise(resolve => {
|
|
979
|
+
requestAnimationFrame(() => {
|
|
980
|
+
resolve();
|
|
981
|
+
});
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
const lyn = {
|
|
986
|
+
log: showLog,
|
|
987
|
+
info: showMessageSistemInfo,
|
|
988
|
+
confirm: showMessageSistemConfirm,
|
|
989
|
+
prompt: showMessageSistemPrompt,
|
|
990
|
+
toast: showMessageSistemToast,
|
|
991
|
+
dynamicIsland: showDynamicIsland,
|
|
992
|
+
setLang: setBahasa,
|
|
993
|
+
soundNotification: setSoundNotification
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
if (isBrowser) {
|
|
997
|
+
window.lyn = lyn;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
if (
|
|
1001
|
+
typeof exports === "object" &&
|
|
1002
|
+
typeof module !== "undefined"
|
|
1003
|
+
) {
|
|
1004
|
+
module.exports = lyn;
|
|
1005
|
+
} else if (
|
|
1006
|
+
typeof define === "function" &&
|
|
1007
|
+
define.amd
|
|
1008
|
+
) {
|
|
1009
|
+
define(() => lyn);
|
|
1010
|
+
}
|