@zoreal/oauth2-js 0.1.10 → 0.1.12

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/dist/index.cjs CHANGED
@@ -59,7 +59,7 @@ function unsafeClaims(idToken) {
59
59
 
60
60
  // src/wire.ts
61
61
  var WIRE_VERSION = 1;
62
- var SDK_VERSION = "0.1.10";
62
+ var SDK_VERSION = "0.1.12";
63
63
  var SDK_NAME = "@zoreal/oauth2-js";
64
64
  var DEFAULT_ISSUER = "https://id.zoreal.com";
65
65
  var POLL_INTERVAL_MS = 2e3;
@@ -1022,9 +1022,111 @@ var CSS = `
1022
1022
  margin: 20px auto 0;
1023
1023
  padding: 12px;
1024
1024
  border: 1px solid var(--zrl-line);
1025
- border-radius: 16px;
1025
+ border-radius: var(--zrl-radius);
1026
1026
  background: var(--zrl-qr-bg);
1027
+ /* The light on the edge takes its shape and colour from here. The colour
1028
+ is fixed, not themed: the brand blue on both grounds, a lighter tint of
1029
+ it at the head, no other hue. */
1030
+ --zrl-radius: 16px;
1031
+ --zrl-beam: #00b4d9;
1032
+ --zrl-beam-head: #7fe0f4;
1033
+ --zrl-beam-size: 100px;
1034
+ --zrl-beam-time: 4s;
1035
+ --zrl-glow-reach: 20px;
1036
+ --zrl-glow-core: 3px;
1037
+ }
1038
+
1039
+ /* The light on the well's edge: a short comet running along the border, with
1040
+ a soft glow outside it. Three overlays inside the well, each masked so the
1041
+ comet can only ever paint where its mask allows, and the white interior lies
1042
+ outside every mask: nothing here can reach the quiet zone a camera needs,
1043
+ whatever the comet is doing. The mask is the padding box cut out of the
1044
+ border box, a transparent layer clipped to the padding box intersected
1045
+ with a solid one clipped to the border box. The prefixed form is for Chrome
1046
+ before 120 and Safari before 15.4; the unprefixed one, declared after it,
1047
+ wins everywhere else.
1048
+
1049
+ qr-beam keeps a 1px ring on the border line: the comet itself.
1050
+ qr-beam-glow is the glow: a wide band outside the well that blurs whatever
1051
+ is inside it, and inside it qr-beam-glow-band keeps a 3px ring with a
1052
+ second copy of the comet. The blur has to sit on the parent because a
1053
+ filter is applied before a mask: blurred on the band itself, the glow
1054
+ would be cut back to the band's own edge. On the parent it runs after the
1055
+ band has clipped the comet thin and before the parent's mask cuts away the
1056
+ inward half, which is what makes it fade outward and never over the QR.
1057
+ All three share one containing block, the well's padding box, so the two
1058
+ comets ride the same path; the spent badge is a later sibling and paints
1059
+ above them. */
1060
+ .${PREFIX}-qr-beam,
1061
+ .${PREFIX}-qr-beam-glow,
1062
+ .${PREFIX}-qr-beam-glow-band {
1063
+ position: absolute;
1064
+ inset: -1px;
1065
+ border: 1px solid transparent;
1066
+ border-radius: var(--zrl-radius);
1067
+ pointer-events: none;
1068
+ -webkit-mask: linear-gradient(transparent, transparent), linear-gradient(#fff, #fff);
1069
+ -webkit-mask-clip: padding-box, border-box;
1070
+ -webkit-mask-composite: source-in;
1071
+ mask: linear-gradient(transparent, transparent), linear-gradient(#fff, #fff);
1072
+ mask-clip: padding-box, border-box;
1073
+ mask-composite: intersect;
1074
+ }
1075
+ .${PREFIX}-qr-beam-glow {
1076
+ inset: calc(0px - var(--zrl-glow-reach));
1077
+ border-width: var(--zrl-glow-reach);
1078
+ border-radius: calc(var(--zrl-radius) - 1px + var(--zrl-glow-reach));
1079
+ filter: blur(6px);
1080
+ opacity: 0.7;
1081
+ }
1082
+ .${PREFIX}-qr-beam-glow-band {
1083
+ inset: calc(0px - var(--zrl-glow-core));
1084
+ border-width: var(--zrl-glow-core);
1085
+ border-radius: calc(var(--zrl-radius) - 1px + var(--zrl-glow-core));
1086
+ }
1087
+
1088
+ /* At rest the edge holds a dim, even blue: a 1px line on the border and, from
1089
+ the glow band, a soft halo outside it. Hidden while the comet runs, so the
1090
+ border reads as the well's own line with a light passing over it; shown
1091
+ once the light has stopped. Every path below ends here, which is what
1092
+ makes them look the same at rest. */
1093
+ .${PREFIX}-qr-beam::before,
1094
+ .${PREFIX}-qr-beam-glow-band::before {
1095
+ content: '';
1096
+ position: absolute;
1097
+ inset: -50%;
1098
+ background: var(--zrl-beam);
1099
+ opacity: 0;
1100
+ transition: opacity 400ms cubic-bezier(0.23, 1, 0.32, 1);
1101
+ }
1102
+
1103
+ /* The moving light. Declared bottom-up: the transform fallback here, and each
1104
+ @supports block further down replaces it where the browser allows. */
1105
+ .${PREFIX}-qr-beam::after,
1106
+ .${PREFIX}-qr-beam-glow-band::after {
1107
+ content: '';
1108
+ position: absolute;
1109
+ inset: -50%;
1110
+ background: conic-gradient(
1111
+ from var(--zrl-angle, 0deg),
1112
+ transparent 0deg 245deg,
1113
+ var(--zrl-beam) 332deg 346deg,
1114
+ transparent 356deg 360deg
1115
+ );
1116
+ animation: ${PREFIX}-orbit 3s linear infinite;
1117
+ transition: opacity 400ms cubic-bezier(0.23, 1, 0.32, 1);
1118
+ }
1119
+
1120
+ /* Spent: the light stops where it is and fades, and the edge settles to the
1121
+ dim glow. Paused rather than removed, so it does not jump back to its start
1122
+ on the way out. */
1123
+ .${PREFIX}-qr-well[data-spent="true"] .${PREFIX}-qr-beam::after,
1124
+ .${PREFIX}-qr-well[data-spent="true"] .${PREFIX}-qr-beam-glow-band::after {
1125
+ animation-play-state: paused;
1126
+ opacity: 0;
1027
1127
  }
1128
+ .${PREFIX}-qr-well[data-spent="true"] .${PREFIX}-qr-beam::before { opacity: 0.55; }
1129
+ .${PREFIX}-qr-well[data-spent="true"] .${PREFIX}-qr-beam-glow-band::before { opacity: 0.7; }
1028
1130
 
1029
1131
  .${PREFIX}-qr {
1030
1132
  display: block;
@@ -1168,6 +1270,54 @@ var CSS = `
1168
1270
  70%, 100% { transform: scale(2.6); opacity: 0 }
1169
1271
  }
