@zoreal/oauth2-react 0.2.9 → 0.2.10

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
@@ -39,7 +39,7 @@ var import_react2 = require("react");
39
39
 
40
40
  // src/wire.ts
41
41
  var WIRE_VERSION = 1;
42
- var SDK_VERSION = "0.2.9";
42
+ var SDK_VERSION = "0.2.10";
43
43
  var DEFAULT_ISSUER = "https://id.zoreal.com";
44
44
  var POLL_INTERVAL_MS = 2e3;
45
45
  var POLL_INTERVAL_ENROLLING_MS = 5e3;
@@ -940,20 +940,110 @@ var CSS = `
940
940
  color: var(--zrl-ink-soft);
941
941
  }
942
942
 
943
+ /* The light around the well: a thin ring in the accent, one bright arc
944
+ travelling round it, and a soft glow of the same colour bleeding a few
945
+ pixels outward. It says the pairing is live without a word.
946
+
947
+ It sits BELOW the well, which is why the well is wrapped instead of given a
948
+ pseudo-element. Anything drawn inside the well paints over the white quiet
949
+ zone the camera needs, and a negative z-index from inside the well lands
950
+ wherever the card's stacking context happens to be that frame (the card's
951
+ entrance animation makes and unmakes one). The wrapper is the well's old
952
+ box exactly, same size, same margin, so nothing moves; the well keeps its
953
+ own stacking order on top, and the ring cannot touch the QR. */
954
+ .${PREFIX}-qr-halo {
955
+ position: relative;
956
+ isolation: isolate;
957
+ width: 204px;
958
+ height: 204px;
959
+ margin: 20px auto 0;
960
+ }
961
+
943
962
  .${PREFIX}-qr-well {
944
963
  position: relative;
964
+ z-index: 1;
945
965
  display: grid;
946
966
  place-items: center;
947
967
  box-sizing: border-box;
948
968
  width: 204px;
949
969
  height: 204px;
950
- margin: 20px auto 0;
970
+ margin: 0;
951
971
  padding: 12px;
952
972
  border: 1px solid var(--zrl-line);
953
973
  border-radius: 16px;
954
974
  background: var(--zrl-qr-bg);
955
975
  }
956
976
 
977
+ /* The glow is the ring's own alpha, blurred and drawn beneath it, so it
978
+ follows the arc round and fades with it. It has to be a parent of the
979
+ masked band: a filter is applied before a mask, so a shadow cast from the
980
+ band itself would be cut off at the band's edge. Two shadows because one
981
+ 2px source blurred over 10px is too faint to read as light; the second
982
+ blurs the first. */
983
+ .${PREFIX}-qr-glow {
984
+ position: absolute;
985
+ inset: -2px;
986
+ pointer-events: none;
987
+ filter: drop-shadow(0 0 3px var(--zrl-accent)) drop-shadow(0 0 10px var(--zrl-accent));
988
+ }
989
+
990
+ /* The band: a 2px ring just outside the well, cut with a mask that keeps the
991
+ padding and drops the content box. The gradient is on a pseudo-element
992
+ rather than on the band, because in the fallback it has to rotate as a
993
+ whole while the band stays put. The prefixed mask is for Chrome before 120;
994
+ the unprefixed one, declared after it, wins everywhere else. */
995
+ .${PREFIX}-qr-arc {
996
+ position: absolute;
997
+ inset: 0;
998
+ padding: 2px;
999
+ border-radius: 18px;
1000
+ overflow: hidden;
1001
+ -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
1002
+ -webkit-mask-composite: xor;
1003
+ mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
1004
+ mask-composite: exclude;
1005
+ }
1006
+ .${PREFIX}-qr-arc::before,
1007
+ .${PREFIX}-qr-arc::after {
1008
+ content: '';
1009
+ position: absolute;
1010
+ transition: opacity 400ms cubic-bezier(0.23, 1, 0.32, 1);
1011
+ }
1012
+
1013
+ /* The light. Mostly transparent, a tail that builds over a quarter turn, a
1014
+ short full-strength head and a drop-off within a few degrees, so it reads
1015
+ as travelling rather than blinking. One revolution every 3s, linear:
1016
+ continuous motion has no ease. Oversized so its corners still cover the
1017
+ band mid-rotation in the transform fallback; the property path shrinks it
1018
+ back to the band. */
1019
+ .${PREFIX}-qr-arc::before {
1020
+ inset: -50%;
1021
+ background: conic-gradient(
1022
+ from var(--zrl-angle, 0deg),
1023
+ transparent 0deg 245deg,
1024
+ var(--zrl-accent) 332deg 346deg,
1025
+ transparent 356deg 360deg
1026
+ );
1027
+ animation: ${PREFIX}-orbit 3s linear infinite;
1028
+ }
1029
+
1030
+ /* The rest state: the same ring, evenly lit. Faint under the moving light so
1031
+ the ring reads as a ring; stronger once the light has stopped. */
1032
+ .${PREFIX}-qr-arc::after {
1033
+ inset: 0;
1034
+ background: var(--zrl-accent);
1035
+ opacity: 0.16;
1036
+ }
1037
+
1038
+ /* Spent: the light stops where it is and fades, and the ring settles to a
1039
+ dim, even glow. Paused rather than removed, so it does not jump back to
1040
+ its start on the way out. */
1041
+ .${PREFIX}-qr-halo[data-spent="true"] .${PREFIX}-qr-arc::before {
1042
+ animation-play-state: paused;
1043
+ opacity: 0;
1044
+ }
1045
+ .${PREFIX}-qr-halo[data-spent="true"] .${PREFIX}-qr-arc::after { opacity: 0.34; }
1046
+
957
1047
  .${PREFIX}-qr {
958
1048
  display: block;
959
1049
  width: 100%;
@@ -1096,6 +1186,33 @@ var CSS = `
1096
1186
  70%, 100% { transform: scale(2.6); opacity: 0 }
