@gerege-systems/eid-mongolia-sdk 0.13.0 → 0.14.1
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 +176 -99
- package/dist/{browser-C6JHm0lR.d.cts → browser-CuMH5IVG.d.cts} +40 -1
- package/dist/{browser-C6JHm0lR.d.ts → browser-CuMH5IVG.d.ts} +40 -1
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/button.cjs +1005 -0
- package/dist/button.d.cts +93 -0
- package/dist/button.d.ts +93 -0
- package/dist/button.js +975 -0
- package/dist/index.cjs +591 -305
- package/dist/index.d.cts +254 -146
- package/dist/index.d.ts +254 -146
- package/dist/index.js +586 -301
- package/package.json +12 -4
package/dist/button.js
ADDED
|
@@ -0,0 +1,975 @@
|
|
|
1
|
+
// src/devicelink.ts
|
|
2
|
+
function isMobileUserAgent(nav) {
|
|
3
|
+
const n = nav ?? globalThis.navigator;
|
|
4
|
+
if (!n) return false;
|
|
5
|
+
if (n.userAgentData?.mobile === true) return true;
|
|
6
|
+
const ua = n.userAgent ?? "";
|
|
7
|
+
if (/Android|iPhone|iPod|iPad/i.test(ua)) return true;
|
|
8
|
+
return /Macintosh/.test(ua) && (n.maxTouchPoints ?? 0) > 1;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/logo.ts
|
|
12
|
+
var EID_LOGO_DATA_URI = "data:image/png;base64,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";
|
|
13
|
+
|
|
14
|
+
// src/qr.ts
|
|
15
|
+
var ECC_PER_BLOCK_M = [
|
|
16
|
+
-1,
|
|
17
|
+
10,
|
|
18
|
+
16,
|
|
19
|
+
26,
|
|
20
|
+
18,
|
|
21
|
+
24,
|
|
22
|
+
16,
|
|
23
|
+
18,
|
|
24
|
+
22,
|
|
25
|
+
22,
|
|
26
|
+
26,
|
|
27
|
+
30,
|
|
28
|
+
22,
|
|
29
|
+
22,
|
|
30
|
+
24,
|
|
31
|
+
24,
|
|
32
|
+
28,
|
|
33
|
+
28,
|
|
34
|
+
26,
|
|
35
|
+
26,
|
|
36
|
+
26,
|
|
37
|
+
26,
|
|
38
|
+
28,
|
|
39
|
+
28,
|
|
40
|
+
28,
|
|
41
|
+
28,
|
|
42
|
+
28,
|
|
43
|
+
28,
|
|
44
|
+
28,
|
|
45
|
+
28,
|
|
46
|
+
28,
|
|
47
|
+
28,
|
|
48
|
+
28,
|
|
49
|
+
28,
|
|
50
|
+
28,
|
|
51
|
+
28,
|
|
52
|
+
28,
|
|
53
|
+
28,
|
|
54
|
+
28,
|
|
55
|
+
28,
|
|
56
|
+
28
|
|
57
|
+
];
|
|
58
|
+
var BLOCKS_M = [
|
|
59
|
+
-1,
|
|
60
|
+
1,
|
|
61
|
+
1,
|
|
62
|
+
1,
|
|
63
|
+
2,
|
|
64
|
+
2,
|
|
65
|
+
4,
|
|
66
|
+
4,
|
|
67
|
+
4,
|
|
68
|
+
5,
|
|
69
|
+
5,
|
|
70
|
+
5,
|
|
71
|
+
8,
|
|
72
|
+
9,
|
|
73
|
+
9,
|
|
74
|
+
10,
|
|
75
|
+
10,
|
|
76
|
+
11,
|
|
77
|
+
13,
|
|
78
|
+
14,
|
|
79
|
+
16,
|
|
80
|
+
17,
|
|
81
|
+
17,
|
|
82
|
+
18,
|
|
83
|
+
20,
|
|
84
|
+
21,
|
|
85
|
+
23,
|
|
86
|
+
25,
|
|
87
|
+
26,
|
|
88
|
+
28,
|
|
89
|
+
29,
|
|
90
|
+
31,
|
|
91
|
+
33,
|
|
92
|
+
35,
|
|
93
|
+
37,
|
|
94
|
+
38,
|
|
95
|
+
40,
|
|
96
|
+
43,
|
|
97
|
+
45,
|
|
98
|
+
47,
|
|
99
|
+
49
|
|
100
|
+
];
|
|
101
|
+
var FORMAT_BITS_M = 0;
|
|
102
|
+
function rawModules(ver) {
|
|
103
|
+
let r = (16 * ver + 128) * ver + 64;
|
|
104
|
+
if (ver >= 2) {
|
|
105
|
+
const n = Math.floor(ver / 7) + 2;
|
|
106
|
+
r -= (25 * n - 10) * n - 55;
|
|
107
|
+
if (ver >= 7) r -= 36;
|
|
108
|
+
}
|
|
109
|
+
return r;
|
|
110
|
+
}
|
|
111
|
+
function dataCodewords(ver) {
|
|
112
|
+
return Math.floor(rawModules(ver) / 8) - ECC_PER_BLOCK_M[ver] * BLOCKS_M[ver];
|
|
113
|
+
}
|
|
114
|
+
function gfMul(x, y) {
|
|
115
|
+
let z = 0;
|
|
116
|
+
for (let i = 7; i >= 0; i--) {
|
|
117
|
+
z = z << 1 ^ (z >>> 7) * 285;
|
|
118
|
+
z ^= (y >>> i & 1) * x;
|
|
119
|
+
}
|
|
120
|
+
return z;
|
|
121
|
+
}
|
|
122
|
+
function rsDivisor(degree) {
|
|
123
|
+
const r = new Array(degree).fill(0);
|
|
124
|
+
r[degree - 1] = 1;
|
|
125
|
+
let root = 1;
|
|
126
|
+
for (let i = 0; i < degree; i++) {
|
|
127
|
+
for (let j = 0; j < r.length; j++) {
|
|
128
|
+
r[j] = gfMul(r[j], root);
|
|
129
|
+
if (j + 1 < r.length) r[j] ^= r[j + 1];
|
|
130
|
+
}
|
|
131
|
+
root = gfMul(root, 2);
|
|
132
|
+
}
|
|
133
|
+
return r;
|
|
134
|
+
}
|
|
135
|
+
function rsRemainder(data, divisor) {
|
|
136
|
+
const r = divisor.map(() => 0);
|
|
137
|
+
for (const b of data) {
|
|
138
|
+
const f = b ^ r.shift();
|
|
139
|
+
r.push(0);
|
|
140
|
+
divisor.forEach((c, i) => r[i] ^= gfMul(c, f));
|
|
141
|
+
}
|
|
142
|
+
return r;
|
|
143
|
+
}
|
|
144
|
+
function encodeQr(text) {
|
|
145
|
+
const bytes = Array.from(new TextEncoder().encode(text));
|
|
146
|
+
let ver = 1;
|
|
147
|
+
for (; ; ver++) {
|
|
148
|
+
if (ver > 40) throw new Error("qr: \u04E9\u0433\u04E9\u0433\u0434\u04E9\u043B \u0445\u044D\u0442 \u0443\u0440\u0442");
|
|
149
|
+
const bits = 4 + (ver <= 9 ? 8 : 16) + bytes.length * 8;
|
|
150
|
+
if (bits <= dataCodewords(ver) * 8) break;
|
|
151
|
+
}
|
|
152
|
+
const bb = [];
|
|
153
|
+
const put = (v, n) => {
|
|
154
|
+
for (let i2 = n - 1; i2 >= 0; i2--) bb.push(v >>> i2 & 1);
|
|
155
|
+
};
|
|
156
|
+
put(4, 4);
|
|
157
|
+
put(bytes.length, ver <= 9 ? 8 : 16);
|
|
158
|
+
for (const b of bytes) put(b, 8);
|
|
159
|
+
const cap = dataCodewords(ver) * 8;
|
|
160
|
+
put(0, Math.min(4, cap - bb.length));
|
|
161
|
+
put(0, (8 - bb.length % 8) % 8);
|
|
162
|
+
for (let pad = 236; bb.length < cap; pad ^= 236 ^ 17) put(pad, 8);
|
|
163
|
+
const data = [];
|
|
164
|
+
for (let i2 = 0; i2 < bb.length; i2 += 8) data.push(parseInt(bb.slice(i2, i2 + 8).join(""), 2));
|
|
165
|
+
const nBlocks = BLOCKS_M[ver];
|
|
166
|
+
const eccLen = ECC_PER_BLOCK_M[ver];
|
|
167
|
+
const raw = Math.floor(rawModules(ver) / 8);
|
|
168
|
+
const nShort = nBlocks - raw % nBlocks;
|
|
169
|
+
const shortLen = Math.floor(raw / nBlocks);
|
|
170
|
+
const div = rsDivisor(eccLen);
|
|
171
|
+
const blocks = [];
|
|
172
|
+
for (let i2 = 0, k = 0; i2 < nBlocks; i2++) {
|
|
173
|
+
const dat = data.slice(k, k + shortLen - eccLen + (i2 < nShort ? 0 : 1));
|
|
174
|
+
k += dat.length;
|
|
175
|
+
const ecc = rsRemainder(dat, div);
|
|
176
|
+
if (i2 < nShort) dat.push(0);
|
|
177
|
+
blocks.push(dat.concat(ecc));
|
|
178
|
+
}
|
|
179
|
+
const codewords = [];
|
|
180
|
+
for (let i2 = 0; i2 < blocks[0].length; i2++) {
|
|
181
|
+
blocks.forEach((b, j) => {
|
|
182
|
+
if (i2 !== shortLen - eccLen || j >= nShort) codewords.push(b[i2]);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
const size = ver * 4 + 17;
|
|
186
|
+
const mod = Array.from({ length: size }, () => new Array(size).fill(false));
|
|
187
|
+
const fn = Array.from({ length: size }, () => new Array(size).fill(false));
|
|
188
|
+
const set = (x, y, dark) => {
|
|
189
|
+
mod[y][x] = dark;
|
|
190
|
+
fn[y][x] = true;
|
|
191
|
+
};
|
|
192
|
+
for (let i2 = 0; i2 < size; i2++) {
|
|
193
|
+
set(6, i2, i2 % 2 === 0);
|
|
194
|
+
set(i2, 6, i2 % 2 === 0);
|
|
195
|
+
}
|
|
196
|
+
for (const [cx, cy] of [[3, 3], [size - 4, 3], [3, size - 4]]) {
|
|
197
|
+
for (let dy = -4; dy <= 4; dy++) {
|
|
198
|
+
for (let dx = -4; dx <= 4; dx++) {
|
|
199
|
+
const d = Math.max(Math.abs(dx), Math.abs(dy));
|
|
200
|
+
const x = cx + dx;
|
|
201
|
+
const y = cy + dy;
|
|
202
|
+
if (x >= 0 && x < size && y >= 0 && y < size) set(x, y, d !== 2 && d !== 4);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const align = [];
|
|
207
|
+
if (ver > 1) {
|
|
208
|
+
const n = Math.floor(ver / 7) + 2;
|
|
209
|
+
const step = ver === 32 ? 26 : Math.ceil((ver * 4 + 4) / (n * 2 - 2)) * 2;
|
|
210
|
+
align.push(6);
|
|
211
|
+
for (let p = size - 7; align.length < n; p -= step) align.splice(1, 0, p);
|
|
212
|
+
}
|
|
213
|
+
const na = align.length;
|
|
214
|
+
for (let i2 = 0; i2 < na; i2++) {
|
|
215
|
+
for (let j = 0; j < na; j++) {
|
|
216
|
+
if (i2 === 0 && j === 0 || i2 === 0 && j === na - 1 || i2 === na - 1 && j === 0) continue;
|
|
217
|
+
for (let dy = -2; dy <= 2; dy++) {
|
|
218
|
+
for (let dx = -2; dx <= 2; dx++) set(align[i2] + dx, align[j] + dy, Math.max(Math.abs(dx), Math.abs(dy)) !== 1);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const bit = (v, i2) => (v >>> i2 & 1) !== 0;
|
|
223
|
+
const drawFormat = (mask) => {
|
|
224
|
+
const d = FORMAT_BITS_M << 3 | mask;
|
|
225
|
+
let rem = d;
|
|
226
|
+
for (let i2 = 0; i2 < 10; i2++) rem = rem << 1 ^ (rem >>> 9) * 1335;
|
|
227
|
+
const bits = (d << 10 | rem) ^ 21522;
|
|
228
|
+
for (let i2 = 0; i2 <= 5; i2++) set(8, i2, bit(bits, i2));
|
|
229
|
+
set(8, 7, bit(bits, 6));
|
|
230
|
+
set(8, 8, bit(bits, 7));
|
|
231
|
+
set(7, 8, bit(bits, 8));
|
|
232
|
+
for (let i2 = 9; i2 < 15; i2++) set(14 - i2, 8, bit(bits, i2));
|
|
233
|
+
for (let i2 = 0; i2 < 8; i2++) set(size - 1 - i2, 8, bit(bits, i2));
|
|
234
|
+
for (let i2 = 8; i2 < 15; i2++) set(8, size - 15 + i2, bit(bits, i2));
|
|
235
|
+
set(8, size - 8, true);
|
|
236
|
+
};
|
|
237
|
+
drawFormat(0);
|
|
238
|
+
if (ver >= 7) {
|
|
239
|
+
let rem = ver;
|
|
240
|
+
for (let i2 = 0; i2 < 12; i2++) rem = rem << 1 ^ (rem >>> 11) * 7973;
|
|
241
|
+
const bits = ver << 12 | rem;
|
|
242
|
+
for (let i2 = 0; i2 < 18; i2++) {
|
|
243
|
+
const a = size - 11 + i2 % 3;
|
|
244
|
+
const b = Math.floor(i2 / 3);
|
|
245
|
+
set(a, b, bit(bits, i2));
|
|
246
|
+
set(b, a, bit(bits, i2));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
let i = 0;
|
|
250
|
+
for (let right = size - 1; right >= 1; right -= 2) {
|
|
251
|
+
if (right === 6) right = 5;
|
|
252
|
+
for (let vert = 0; vert < size; vert++) {
|
|
253
|
+
for (let j = 0; j < 2; j++) {
|
|
254
|
+
const x = right - j;
|
|
255
|
+
const y = (right + 1 & 2) === 0 ? size - 1 - vert : vert;
|
|
256
|
+
if (!fn[y][x] && i < codewords.length * 8) {
|
|
257
|
+
mod[y][x] = bit(codewords[i >>> 3], 7 - (i & 7));
|
|
258
|
+
i++;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const applyMask = (m) => {
|
|
264
|
+
for (let y = 0; y < size; y++) {
|
|
265
|
+
for (let x = 0; x < size; x++) {
|
|
266
|
+
if (fn[y][x]) continue;
|
|
267
|
+
let inv;
|
|
268
|
+
switch (m) {
|
|
269
|
+
case 0:
|
|
270
|
+
inv = (x + y) % 2 === 0;
|
|
271
|
+
break;
|
|
272
|
+
case 1:
|
|
273
|
+
inv = y % 2 === 0;
|
|
274
|
+
break;
|
|
275
|
+
case 2:
|
|
276
|
+
inv = x % 3 === 0;
|
|
277
|
+
break;
|
|
278
|
+
case 3:
|
|
279
|
+
inv = (x + y) % 3 === 0;
|
|
280
|
+
break;
|
|
281
|
+
case 4:
|
|
282
|
+
inv = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0;
|
|
283
|
+
break;
|
|
284
|
+
case 5:
|
|
285
|
+
inv = x * y % 2 + x * y % 3 === 0;
|
|
286
|
+
break;
|
|
287
|
+
case 6:
|
|
288
|
+
inv = (x * y % 2 + x * y % 3) % 2 === 0;
|
|
289
|
+
break;
|
|
290
|
+
default:
|
|
291
|
+
inv = ((x + y) % 2 + x * y % 3) % 2 === 0;
|
|
292
|
+
}
|
|
293
|
+
if (inv) mod[y][x] = !mod[y][x];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
let best = 0;
|
|
298
|
+
let bestScore = Infinity;
|
|
299
|
+
for (let m = 0; m < 8; m++) {
|
|
300
|
+
applyMask(m);
|
|
301
|
+
drawFormat(m);
|
|
302
|
+
const s = penalty(mod, size);
|
|
303
|
+
if (s < bestScore) {
|
|
304
|
+
best = m;
|
|
305
|
+
bestScore = s;
|
|
306
|
+
}
|
|
307
|
+
applyMask(m);
|
|
308
|
+
}
|
|
309
|
+
applyMask(best);
|
|
310
|
+
drawFormat(best);
|
|
311
|
+
return { size, modules: mod };
|
|
312
|
+
}
|
|
313
|
+
function penalty(m, size) {
|
|
314
|
+
let s = 0;
|
|
315
|
+
const at = (x, y, horiz) => horiz ? m[y][x] : m[x][y];
|
|
316
|
+
for (const horiz of [true, false]) {
|
|
317
|
+
for (let a = 0; a < size; a++) {
|
|
318
|
+
let run = 1;
|
|
319
|
+
for (let b = 1; b <= size; b++) {
|
|
320
|
+
if (b < size && at(b, a, horiz) === at(b - 1, a, horiz)) {
|
|
321
|
+
run++;
|
|
322
|
+
} else {
|
|
323
|
+
if (run >= 5) s += run - 2;
|
|
324
|
+
run = 1;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
for (let b = 0; b + 7 <= size; b++) {
|
|
328
|
+
const p = [1, 0, 1, 1, 1, 0, 1].every((v, k) => at(b + k, a, horiz) === (v === 1));
|
|
329
|
+
if (!p) continue;
|
|
330
|
+
const light = (from) => {
|
|
331
|
+
for (let k = from; k < from + 4; k++) if (k >= 0 && k < size && at(k, a, horiz)) return false;
|
|
332
|
+
return true;
|
|
333
|
+
};
|
|
334
|
+
if (light(b - 4) || light(b + 7)) s += 40;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
let dark = 0;
|
|
339
|
+
for (let y = 0; y < size; y++) {
|
|
340
|
+
for (let x = 0; x < size; x++) {
|
|
341
|
+
if (m[y][x]) dark++;
|
|
342
|
+
if (x < size - 1 && y < size - 1) {
|
|
343
|
+
const c = m[y][x];
|
|
344
|
+
if (c === m[y][x + 1] && c === m[y + 1][x] && c === m[y + 1][x + 1]) s += 3;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const total = size * size;
|
|
349
|
+
s += (Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1) * 10;
|
|
350
|
+
return s;
|
|
351
|
+
}
|
|
352
|
+
function qrSvgPath(q, border = 4) {
|
|
353
|
+
let d = "";
|
|
354
|
+
for (let y = 0; y < q.size; y++) {
|
|
355
|
+
for (let x = 0; x < q.size; x++) {
|
|
356
|
+
if (q.modules[y][x]) d += `M${x + border},${y + border}h1v1h-1z`;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return d;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// src/button.ts
|
|
363
|
+
var T = {
|
|
364
|
+
mn: {
|
|
365
|
+
button: "eID-\u044D\u044D\u0440 \u043D\u044D\u0432\u0442\u0440\u044D\u0445",
|
|
366
|
+
title: "eID-\u044D\u044D\u0440 \u043D\u044D\u0432\u0442\u0440\u044D\u0445",
|
|
367
|
+
close: "\u0425\u0430\u0430\u0445",
|
|
368
|
+
loading: "\u0410\u0447\u0430\u0430\u043B\u0436 \u0431\u0430\u0439\u043D\u0430",
|
|
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
|
+
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
|
+
code: "\u0423\u0442\u0441\u0430\u043D \u0434\u044D\u044D\u0440\u0445 \u043A\u043E\u0434:",
|
|
372
|
+
or: "\u044D\u0441\u0432\u044D\u043B",
|
|
373
|
+
idLabel: "\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0439\u043D \u0434\u0443\u0433\u0430\u0430\u0440",
|
|
374
|
+
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
|
+
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",
|
|
376
|
+
idLatin: "\u04AE\u0441\u0433\u0438\u0439\u0433 \u043A\u0438\u0440\u0438\u043B\u043B\u044D\u044D\u0440 \u0431\u0438\u0447\u043D\u044D \u04AF\u04AF: \u0423\u041112345678",
|
|
377
|
+
idBad: "\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0439\u043D \u0434\u0443\u0433\u0430\u0430\u0440 2 \u04AF\u0441\u044D\u0433, 8 \u0446\u0438\u0444\u0440\u0442\u044D\u0439 \u0431\u0430\u0439\u043D\u0430: \u0423\u041112345678",
|
|
378
|
+
push: "\u041C\u044D\u0434\u044D\u0433\u0434\u044D\u043B \u0438\u043B\u0433\u044D\u044D\u0445",
|
|
379
|
+
pushing: "\u0418\u043B\u0433\u044D\u044D\u0436 \u0431\u0430\u0439\u043D\u0430",
|
|
380
|
+
rateLimited: "\u0425\u044D\u0442 \u043E\u043B\u043E\u043D \u043E\u0440\u043E\u043B\u0434\u043B\u043E\u0433\u043E. \u0422\u04AF\u0440 \u0445\u04AF\u043B\u044D\u044D\u0433\u044D\u044D\u0434 \u0434\u0430\u0445\u0438\u043D \u043E\u0440\u043E\u043B\u0434\u043E\u043D\u043E \u0443\u0443",
|
|
381
|
+
pushFailed: "\u041C\u044D\u0434\u044D\u0433\u0434\u044D\u043B \u0438\u043B\u0433\u044D\u044D\u0436 \u0447\u0430\u0434\u0441\u0430\u043D\u0433\u04AF\u0439. \u0414\u0430\u0445\u0438\u043D \u043E\u0440\u043E\u043B\u0434\u043E\u043D\u043E \u0443\u0443",
|
|
382
|
+
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
|
+
waiting: "\u0425\u04AF\u043B\u044D\u044D\u0436 \u0431\u0430\u0439\u043D\u0430",
|
|
384
|
+
back: "\u0411\u0443\u0446\u0430\u0445",
|
|
385
|
+
left: "\u04AE\u043B\u0434\u0441\u044D\u043D \u0445\u0443\u0433\u0430\u0446\u0430\u0430",
|
|
386
|
+
stale: "QR \u043A\u043E\u0434 \u0445\u0443\u0443\u0447\u0438\u0440\u0441\u0430\u043D",
|
|
387
|
+
refresh: "\u0428\u0438\u043D\u044D\u0447\u043B\u044D\u0445",
|
|
388
|
+
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.",
|
|
389
|
+
expiredTitle: "\u041D\u044D\u0432\u0442\u0440\u044D\u043B\u0442\u0438\u0439\u043D \u0445\u0443\u0433\u0430\u0446\u0430\u0430 \u0434\u0443\u0443\u0441\u0441\u0430\u043D",
|
|
390
|
+
refusedTitle: "\u041D\u044D\u0432\u0442\u0440\u044D\u043B\u0442\u044D\u044D\u0441 \u0442\u0430\u0442\u0433\u0430\u043B\u0437\u0441\u0430\u043D",
|
|
391
|
+
failedTitle: "\u041D\u044D\u0432\u0442\u044D\u0440\u0447 \u0447\u0430\u0434\u0441\u0430\u043D\u0433\u04AF\u0439",
|
|
392
|
+
failedText: "\u0411\u0430\u0442\u0430\u043B\u0433\u0430\u0430\u0436\u0443\u0443\u043B\u0430\u043B\u0442 \u0430\u043C\u0436\u0438\u043B\u0442\u0433\u04AF\u0439 \u0431\u043E\u043B\u043B\u043E\u043E. \u0414\u0430\u0445\u0438\u043D \u043E\u0440\u043E\u043B\u0434\u043E\u043D\u043E \u0443\u0443.",
|
|
393
|
+
unavailable: "eID \u04AF\u0439\u043B\u0447\u0438\u043B\u0433\u044D\u044D\u043D\u0434 \u0445\u043E\u043B\u0431\u043E\u0433\u0434\u043E\u0436 \u0447\u0430\u0434\u0441\u0430\u043D\u0433\u04AF\u0439. \u0422\u04AF\u0440 \u0445\u04AF\u043B\u044D\u044D\u0433\u044D\u044D\u0434 \u0434\u0430\u0445\u0438\u043D \u043E\u0440\u043E\u043B\u0434\u043E\u043D\u043E \u0443\u0443.",
|
|
394
|
+
callbackTitle: "\u0423\u0442\u0441\u0430\u043D \u0434\u044D\u044D\u0440\u0445 \u0445\u04E9\u0442\u0447\u04E9\u04E9\u0440 \u04AF\u0440\u0433\u044D\u043B\u0436\u0438\u043B\u043D\u044D",
|
|
395
|
+
callbackText: "\u0411\u0430\u0442\u0430\u043B\u0433\u0430\u0430\u0436\u0443\u0443\u043B\u0430\u043B\u0442 \u0430\u043C\u0436\u0438\u043B\u0442\u0442\u0430\u0439. \u0410\u043F\u043F\u0430\u0430\u0441 \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D \u0445\u04E9\u0442\u0447\u0438\u0439\u043D \u0446\u043E\u043D\u0445\u043E\u043D\u0434 \u043D\u044D\u0432\u0442\u0440\u044D\u043B\u0442 \u04AF\u0440\u0433\u044D\u043B\u0436\u0438\u043B\u043D\u044D.",
|
|
396
|
+
retry: "\u0414\u0430\u0445\u0438\u043D \u043E\u0440\u043E\u043B\u0434\u043E\u0445",
|
|
397
|
+
success: "\u0410\u043C\u0436\u0438\u043B\u0442\u0442\u0430\u0439 \u043D\u044D\u0432\u0442\u044D\u0440\u043B\u044D\u044D",
|
|
398
|
+
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
|
+
minute: "1 \u043C\u0438\u043D\u0443\u0442 \u04AF\u043B\u0434\u043B\u044D\u044D"
|
|
400
|
+
},
|
|
401
|
+
en: {
|
|
402
|
+
button: "Log in with eID",
|
|
403
|
+
title: "Log in with eID",
|
|
404
|
+
close: "Close",
|
|
405
|
+
loading: "Loading",
|
|
406
|
+
qrAlt: "Login QR code \u2014 scan it with the eID Mongolia app on your phone",
|
|
407
|
+
steps: ["Open the eID Mongolia app on your phone", "Scan the QR code", "Enter your PIN1"],
|
|
408
|
+
code: "Code on your phone:",
|
|
409
|
+
or: "or",
|
|
410
|
+
idLabel: "Registration number",
|
|
411
|
+
idHint: "A notification will be sent to your phone. The 12-digit civil ID also works.",
|
|
412
|
+
idEmpty: "Enter your registration number",
|
|
413
|
+
idLatin: "Use Cyrillic letters: \u0423\u041112345678",
|
|
414
|
+
idBad: "Registration number is 2 letters and 8 digits: \u0423\u041112345678",
|
|
415
|
+
push: "Send notification",
|
|
416
|
+
pushing: "Sending",
|
|
417
|
+
rateLimited: "Too many attempts. Please wait and try again",
|
|
418
|
+
pushFailed: "Could not send the notification. Please try again",
|
|
419
|
+
waitText: "If the code on your phone matches, enter PIN1. Otherwise decline.",
|
|
420
|
+
waiting: "Waiting",
|
|
421
|
+
back: "Back",
|
|
422
|
+
left: "Time left",
|
|
423
|
+
stale: "QR code expired",
|
|
424
|
+
refresh: "Refresh",
|
|
425
|
+
offline: "Connection lost. Check your internet \u2014 reconnecting.",
|
|
426
|
+
expiredTitle: "Login expired",
|
|
427
|
+
refusedTitle: "Login declined",
|
|
428
|
+
failedTitle: "Login failed",
|
|
429
|
+
failedText: "Verification failed. Please try again.",
|
|
430
|
+
unavailable: "Could not reach the eID service. Please try again shortly.",
|
|
431
|
+
callbackTitle: "Continue in your phone's browser",
|
|
432
|
+
callbackText: "Verified. Login continues in the browser window the app opened.",
|
|
433
|
+
retry: "Try again",
|
|
434
|
+
success: "Logged in",
|
|
435
|
+
sent: (vc) => `Notification sent. Code on your phone ${vc.split("").join(" ")}`,
|
|
436
|
+
minute: "1 minute left"
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
var CSS_BASE = `
|
|
440
|
+
:host { display: inline-block;
|
|
441
|
+
--eid-bg: hsl(0 0% 100%); --eid-bg-subtle: hsl(210 40% 98%); --eid-bg-muted: hsl(210 40% 96%);
|
|
442
|
+
--eid-fg: hsl(222 47% 11%); --eid-fg-muted: hsl(215 19% 35%); --eid-fg-subtle: hsl(215 16% 45%);
|
|
443
|
+
--eid-border: hsl(214 32% 91%); --eid-border-strong: hsl(213 27% 84%);
|
|
444
|
+
--eid-accent: oklch(0.534 0.2 259); --eid-accent-fg: #fff; --eid-accent-subtle: oklch(0.97 0.03 259);
|
|
445
|
+
--eid-accent-subtle-fg: oklch(0.474 0.19 259); --eid-ring: oklch(0.604 0.2 259);
|
|
446
|
+
--eid-warning-bg: hsl(48 100% 96%); --eid-warning-border: hsl(45 95% 78%); --eid-warning-fg: hsl(23 75% 33%);
|
|
447
|
+
--eid-danger-fg: hsl(0 74% 42%); --eid-radius: 6px; --eid-radius-lg: 8px; font-family: inherit; color-scheme: light; }
|
|
448
|
+
button, input { font-family: inherit; }
|
|
449
|
+
`;
|
|
450
|
+
var DARK_CSS = `:host { color-scheme: dark;
|
|
451
|
+
--eid-bg: hsl(229 50% 6%); --eid-bg-subtle: hsl(222 47% 9%); --eid-bg-muted: hsl(217 33% 13%);
|
|
452
|
+
--eid-fg: hsl(210 40% 98%); --eid-fg-muted: hsl(213 27% 84%); --eid-fg-subtle: hsl(215 20% 65%);
|
|
453
|
+
--eid-border: hsl(217 33% 17%); --eid-border-strong: hsl(215 25% 27%);
|
|
454
|
+
--eid-accent: oklch(0.64 0.15 259); --eid-accent-fg: hsl(229 50% 6%); --eid-accent-subtle: oklch(0.24 0.06 259);
|
|
455
|
+
--eid-accent-subtle-fg: oklch(0.82 0.1 259); --eid-ring: oklch(0.68 0.15 259);
|
|
456
|
+
--eid-warning-bg: hsl(20 60% 10%); --eid-warning-border: hsl(22 70% 26%); --eid-warning-fg: hsl(40 92% 65%);
|
|
457
|
+
--eid-danger-fg: hsl(0 91% 71%); }
|
|
458
|
+
`;
|
|
459
|
+
var CSS_REST = `
|
|
460
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
461
|
+
[hidden] { display: none !important; }
|
|
462
|
+
h2, p, ol { margin: 0; }
|
|
463
|
+
:focus-visible { outline: 2px solid var(--eid-ring); outline-offset: 2px; }
|
|
464
|
+
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
465
|
+
.btn { display: inline-flex; width: 100%; align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 0 20px;
|
|
466
|
+
border-radius: var(--eid-radius); font-family: inherit; font-weight: 500; font-size: 1rem; line-height: 1.25; text-decoration: none; border: 1px solid transparent; cursor: pointer;
|
|
467
|
+
transition: background-color 160ms cubic-bezier(0,0,0.2,1); }
|
|
468
|
+
.btn:disabled { opacity: 0.6; cursor: progress; }
|
|
469
|
+
.btn-primary { background: var(--eid-accent); color: var(--eid-accent-fg); }
|
|
470
|
+
.btn-primary:hover { background: color-mix(in oklab, var(--eid-accent) 88%, black); }
|
|
471
|
+
.btn-outline { background: var(--eid-bg); color: var(--eid-fg); border-color: var(--eid-border-strong); }
|
|
472
|
+
.btn-outline:hover { background: var(--eid-bg-muted); }
|
|
473
|
+
.btn-sm { width: auto; min-height: 36px; padding: 0 14px; font-size: 0.8125rem; }
|
|
474
|
+
.trigger { width: auto; }
|
|
475
|
+
.trigger img { width: 20px; height: 20px; border-radius: 4px; }
|
|
476
|
+
.backdrop { position: fixed; inset: 0; z-index: 2147483000; background: hsl(222 47% 11% / 0.5); display: flex; align-items: center;
|
|
477
|
+
justify-content: center; padding: 16px; overflow-y: auto; }
|
|
478
|
+
.dialog { position: relative; width: 100%; max-width: 26rem; max-height: calc(100dvh - 32px); overflow-y: auto; background: var(--eid-bg);
|
|
479
|
+
color: var(--eid-fg); border: 1px solid var(--eid-border); border-radius: var(--eid-radius-lg); padding: 24px; font-size: 0.875rem; line-height: 1.5rem; }
|
|
480
|
+
@media (max-width: 639px) { .dialog { padding: 16px; } }
|
|
481
|
+
.head { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; }
|
|
482
|
+
.head img { width: 28px; height: 28px; border-radius: var(--eid-radius); }
|
|
483
|
+
.head h2 { flex: 1; font-size: 1.125rem; line-height: 1.75rem; font-weight: 600; }
|
|
484
|
+
.x { width: 36px; height: 36px; border: 0; border-radius: var(--eid-radius); background: transparent; color: var(--eid-fg-muted); cursor: pointer; font-size: 1.25rem; line-height: 1; }
|
|
485
|
+
.x:hover { background: var(--eid-bg-muted); color: var(--eid-fg); }
|
|
486
|
+
.qr { position: relative; width: 256px; max-width: 100%; aspect-ratio: 1; margin: 0 auto; border: 1px solid var(--eid-border);
|
|
487
|
+
border-radius: var(--eid-radius-lg); background: #fff; overflow: hidden; }
|
|
488
|
+
.qr svg { display: block; width: 100%; height: 100%; }
|
|
489
|
+
.qr.stale svg { opacity: 0.12; }
|
|
490
|
+
.qr-stale { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
|
|
491
|
+
color: hsl(222 47% 11%); font-weight: 500; }
|
|
492
|
+
.qr-vc { margin-top: 8px; text-align: center; font-size: 0.8125rem; color: var(--eid-fg-subtle); }
|
|
493
|
+
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; letter-spacing: 0.08em; color: var(--eid-fg-muted); }
|
|
494
|
+
.steps { margin-top: 16px; padding: 0; list-style: none; counter-reset: st; display: grid; gap: 8px; }
|
|
495
|
+
.steps li { counter-increment: st; display: flex; align-items: center; gap: 12px; }
|
|
496
|
+
.steps li::before { content: counter(st); flex: none; width: 24px; height: 24px; border-radius: 9999px; background: var(--eid-accent-subtle);
|
|
497
|
+
color: var(--eid-accent-subtle-fg); display: flex; align-items: center; justify-content: center; font-size: 0.75rem; font-weight: 600; }
|
|
498
|
+
.or { display: flex; align-items: center; gap: 12px; margin: 24px 0; color: var(--eid-fg-subtle); font-size: 0.8125rem; }
|
|
499
|
+
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--eid-border); }
|
|
500
|
+
.field { display: grid; gap: 8px; }
|
|
501
|
+
.field label { font-weight: 500; }
|
|
502
|
+
.field input { width: 100%; height: 44px; padding: 0 12px; border: 1px solid var(--eid-border-strong); border-radius: var(--eid-radius);
|
|
503
|
+
background: var(--eid-bg); color: var(--eid-fg); font-family: inherit; font-size: 1rem; line-height: 1.5rem; letter-spacing: 0.02em; text-transform: uppercase; }
|
|
504
|
+
.field input::placeholder { color: var(--eid-fg-subtle); text-transform: none; }
|
|
505
|
+
.field input[aria-invalid="true"] { border-color: var(--eid-danger-fg); }
|
|
506
|
+
.hint { font-size: 0.8125rem; color: var(--eid-fg-subtle); }
|
|
507
|
+
.err { font-size: 0.8125rem; color: var(--eid-danger-fg); font-weight: 500; }
|
|
508
|
+
.push { margin-top: 16px; }
|
|
509
|
+
.center { text-align: center; }
|
|
510
|
+
.vc { font: 600 2.25rem/2.5rem ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.16em; padding-left: 0.16em; }
|
|
511
|
+
.vc:focus, h2:focus { outline: none; }
|
|
512
|
+
.text { margin-top: 12px; color: var(--eid-fg-muted); }
|
|
513
|
+
.pending { margin-top: 16px; display: inline-flex; align-items: center; gap: 8px; color: var(--eid-fg-muted); }
|
|
514
|
+
.end .btn, .center .btn { margin-top: 24px; }
|
|
515
|
+
.spinner { width: 16px; height: 16px; flex: none; border: 2px solid currentColor; border-right-color: transparent; border-radius: 9999px; animation: spin 0.8s linear infinite; }
|
|
516
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
517
|
+
.netwarn { margin-top: 16px; padding: 8px 12px; border: 1px solid var(--eid-warning-border); border-radius: var(--eid-radius); background: var(--eid-warning-bg);
|
|
518
|
+
color: var(--eid-warning-fg); font-size: 0.8125rem; }
|
|
519
|
+
.meta { margin-top: 16px; font-size: 0.8125rem; color: var(--eid-fg-subtle); }
|
|
520
|
+
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; }
|
|
521
|
+
.spinner { animation: none; border-right-color: currentColor; opacity: 0.6; } }
|
|
522
|
+
`;
|
|
523
|
+
var CSS = CSS_BASE + CSS_REST;
|
|
524
|
+
function resolveEidTheme(theme, doc = document) {
|
|
525
|
+
if (theme === "light" || theme === "dark") return theme;
|
|
526
|
+
const html = doc.documentElement;
|
|
527
|
+
const dt = html?.getAttribute("data-theme");
|
|
528
|
+
if (dt === "dark" || dt === "light") return dt;
|
|
529
|
+
if (html?.classList.contains("dark")) return "dark";
|
|
530
|
+
if (html?.classList.contains("light")) return "light";
|
|
531
|
+
const mq = doc.defaultView?.matchMedia?.("(prefers-color-scheme: dark)");
|
|
532
|
+
return mq?.matches ? "dark" : "light";
|
|
533
|
+
}
|
|
534
|
+
var ID_RE = /^([А-ЯЁӨҮ]{2}[0-9]{8}|[0-9]{8,14})$/;
|
|
535
|
+
var FOCUSABLE = 'button:not([disabled]), input:not([disabled]), a[href], [tabindex]:not([tabindex="-1"])';
|
|
536
|
+
function el(tag, attrs = {}, text) {
|
|
537
|
+
const e = document.createElement(tag);
|
|
538
|
+
for (const [k, v] of Object.entries(attrs)) e.setAttribute(k, v);
|
|
539
|
+
if (text != null) e.textContent = text;
|
|
540
|
+
return e;
|
|
541
|
+
}
|
|
542
|
+
var Base = typeof HTMLElement === "undefined" ? class {
|
|
543
|
+
} : HTMLElement;
|
|
544
|
+
var EidLoginButton = class extends Base {
|
|
545
|
+
static observedAttributes = ["lang", "theme"];
|
|
546
|
+
/** Тест/дотоод: гар утас эсэхийг дарж бичих. */
|
|
547
|
+
isMobile = () => isMobileUserAgent();
|
|
548
|
+
/** Тест/дотоод: шилжилт (location.assign). */
|
|
549
|
+
navigate = (url) => location.assign(url);
|
|
550
|
+
root;
|
|
551
|
+
trigger;
|
|
552
|
+
backdrop = null;
|
|
553
|
+
body;
|
|
554
|
+
live;
|
|
555
|
+
timer = 0;
|
|
556
|
+
tick = 0;
|
|
557
|
+
left = -1;
|
|
558
|
+
fails = 0;
|
|
559
|
+
gen = 0;
|
|
560
|
+
// цонх нээх бүрд нэмэгдэнэ — хуучин fetch-ийн хариуг үл тооно
|
|
561
|
+
lastFocus = null;
|
|
562
|
+
darkStyle;
|
|
563
|
+
themeObs = null;
|
|
564
|
+
mq = null;
|
|
565
|
+
onScheme = () => this.applyTheme();
|
|
566
|
+
get t() {
|
|
567
|
+
return T[this.getAttribute("lang") === "en" ? "en" : "mn"];
|
|
568
|
+
}
|
|
569
|
+
attr(name, def = "") {
|
|
570
|
+
return this.getAttribute(name) ?? def;
|
|
571
|
+
}
|
|
572
|
+
connectedCallback() {
|
|
573
|
+
if (!this.root) {
|
|
574
|
+
this.root = this.attachShadow({ mode: "open" });
|
|
575
|
+
const style = el("style");
|
|
576
|
+
style.textContent = CSS;
|
|
577
|
+
this.darkStyle = el("style", { "data-eid-theme": "dark" });
|
|
578
|
+
this.trigger = el("button", { type: "button", class: "btn btn-outline trigger", part: "button", "aria-haspopup": "dialog" });
|
|
579
|
+
this.trigger.append(el("img", { src: EID_LOGO_DATA_URI, alt: "", width: "20", height: "20" }), el("span", {}, this.t.button));
|
|
580
|
+
this.trigger.addEventListener("click", () => this.start());
|
|
581
|
+
this.root.append(style, this.darkStyle, this.trigger);
|
|
582
|
+
}
|
|
583
|
+
this.watchTheme();
|
|
584
|
+
this.applyTheme();
|
|
585
|
+
}
|
|
586
|
+
attributeChangedCallback(name) {
|
|
587
|
+
if (name === "theme") {
|
|
588
|
+
if (this.root) this.applyTheme();
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
const label = this.trigger?.querySelector("span");
|
|
592
|
+
if (label) label.textContent = this.t.button;
|
|
593
|
+
}
|
|
594
|
+
disconnectedCallback() {
|
|
595
|
+
this.close();
|
|
596
|
+
this.themeObs?.disconnect();
|
|
597
|
+
this.themeObs = null;
|
|
598
|
+
this.mq?.removeEventListener?.("change", this.onScheme);
|
|
599
|
+
this.mq = null;
|
|
600
|
+
}
|
|
601
|
+
/** Одоогийн бодит схем (`theme` + auto үед хуудас/OS). */
|
|
602
|
+
get scheme() {
|
|
603
|
+
return resolveEidTheme(this.getAttribute("theme"));
|
|
604
|
+
}
|
|
605
|
+
applyTheme() {
|
|
606
|
+
const css = this.scheme === "dark" ? DARK_CSS : "";
|
|
607
|
+
if (this.darkStyle.textContent !== css) this.darkStyle.textContent = css;
|
|
608
|
+
}
|
|
609
|
+
/** auto үед хуудасны html[data-theme]/class ба OS-ийн схемийн өөрчлөлтийг дагана. */
|
|
610
|
+
watchTheme() {
|
|
611
|
+
if (!this.themeObs && typeof MutationObserver !== "undefined" && document.documentElement) {
|
|
612
|
+
this.themeObs = new MutationObserver(this.onScheme);
|
|
613
|
+
this.themeObs.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme", "class"] });
|
|
614
|
+
}
|
|
615
|
+
if (!this.mq && typeof matchMedia === "function") {
|
|
616
|
+
this.mq = matchMedia("(prefers-color-scheme: dark)");
|
|
617
|
+
this.mq.addEventListener?.("change", this.onScheme);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
/** Товчны үйлдэл (программаар ч дуудаж болно). */
|
|
621
|
+
start() {
|
|
622
|
+
const mode = this.attr("mode", "auto");
|
|
623
|
+
if (mode === "app" || mode === "auto" && this.isMobile()) {
|
|
624
|
+
const u = new URL(this.attr("start-url"), location.href);
|
|
625
|
+
u.searchParams.set("mode", "web2app");
|
|
626
|
+
u.searchParams.set("lang", this.attr("lang") === "en" ? "en" : "mn");
|
|
627
|
+
this.navigate(u.toString());
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
this.open();
|
|
631
|
+
}
|
|
632
|
+
open() {
|
|
633
|
+
this.close();
|
|
634
|
+
const gen = ++this.gen;
|
|
635
|
+
this.lastFocus = this.getRootNode().activeElement ?? document.activeElement;
|
|
636
|
+
const bd = el("div", { class: "backdrop", part: "backdrop" });
|
|
637
|
+
const dlg = el("div", { class: "dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "eid-title", part: "dialog" });
|
|
638
|
+
const head = el("div", { class: "head" });
|
|
639
|
+
const x = el("button", { type: "button", class: "x", "aria-label": this.t.close }, "\xD7");
|
|
640
|
+
x.addEventListener("click", () => this.close());
|
|
641
|
+
head.append(el("img", { src: EID_LOGO_DATA_URI, alt: "", width: "28", height: "28" }), el("h2", { id: "eid-title" }, this.t.title), x);
|
|
642
|
+
this.body = el("div");
|
|
643
|
+
this.live = el("p", { class: "sr-only", "aria-live": "polite" });
|
|
644
|
+
dlg.append(head, this.body, this.live);
|
|
645
|
+
bd.append(dlg);
|
|
646
|
+
bd.addEventListener("mousedown", (e) => {
|
|
647
|
+
if (e.target === bd) this.close();
|
|
648
|
+
});
|
|
649
|
+
bd.addEventListener("keydown", (e) => this.onKey(e));
|
|
650
|
+
this.root.append(bd);
|
|
651
|
+
this.backdrop = bd;
|
|
652
|
+
this.showLoading();
|
|
653
|
+
x.focus();
|
|
654
|
+
void this.begin(gen, { mode: "qr" });
|
|
655
|
+
}
|
|
656
|
+
/** Цонхыг хааж poll-ийг зогсооно. */
|
|
657
|
+
close() {
|
|
658
|
+
this.gen++;
|
|
659
|
+
clearTimeout(this.timer);
|
|
660
|
+
clearInterval(this.tick);
|
|
661
|
+
if (!this.backdrop) return;
|
|
662
|
+
this.backdrop.remove();
|
|
663
|
+
this.backdrop = null;
|
|
664
|
+
this.lastFocus?.focus?.();
|
|
665
|
+
if (!this.lastFocus) this.trigger.focus();
|
|
666
|
+
}
|
|
667
|
+
onKey(e) {
|
|
668
|
+
if (e.key === "Escape") {
|
|
669
|
+
e.preventDefault();
|
|
670
|
+
this.close();
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
if (e.key !== "Tab" || !this.backdrop) return;
|
|
674
|
+
const items = Array.from(this.backdrop.querySelectorAll(FOCUSABLE)).filter((n) => !n.closest("[hidden]"));
|
|
675
|
+
if (items.length === 0) return;
|
|
676
|
+
const first = items[0];
|
|
677
|
+
const last = items[items.length - 1];
|
|
678
|
+
const active = this.root.activeElement;
|
|
679
|
+
if (e.shiftKey && active === first) {
|
|
680
|
+
e.preventDefault();
|
|
681
|
+
last.focus();
|
|
682
|
+
} else if (!e.shiftKey && active === last) {
|
|
683
|
+
e.preventDefault();
|
|
684
|
+
first.focus();
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
say(text) {
|
|
688
|
+
this.live.textContent = text;
|
|
689
|
+
}
|
|
690
|
+
view(...nodes) {
|
|
691
|
+
this.body.replaceChildren(...nodes);
|
|
692
|
+
}
|
|
693
|
+
showLoading() {
|
|
694
|
+
const p = el("p", { class: "pending", role: "status" });
|
|
695
|
+
p.append(el("span", { class: "spinner", "aria-hidden": "true" }), el("span", {}, this.t.loading));
|
|
696
|
+
const c = el("div", { class: "center" });
|
|
697
|
+
c.append(p);
|
|
698
|
+
this.view(c);
|
|
699
|
+
}
|
|
700
|
+
async begin(gen, body) {
|
|
701
|
+
let r;
|
|
702
|
+
try {
|
|
703
|
+
r = await fetch(this.attr("start-url"), {
|
|
704
|
+
method: "POST",
|
|
705
|
+
credentials: "same-origin",
|
|
706
|
+
cache: "no-store",
|
|
707
|
+
headers: { "Content-Type": "application/json" },
|
|
708
|
+
body: JSON.stringify({ ...body, lang: this.attr("lang") === "en" ? "en" : "mn" })
|
|
709
|
+
});
|
|
710
|
+
} catch {
|
|
711
|
+
if (gen === this.gen && body.mode === "qr") this.end("unavailable");
|
|
712
|
+
return null;
|
|
713
|
+
}
|
|
714
|
+
if (gen !== this.gen) return null;
|
|
715
|
+
if (body.mode === "push") return r;
|
|
716
|
+
if (!r.ok) {
|
|
717
|
+
this.end("unavailable");
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
const s = await r.json();
|
|
721
|
+
this.showQr(s);
|
|
722
|
+
this.startTimer(s.expiresIn ?? -1);
|
|
723
|
+
this.schedule(gen, 1e3);
|
|
724
|
+
return r;
|
|
725
|
+
}
|
|
726
|
+
qrBox;
|
|
727
|
+
qrStale;
|
|
728
|
+
netwarn;
|
|
729
|
+
drawQr(link) {
|
|
730
|
+
const q = encodeQr(link);
|
|
731
|
+
const n = q.size + 8;
|
|
732
|
+
const NS = "http://www.w3.org/2000/svg";
|
|
733
|
+
const svg = document.createElementNS(NS, "svg");
|
|
734
|
+
svg.setAttribute("viewBox", `0 0 ${n} ${n}`);
|
|
735
|
+
svg.setAttribute("role", "img");
|
|
736
|
+
svg.setAttribute("aria-label", this.t.qrAlt);
|
|
737
|
+
svg.setAttribute("shape-rendering", "crispEdges");
|
|
738
|
+
const path = document.createElementNS(NS, "path");
|
|
739
|
+
path.setAttribute("d", qrSvgPath(q));
|
|
740
|
+
path.setAttribute("fill", "#000");
|
|
741
|
+
svg.append(path);
|
|
742
|
+
this.qrBox.querySelector("svg")?.remove();
|
|
743
|
+
this.qrBox.prepend(svg);
|
|
744
|
+
}
|
|
745
|
+
showQr(s) {
|
|
746
|
+
const t = this.t;
|
|
747
|
+
this.qrBox = el("div", { class: "qr" });
|
|
748
|
+
this.qrStale = el("div", { class: "qr-stale", hidden: "" });
|
|
749
|
+
const refresh = el("button", { type: "button", class: "btn btn-outline btn-sm" }, t.refresh);
|
|
750
|
+
refresh.addEventListener("click", () => this.schedule(this.gen, 0));
|
|
751
|
+
this.qrStale.append(el("p", {}, t.stale), refresh);
|
|
752
|
+
this.qrBox.append(this.qrStale);
|
|
753
|
+
if (s.qr) this.drawQr(s.qr);
|
|
754
|
+
const nodes = [this.qrBox];
|
|
755
|
+
if (s.vc) {
|
|
756
|
+
const vc = el("p", { class: "qr-vc" }, t.code + " ");
|
|
757
|
+
vc.append(el("span", { class: "mono" }, s.vc));
|
|
758
|
+
nodes.push(vc);
|
|
759
|
+
}
|
|
760
|
+
const steps = el("ol", { class: "steps" });
|
|
761
|
+
for (const st of t.steps) steps.append(el("li", {}, st));
|
|
762
|
+
nodes.push(steps, el("div", { class: "or", role: "separator", "aria-label": t.or }, t.or), this.pushForm());
|
|
763
|
+
this.netwarn = el("p", { class: "netwarn", role: "status", hidden: "" }, t.offline);
|
|
764
|
+
nodes.push(this.netwarn, this.meta());
|
|
765
|
+
this.view(...nodes);
|
|
766
|
+
}
|
|
767
|
+
leftEl = null;
|
|
768
|
+
meta() {
|
|
769
|
+
const p = el("p", { class: "meta" }, this.t.left + " ");
|
|
770
|
+
this.leftEl = el("span", { class: "mono", role: "timer", "aria-live": "off" }, "--:--");
|
|
771
|
+
p.append(this.leftEl);
|
|
772
|
+
if (this.left < 0) p.hidden = true;
|
|
773
|
+
return p;
|
|
774
|
+
}
|
|
775
|
+
startTimer(seconds) {
|
|
776
|
+
clearInterval(this.tick);
|
|
777
|
+
this.left = seconds;
|
|
778
|
+
const render = () => {
|
|
779
|
+
if (!this.leftEl || this.left < 0) return;
|
|
780
|
+
this.leftEl.parentElement.hidden = false;
|
|
781
|
+
const m = Math.floor(this.left / 60);
|
|
782
|
+
const s = this.left % 60;
|
|
783
|
+
this.leftEl.textContent = `${m < 10 ? "0" : ""}${m}:${s < 10 ? "0" : ""}${s}`;
|
|
784
|
+
if (this.left === 60) this.say(this.t.minute);
|
|
785
|
+
};
|
|
786
|
+
render();
|
|
787
|
+
if (seconds < 0) return;
|
|
788
|
+
this.tick = setInterval(() => {
|
|
789
|
+
this.left -= 1;
|
|
790
|
+
render();
|
|
791
|
+
if (this.left <= 0) this.end("expired");
|
|
792
|
+
}, 1e3);
|
|
793
|
+
}
|
|
794
|
+
pushForm() {
|
|
795
|
+
const t = this.t;
|
|
796
|
+
const form = el("form", { novalidate: "" });
|
|
797
|
+
const field = el("div", { class: "field" });
|
|
798
|
+
const input = el("input", {
|
|
799
|
+
id: "eid-id",
|
|
800
|
+
name: "idCode",
|
|
801
|
+
type: "text",
|
|
802
|
+
autocapitalize: "characters",
|
|
803
|
+
autocomplete: "off",
|
|
804
|
+
autocorrect: "off",
|
|
805
|
+
spellcheck: "false",
|
|
806
|
+
maxlength: "14",
|
|
807
|
+
placeholder: "\u0423\u041112345678",
|
|
808
|
+
"aria-describedby": "eid-id-hint eid-id-err"
|
|
809
|
+
});
|
|
810
|
+
const err = el("p", { class: "err", id: "eid-id-err", hidden: "" });
|
|
811
|
+
field.append(el("label", { for: "eid-id" }, t.idLabel), input, el("p", { class: "hint", id: "eid-id-hint" }, t.idHint), err);
|
|
812
|
+
const btn = el("button", { type: "submit", class: "btn btn-primary push" });
|
|
813
|
+
const spin = el("span", { class: "spinner", hidden: "", "aria-hidden": "true" });
|
|
814
|
+
const label = el("span", {}, t.push);
|
|
815
|
+
btn.append(spin, label);
|
|
816
|
+
form.append(field, btn);
|
|
817
|
+
const check = () => {
|
|
818
|
+
const v = input.value.replace(/\s+/g, "").toUpperCase();
|
|
819
|
+
if (v === "") return t.idEmpty;
|
|
820
|
+
if (ID_RE.test(v)) return "";
|
|
821
|
+
if (/^[A-Z]{2}[0-9]{8}$/.test(v)) return t.idLatin;
|
|
822
|
+
return t.idBad;
|
|
823
|
+
};
|
|
824
|
+
const setErr = (msg) => {
|
|
825
|
+
err.textContent = msg;
|
|
826
|
+
err.hidden = !msg;
|
|
827
|
+
if (msg) input.setAttribute("aria-invalid", "true");
|
|
828
|
+
else input.removeAttribute("aria-invalid");
|
|
829
|
+
};
|
|
830
|
+
const busy = (on) => {
|
|
831
|
+
btn.disabled = on;
|
|
832
|
+
spin.hidden = !on;
|
|
833
|
+
label.textContent = on ? t.pushing : t.push;
|
|
834
|
+
};
|
|
835
|
+
form.addEventListener("submit", (e) => {
|
|
836
|
+
e.preventDefault();
|
|
837
|
+
if (btn.disabled) return;
|
|
838
|
+
const msg = check();
|
|
839
|
+
setErr(msg);
|
|
840
|
+
if (msg) {
|
|
841
|
+
input.focus();
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
busy(true);
|
|
845
|
+
const gen = this.gen;
|
|
846
|
+
void this.begin(gen, { mode: "push", idCode: input.value.replace(/\s+/g, "").toUpperCase() }).then(async (r) => {
|
|
847
|
+
if (gen !== this.gen) return;
|
|
848
|
+
busy(false);
|
|
849
|
+
if (!r) return setErr(t.pushFailed);
|
|
850
|
+
const b = await r.json().catch(() => ({}));
|
|
851
|
+
if (r.ok && b.vc) return this.showWait(b);
|
|
852
|
+
if (r.status === 429) return setErr(t.rateLimited);
|
|
853
|
+
if (r.status === 400) return setErr(t.idBad);
|
|
854
|
+
setErr(t.pushFailed);
|
|
855
|
+
});
|
|
856
|
+
});
|
|
857
|
+
return form;
|
|
858
|
+
}
|
|
859
|
+
showWait(s) {
|
|
860
|
+
const t = this.t;
|
|
861
|
+
const c = el("div", { class: "center" });
|
|
862
|
+
c.append(el("h2", { class: "sr-only" }, t.waiting));
|
|
863
|
+
const vc = el("p", { class: "vc", tabindex: "-1", "aria-describedby": "eid-wait" }, s.vc ?? "");
|
|
864
|
+
const pending = el("p", { class: "pending" });
|
|
865
|
+
pending.append(el("span", { class: "spinner", "aria-hidden": "true" }), el("span", {}, t.waiting));
|
|
866
|
+
const back = el("button", { type: "button", class: "btn btn-outline" }, t.back);
|
|
867
|
+
back.addEventListener("click", () => this.open());
|
|
868
|
+
this.netwarn = el("p", { class: "netwarn", role: "status", hidden: "" }, t.offline);
|
|
869
|
+
c.append(vc, el("p", { class: "text", id: "eid-wait" }, t.waitText), pending, back, this.netwarn, this.meta());
|
|
870
|
+
this.view(c);
|
|
871
|
+
this.startTimer(s.expiresIn ?? -1);
|
|
872
|
+
vc.focus();
|
|
873
|
+
this.say(t.sent(s.vc ?? ""));
|
|
874
|
+
}
|
|
875
|
+
schedule(gen, ms) {
|
|
876
|
+
clearTimeout(this.timer);
|
|
877
|
+
this.timer = setTimeout(() => void this.poll(gen), ms);
|
|
878
|
+
}
|
|
879
|
+
async poll(gen) {
|
|
880
|
+
if (gen !== this.gen) return;
|
|
881
|
+
let s;
|
|
882
|
+
try {
|
|
883
|
+
const r = await fetch(this.attr("status-url"), { credentials: "same-origin", cache: "no-store" });
|
|
884
|
+
if (!r.ok) throw new Error(`status ${r.status}`);
|
|
885
|
+
s = await r.json();
|
|
886
|
+
} catch {
|
|
887
|
+
if (gen !== this.gen) return;
|
|
888
|
+
this.fails++;
|
|
889
|
+
if (this.fails >= 3) {
|
|
890
|
+
this.netwarn.hidden = false;
|
|
891
|
+
this.qrBox?.classList.add("stale");
|
|
892
|
+
if (this.qrStale) this.qrStale.hidden = false;
|
|
893
|
+
}
|
|
894
|
+
this.schedule(gen, 2e3);
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
if (gen !== this.gen) return;
|
|
898
|
+
this.fails = 0;
|
|
899
|
+
this.netwarn.hidden = true;
|
|
900
|
+
this.qrBox?.classList.remove("stale");
|
|
901
|
+
if (this.qrStale) this.qrStale.hidden = true;
|
|
902
|
+
switch (s.state) {
|
|
903
|
+
case "PENDING":
|
|
904
|
+
if (s.qr && this.qrBox?.isConnected) this.drawQr(s.qr);
|
|
905
|
+
if (typeof s.expiresIn === "number" && Math.abs(s.expiresIn - this.left) > 2) this.startTimer(s.expiresIn);
|
|
906
|
+
this.schedule(gen, 1e3);
|
|
907
|
+
return;
|
|
908
|
+
case "OK":
|
|
909
|
+
return this.succeed(s);
|
|
910
|
+
case "WAIT_CALLBACK":
|
|
911
|
+
return this.end("callback");
|
|
912
|
+
case "EXPIRED":
|
|
913
|
+
return this.end("expired");
|
|
914
|
+
default:
|
|
915
|
+
return this.end(s.error && s.error.startsWith("USER_REFUSED") ? "refused" : s.error === "TIMEOUT" ? "expired" : "failed", s.error);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
succeed(s) {
|
|
919
|
+
clearInterval(this.tick);
|
|
920
|
+
const c = el("div", { class: "center" });
|
|
921
|
+
const h = el("h2", { tabindex: "-1" }, this.t.success);
|
|
922
|
+
c.append(h);
|
|
923
|
+
this.view(c);
|
|
924
|
+
h.focus();
|
|
925
|
+
const ev = new CustomEvent("eid-login-success", { detail: s, bubbles: true, composed: true, cancelable: true });
|
|
926
|
+
const go = this.dispatchEvent(ev);
|
|
927
|
+
const to = s.redirect ?? this.getAttribute("success-url");
|
|
928
|
+
if (go && to) this.navigate(to);
|
|
929
|
+
}
|
|
930
|
+
end(kind, error) {
|
|
931
|
+
clearTimeout(this.timer);
|
|
932
|
+
clearInterval(this.tick);
|
|
933
|
+
this.gen++;
|
|
934
|
+
const t = this.t;
|
|
935
|
+
const titles = { expired: t.expiredTitle, refused: t.refusedTitle, failed: t.failedTitle, unavailable: t.failedTitle, callback: t.callbackTitle };
|
|
936
|
+
const c = el("div", { class: "end", role: "alert" });
|
|
937
|
+
const h = el("h2", { tabindex: "-1" }, titles[kind]);
|
|
938
|
+
c.append(h);
|
|
939
|
+
if (kind === "failed") c.append(el("p", { class: "text" }, t.failedText));
|
|
940
|
+
if (kind === "unavailable") c.append(el("p", { class: "text" }, t.unavailable));
|
|
941
|
+
if (kind === "callback") c.append(el("p", { class: "text" }, t.callbackText));
|
|
942
|
+
if (kind !== "callback") {
|
|
943
|
+
const retry = el("button", { type: "button", class: "btn btn-primary" }, t.retry);
|
|
944
|
+
retry.addEventListener("click", () => this.open());
|
|
945
|
+
c.append(retry);
|
|
946
|
+
this.dispatchEvent(new CustomEvent("eid-login-error", { detail: { error: error ?? kind.toUpperCase() }, bubbles: true, composed: true }));
|
|
947
|
+
}
|
|
948
|
+
this.view(c);
|
|
949
|
+
h.focus();
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
function defineEidLoginButton(tag = "eid-login-button") {
|
|
953
|
+
if (typeof customElements !== "undefined" && !customElements.get(tag)) customElements.define(tag, EidLoginButton);
|
|
954
|
+
}
|
|
955
|
+
function mountEidLoginButton(target, opts) {
|
|
956
|
+
defineEidLoginButton();
|
|
957
|
+
const b = document.createElement("eid-login-button");
|
|
958
|
+
b.setAttribute("start-url", opts.startUrl);
|
|
959
|
+
b.setAttribute("status-url", opts.statusUrl);
|
|
960
|
+
b.setAttribute("lang", opts.lang ?? "mn");
|
|
961
|
+
if (opts.mode) b.setAttribute("mode", opts.mode);
|
|
962
|
+
if (opts.theme) b.setAttribute("theme", opts.theme);
|
|
963
|
+
if (opts.successUrl) b.setAttribute("success-url", opts.successUrl);
|
|
964
|
+
if (opts.onSuccess) b.addEventListener("eid-login-success", (e) => opts.onSuccess(e.detail));
|
|
965
|
+
if (opts.onError) b.addEventListener("eid-login-error", (e) => opts.onError(e.detail.error));
|
|
966
|
+
target.append(b);
|
|
967
|
+
return b;
|
|
968
|
+
}
|
|
969
|
+
defineEidLoginButton();
|
|
970
|
+
export {
|
|
971
|
+
EidLoginButton,
|
|
972
|
+
defineEidLoginButton,
|
|
973
|
+
mountEidLoginButton,
|
|
974
|
+
resolveEidTheme
|
|
975
|
+
};
|