@gerege-systems/eid-mongolia-sdk 0.15.2 → 0.15.3
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 +1 -1
- package/dist/button.cjs +70 -20
- package/dist/button.d.cts +2 -0
- package/dist/button.d.ts +2 -0
- package/dist/button.js +70 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Smart-ID-тэй RP-үүдийн хэв маяг: хөтөчид **нэг тов
|
|
|
35
35
|
|
|
36
36
|
| Хаана | Юу болно |
|
|
37
37
|
|---|---|
|
|
38
|
-
| Desktop хөтөч | Цонх: QR (секунд тутам шинэчлэгдэнэ) +
|
|
38
|
+
| Desktop хөтөч | Цонх: QR (секунд тутам шинэчлэгдэнэ) + баталгаажуулах код + «Хүсэлтийн хугацаа m:ss» (сүүлийн 30с анхааруулах өнгө) + «Регистрийн дугаараар нэвтрэх» товч (ижил цонхонд доош дэлгэгдэх push хэсэг), шууд төлөв |
|
|
39
39
|
| Утасны хөтөч | Товч → `start?mode=web2app` → сервер 302 → eID апп (Web2App). Апп баталгаажуулаад `/auth/eid/callback` руу буцаана |
|
|
40
40
|
| Backend | session эхлүүлэх, QR угсрах (`sessionSecret` серверт), poll, `validateAuth` (гинж + ACSP_V2 + `flowType` + Web2App-д `userChallengeVerifier`) → таны `onSuccess` |
|
|
41
41
|
|
package/dist/button.cjs
CHANGED
|
@@ -397,8 +397,9 @@ var T = {
|
|
|
397
397
|
loading: "\u0410\u0447\u0430\u0430\u043B\u0436 \u0431\u0430\u0439\u043D\u0430",
|
|
398
398
|
qrAlt: "\u041D\u044D\u0432\u0442\u0440\u044D\u0445 QR \u043A\u043E\u0434 \u2014 \u0443\u0442\u0441\u0430\u043D \u0434\u044D\u044D\u0440\u0445 eID Mongolia \u0430\u043F\u043F\u0430\u0430\u0440 \u0443\u043D\u0448\u0443\u0443\u043B\u043D\u0430",
|
|
399
399
|
steps: ["\u0423\u0442\u0441\u0430\u043D \u0434\u044D\u044D\u0440\u0445 eID Mongolia \u0430\u043F\u043F\u044B\u0433 \u043D\u044D\u044D\u043D\u044D", "QR \u043A\u043E\u0434\u044B\u0433 \u0443\u043D\u0448\u0443\u0443\u043B\u043D\u0430", "PIN1 \u043A\u043E\u0434\u043E\u043E \u043E\u0440\u0443\u0443\u043B\u043D\u0430"],
|
|
400
|
-
|
|
400
|
+
vcLabel: "\u0411\u0430\u0442\u0430\u043B\u0433\u0430\u0430\u0436\u0443\u0443\u043B\u0430\u0445 \u043A\u043E\u0434",
|
|
401
401
|
or: "\u044D\u0441\u0432\u044D\u043B",
|
|
402
|
+
usePush: "\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0439\u043D \u0434\u0443\u0433\u0430\u0430\u0440\u0430\u0430\u0440 \u043D\u044D\u0432\u0442\u0440\u044D\u0445",
|
|
402
403
|
idLabel: "\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0439\u043D \u0434\u0443\u0433\u0430\u0430\u0440",
|
|
403
404
|
idHint: "\u0423\u0442\u0441\u0430\u043D\u0434 \u0442\u0430\u043D\u044C \u043C\u044D\u0434\u044D\u0433\u0434\u044D\u043B \u043E\u0447\u043D\u043E. \u0418\u0440\u0433\u044D\u043D\u0438\u0439 12 \u043E\u0440\u043E\u043D\u0442\u043E\u0439 \u0434\u0443\u0433\u0430\u0430\u0440\u0430\u0430\u0440 \u0447 \u0431\u043E\u043B\u043D\u043E.",
|
|
404
405
|
idEmpty: "\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0439\u043D \u0434\u0443\u0433\u0430\u0430\u0440 \u043E\u0440\u0443\u0443\u043B\u043D\u0430 \u0443\u0443",
|
|
@@ -411,7 +412,7 @@ var T = {
|
|
|
411
412
|
waitText: "\u0423\u0442\u0441\u0430\u043D \u0434\u044D\u044D\u0440\u0445 \u043A\u043E\u0434 \u0438\u0436\u0438\u043B \u0431\u043E\u043B PIN1 \u043E\u0440\u0443\u0443\u043B\u043D\u0430 \u0443\u0443. \u0418\u0436\u0438\u043B \u0431\u0438\u0448 \u0431\u043E\u043B \u0442\u0430\u0442\u0433\u0430\u043B\u0437\u0430\u043D\u0430 \u0443\u0443.",
|
|
412
413
|
waiting: "\u0425\u04AF\u043B\u044D\u044D\u0436 \u0431\u0430\u0439\u043D\u0430",
|
|
413
414
|
back: "\u0411\u0443\u0446\u0430\u0445",
|
|
414
|
-
left: "\
|
|
415
|
+
left: "\u0425\u04AF\u0441\u044D\u043B\u0442\u0438\u0439\u043D \u0445\u0443\u0433\u0430\u0446\u0430\u0430:",
|
|
415
416
|
stale: "QR \u043A\u043E\u0434 \u0445\u0443\u0443\u0447\u0438\u0440\u0441\u0430\u043D",
|
|
416
417
|
refresh: "\u0428\u0438\u043D\u044D\u0447\u043B\u044D\u0445",
|
|
417
418
|
offline: "\u0425\u043E\u043B\u0431\u043E\u043B\u0442 \u0442\u0430\u0441\u0430\u0440\u0441\u0430\u043D. \u0418\u043D\u0442\u0435\u0440\u043D\u044D\u0442\u044D\u044D \u0448\u0430\u043B\u0433\u0430\u043D\u0430 \u0443\u0443 \u2014 \u0434\u0430\u0445\u0438\u043D \u0445\u043E\u043B\u0431\u043E\u0433\u0434\u043E\u0445\u044B\u0433 \u043E\u0440\u043E\u043B\u0434\u043E\u0436 \u0431\u0430\u0439\u043D\u0430.",
|
|
@@ -425,7 +426,7 @@ var T = {
|
|
|
425
426
|
retry: "\u0414\u0430\u0445\u0438\u043D \u043E\u0440\u043E\u043B\u0434\u043E\u0445",
|
|
426
427
|
success: "\u0410\u043C\u0436\u0438\u043B\u0442\u0442\u0430\u0439 \u043D\u044D\u0432\u0442\u044D\u0440\u043B\u044D\u044D",
|
|
427
428
|
sent: (vc) => `\u041C\u044D\u0434\u044D\u0433\u0434\u044D\u043B \u0438\u043B\u0433\u044D\u044D\u043B\u044D\u044D. \u0423\u0442\u0441\u0430\u043D \u0434\u044D\u044D\u0440\u0445 \u043A\u043E\u0434 ${vc.split("").join(" ")}`,
|
|
428
|
-
|
|
429
|
+
minutes: (n) => `${n} \u043C\u0438\u043D\u0443\u0442 \u04AF\u043B\u0434\u043B\u044D\u044D`
|
|
429
430
|
},
|
|
430
431
|
en: {
|
|
431
432
|
button: "Log in with eID",
|
|
@@ -434,8 +435,9 @@ var T = {
|
|
|
434
435
|
loading: "Loading",
|
|
435
436
|
qrAlt: "Login QR code \u2014 scan it with the eID Mongolia app on your phone",
|
|
436
437
|
steps: ["Open the eID Mongolia app on your phone", "Scan the QR code", "Enter your PIN1"],
|
|
437
|
-
|
|
438
|
+
vcLabel: "Verification code",
|
|
438
439
|
or: "or",
|
|
440
|
+
usePush: "Log in with registration number",
|
|
439
441
|
idLabel: "Registration number",
|
|
440
442
|
idHint: "A notification will be sent to your phone. The 12-digit civil ID also works.",
|
|
441
443
|
idEmpty: "Enter your registration number",
|
|
@@ -448,7 +450,7 @@ var T = {
|
|
|
448
450
|
waitText: "If the code on your phone matches, enter PIN1. Otherwise decline.",
|
|
449
451
|
waiting: "Waiting",
|
|
450
452
|
back: "Back",
|
|
451
|
-
left: "
|
|
453
|
+
left: "Request expires in:",
|
|
452
454
|
stale: "QR code expired",
|
|
453
455
|
refresh: "Refresh",
|
|
454
456
|
offline: "Connection lost. Check your internet \u2014 reconnecting.",
|
|
@@ -462,7 +464,7 @@ var T = {
|
|
|
462
464
|
retry: "Try again",
|
|
463
465
|
success: "Logged in",
|
|
464
466
|
sent: (vc) => `Notification sent. Code on your phone ${vc.split("").join(" ")}`,
|
|
465
|
-
minute: "
|
|
467
|
+
minutes: (n) => `${n} minute${n === 1 ? "" : "s"} left`
|
|
466
468
|
}
|
|
467
469
|
};
|
|
468
470
|
var EID_COLOR_TOKENS = [
|
|
@@ -528,7 +530,8 @@ h2, p, ol { margin: 0; }
|
|
|
528
530
|
.qr.stale svg { opacity: 0.12; }
|
|
529
531
|
.qr-stale { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
|
|
530
532
|
color: hsl(222 47% 11%); font-weight: 500; }
|
|
531
|
-
.qr-vc { margin-top:
|
|
533
|
+
.qr-vc { margin-top: 12px; text-align: center; }
|
|
534
|
+
.vc-label { font-size: 0.8125rem; color: var(--_eid-fg-subtle); }
|
|
532
535
|
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; letter-spacing: 0.08em; color: var(--_eid-fg-muted); }
|
|
533
536
|
.steps { margin-top: 16px; padding: 0; list-style: none; counter-reset: st; display: grid; gap: 8px; }
|
|
534
537
|
.steps li { counter-increment: st; display: flex; align-items: center; gap: 12px; }
|
|
@@ -536,6 +539,13 @@ h2, p, ol { margin: 0; }
|
|
|
536
539
|
color: var(--_eid-accent-subtle-fg); display: flex; align-items: center; justify-content: center; font-size: 0.75rem; font-weight: 600; }
|
|
537
540
|
.or { display: flex; align-items: center; gap: 12px; margin: 24px 0; color: var(--_eid-fg-subtle); font-size: 0.8125rem; }
|
|
538
541
|
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--_eid-border); }
|
|
542
|
+
.disc-btn .chev { width: 16px; height: 16px; flex: none; transition: transform 200ms cubic-bezier(0,0,0.2,1); }
|
|
543
|
+
.disc-btn[aria-expanded="true"] .chev { transform: rotate(180deg); }
|
|
544
|
+
.disc { margin: 0 -4px; display: grid; grid-template-rows: 0fr; transition: grid-template-rows 200ms cubic-bezier(0,0,0.2,1); }
|
|
545
|
+
.disc.open { grid-template-rows: 1fr; }
|
|
546
|
+
.disc > div { min-height: 0; overflow: hidden; visibility: hidden; transition: visibility 0s linear 200ms; }
|
|
547
|
+
.disc.open > div { visibility: visible; transition-delay: 0s; }
|
|
548
|
+
.disc form { padding: 16px 4px 4px; }
|
|
539
549
|
.field { display: grid; gap: 8px; }
|
|
540
550
|
.field label { font-weight: 500; }
|
|
541
551
|
.field input { width: 100%; height: 44px; padding: 0 12px; border: 1px solid var(--_eid-border-strong); border-radius: var(--_eid-radius);
|
|
@@ -546,7 +556,8 @@ h2, p, ol { margin: 0; }
|
|
|
546
556
|
.err { font-size: 0.8125rem; color: var(--_eid-danger-fg); font-weight: 500; }
|
|
547
557
|
.push { margin-top: 16px; }
|
|
548
558
|
.center { text-align: center; }
|
|
549
|
-
.vc { font:
|
|
559
|
+
.vc { font: 700 2rem/2.5rem ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; letter-spacing: 0.16em;
|
|
560
|
+
padding-left: 0.16em; color: var(--_eid-fg); }
|
|
550
561
|
.vc:focus, h2:focus { outline: none; }
|
|
551
562
|
.text { margin-top: 12px; color: var(--_eid-fg-muted); }
|
|
552
563
|
.pending { margin-top: 16px; display: inline-flex; align-items: center; gap: 8px; color: var(--_eid-fg-muted); }
|
|
@@ -555,7 +566,8 @@ h2, p, ol { margin: 0; }
|
|
|
555
566
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
556
567
|
.netwarn { margin-top: 16px; padding: 8px 12px; border: 1px solid var(--_eid-warning-border); border-radius: var(--_eid-radius); background: var(--_eid-warning-bg);
|
|
557
568
|
color: var(--_eid-warning-fg); font-size: 0.8125rem; }
|
|
558
|
-
.meta { margin-top:
|
|
569
|
+
.meta { margin-top: 4px; text-align: center; font-size: 0.8125rem; color: var(--_eid-fg-subtle); }
|
|
570
|
+
.meta.low, .meta.low .mono { color: var(--_eid-warning-fg); }
|
|
559
571
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; }
|
|
560
572
|
.spinner { animation: none; border-right-color: currentColor; opacity: 0.6; } }
|
|
561
573
|
`;
|
|
@@ -578,6 +590,24 @@ function el(tag, attrs = {}, text) {
|
|
|
578
590
|
if (text != null) e.textContent = text;
|
|
579
591
|
return e;
|
|
580
592
|
}
|
|
593
|
+
function chevron() {
|
|
594
|
+
const NS = "http://www.w3.org/2000/svg";
|
|
595
|
+
const svg = document.createElementNS(NS, "svg");
|
|
596
|
+
for (const [k, v] of Object.entries({
|
|
597
|
+
class: "chev",
|
|
598
|
+
viewBox: "0 0 24 24",
|
|
599
|
+
fill: "none",
|
|
600
|
+
stroke: "currentColor",
|
|
601
|
+
"stroke-width": "2",
|
|
602
|
+
"stroke-linecap": "round",
|
|
603
|
+
"stroke-linejoin": "round",
|
|
604
|
+
"aria-hidden": "true"
|
|
605
|
+
})) svg.setAttribute(k, v);
|
|
606
|
+
const path = document.createElementNS(NS, "path");
|
|
607
|
+
path.setAttribute("d", "m6 9 6 6 6-6");
|
|
608
|
+
svg.append(path);
|
|
609
|
+
return svg;
|
|
610
|
+
}
|
|
581
611
|
var Base = typeof HTMLElement === "undefined" ? class {
|
|
582
612
|
} : HTMLElement;
|
|
583
613
|
var EidLoginButton = class extends Base {
|
|
@@ -710,7 +740,7 @@ var EidLoginButton = class extends Base {
|
|
|
710
740
|
return;
|
|
711
741
|
}
|
|
712
742
|
if (e.key !== "Tab" || !this.backdrop) return;
|
|
713
|
-
const items = Array.from(this.backdrop.querySelectorAll(FOCUSABLE)).filter((n) => !n.closest("[hidden]"));
|
|
743
|
+
const items = Array.from(this.backdrop.querySelectorAll(FOCUSABLE)).filter((n) => !n.closest("[hidden], [inert]"));
|
|
714
744
|
if (items.length === 0) return;
|
|
715
745
|
const first = items[0];
|
|
716
746
|
const last = items[items.length - 1];
|
|
@@ -792,21 +822,22 @@ var EidLoginButton = class extends Base {
|
|
|
792
822
|
if (s.qr) this.drawQr(s.qr);
|
|
793
823
|
const nodes = [this.qrBox];
|
|
794
824
|
if (s.vc) {
|
|
795
|
-
const vc = el("
|
|
796
|
-
vc.append(el("
|
|
825
|
+
const vc = el("div", { class: "qr-vc" });
|
|
826
|
+
vc.append(el("p", { class: "vc-label", id: "eid-vc-label" }, t.vcLabel), el("p", { class: "vc" }, s.vc));
|
|
797
827
|
nodes.push(vc);
|
|
798
828
|
}
|
|
829
|
+
nodes.push(this.meta());
|
|
799
830
|
const steps = el("ol", { class: "steps" });
|
|
800
831
|
for (const st of t.steps) steps.append(el("li", {}, st));
|
|
801
|
-
nodes.push(steps, el("div", { class: "or", role: "separator", "aria-label": t.or }, t.or), this.
|
|
832
|
+
nodes.push(steps, el("div", { class: "or", role: "separator", "aria-label": t.or }, t.or), ...this.pushToggle());
|
|
802
833
|
this.netwarn = el("p", { class: "netwarn", role: "status", hidden: "" }, t.offline);
|
|
803
|
-
nodes.push(this.netwarn
|
|
834
|
+
nodes.push(this.netwarn);
|
|
804
835
|
this.view(...nodes);
|
|
805
836
|
}
|
|
806
837
|
leftEl = null;
|
|
807
838
|
meta() {
|
|
808
839
|
const p = el("p", { class: "meta" }, this.t.left + " ");
|
|
809
|
-
this.leftEl = el("span", { class: "mono", role: "timer", "aria-live": "off" }, "
|
|
840
|
+
this.leftEl = el("span", { class: "mono", role: "timer", "aria-live": "off" }, "-:--");
|
|
810
841
|
p.append(this.leftEl);
|
|
811
842
|
if (this.left < 0) p.hidden = true;
|
|
812
843
|
return p;
|
|
@@ -819,8 +850,9 @@ var EidLoginButton = class extends Base {
|
|
|
819
850
|
this.leftEl.parentElement.hidden = false;
|
|
820
851
|
const m = Math.floor(this.left / 60);
|
|
821
852
|
const s = this.left % 60;
|
|
822
|
-
this.leftEl.textContent = `${m
|
|
823
|
-
|
|
853
|
+
this.leftEl.textContent = `${m}:${s < 10 ? "0" : ""}${s}`;
|
|
854
|
+
this.leftEl.parentElement.classList.toggle("low", this.left <= 30);
|
|
855
|
+
if (this.left > 0 && s === 0 && this.left !== seconds) this.say(this.t.minutes(m));
|
|
824
856
|
};
|
|
825
857
|
render();
|
|
826
858
|
if (seconds < 0) return;
|
|
@@ -830,6 +862,24 @@ var EidLoginButton = class extends Base {
|
|
|
830
862
|
if (this.left <= 0) this.end("expired");
|
|
831
863
|
}, 1e3);
|
|
832
864
|
}
|
|
865
|
+
/** «Регистрийн дугаараар нэвтрэх» товч + ижил цонхонд доошоо дэлгэгдэх push хэсэг (QR, код харагдсаар; QR poll үргэлжилнэ). */
|
|
866
|
+
pushToggle() {
|
|
867
|
+
const toggle = el("button", { type: "button", class: "btn btn-outline disc-btn", "aria-expanded": "false", "aria-controls": "eid-push" });
|
|
868
|
+
toggle.append(el("span", {}, this.t.usePush), chevron());
|
|
869
|
+
const disc = el("div", { class: "disc", id: "eid-push" });
|
|
870
|
+
const inner = el("div", { inert: "" });
|
|
871
|
+
const form = this.pushForm();
|
|
872
|
+
inner.append(form);
|
|
873
|
+
disc.append(inner);
|
|
874
|
+
toggle.addEventListener("click", () => {
|
|
875
|
+
const open = toggle.getAttribute("aria-expanded") !== "true";
|
|
876
|
+
toggle.setAttribute("aria-expanded", String(open));
|
|
877
|
+
disc.classList.toggle("open", open);
|
|
878
|
+
inner.toggleAttribute("inert", !open);
|
|
879
|
+
if (open) form.querySelector("input")?.focus();
|
|
880
|
+
});
|
|
881
|
+
return [toggle, disc];
|
|
882
|
+
}
|
|
833
883
|
pushForm() {
|
|
834
884
|
const t = this.t;
|
|
835
885
|
const form = el("form", { novalidate: "" });
|
|
@@ -898,14 +948,14 @@ var EidLoginButton = class extends Base {
|
|
|
898
948
|
showWait(s) {
|
|
899
949
|
const t = this.t;
|
|
900
950
|
const c = el("div", { class: "center" });
|
|
901
|
-
c.append(el("h2", { class: "sr-only" }, t.waiting));
|
|
902
|
-
const vc = el("p", { class: "vc", tabindex: "-1", "aria-describedby": "eid-wait" }, s.vc ?? "");
|
|
951
|
+
c.append(el("h2", { class: "sr-only" }, t.waiting), el("p", { class: "vc-label", id: "eid-vc-label" }, t.vcLabel));
|
|
952
|
+
const vc = el("p", { class: "vc", tabindex: "-1", "aria-labelledby": "eid-vc-label", "aria-describedby": "eid-wait" }, s.vc ?? "");
|
|
903
953
|
const pending = el("p", { class: "pending" });
|
|
904
954
|
pending.append(el("span", { class: "spinner", "aria-hidden": "true" }), el("span", {}, t.waiting));
|
|
905
955
|
const back = el("button", { type: "button", class: "btn btn-outline" }, t.back);
|
|
906
956
|
back.addEventListener("click", () => this.open());
|
|
907
957
|
this.netwarn = el("p", { class: "netwarn", role: "status", hidden: "" }, t.offline);
|
|
908
|
-
c.append(vc, el("p", { class: "text", id: "eid-wait" }, t.waitText), pending, back, this.netwarn
|
|
958
|
+
c.append(vc, this.meta(), el("p", { class: "text", id: "eid-wait" }, t.waitText), pending, back, this.netwarn);
|
|
909
959
|
this.view(c);
|
|
910
960
|
this.startTimer(s.expiresIn ?? -1);
|
|
911
961
|
vc.focus();
|
package/dist/button.d.cts
CHANGED
|
@@ -78,6 +78,8 @@ declare class EidLoginButton extends Base {
|
|
|
78
78
|
private leftEl;
|
|
79
79
|
private meta;
|
|
80
80
|
private startTimer;
|
|
81
|
+
/** «Регистрийн дугаараар нэвтрэх» товч + ижил цонхонд доошоо дэлгэгдэх push хэсэг (QR, код харагдсаар; QR poll үргэлжилнэ). */
|
|
82
|
+
private pushToggle;
|
|
81
83
|
private pushForm;
|
|
82
84
|
private showWait;
|
|
83
85
|
private schedule;
|
package/dist/button.d.ts
CHANGED
|
@@ -78,6 +78,8 @@ declare class EidLoginButton extends Base {
|
|
|
78
78
|
private leftEl;
|
|
79
79
|
private meta;
|
|
80
80
|
private startTimer;
|
|
81
|
+
/** «Регистрийн дугаараар нэвтрэх» товч + ижил цонхонд доошоо дэлгэгдэх push хэсэг (QR, код харагдсаар; QR poll үргэлжилнэ). */
|
|
82
|
+
private pushToggle;
|
|
81
83
|
private pushForm;
|
|
82
84
|
private showWait;
|
|
83
85
|
private schedule;
|
package/dist/button.js
CHANGED
|
@@ -368,8 +368,9 @@ var T = {
|
|
|
368
368
|
loading: "\u0410\u0447\u0430\u0430\u043B\u0436 \u0431\u0430\u0439\u043D\u0430",
|
|
369
369
|
qrAlt: "\u041D\u044D\u0432\u0442\u0440\u044D\u0445 QR \u043A\u043E\u0434 \u2014 \u0443\u0442\u0441\u0430\u043D \u0434\u044D\u044D\u0440\u0445 eID Mongolia \u0430\u043F\u043F\u0430\u0430\u0440 \u0443\u043D\u0448\u0443\u0443\u043B\u043D\u0430",
|
|
370
370
|
steps: ["\u0423\u0442\u0441\u0430\u043D \u0434\u044D\u044D\u0440\u0445 eID Mongolia \u0430\u043F\u043F\u044B\u0433 \u043D\u044D\u044D\u043D\u044D", "QR \u043A\u043E\u0434\u044B\u0433 \u0443\u043D\u0448\u0443\u0443\u043B\u043D\u0430", "PIN1 \u043A\u043E\u0434\u043E\u043E \u043E\u0440\u0443\u0443\u043B\u043D\u0430"],
|
|
371
|
-
|
|
371
|
+
vcLabel: "\u0411\u0430\u0442\u0430\u043B\u0433\u0430\u0430\u0436\u0443\u0443\u043B\u0430\u0445 \u043A\u043E\u0434",
|
|
372
372
|
or: "\u044D\u0441\u0432\u044D\u043B",
|
|
373
|
+
usePush: "\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0439\u043D \u0434\u0443\u0433\u0430\u0430\u0440\u0430\u0430\u0440 \u043D\u044D\u0432\u0442\u0440\u044D\u0445",
|
|
373
374
|
idLabel: "\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0439\u043D \u0434\u0443\u0433\u0430\u0430\u0440",
|
|
374
375
|
idHint: "\u0423\u0442\u0441\u0430\u043D\u0434 \u0442\u0430\u043D\u044C \u043C\u044D\u0434\u044D\u0433\u0434\u044D\u043B \u043E\u0447\u043D\u043E. \u0418\u0440\u0433\u044D\u043D\u0438\u0439 12 \u043E\u0440\u043E\u043D\u0442\u043E\u0439 \u0434\u0443\u0433\u0430\u0430\u0440\u0430\u0430\u0440 \u0447 \u0431\u043E\u043B\u043D\u043E.",
|
|
375
376
|
idEmpty: "\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0439\u043D \u0434\u0443\u0433\u0430\u0430\u0440 \u043E\u0440\u0443\u0443\u043B\u043D\u0430 \u0443\u0443",
|
|
@@ -382,7 +383,7 @@ var T = {
|
|
|
382
383
|
waitText: "\u0423\u0442\u0441\u0430\u043D \u0434\u044D\u044D\u0440\u0445 \u043A\u043E\u0434 \u0438\u0436\u0438\u043B \u0431\u043E\u043B PIN1 \u043E\u0440\u0443\u0443\u043B\u043D\u0430 \u0443\u0443. \u0418\u0436\u0438\u043B \u0431\u0438\u0448 \u0431\u043E\u043B \u0442\u0430\u0442\u0433\u0430\u043B\u0437\u0430\u043D\u0430 \u0443\u0443.",
|
|
383
384
|
waiting: "\u0425\u04AF\u043B\u044D\u044D\u0436 \u0431\u0430\u0439\u043D\u0430",
|
|
384
385
|
back: "\u0411\u0443\u0446\u0430\u0445",
|
|
385
|
-
left: "\
|
|
386
|
+
left: "\u0425\u04AF\u0441\u044D\u043B\u0442\u0438\u0439\u043D \u0445\u0443\u0433\u0430\u0446\u0430\u0430:",
|
|
386
387
|
stale: "QR \u043A\u043E\u0434 \u0445\u0443\u0443\u0447\u0438\u0440\u0441\u0430\u043D",
|
|
387
388
|
refresh: "\u0428\u0438\u043D\u044D\u0447\u043B\u044D\u0445",
|
|
388
389
|
offline: "\u0425\u043E\u043B\u0431\u043E\u043B\u0442 \u0442\u0430\u0441\u0430\u0440\u0441\u0430\u043D. \u0418\u043D\u0442\u0435\u0440\u043D\u044D\u0442\u044D\u044D \u0448\u0430\u043B\u0433\u0430\u043D\u0430 \u0443\u0443 \u2014 \u0434\u0430\u0445\u0438\u043D \u0445\u043E\u043B\u0431\u043E\u0433\u0434\u043E\u0445\u044B\u0433 \u043E\u0440\u043E\u043B\u0434\u043E\u0436 \u0431\u0430\u0439\u043D\u0430.",
|
|
@@ -396,7 +397,7 @@ var T = {
|
|
|
396
397
|
retry: "\u0414\u0430\u0445\u0438\u043D \u043E\u0440\u043E\u043B\u0434\u043E\u0445",
|
|
397
398
|
success: "\u0410\u043C\u0436\u0438\u043B\u0442\u0442\u0430\u0439 \u043D\u044D\u0432\u0442\u044D\u0440\u043B\u044D\u044D",
|
|
398
399
|
sent: (vc) => `\u041C\u044D\u0434\u044D\u0433\u0434\u044D\u043B \u0438\u043B\u0433\u044D\u044D\u043B\u044D\u044D. \u0423\u0442\u0441\u0430\u043D \u0434\u044D\u044D\u0440\u0445 \u043A\u043E\u0434 ${vc.split("").join(" ")}`,
|
|
399
|
-
|
|
400
|
+
minutes: (n) => `${n} \u043C\u0438\u043D\u0443\u0442 \u04AF\u043B\u0434\u043B\u044D\u044D`
|
|
400
401
|
},
|
|
401
402
|
en: {
|
|
402
403
|
button: "Log in with eID",
|
|
@@ -405,8 +406,9 @@ var T = {
|
|
|
405
406
|
loading: "Loading",
|
|
406
407
|
qrAlt: "Login QR code \u2014 scan it with the eID Mongolia app on your phone",
|
|
407
408
|
steps: ["Open the eID Mongolia app on your phone", "Scan the QR code", "Enter your PIN1"],
|
|
408
|
-
|
|
409
|
+
vcLabel: "Verification code",
|
|
409
410
|
or: "or",
|
|
411
|
+
usePush: "Log in with registration number",
|
|
410
412
|
idLabel: "Registration number",
|
|
411
413
|
idHint: "A notification will be sent to your phone. The 12-digit civil ID also works.",
|
|
412
414
|
idEmpty: "Enter your registration number",
|
|
@@ -419,7 +421,7 @@ var T = {
|
|
|
419
421
|
waitText: "If the code on your phone matches, enter PIN1. Otherwise decline.",
|
|
420
422
|
waiting: "Waiting",
|
|
421
423
|
back: "Back",
|
|
422
|
-
left: "
|
|
424
|
+
left: "Request expires in:",
|
|
423
425
|
stale: "QR code expired",
|
|
424
426
|
refresh: "Refresh",
|
|
425
427
|
offline: "Connection lost. Check your internet \u2014 reconnecting.",
|
|
@@ -433,7 +435,7 @@ var T = {
|
|
|
433
435
|
retry: "Try again",
|
|
434
436
|
success: "Logged in",
|
|
435
437
|
sent: (vc) => `Notification sent. Code on your phone ${vc.split("").join(" ")}`,
|
|
436
|
-
minute: "
|
|
438
|
+
minutes: (n) => `${n} minute${n === 1 ? "" : "s"} left`
|
|
437
439
|
}
|
|
438
440
|
};
|
|
439
441
|
var EID_COLOR_TOKENS = [
|
|
@@ -499,7 +501,8 @@ h2, p, ol { margin: 0; }
|
|
|
499
501
|
.qr.stale svg { opacity: 0.12; }
|
|
500
502
|
.qr-stale { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
|
|
501
503
|
color: hsl(222 47% 11%); font-weight: 500; }
|
|
502
|
-
.qr-vc { margin-top:
|
|
504
|
+
.qr-vc { margin-top: 12px; text-align: center; }
|
|
505
|
+
.vc-label { font-size: 0.8125rem; color: var(--_eid-fg-subtle); }
|
|
503
506
|
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; letter-spacing: 0.08em; color: var(--_eid-fg-muted); }
|
|
504
507
|
.steps { margin-top: 16px; padding: 0; list-style: none; counter-reset: st; display: grid; gap: 8px; }
|
|
505
508
|
.steps li { counter-increment: st; display: flex; align-items: center; gap: 12px; }
|
|
@@ -507,6 +510,13 @@ h2, p, ol { margin: 0; }
|
|
|
507
510
|
color: var(--_eid-accent-subtle-fg); display: flex; align-items: center; justify-content: center; font-size: 0.75rem; font-weight: 600; }
|
|
508
511
|
.or { display: flex; align-items: center; gap: 12px; margin: 24px 0; color: var(--_eid-fg-subtle); font-size: 0.8125rem; }
|
|
509
512
|
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--_eid-border); }
|
|
513
|
+
.disc-btn .chev { width: 16px; height: 16px; flex: none; transition: transform 200ms cubic-bezier(0,0,0.2,1); }
|
|
514
|
+
.disc-btn[aria-expanded="true"] .chev { transform: rotate(180deg); }
|
|
515
|
+
.disc { margin: 0 -4px; display: grid; grid-template-rows: 0fr; transition: grid-template-rows 200ms cubic-bezier(0,0,0.2,1); }
|
|
516
|
+
.disc.open { grid-template-rows: 1fr; }
|
|
517
|
+
.disc > div { min-height: 0; overflow: hidden; visibility: hidden; transition: visibility 0s linear 200ms; }
|
|
518
|
+
.disc.open > div { visibility: visible; transition-delay: 0s; }
|
|
519
|
+
.disc form { padding: 16px 4px 4px; }
|
|
510
520
|
.field { display: grid; gap: 8px; }
|
|
511
521
|
.field label { font-weight: 500; }
|
|
512
522
|
.field input { width: 100%; height: 44px; padding: 0 12px; border: 1px solid var(--_eid-border-strong); border-radius: var(--_eid-radius);
|
|
@@ -517,7 +527,8 @@ h2, p, ol { margin: 0; }
|
|
|
517
527
|
.err { font-size: 0.8125rem; color: var(--_eid-danger-fg); font-weight: 500; }
|
|
518
528
|
.push { margin-top: 16px; }
|
|
519
529
|
.center { text-align: center; }
|
|
520
|
-
.vc { font:
|
|
530
|
+
.vc { font: 700 2rem/2.5rem ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; letter-spacing: 0.16em;
|
|
531
|
+
padding-left: 0.16em; color: var(--_eid-fg); }
|
|
521
532
|
.vc:focus, h2:focus { outline: none; }
|
|
522
533
|
.text { margin-top: 12px; color: var(--_eid-fg-muted); }
|
|
523
534
|
.pending { margin-top: 16px; display: inline-flex; align-items: center; gap: 8px; color: var(--_eid-fg-muted); }
|
|
@@ -526,7 +537,8 @@ h2, p, ol { margin: 0; }
|
|
|
526
537
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
527
538
|
.netwarn { margin-top: 16px; padding: 8px 12px; border: 1px solid var(--_eid-warning-border); border-radius: var(--_eid-radius); background: var(--_eid-warning-bg);
|
|
528
539
|
color: var(--_eid-warning-fg); font-size: 0.8125rem; }
|
|
529
|
-
.meta { margin-top:
|
|
540
|
+
.meta { margin-top: 4px; text-align: center; font-size: 0.8125rem; color: var(--_eid-fg-subtle); }
|
|
541
|
+
.meta.low, .meta.low .mono { color: var(--_eid-warning-fg); }
|
|
530
542
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; }
|
|
531
543
|
.spinner { animation: none; border-right-color: currentColor; opacity: 0.6; } }
|
|
532
544
|
`;
|
|
@@ -549,6 +561,24 @@ function el(tag, attrs = {}, text) {
|
|
|
549
561
|
if (text != null) e.textContent = text;
|
|
550
562
|
return e;
|
|
551
563
|
}
|
|
564
|
+
function chevron() {
|
|
565
|
+
const NS = "http://www.w3.org/2000/svg";
|
|
566
|
+
const svg = document.createElementNS(NS, "svg");
|
|
567
|
+
for (const [k, v] of Object.entries({
|
|
568
|
+
class: "chev",
|
|
569
|
+
viewBox: "0 0 24 24",
|
|
570
|
+
fill: "none",
|
|
571
|
+
stroke: "currentColor",
|
|
572
|
+
"stroke-width": "2",
|
|
573
|
+
"stroke-linecap": "round",
|
|
574
|
+
"stroke-linejoin": "round",
|
|
575
|
+
"aria-hidden": "true"
|
|
576
|
+
})) svg.setAttribute(k, v);
|
|
577
|
+
const path = document.createElementNS(NS, "path");
|
|
578
|
+
path.setAttribute("d", "m6 9 6 6 6-6");
|
|
579
|
+
svg.append(path);
|
|
580
|
+
return svg;
|
|
581
|
+
}
|
|
552
582
|
var Base = typeof HTMLElement === "undefined" ? class {
|
|
553
583
|
} : HTMLElement;
|
|
554
584
|
var EidLoginButton = class extends Base {
|
|
@@ -681,7 +711,7 @@ var EidLoginButton = class extends Base {
|
|
|
681
711
|
return;
|
|
682
712
|
}
|
|
683
713
|
if (e.key !== "Tab" || !this.backdrop) return;
|
|
684
|
-
const items = Array.from(this.backdrop.querySelectorAll(FOCUSABLE)).filter((n) => !n.closest("[hidden]"));
|
|
714
|
+
const items = Array.from(this.backdrop.querySelectorAll(FOCUSABLE)).filter((n) => !n.closest("[hidden], [inert]"));
|
|
685
715
|
if (items.length === 0) return;
|
|
686
716
|
const first = items[0];
|
|
687
717
|
const last = items[items.length - 1];
|
|
@@ -763,21 +793,22 @@ var EidLoginButton = class extends Base {
|
|
|
763
793
|
if (s.qr) this.drawQr(s.qr);
|
|
764
794
|
const nodes = [this.qrBox];
|
|
765
795
|
if (s.vc) {
|
|
766
|
-
const vc = el("
|
|
767
|
-
vc.append(el("
|
|
796
|
+
const vc = el("div", { class: "qr-vc" });
|
|
797
|
+
vc.append(el("p", { class: "vc-label", id: "eid-vc-label" }, t.vcLabel), el("p", { class: "vc" }, s.vc));
|
|
768
798
|
nodes.push(vc);
|
|
769
799
|
}
|
|
800
|
+
nodes.push(this.meta());
|
|
770
801
|
const steps = el("ol", { class: "steps" });
|
|
771
802
|
for (const st of t.steps) steps.append(el("li", {}, st));
|
|
772
|
-
nodes.push(steps, el("div", { class: "or", role: "separator", "aria-label": t.or }, t.or), this.
|
|
803
|
+
nodes.push(steps, el("div", { class: "or", role: "separator", "aria-label": t.or }, t.or), ...this.pushToggle());
|
|
773
804
|
this.netwarn = el("p", { class: "netwarn", role: "status", hidden: "" }, t.offline);
|
|
774
|
-
nodes.push(this.netwarn
|
|
805
|
+
nodes.push(this.netwarn);
|
|
775
806
|
this.view(...nodes);
|
|
776
807
|
}
|
|
777
808
|
leftEl = null;
|
|
778
809
|
meta() {
|
|
779
810
|
const p = el("p", { class: "meta" }, this.t.left + " ");
|
|
780
|
-
this.leftEl = el("span", { class: "mono", role: "timer", "aria-live": "off" }, "
|
|
811
|
+
this.leftEl = el("span", { class: "mono", role: "timer", "aria-live": "off" }, "-:--");
|
|
781
812
|
p.append(this.leftEl);
|
|
782
813
|
if (this.left < 0) p.hidden = true;
|
|
783
814
|
return p;
|
|
@@ -790,8 +821,9 @@ var EidLoginButton = class extends Base {
|
|
|
790
821
|
this.leftEl.parentElement.hidden = false;
|
|
791
822
|
const m = Math.floor(this.left / 60);
|
|
792
823
|
const s = this.left % 60;
|
|
793
|
-
this.leftEl.textContent = `${m
|
|
794
|
-
|
|
824
|
+
this.leftEl.textContent = `${m}:${s < 10 ? "0" : ""}${s}`;
|
|
825
|
+
this.leftEl.parentElement.classList.toggle("low", this.left <= 30);
|
|
826
|
+
if (this.left > 0 && s === 0 && this.left !== seconds) this.say(this.t.minutes(m));
|
|
795
827
|
};
|
|
796
828
|
render();
|
|
797
829
|
if (seconds < 0) return;
|
|
@@ -801,6 +833,24 @@ var EidLoginButton = class extends Base {
|
|
|
801
833
|
if (this.left <= 0) this.end("expired");
|
|
802
834
|
}, 1e3);
|
|
803
835
|
}
|
|
836
|
+
/** «Регистрийн дугаараар нэвтрэх» товч + ижил цонхонд доошоо дэлгэгдэх push хэсэг (QR, код харагдсаар; QR poll үргэлжилнэ). */
|
|
837
|
+
pushToggle() {
|
|
838
|
+
const toggle = el("button", { type: "button", class: "btn btn-outline disc-btn", "aria-expanded": "false", "aria-controls": "eid-push" });
|
|
839
|
+
toggle.append(el("span", {}, this.t.usePush), chevron());
|
|
840
|
+
const disc = el("div", { class: "disc", id: "eid-push" });
|
|
841
|
+
const inner = el("div", { inert: "" });
|
|
842
|
+
const form = this.pushForm();
|
|
843
|
+
inner.append(form);
|
|
844
|
+
disc.append(inner);
|
|
845
|
+
toggle.addEventListener("click", () => {
|
|
846
|
+
const open = toggle.getAttribute("aria-expanded") !== "true";
|
|
847
|
+
toggle.setAttribute("aria-expanded", String(open));
|
|
848
|
+
disc.classList.toggle("open", open);
|
|
849
|
+
inner.toggleAttribute("inert", !open);
|
|
850
|
+
if (open) form.querySelector("input")?.focus();
|
|
851
|
+
});
|
|
852
|
+
return [toggle, disc];
|
|
853
|
+
}
|
|
804
854
|
pushForm() {
|
|
805
855
|
const t = this.t;
|
|
806
856
|
const form = el("form", { novalidate: "" });
|
|
@@ -869,14 +919,14 @@ var EidLoginButton = class extends Base {
|
|
|
869
919
|
showWait(s) {
|
|
870
920
|
const t = this.t;
|
|
871
921
|
const c = el("div", { class: "center" });
|
|
872
|
-
c.append(el("h2", { class: "sr-only" }, t.waiting));
|
|
873
|
-
const vc = el("p", { class: "vc", tabindex: "-1", "aria-describedby": "eid-wait" }, s.vc ?? "");
|
|
922
|
+
c.append(el("h2", { class: "sr-only" }, t.waiting), el("p", { class: "vc-label", id: "eid-vc-label" }, t.vcLabel));
|
|
923
|
+
const vc = el("p", { class: "vc", tabindex: "-1", "aria-labelledby": "eid-vc-label", "aria-describedby": "eid-wait" }, s.vc ?? "");
|
|
874
924
|
const pending = el("p", { class: "pending" });
|
|
875
925
|
pending.append(el("span", { class: "spinner", "aria-hidden": "true" }), el("span", {}, t.waiting));
|
|
876
926
|
const back = el("button", { type: "button", class: "btn btn-outline" }, t.back);
|
|
877
927
|
back.addEventListener("click", () => this.open());
|
|
878
928
|
this.netwarn = el("p", { class: "netwarn", role: "status", hidden: "" }, t.offline);
|
|
879
|
-
c.append(vc, el("p", { class: "text", id: "eid-wait" }, t.waitText), pending, back, this.netwarn
|
|
929
|
+
c.append(vc, this.meta(), el("p", { class: "text", id: "eid-wait" }, t.waitText), pending, back, this.netwarn);
|
|
880
930
|
this.view(c);
|
|
881
931
|
this.startTimer(s.expiresIn ?? -1);
|
|
882
932
|
vc.focus();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gerege-systems/eid-mongolia-sdk",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.3",
|
|
4
4
|
"description": "e-ID Mongolia Relying Party SDK — иргэнээр утсаар нь нэвтрэлт ба хууль ёсны цахим гарын үсэг (RP-API v3, Smart-ID нийцтэй).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|