1097
1187
  }
1098
1188
 
1189
+ /* Two ways to turn the light, one look.
1190
+ Where the browser can register a typed custom property, the gradient's own
1191
+ angle animates and the element never moves. Where it cannot (Firefox before
1192
+ 128), an untyped custom property cannot interpolate and the light would
1193
+ snap once a cycle, so the oversized pseudo-element rotates instead and the
1194
+ band's mask keeps the ring in place. At rest the two are the same pixels:
1195
+ same gradient, same centre, angle zero.
1196
+ There is no direct query for @property support. transition-behavior
1197
+ shipped after it in every engine (Chrome 117 vs 85, Firefox 129 vs 128,
1198
+ Safari 17.4 vs 16.4), so it stands in: a yes is never wrong, and a no only
1199
+ sends a capable browser down the fallback, which looks the same.
1200
+ inherits: false so the angle stays on the element that animates it and
1201
+ never reaches the host page or the well. */
1202
+ @property --zrl-angle {
1203
+ syntax: '<angle>';
1204
+ inherits: false;
1205
+ initial-value: 0deg;
1206
+ }
1207
+ @keyframes ${PREFIX}-orbit { to { transform: rotate(360deg) } }
1208
+ @keyframes ${PREFIX}-orbit-angle { to { --zrl-angle: 360deg } }
1209
+ @supports (transition-behavior: allow-discrete) {
1210
+ .${PREFIX}-qr-arc::before {
1211
+ inset: 0;
1212
+ animation-name: ${PREFIX}-orbit-angle;
1213
+ }
1214
+ }
1215
+
1099
1216
  @media (prefers-reduced-motion: reduce) {
1100
1217
  .${PREFIX}-scrim,
1101
1218
  .${PREFIX}-card,
@@ -1105,6 +1222,10 @@ var CSS = `
1105
1222
  .${PREFIX}-cancel,
1106
1223
  .${PREFIX}-close,
1107
1224
  .${PREFIX}-timer { transition: none }
1225
+ /* No travelling light. The ring keeps a still, soft glow instead, a step
1226
+ brighter than the spent state so pending and spent still read apart. */
1227
+ .${PREFIX}-qr-arc::before { animation: none; opacity: 0 }
1228
+ .${PREFIX}-qr-arc::after { opacity: 0.5 }
1108
1229
  }
1109
1230
  `;
1110
1231
  function ensureStyles() {
@@ -1215,9 +1336,12 @@ function PairingModal({
1215
1336
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ZorealLockup, { height: 44, className: cx("lockup") }),
1216
1337
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { id: titleId, className: cx("title"), children: settled ? t.titleApprove : t.title }),
1217
1338
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: cx("body-text"), children: body }),
1218
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: cx("qr-well"), children: [
1219
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("img", { className: cx("qr"), "data-spent": settled, src: frameUrl, alt: t.qrAlt, width: 180, height: 180 }),
1220
- settled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: cx("qr-overlay"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: cx("qr-badge"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconPhone, {}) }) })
1339
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: cx("qr-halo"), "data-spent": settled, children: [
1340
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: cx("qr-glow"), "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: cx("qr-arc") }) }),
1341
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: cx("qr-well"), children: [
1342
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("img", { className: cx("qr"), "data-spent": settled, src: frameUrl, alt: t.qrAlt, width: 180, height: 180 }),
1343
+ settled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: cx("qr-overlay"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: cx("qr-badge"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconPhone, {}) }) })
1344
+ ] })
1221
1345
  ] }),
1222
1346
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: cx("status"), children: [
1223
1347
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: cx("dot"), children: [