1170
1272
 
1273
+ /* Three ways to move the light, one look at rest.
1274
+ Where offset-path takes a rect() (Chrome 116, Firefox 122, Safari 18) the
1275
+ comet rides the edge. Before that, a conic gradient turns inside the same
1276
+ masks instead: on a registered custom property where @property exists, and
1277
+ by rotating an oversized square where it does not, since an untyped custom
1278
+ property cannot interpolate and the light would snap once a cycle.
1279
+ There is no direct query for @property support. transition-behavior
1280
+ shipped after it in every engine (Chrome 117 vs 85, Firefox 129 vs 128,
1281
+ Safari 17.4 vs 16.4), so it stands in: a yes is never wrong, and a no only
1282
+ sends a capable browser down the transform tier, which looks the same.
1283
+ inherits: false so the angle stays on the element that animates it and
1284
+ never reaches the host page or the well. */
1285
+ @property --zrl-angle {
1286
+ syntax: '<angle>';
1287
+ inherits: false;
1288
+ initial-value: 0deg;
1289
+ }
1290
+ @keyframes ${PREFIX}-orbit { to { transform: rotate(360deg) } }
1291
+ @keyframes ${PREFIX}-orbit-angle { to { --zrl-angle: 360deg } }
1292
+ @keyframes ${PREFIX}-beam { to { offset-distance: 100% } }
1293
+ @supports (transition-behavior: allow-discrete) {
1294
+ .${PREFIX}-qr-beam::after {
1295
+ inset: -1px;
1296
+ animation-name: ${PREFIX}-orbit-angle;
1297
+ }
1298
+ .${PREFIX}-qr-beam-glow-band::after {
1299
+ inset: calc(0px - var(--zrl-glow-core));
1300
+ animation-name: ${PREFIX}-orbit-angle;
1301
+ }
1302
+ }
1303
+ /* The comet: a square that rides the well's edge on a rounded-rect path, its
1304
+ anchor a little ahead of centre, turned to face the way it travels, and
1305
+ masked down to what its overlay allows. The gradient runs against the
1306
+ direction of travel: a light head, the blue body, nothing behind. One lap
1307
+ in 4s, linear: continuous motion has no ease. */
1308
+ @supports (offset-path: rect(0 auto auto 0)) {
1309
+ .${PREFIX}-qr-beam::after,
1310
+ .${PREFIX}-qr-beam-glow-band::after {
1311
+ inset: auto;
1312
+ width: var(--zrl-beam-size);
1313
+ height: var(--zrl-beam-size);
1314
+ background: linear-gradient(to left, var(--zrl-beam-head), var(--zrl-beam), transparent);
1315
+ offset-path: rect(0 auto auto 0 round calc(var(--zrl-radius) - 1px));
1316
+ offset-anchor: 60% 50%;
1317
+ animation: ${PREFIX}-beam var(--zrl-beam-time) linear infinite;
1318
+ }
1319
+ }
1320
+
1171
1321
  @media (prefers-reduced-motion: reduce) {
1172
1322
  .${PREFIX}-scrim,
1173
1323
  .${PREFIX}-card,
@@ -1177,6 +1327,11 @@ var CSS = `
1177
1327
  .${PREFIX}-cancel,
1178
1328
  .${PREFIX}-close,
1179
1329
  .${PREFIX}-timer { transition: none }
1330
+ /* No travelling light; the edge keeps its dim static glow instead. */
1331
+ .${PREFIX}-qr-beam::after,
1332
+ .${PREFIX}-qr-beam-glow-band::after { animation: none; opacity: 0 }
1333
+ .${PREFIX}-qr-beam::before { opacity: 0.55 }
1334
+ .${PREFIX}-qr-beam-glow-band::before { opacity: 0.7 }
1180
1335
  }
1181
1336
  `;
1182
1337
  function ensureStyles() {
@@ -1282,6 +1437,12 @@ function mountPairingModal(state, options) {
1282
1437
  title.id = titleId;
1283
1438
  const bodyText = el("p", cx("body-text"));
1284
1439
  const well = el("div", cx("qr-well"));
1440
+ const glow = el("span", cx("qr-beam-glow"));
1441
+ glow.setAttribute("aria-hidden", "true");
1442
+ glow.appendChild(el("span", cx("qr-beam-glow-band")));
1443
+ const beam = el("span", cx("qr-beam"));
1444
+ beam.setAttribute("aria-hidden", "true");
1445
+ well.append(glow, beam);
1285
1446
  const qr = el("img", cx("qr"));
1286
1447
  qr.alt = t.qrAlt;
1287
1448
  qr.width = 180;
@@ -1340,6 +1501,7 @@ function mountPairingModal(state, options) {
1340
1501
  bodyText.textContent = s.status === "enrolling" ? t.bodyEnrolling : settled ? t.bodyApprove : t.bodyScan;
1341
1502
  statusLabel.textContent = settled ? t.waitingApproval : t.waiting;
1342
1503
  qr.dataset.spent = String(settled);
1504
+ well.dataset.spent = String(settled);
1343
1505
  overlay.style.display = settled ? "" : "none";
1344
1506
  if (s.qrUrl) showFrame(s.qrUrl);
1345
1507
  };