@tn3w/openage 1.0.5 → 1.0.6
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 +22 -6
- package/dist/openage.esm.js +144 -18
- package/dist/openage.esm.js.map +1 -1
- package/dist/openage.min.js +1 -1
- package/dist/openage.min.js.map +1 -1
- package/dist/openage.umd.js +144 -18
- package/dist/openage.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/challenge.js +25 -6
- package/src/constants.js +1 -2
- package/src/index.d.ts +1 -0
- package/src/index.js +17 -0
- package/src/ui.js +14 -0
- package/src/widget.d.ts +1 -0
- package/src/widget.js +87 -10
package/dist/openage.umd.js
CHANGED
|
@@ -547,6 +547,20 @@
|
|
|
547
547
|
flex-direction: column;
|
|
548
548
|
}
|
|
549
549
|
|
|
550
|
+
.oa-inline-shell {
|
|
551
|
+
background: var(--oa-bg);
|
|
552
|
+
border: 1px solid var(--oa-border);
|
|
553
|
+
border-radius: var(--oa-radius);
|
|
554
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.18),
|
|
555
|
+
0 0 0 1px rgba(0,0,0,0.06);
|
|
556
|
+
width: min(100%, 360px);
|
|
557
|
+
max-width: 100%;
|
|
558
|
+
overflow: hidden;
|
|
559
|
+
display: flex;
|
|
560
|
+
flex-direction: column;
|
|
561
|
+
margin: 0 auto;
|
|
562
|
+
}
|
|
563
|
+
|
|
550
564
|
.oa-modal-overlay {
|
|
551
565
|
position: fixed;
|
|
552
566
|
inset: 0;
|
|
@@ -1114,8 +1128,7 @@
|
|
|
1114
1128
|
'face_landmarker/face_landmarker/float16/1/' +
|
|
1115
1129
|
'face_landmarker.task';
|
|
1116
1130
|
|
|
1117
|
-
const FACEAPI_CDN =
|
|
1118
|
-
'https://cdn.jsdelivr.net/npm/face-api.js@0.22.2/dist/face-api.min.js';
|
|
1131
|
+
const FACEAPI_CDN = 'https://cdn.jsdelivr.net/npm/face-api.js@0.22.2/dist/face-api.min.js';
|
|
1119
1132
|
|
|
1120
1133
|
const FACEAPI_MODEL_CDN =
|
|
1121
1134
|
'https://cdn.jsdelivr.net/gh/justadudewhohacks/face-api.js@master/weights';
|
|
@@ -1152,6 +1165,7 @@
|
|
|
1152
1165
|
this.popup = null;
|
|
1153
1166
|
this.shadow = null;
|
|
1154
1167
|
this.elements = {};
|
|
1168
|
+
this.popupElements = null;
|
|
1155
1169
|
this.onChallenge = null;
|
|
1156
1170
|
this.onStartClick = null;
|
|
1157
1171
|
this.popupFrame = 0;
|
|
@@ -1164,6 +1178,7 @@
|
|
|
1164
1178
|
const host = document.createElement('div');
|
|
1165
1179
|
host.id = this.id;
|
|
1166
1180
|
this.shadow = host.attachShadow({ mode: 'open' });
|
|
1181
|
+
this.host = host;
|
|
1167
1182
|
|
|
1168
1183
|
const style = document.createElement('style');
|
|
1169
1184
|
style.textContent = STYLES;
|
|
@@ -1176,7 +1191,12 @@
|
|
|
1176
1191
|
if (this.params.size === 'invisible') {
|
|
1177
1192
|
host.style.display = 'none';
|
|
1178
1193
|
this.container.appendChild(host);
|
|
1179
|
-
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
if (this.isInlineLayout()) {
|
|
1198
|
+
this.renderInlineShell();
|
|
1199
|
+
this.container.appendChild(host);
|
|
1180
1200
|
return;
|
|
1181
1201
|
}
|
|
1182
1202
|
|
|
@@ -1212,7 +1232,32 @@
|
|
|
1212
1232
|
this.elements.errorSlot = this.shadow.querySelector('.oa-error-slot');
|
|
1213
1233
|
|
|
1214
1234
|
this.container.appendChild(host);
|
|
1215
|
-
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
isInlineLayout() {
|
|
1238
|
+
return this.params.layout === 'inline';
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
renderInlineShell() {
|
|
1242
|
+
const inlineShell = document.createElement('div');
|
|
1243
|
+
inlineShell.className = 'oa-inline-shell';
|
|
1244
|
+
inlineShell.innerHTML = this.buildPopupContent({ closeable: false });
|
|
1245
|
+
this.shadow.appendChild(inlineShell);
|
|
1246
|
+
|
|
1247
|
+
this.popup = {
|
|
1248
|
+
host: this.host,
|
|
1249
|
+
root: inlineShell,
|
|
1250
|
+
inline: true,
|
|
1251
|
+
};
|
|
1252
|
+
|
|
1253
|
+
this.bindPopupEvents(inlineShell);
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
resetInlineShell() {
|
|
1257
|
+
if (!this.popup?.root) return;
|
|
1258
|
+
|
|
1259
|
+
this.popup.root.innerHTML = this.buildPopupContent({ closeable: false });
|
|
1260
|
+
this.bindPopupEvents(this.popup.root);
|
|
1216
1261
|
}
|
|
1217
1262
|
|
|
1218
1263
|
startChallenge() {
|
|
@@ -1245,6 +1290,14 @@
|
|
|
1245
1290
|
}
|
|
1246
1291
|
|
|
1247
1292
|
openPopup() {
|
|
1293
|
+
if (this.isInlineLayout()) {
|
|
1294
|
+
if (!this.popup) {
|
|
1295
|
+
this.renderInlineShell();
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
return this.getVideo();
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1248
1301
|
if (this.popup) return this.getVideo();
|
|
1249
1302
|
|
|
1250
1303
|
const anchor = this.getPopupAnchor();
|
|
@@ -1422,7 +1475,7 @@
|
|
|
1422
1475
|
this.popup.root.style.pointerEvents = 'auto';
|
|
1423
1476
|
}
|
|
1424
1477
|
|
|
1425
|
-
buildPopupContent() {
|
|
1478
|
+
buildPopupContent({ closeable = true } = {}) {
|
|
1426
1479
|
return `
|
|
1427
1480
|
<div class="oa-header">
|
|
1428
1481
|
<div class="oa-title">
|
|
@@ -1433,10 +1486,14 @@
|
|
|
1433
1486
|
</a>
|
|
1434
1487
|
<span class="oa-badge">on-device</span>
|
|
1435
1488
|
</div>
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1489
|
+
${
|
|
1490
|
+
closeable
|
|
1491
|
+
? `<button class="oa-close-btn"
|
|
1492
|
+
aria-label="Close">
|
|
1493
|
+
${CLOSE_SVG}
|
|
1494
|
+
</button>`
|
|
1495
|
+
: ''
|
|
1496
|
+
}
|
|
1440
1497
|
</div>
|
|
1441
1498
|
<div class="oa-body">
|
|
1442
1499
|
${heroTemplate('Initializing…')}
|
|
@@ -1449,7 +1506,7 @@
|
|
|
1449
1506
|
`;
|
|
1450
1507
|
}
|
|
1451
1508
|
|
|
1452
|
-
bindPopupEvents(root
|
|
1509
|
+
bindPopupEvents(root) {
|
|
1453
1510
|
const closeBtn = root.querySelector('.oa-close-btn');
|
|
1454
1511
|
if (closeBtn) {
|
|
1455
1512
|
closeBtn.addEventListener('click', () => {
|
|
@@ -1567,6 +1624,22 @@
|
|
|
1567
1624
|
}
|
|
1568
1625
|
|
|
1569
1626
|
showResult(outcome, message) {
|
|
1627
|
+
if (this.isInlineLayout()) {
|
|
1628
|
+
if (!this.popupElements?.body) return;
|
|
1629
|
+
|
|
1630
|
+
this.popupElements.body.innerHTML = resultTemplate(outcome, message);
|
|
1631
|
+
this.hideActions();
|
|
1632
|
+
|
|
1633
|
+
if (outcome === 'pass') {
|
|
1634
|
+
this.setState('verified');
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
this.setState(outcome === 'fail' ? 'failed' : 'retry');
|
|
1639
|
+
this.showActions('Try Again');
|
|
1640
|
+
return;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1570
1643
|
if (outcome === 'pass') {
|
|
1571
1644
|
this.closePopup();
|
|
1572
1645
|
this.setState('verified');
|
|
@@ -1606,8 +1679,9 @@
|
|
|
1606
1679
|
if (!this.popupElements?.body) return;
|
|
1607
1680
|
|
|
1608
1681
|
this.popupElements.body.innerHTML = errorStepTemplate(message);
|
|
1609
|
-
this.popupElements.errorCountdown =
|
|
1610
|
-
|
|
1682
|
+
this.popupElements.errorCountdown = this.popupElements.body.querySelector(
|
|
1683
|
+
'.oa-error-step-countdown'
|
|
1684
|
+
);
|
|
1611
1685
|
this.hideActions();
|
|
1612
1686
|
}
|
|
1613
1687
|
|
|
@@ -1626,6 +1700,22 @@
|
|
|
1626
1700
|
|
|
1627
1701
|
closePopup() {
|
|
1628
1702
|
if (!this.popup) return;
|
|
1703
|
+
|
|
1704
|
+
if (this.popup.inline) {
|
|
1705
|
+
this.popup.cleanup?.();
|
|
1706
|
+
if (this.popupFrame) {
|
|
1707
|
+
cancelAnimationFrame(this.popupFrame);
|
|
1708
|
+
this.popupFrame = 0;
|
|
1709
|
+
}
|
|
1710
|
+
this.resetInlineShell();
|
|
1711
|
+
|
|
1712
|
+
if (this.state === 'loading') {
|
|
1713
|
+
this.setState('idle');
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1629
1719
|
this.popup.cleanup?.();
|
|
1630
1720
|
this.popup.themeCleanup?.();
|
|
1631
1721
|
this.popup.host.remove();
|
|
@@ -2825,9 +2915,18 @@
|
|
|
2825
2915
|
return 'Verification failed. Please try again.';
|
|
2826
2916
|
}
|
|
2827
2917
|
|
|
2918
|
+
function isInlineLayout(widget) {
|
|
2919
|
+
return widget?.params?.layout === 'inline';
|
|
2920
|
+
}
|
|
2921
|
+
|
|
2828
2922
|
async function showErrorStep(widget, error) {
|
|
2829
2923
|
const message = resolveChallengeErrorMessage(error);
|
|
2830
2924
|
|
|
2925
|
+
if (isInlineLayout(widget)) {
|
|
2926
|
+
widget.showResult?.('retry', message);
|
|
2927
|
+
return;
|
|
2928
|
+
}
|
|
2929
|
+
|
|
2831
2930
|
if (!widget.popup) {
|
|
2832
2931
|
widget.openPopup?.();
|
|
2833
2932
|
}
|
|
@@ -2880,10 +2979,14 @@
|
|
|
2880
2979
|
await Promise.all([loadVision(), initAgeEstimator()]);
|
|
2881
2980
|
|
|
2882
2981
|
modelBuffer = await loadModel();
|
|
2883
|
-
widget.showReady();
|
|
2884
2982
|
|
|
2885
|
-
|
|
2886
|
-
|
|
2983
|
+
if (isInlineLayout(widget)) {
|
|
2984
|
+
await startCameraFlow(widget, modelBuffer);
|
|
2985
|
+
} else {
|
|
2986
|
+
widget.showReady();
|
|
2987
|
+
await waitForStart(widget);
|
|
2988
|
+
await startCameraFlow(widget, modelBuffer);
|
|
2989
|
+
}
|
|
2887
2990
|
|
|
2888
2991
|
const transport = createTransport('serverless', params);
|
|
2889
2992
|
|
|
@@ -2972,10 +3075,16 @@
|
|
|
2972
3075
|
captureFrame: () => (captureFrame() ? 'true' : 'null'),
|
|
2973
3076
|
});
|
|
2974
3077
|
|
|
2975
|
-
|
|
2976
|
-
|
|
3078
|
+
let video;
|
|
3079
|
+
|
|
3080
|
+
if (isInlineLayout(widget)) {
|
|
3081
|
+
video = widget.showCamera();
|
|
3082
|
+
} else {
|
|
3083
|
+
widget.showReady();
|
|
3084
|
+
await waitForStart(widget);
|
|
3085
|
+
video = widget.showCamera();
|
|
3086
|
+
}
|
|
2977
3087
|
|
|
2978
|
-
const video = widget.showCamera();
|
|
2979
3088
|
widget.setVideoStatus('Requesting camera…');
|
|
2980
3089
|
await startCamera(video);
|
|
2981
3090
|
exposeMirrorVideo(video);
|
|
@@ -3278,8 +3387,19 @@
|
|
|
3278
3387
|
const emitter = new EventEmitter();
|
|
3279
3388
|
const widgets = new Map();
|
|
3280
3389
|
|
|
3390
|
+
function normalizeLayout(layout) {
|
|
3391
|
+
if (layout === 'inline' || layout === 'embed' || layout === 'embedded') {
|
|
3392
|
+
return 'inline';
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
return 'widget';
|
|
3396
|
+
}
|
|
3397
|
+
|
|
3281
3398
|
function normalizeParams(params) {
|
|
3282
3399
|
const globalConfig = typeof window !== 'undefined' ? window.openage || {} : {};
|
|
3400
|
+
const layout = normalizeLayout(
|
|
3401
|
+
params.layout ?? params.display ?? globalConfig.layout ?? globalConfig.display
|
|
3402
|
+
);
|
|
3283
3403
|
|
|
3284
3404
|
return {
|
|
3285
3405
|
mode: 'serverless',
|
|
@@ -3288,6 +3408,7 @@
|
|
|
3288
3408
|
minAge: 18,
|
|
3289
3409
|
...globalConfig,
|
|
3290
3410
|
...params,
|
|
3411
|
+
layout,
|
|
3291
3412
|
};
|
|
3292
3413
|
}
|
|
3293
3414
|
|
|
@@ -3296,6 +3417,10 @@
|
|
|
3296
3417
|
emitter.emit('opened', widget.id);
|
|
3297
3418
|
runChallenge(widget, emitter);
|
|
3298
3419
|
};
|
|
3420
|
+
|
|
3421
|
+
if (widget.params.layout === 'inline') {
|
|
3422
|
+
widget.startChallenge();
|
|
3423
|
+
}
|
|
3299
3424
|
}
|
|
3300
3425
|
|
|
3301
3426
|
function render(container, params = {}) {
|
|
@@ -3444,6 +3569,7 @@
|
|
|
3444
3569
|
size: element.dataset.size,
|
|
3445
3570
|
action: element.dataset.action,
|
|
3446
3571
|
mode: element.dataset.mode,
|
|
3572
|
+
layout: element.dataset.layout || element.dataset.display,
|
|
3447
3573
|
server: element.dataset.server,
|
|
3448
3574
|
};
|
|
3449
3575
|
|