@bkazemi/verily 0.5.0 → 0.6.0
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 +4 -2
- package/dist/browser/badge.d.ts +4 -1
- package/dist/browser/badge.js +7 -4
- package/dist/browser/connect-dialog.js +10 -6
- package/dist/browser/evidence-dialog.d.ts +17 -3
- package/dist/browser/evidence-dialog.js +278 -28
- package/dist/browser/index.d.ts +7 -1
- package/dist/browser/index.js +24 -42
- package/dist/core/index.d.ts +28 -0
- package/dist/core/index.js +48 -0
- package/dist/server/index.js +83 -7
- package/dist/server/openpgp.d.ts +4 -0
- package/dist/server/openpgp.js +10 -1
- package/dist/server/service.d.ts +15 -1
- package/dist/server/service.js +15 -3
- package/dist/server/style.d.ts +1 -1
- package/dist/server/style.js +40 -0
- package/dist/verily.js +286 -64
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/verily.js
CHANGED
|
@@ -9574,10 +9574,12 @@ var Verily = (() => {
|
|
|
9574
9574
|
var browser_exports = {};
|
|
9575
9575
|
__export(browser_exports, {
|
|
9576
9576
|
Refused: () => Refused,
|
|
9577
|
+
accountsOf: () => accountsOf,
|
|
9577
9578
|
attestationLabel: () => attestationLabel,
|
|
9578
9579
|
dialogPath: () => dialogPath,
|
|
9579
9580
|
dialogRoute: () => dialogRoute,
|
|
9580
9581
|
externalId: () => externalId,
|
|
9582
|
+
externalIdGroups: () => externalIdGroups,
|
|
9581
9583
|
externalLink: () => externalLink,
|
|
9582
9584
|
externalName: () => externalName,
|
|
9583
9585
|
fresh: () => fresh,
|
|
@@ -9588,6 +9590,7 @@ var Verily = (() => {
|
|
|
9588
9590
|
isRedirectProvider: () => isRedirectProvider,
|
|
9589
9591
|
lastProved: () => lastProved,
|
|
9590
9592
|
localSide: () => localSide,
|
|
9593
|
+
place: () => place,
|
|
9591
9594
|
presentConnections: () => presentConnections,
|
|
9592
9595
|
proofTitle: () => proofTitle,
|
|
9593
9596
|
providerMethod: () => providerMethod,
|
|
@@ -9747,6 +9750,29 @@ var Verily = (() => {
|
|
|
9747
9750
|
if (evidence.status === "expired" || evidence.expiresAt <= now) return "Expired";
|
|
9748
9751
|
return evidence.status === "unconfirmed" ? "Unconfirmed" : "Verified";
|
|
9749
9752
|
}
|
|
9753
|
+
function place(account) {
|
|
9754
|
+
if (account.status === "retired") return 3;
|
|
9755
|
+
return account.mark === "preferred" ? 0 : account.mark === "unused" ? 2 : 1;
|
|
9756
|
+
}
|
|
9757
|
+
function accountsOf(records, now) {
|
|
9758
|
+
const when = (e2) => e2.connectedAt ?? e2.approvedAt;
|
|
9759
|
+
const byAccount = /* @__PURE__ */ new Map();
|
|
9760
|
+
for (const record2 of records) {
|
|
9761
|
+
const key2 = JSON.stringify([record2.provider, record2.external.id]);
|
|
9762
|
+
byAccount.set(key2, [...byAccount.get(key2) ?? [], record2]);
|
|
9763
|
+
}
|
|
9764
|
+
return [...byAccount.values()].map((unsorted) => {
|
|
9765
|
+
const held = [...unsorted].sort((a2, b2) => when(a2) - when(b2));
|
|
9766
|
+
const verified = held.filter((e2) => e2.status === "verified" && e2.expiresAt > now);
|
|
9767
|
+
const lead = verified[0] ?? held.reduce((a2, b2) => b2.approvedAt > a2.approvedAt ? b2 : a2);
|
|
9768
|
+
const external = [...lead.attestations.external];
|
|
9769
|
+
for (const other of verified.slice(1))
|
|
9770
|
+
for (const attestation of other.attestations.external)
|
|
9771
|
+
if (!external.some((shown3) => shown3.method === attestation.method))
|
|
9772
|
+
external.push(attestation);
|
|
9773
|
+
return { lead, held, verified, external, connectedAt: when(held[0]) };
|
|
9774
|
+
}).sort((a2, b2) => place(a2.lead) - place(b2.lead) || a2.connectedAt - b2.connectedAt);
|
|
9775
|
+
}
|
|
9750
9776
|
function localSide(local, fallback) {
|
|
9751
9777
|
const siteName = local.siteName ?? fallback;
|
|
9752
9778
|
if (local.kind === "site") return { heading: "Website", value: siteName };
|
|
@@ -9776,6 +9802,9 @@ var Verily = (() => {
|
|
|
9776
9802
|
function externalId(external) {
|
|
9777
9803
|
return external.kind === "mailbox" || external.kind === "domain" ? void 0 : external.id;
|
|
9778
9804
|
}
|
|
9805
|
+
function externalIdGroups(external) {
|
|
9806
|
+
return external.kind === "key" ? external.id.match(/.{1,4}/g) ?? void 0 : void 0;
|
|
9807
|
+
}
|
|
9779
9808
|
function externalLink(external) {
|
|
9780
9809
|
return external.kind === "mailbox" ? void 0 : external.profileUrl;
|
|
9781
9810
|
}
|
|
@@ -10067,11 +10096,12 @@ var Verily = (() => {
|
|
|
10067
10096
|
function badgeShown(element) {
|
|
10068
10097
|
return intact(element) && shown.has(element);
|
|
10069
10098
|
}
|
|
10070
|
-
function renderKey(evidence, current, label, more, linked, rows, peek) {
|
|
10099
|
+
function renderKey(evidence, current, label, more, linked, rows, peek, href) {
|
|
10071
10100
|
return JSON.stringify([
|
|
10072
10101
|
more,
|
|
10073
10102
|
linked,
|
|
10074
10103
|
peek,
|
|
10104
|
+
href,
|
|
10075
10105
|
rows.map((row) => [row.provider, row.providerName, externalName(row.external)]),
|
|
10076
10106
|
evidence.provider,
|
|
10077
10107
|
evidence.providerName,
|
|
@@ -10122,14 +10152,15 @@ var Verily = (() => {
|
|
|
10122
10152
|
more = 0,
|
|
10123
10153
|
linked = true,
|
|
10124
10154
|
rows = [],
|
|
10125
|
-
peek = false
|
|
10155
|
+
peek = false,
|
|
10156
|
+
href = evidence.evidenceUrl
|
|
10126
10157
|
} = {}) {
|
|
10127
10158
|
const provider = evidence.providerName;
|
|
10128
10159
|
const current = evidence.status === "verified" && evidence.expiresAt > Date.now();
|
|
10129
10160
|
const retired = evidence.status === "retired";
|
|
10130
10161
|
const state = current ? "verified" : retired ? "retired" : evidence.status === "revoked" ? "revoked" : "expired";
|
|
10131
10162
|
const label = statusLabel(evidence, Date.now());
|
|
10132
|
-
const key2 = renderKey(evidence, current, label, more, linked, rows, peek);
|
|
10163
|
+
const key2 = renderKey(evidence, current, label, more, linked, rows, peek, href);
|
|
10133
10164
|
if (intact(element) && shown.get(element) === key2) return null;
|
|
10134
10165
|
const handle = externalName(evidence.external);
|
|
10135
10166
|
const { pill: badge, mark: mark2 } = frame(element, state, !linked);
|
|
@@ -10138,7 +10169,7 @@ var Verily = (() => {
|
|
|
10138
10169
|
const others = `${named}${unnamed ? ` and ${unnamed} more` : ""}`;
|
|
10139
10170
|
paintMark(mark2, current ? "current" : retired ? "pending" : "inactive");
|
|
10140
10171
|
if (linked) {
|
|
10141
|
-
badge.href =
|
|
10172
|
+
badge.href = href;
|
|
10142
10173
|
badge.rel = "noreferrer";
|
|
10143
10174
|
} else badge.type = "button";
|
|
10144
10175
|
badge.setAttribute(
|
|
@@ -10213,7 +10244,7 @@ var Verily = (() => {
|
|
|
10213
10244
|
} catch {
|
|
10214
10245
|
return;
|
|
10215
10246
|
}
|
|
10216
|
-
|
|
10247
|
+
place2(panel, pill, listed, unnamed);
|
|
10217
10248
|
globalThis.addEventListener?.("scroll", hide, true);
|
|
10218
10249
|
};
|
|
10219
10250
|
panel.setAttribute("popover", "manual");
|
|
@@ -10235,7 +10266,7 @@ var Verily = (() => {
|
|
|
10235
10266
|
if (event.key === "Escape") hide();
|
|
10236
10267
|
};
|
|
10237
10268
|
}
|
|
10238
|
-
function
|
|
10269
|
+
function place2(panel, pill, listed, unnamed) {
|
|
10239
10270
|
const gap = 6;
|
|
10240
10271
|
const edge = 8;
|
|
10241
10272
|
const at2 = pill.getBoundingClientRect();
|
|
@@ -10485,7 +10516,7 @@ ${claims(evidence)}`;
|
|
|
10485
10516
|
}
|
|
10486
10517
|
|
|
10487
10518
|
// src/version.ts
|
|
10488
|
-
var version = "v0.
|
|
10519
|
+
var version = "v0.6.0";
|
|
10489
10520
|
|
|
10490
10521
|
// src/browser/evidence-dialog.ts
|
|
10491
10522
|
function stampLink() {
|
|
@@ -10502,8 +10533,16 @@ ${claims(evidence)}`;
|
|
|
10502
10533
|
h2 { margin: 0; font-size: 18px; font-weight: 650; letter-spacing: -.3px; }
|
|
10503
10534
|
button { width: 32px; height: 32px; border: 1px solid #dce2de; border-radius: 8px; background: #fff; color: #52645a; font: 20px system-ui, sans-serif; cursor: pointer; }
|
|
10504
10535
|
button:hover { background: #f2f5f1; }
|
|
10536
|
+
.icon { display: grid; place-items: center; padding: 0; }
|
|
10537
|
+
.icon svg { width: 16px; height: 16px; }
|
|
10538
|
+
.title { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
10539
|
+
.all { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 8px; color: #52645a; }
|
|
10540
|
+
.all:hover { background: #f2f5f1; }
|
|
10541
|
+
.all svg { width: 16px; height: 16px; }
|
|
10505
10542
|
a { color: #245f43; text-underline-offset: 3px; overflow-wrap: anywhere; }
|
|
10506
|
-
a:focus-visible, button:focus-visible { outline: 2px solid #357ce5; outline-offset: 3px; }
|
|
10543
|
+
a:focus-visible, button:focus-visible, summary:focus-visible { outline: 2px solid #357ce5; outline-offset: 3px; }
|
|
10544
|
+
/* An element given its own display would otherwise go on showing while hidden. */
|
|
10545
|
+
[hidden] { display: none !important; }
|
|
10507
10546
|
.summary { display: flex; align-items: center; gap: 8px; margin-top: 16px; }
|
|
10508
10547
|
.mark { width: 36px; height: 36px; flex-shrink: 0; }
|
|
10509
10548
|
.provider { width: 14px; height: 14px; }
|
|
@@ -10515,7 +10554,7 @@ ${claims(evidence)}`;
|
|
|
10515
10554
|
.spinner { width: 14px; height: 14px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin .7s linear infinite; }
|
|
10516
10555
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
10517
10556
|
@media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }
|
|
10518
|
-
.caution { display: inline-block; margin-left: 4px; color: #a15c00; cursor: help; vertical-align:
|
|
10557
|
+
.caution { display: inline-block; margin-left: 4px; color: #a15c00; cursor: help; vertical-align: -1.5px; }
|
|
10519
10558
|
.caution svg { display: block; width: 12px; height: 12px; }
|
|
10520
10559
|
.bad { color: #b3261e; font-weight: 650; text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }
|
|
10521
10560
|
.account { padding: 14px 16px; border: 1px solid #e0e6df; border-radius: 10px; margin-top: 12px; }
|
|
@@ -10524,6 +10563,9 @@ ${claims(evidence)}`;
|
|
|
10524
10563
|
/* The account's own name carries that weight; a link inside a line of prose does not. */
|
|
10525
10564
|
.summary a, .method a, .additional a { font: inherit; }
|
|
10526
10565
|
.reference { margin-top: 2px; }
|
|
10566
|
+
/* A fingerprint in fours: it breaks between groups, and copies as one unbroken word. */
|
|
10567
|
+
.fingerprint { font-family: ui-monospace, monospace; text-wrap: balance; }
|
|
10568
|
+
.fingerprint span { display: inline-block; margin-right: .5ch; }
|
|
10527
10569
|
.method { margin-top: 8px; }
|
|
10528
10570
|
/* In the corner the heading leaves empty, apart from everything that was checked. */
|
|
10529
10571
|
.listing { position: absolute; top: 12px; right: 14px; padding: 1px 8px; border: 1px solid #e0e6df; border-radius: 999px; color: #6b786f; font-size: 11px; font-weight: 550; }
|
|
@@ -10533,6 +10575,15 @@ ${claims(evidence)}`;
|
|
|
10533
10575
|
.account.retired > a, .account.retired > strong { color: #6b786f; }
|
|
10534
10576
|
.account.retired .mark { opacity: .45; }
|
|
10535
10577
|
.group { margin: 20px 0 0; color: #6b786f; font-size: 11px; font-weight: 550; }
|
|
10578
|
+
summary.group { display: flex; align-items: center; gap: 4px; width: fit-content; border-radius: 4px; list-style: none; cursor: pointer; }
|
|
10579
|
+
summary::-webkit-details-marker { display: none; }
|
|
10580
|
+
.fold { display: flex; align-items: center; gap: 4px; width: auto; height: auto; padding: 2px 8px 2px 4px; margin-left: -4px; border: 0; background: none; font: 550 12px/1.6 system-ui, sans-serif; }
|
|
10581
|
+
.fold svg, summary svg { width: 12px; height: 12px; }
|
|
10582
|
+
.fold[aria-expanded="true"] svg, details[open] > summary svg { transform: rotate(90deg); }
|
|
10583
|
+
@media (prefers-reduced-motion: no-preference) { .fold svg, summary svg { transition: transform .15s; } }
|
|
10584
|
+
/* The fold and what the holder may do share a line, until a question needs the whole of it. */
|
|
10585
|
+
.bar { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
|
|
10586
|
+
.account .bar .row { margin: 0 0 0 auto; }
|
|
10536
10587
|
.additional { margin-top: 2px; padding-left: 12px; }
|
|
10537
10588
|
.joiner { display: block; width: 20px; height: 20px; margin: 8px auto -4px; color: #90a096; }
|
|
10538
10589
|
dl { margin: 16px 0 0; padding-top: 12px; border-top: 1px solid #e5e9e3; display: grid; grid-template-columns: auto 1fr; gap: 5px 16px; font-size: 11px; }
|
|
@@ -10547,6 +10598,14 @@ ${claims(evidence)}`;
|
|
|
10547
10598
|
.row { display: flex; justify-content: end; gap: 8px; margin-top: 16px; }
|
|
10548
10599
|
.account .row { align-items: center; justify-content: start; flex-wrap: wrap; margin-top: 12px; }
|
|
10549
10600
|
.account .action { padding: 5px 10px; font-size: 12px; }
|
|
10601
|
+
.account .action.dots { display: grid; place-items: center; align-self: stretch; width: 30px; padding: 0; }
|
|
10602
|
+
.dots svg { width: 16px; height: 16px; }
|
|
10603
|
+
/* Placed under its button each time it opens, above the dialog and clipped by none of it. */
|
|
10604
|
+
.menu { position: fixed; inset: auto; margin: 0; min-width: 170px; padding: 6px; border: 1px solid #dce2de; border-radius: 10px; background: #fff; color: #23312b; box-shadow: 0 12px 40px #10201930; }
|
|
10605
|
+
.menu:popover-open { display: grid; }
|
|
10606
|
+
.account .menu .action { border: 0; border-radius: 6px; padding: 6px 10px; font-weight: 550; }
|
|
10607
|
+
.menu .danger { color: #b3261e; }
|
|
10608
|
+
.menu hr { width: 100%; margin: 4px 0; border: 0; border-top: 1px solid #e5e9e3; }
|
|
10550
10609
|
footer { display: flex; align-items: center; justify-content: start; gap: 6px; margin: 20px 0 -8px; color: #9aa9a0; font-size: 11px; }
|
|
10551
10610
|
footer a { display: flex; color: inherit; }
|
|
10552
10611
|
.logo { display: block; height: 13px; }
|
|
@@ -10564,6 +10623,58 @@ ${claims(evidence)}`;
|
|
|
10564
10623
|
anchor.target = "_blank";
|
|
10565
10624
|
return anchor;
|
|
10566
10625
|
}
|
|
10626
|
+
function subjectUrl(e2) {
|
|
10627
|
+
const url = new URL(e2.evidenceUrl);
|
|
10628
|
+
const path = url.pathname.replace(/\/connections\/[^/]+$/, "/published");
|
|
10629
|
+
if (path === url.pathname) return e2.evidenceUrl;
|
|
10630
|
+
url.pathname = path;
|
|
10631
|
+
url.search = `site=${encodeURIComponent(e2.siteName)}&reference=${encodeURIComponent(e2.local.reference)}`;
|
|
10632
|
+
return url.href;
|
|
10633
|
+
}
|
|
10634
|
+
function awayMark() {
|
|
10635
|
+
const namespace2 = "http://www.w3.org/2000/svg";
|
|
10636
|
+
const svg = document.createElementNS(namespace2, "svg");
|
|
10637
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
10638
|
+
svg.setAttribute("fill", "none");
|
|
10639
|
+
svg.setAttribute("aria-hidden", "true");
|
|
10640
|
+
svg.setAttribute("focusable", "false");
|
|
10641
|
+
for (const d2 of [
|
|
10642
|
+
"M14 5h5v5",
|
|
10643
|
+
"M19 5l-8 8",
|
|
10644
|
+
"M18 14v4a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h4"
|
|
10645
|
+
]) {
|
|
10646
|
+
const path = document.createElementNS(namespace2, "path");
|
|
10647
|
+
path.setAttribute("d", d2);
|
|
10648
|
+
path.setAttribute("stroke", "currentColor");
|
|
10649
|
+
path.setAttribute("stroke-width", "2");
|
|
10650
|
+
path.setAttribute("stroke-linecap", "round");
|
|
10651
|
+
path.setAttribute("stroke-linejoin", "round");
|
|
10652
|
+
svg.append(path);
|
|
10653
|
+
}
|
|
10654
|
+
return svg;
|
|
10655
|
+
}
|
|
10656
|
+
function strokes(box, width, paths) {
|
|
10657
|
+
const namespace2 = "http://www.w3.org/2000/svg";
|
|
10658
|
+
const svg = document.createElementNS(namespace2, "svg");
|
|
10659
|
+
svg.setAttribute("viewBox", `0 0 ${box} ${box}`);
|
|
10660
|
+
svg.setAttribute("fill", "none");
|
|
10661
|
+
svg.setAttribute("aria-hidden", "true");
|
|
10662
|
+
svg.setAttribute("focusable", "false");
|
|
10663
|
+
for (const d2 of paths) {
|
|
10664
|
+
const path = document.createElementNS(namespace2, "path");
|
|
10665
|
+
path.setAttribute("d", d2);
|
|
10666
|
+
path.setAttribute("stroke", "currentColor");
|
|
10667
|
+
path.setAttribute("stroke-width", String(width));
|
|
10668
|
+
path.setAttribute("stroke-linecap", "round");
|
|
10669
|
+
path.setAttribute("stroke-linejoin", "round");
|
|
10670
|
+
svg.append(path);
|
|
10671
|
+
}
|
|
10672
|
+
return svg;
|
|
10673
|
+
}
|
|
10674
|
+
var foldMark = () => strokes(16, 1.8, ["M6 3.5 10.5 8 6 12.5"]);
|
|
10675
|
+
var moreMark = () => strokes(16, 2.4, ["M3 8h.01", "M8 8h.01", "M13 8h.01"]);
|
|
10676
|
+
var closeMark = () => strokes(16, 1.8, ["M4 4l8 8", "M12 4l-8 8"]);
|
|
10677
|
+
var backMark = () => strokes(16, 1.8, ["M10 3.5 5.5 8 10 12.5"]);
|
|
10567
10678
|
function linkMark() {
|
|
10568
10679
|
const namespace2 = "http://www.w3.org/2000/svg";
|
|
10569
10680
|
const svg = document.createElementNS(namespace2, "svg");
|
|
@@ -10609,12 +10720,63 @@ ${claims(evidence)}`;
|
|
|
10609
10720
|
title.append(...heading);
|
|
10610
10721
|
if (value instanceof HTMLAnchorElement) outward(value, url);
|
|
10611
10722
|
card.append(title, value);
|
|
10612
|
-
if (reference) card.append(node("div", reference, "muted reference"));
|
|
10723
|
+
if (typeof reference === "string") card.append(node("div", reference, "muted reference"));
|
|
10724
|
+
else if (reference) {
|
|
10725
|
+
const groups = node("div", "", "muted reference fingerprint");
|
|
10726
|
+
groups.append(...reference.map((group) => node("span", group)));
|
|
10727
|
+
card.append(groups);
|
|
10728
|
+
}
|
|
10613
10729
|
card.append(...extra);
|
|
10614
10730
|
return card;
|
|
10615
10731
|
}
|
|
10616
10732
|
var retiringNote = "Retiring keeps this record as history. It will no longer read as verified, and who can read it cannot be changed afterwards.";
|
|
10617
10733
|
var removable = (evidence) => evidence.links ?? (evidence.status === "revoked" ? [] : [evidence.id]);
|
|
10734
|
+
function actionsMenu(more, choices) {
|
|
10735
|
+
const menu = node("div", "", "menu");
|
|
10736
|
+
if (typeof menu.showPopover !== "function") return void 0;
|
|
10737
|
+
const label = "More actions";
|
|
10738
|
+
more.className = "action dots";
|
|
10739
|
+
more.title = label;
|
|
10740
|
+
more.setAttribute("aria-label", label);
|
|
10741
|
+
more.setAttribute("aria-haspopup", "menu");
|
|
10742
|
+
more.append(moreMark());
|
|
10743
|
+
more.popoverTargetElement = menu;
|
|
10744
|
+
menu.setAttribute("popover", "auto");
|
|
10745
|
+
menu.setAttribute("role", "menu");
|
|
10746
|
+
for (const choice of choices) choice.setAttribute("role", "menuitem");
|
|
10747
|
+
menu.append(...choices.slice(0, -1), node("hr"), choices.at(-1));
|
|
10748
|
+
const shut = () => {
|
|
10749
|
+
try {
|
|
10750
|
+
if (menu.matches(":popover-open")) menu.hidePopover();
|
|
10751
|
+
} catch {
|
|
10752
|
+
}
|
|
10753
|
+
};
|
|
10754
|
+
const gap = 4;
|
|
10755
|
+
const edge = 8;
|
|
10756
|
+
menu.addEventListener("beforetoggle", (event) => {
|
|
10757
|
+
if (event.newState !== "open") return;
|
|
10758
|
+
const at2 = more.getBoundingClientRect();
|
|
10759
|
+
menu.style.top = `${at2.bottom + gap}px`;
|
|
10760
|
+
menu.style.right = `${document.documentElement.clientWidth - at2.right}px`;
|
|
10761
|
+
});
|
|
10762
|
+
menu.addEventListener("toggle", (event) => {
|
|
10763
|
+
if (event.newState !== "open") return;
|
|
10764
|
+
const { height, bottom } = menu.getBoundingClientRect();
|
|
10765
|
+
if (bottom > innerHeight - edge)
|
|
10766
|
+
menu.style.top = `${Math.max(edge, more.getBoundingClientRect().top - gap - height)}px`;
|
|
10767
|
+
menu.closest("dialog")?.addEventListener("scroll", shut, { once: true });
|
|
10768
|
+
choices[0].focus();
|
|
10769
|
+
});
|
|
10770
|
+
menu.addEventListener("click", shut);
|
|
10771
|
+
menu.addEventListener("keydown", (event) => {
|
|
10772
|
+
const step = { ArrowDown: 1, ArrowUp: -1 }[event.key];
|
|
10773
|
+
if (!step) return;
|
|
10774
|
+
event.preventDefault();
|
|
10775
|
+
const at2 = choices.indexOf(event.target);
|
|
10776
|
+
choices[(at2 + step + choices.length) % choices.length].focus();
|
|
10777
|
+
});
|
|
10778
|
+
return menu;
|
|
10779
|
+
}
|
|
10618
10780
|
function manageRow(evidence, manage) {
|
|
10619
10781
|
const row = node("div", "", "row");
|
|
10620
10782
|
const act = (label, danger = false) => {
|
|
@@ -10657,7 +10819,11 @@ ${claims(evidence)}`;
|
|
|
10657
10819
|
retire
|
|
10658
10820
|
);
|
|
10659
10821
|
}
|
|
10660
|
-
|
|
10822
|
+
const said = note ? [node("span", note, "muted")] : [];
|
|
10823
|
+
const more = act("");
|
|
10824
|
+
const menu = listing.length ? actionsMenu(more, [...listing, remove]) : void 0;
|
|
10825
|
+
if (menu) row.replaceChildren(renew, more, menu, ...said);
|
|
10826
|
+
else row.replaceChildren(renew, ...listing, remove, ...said);
|
|
10661
10827
|
};
|
|
10662
10828
|
const retiring = () => {
|
|
10663
10829
|
const cancel = act("Cancel");
|
|
@@ -10700,7 +10866,7 @@ ${claims(evidence)}`;
|
|
|
10700
10866
|
)
|
|
10701
10867
|
);
|
|
10702
10868
|
}
|
|
10703
|
-
function signedMark(evidence, later) {
|
|
10869
|
+
function signedMark(evidence, later, warned) {
|
|
10704
10870
|
const mark2 = node("span");
|
|
10705
10871
|
const link = outward(node("a", "signed"), `${evidence.evidenceUrl}#signed`);
|
|
10706
10872
|
const see = "See the signature (opens in a new tab)";
|
|
@@ -10711,6 +10877,7 @@ ${claims(evidence)}`;
|
|
|
10711
10877
|
warning.setAttribute("role", "alert");
|
|
10712
10878
|
warning.title = `This record does not match the signature ${evidence.verifierName} put on it, so it may have been altered. Do not rely on it.`;
|
|
10713
10879
|
mark2.replaceChildren(document.createTextNode(" \xB7 "), warning);
|
|
10880
|
+
warned();
|
|
10714
10881
|
return;
|
|
10715
10882
|
}
|
|
10716
10883
|
if (first?.state === "valid" && results.every((result) => result.state === "valid")) {
|
|
@@ -10752,7 +10919,25 @@ ${claims(evidence)}`;
|
|
|
10752
10919
|
}
|
|
10753
10920
|
return svg;
|
|
10754
10921
|
}
|
|
10922
|
+
function foldToggle(folded, fold) {
|
|
10923
|
+
const toggle = node("button", "", "fold");
|
|
10924
|
+
let shown3 = fold.open;
|
|
10925
|
+
const set = (open) => {
|
|
10926
|
+
shown3 = open;
|
|
10927
|
+
for (const part of folded) part.hidden = !open;
|
|
10928
|
+
toggle.setAttribute("aria-expanded", String(open));
|
|
10929
|
+
};
|
|
10930
|
+
toggle.type = "button";
|
|
10931
|
+
toggle.append(foldMark(), document.createTextNode("Details"));
|
|
10932
|
+
set(fold.open);
|
|
10933
|
+
toggle.onclick = () => {
|
|
10934
|
+
set(!shown3);
|
|
10935
|
+
fold.toggle(shown3);
|
|
10936
|
+
};
|
|
10937
|
+
return toggle;
|
|
10938
|
+
}
|
|
10755
10939
|
function externalCard(evidence, manage, later = () => {
|
|
10940
|
+
}, fold, warned = () => {
|
|
10756
10941
|
}) {
|
|
10757
10942
|
const current = evidence.status === "verified" && evidence.expiresAt > Date.now();
|
|
10758
10943
|
const status2 = statusLabel(evidence, Date.now());
|
|
@@ -10765,7 +10950,7 @@ ${claims(evidence)}`;
|
|
|
10765
10950
|
verifier.title = `View this record at ${evidence.verifierName} (opens in a new tab)`;
|
|
10766
10951
|
attribution.append(verifier);
|
|
10767
10952
|
} else attribution.append(document.createTextNode(evidence.verifierName));
|
|
10768
|
-
if (evidence.signedUrl) attribution.append(signedMark(evidence, later));
|
|
10953
|
+
if (evidence.signedUrl) attribution.append(signedMark(evidence, later, warned));
|
|
10769
10954
|
copy.append(node("div", status2, "state"), attribution);
|
|
10770
10955
|
const retired = evidence.status === "retired";
|
|
10771
10956
|
summary.append(verificationMark(current ? "current" : retired ? "pending" : "inactive"), copy);
|
|
@@ -10788,6 +10973,13 @@ ${claims(evidence)}`;
|
|
|
10788
10973
|
dates.append(node("dt", label), node("dd", moment(time)));
|
|
10789
10974
|
}
|
|
10790
10975
|
const names2 = { site: evidence.siteName, provider };
|
|
10976
|
+
const row = manage && removable(evidence).length ? [manageRow(evidence, manage)] : [];
|
|
10977
|
+
const bar = node("div", "", "bar");
|
|
10978
|
+
const methods = [
|
|
10979
|
+
...attestationNote(main, names2),
|
|
10980
|
+
...evidence.attestations.external.slice(1).flatMap((a2) => attestationNote(a2, names2, true))
|
|
10981
|
+
];
|
|
10982
|
+
if (fold) bar.append(foldToggle([...methods, dates], fold), ...row);
|
|
10791
10983
|
const logo2 = providerMark(evidence.provider, evidence.attestations.external[0].method);
|
|
10792
10984
|
const card = accountCard(
|
|
10793
10985
|
// The mark and the name, or just the name. A mark that falls back to writing the name
|
|
@@ -10795,16 +10987,14 @@ ${claims(evidence)}`;
|
|
|
10795
10987
|
logo2 ? [logo2, document.createTextNode(provider)] : [document.createTextNode(provider)],
|
|
10796
10988
|
externalName(evidence.external),
|
|
10797
10989
|
// A mailbox's address or a domain is its name already, so there is no second identifier.
|
|
10798
|
-
externalId(evidence.external),
|
|
10990
|
+
externalIdGroups(evidence.external) ?? externalId(evidence.external),
|
|
10799
10991
|
externalLink(evidence.external),
|
|
10800
10992
|
// Status first, then how it was shown, then when. The proof explains the state
|
|
10801
10993
|
// above it, so it cannot sit before that state has been given.
|
|
10802
10994
|
summary,
|
|
10803
|
-
...
|
|
10804
|
-
...evidence.attestations.external.slice(1).flatMap((a2) => attestationNote(a2, names2, true)),
|
|
10995
|
+
...fold ? [] : methods,
|
|
10805
10996
|
...evidence.status === "revoked" || retired ? [] : evidence.mark === "preferred" ? [node("div", "Preferred", "listing preferred")] : evidence.mark === "unused" ? [node("div", "No longer used", "listing")] : [],
|
|
10806
|
-
dates,
|
|
10807
|
-
...manage && removable(evidence).length ? [manageRow(evidence, manage)] : []
|
|
10997
|
+
...fold ? [bar, ...methods, dates] : [dates, ...row]
|
|
10808
10998
|
);
|
|
10809
10999
|
const surface = retired ? "account retired" : "account";
|
|
10810
11000
|
card.className = surface;
|
|
@@ -10832,7 +11022,7 @@ ${claims(evidence)}`;
|
|
|
10832
11022
|
row.append(add);
|
|
10833
11023
|
return row;
|
|
10834
11024
|
}
|
|
10835
|
-
function render(content, records, manage, later) {
|
|
11025
|
+
function render(content, records, manage, later, folds = { open: false, cards: /* @__PURE__ */ new Set() }) {
|
|
10836
11026
|
const [first] = records;
|
|
10837
11027
|
const local = localSide(first.local, first.siteName);
|
|
10838
11028
|
const localCard = accountCard(
|
|
@@ -10849,15 +11039,40 @@ ${claims(evidence)}`;
|
|
|
10849
11039
|
})
|
|
10850
11040
|
);
|
|
10851
11041
|
const retired = records.filter((record2) => record2.status === "retired");
|
|
11042
|
+
const listed = records.filter((record2) => record2.status !== "retired");
|
|
11043
|
+
const cards = (among, warned) => among.map((record2) => {
|
|
11044
|
+
const key2 = `${record2.provider}
|
|
11045
|
+
${record2.external.id}`;
|
|
11046
|
+
return externalCard(
|
|
11047
|
+
record2,
|
|
11048
|
+
manage,
|
|
11049
|
+
later,
|
|
11050
|
+
among.length > 1 ? {
|
|
11051
|
+
open: folds.cards.has(key2) !== folds.open,
|
|
11052
|
+
toggle: (open) => void (open === folds.open ? folds.cards.delete(key2) : folds.cards.add(key2))
|
|
11053
|
+
} : void 0,
|
|
11054
|
+
warned
|
|
11055
|
+
);
|
|
11056
|
+
});
|
|
11057
|
+
const history = node("details", "", "history");
|
|
11058
|
+
const count = node("summary", "", "group");
|
|
11059
|
+
count.append(foldMark(), document.createTextNode(`Retired accounts (${retired.length})`));
|
|
11060
|
+
history.append(
|
|
11061
|
+
count,
|
|
11062
|
+
...cards(retired, () => {
|
|
11063
|
+
history.open = true;
|
|
11064
|
+
})
|
|
11065
|
+
);
|
|
11066
|
+
history.open = folds.retired ?? !listed.length;
|
|
11067
|
+
count.addEventListener("click", () => {
|
|
11068
|
+
folds.retired = !history.open;
|
|
11069
|
+
});
|
|
10852
11070
|
content.replaceChildren(
|
|
10853
11071
|
localCard,
|
|
10854
11072
|
linkMark(),
|
|
10855
|
-
...
|
|
11073
|
+
...cards(listed),
|
|
10856
11074
|
...manage ? [addRow(manage)] : [],
|
|
10857
|
-
...retired.length ? [
|
|
10858
|
-
node("h3", "Retired accounts", "group"),
|
|
10859
|
-
...retired.map((record2) => externalCard(record2, manage, later))
|
|
10860
|
-
] : [],
|
|
11075
|
+
...retired.length ? [history] : [],
|
|
10861
11076
|
// Nothing below the cards may name a provider. Approval, method and dates belong to
|
|
10862
11077
|
// the card they came from, and a second provider on this subject gets its own card.
|
|
10863
11078
|
node(
|
|
@@ -10867,7 +11082,7 @@ ${claims(evidence)}`;
|
|
|
10867
11082
|
)
|
|
10868
11083
|
);
|
|
10869
11084
|
}
|
|
10870
|
-
function openEvidenceDialog(opener, load2, opened, arrange2 = (records) => records, manage) {
|
|
11085
|
+
function openEvidenceDialog(opener, load2, opened, arrange2 = (records) => records, manage, detailsOpen = false) {
|
|
10871
11086
|
const existing = openDialogs.get(opener);
|
|
10872
11087
|
if (existing?.open) {
|
|
10873
11088
|
existing.focus();
|
|
@@ -10880,7 +11095,9 @@ ${claims(evidence)}`;
|
|
|
10880
11095
|
root.adoptedStyleSheets = [sheet2];
|
|
10881
11096
|
const dialog = node("dialog");
|
|
10882
11097
|
const heading = node("h2", "Verification details");
|
|
10883
|
-
const close = node("button", "
|
|
11098
|
+
const close = node("button", "", "icon");
|
|
11099
|
+
const all = node("a", "", "all");
|
|
11100
|
+
const title = node("div", "", "title");
|
|
10884
11101
|
const header = node("header");
|
|
10885
11102
|
const stamp = node("footer");
|
|
10886
11103
|
const content = node("div", "Checking verification\u2026");
|
|
@@ -10890,13 +11107,18 @@ ${claims(evidence)}`;
|
|
|
10890
11107
|
close.setAttribute("aria-label", "Close verification details");
|
|
10891
11108
|
content.setAttribute("aria-live", "polite");
|
|
10892
11109
|
stamp.append(stampLink(), node("span", version));
|
|
10893
|
-
|
|
11110
|
+
all.append(awayMark());
|
|
11111
|
+
close.append(closeMark());
|
|
11112
|
+
close.autofocus = true;
|
|
11113
|
+
title.append(heading);
|
|
11114
|
+
header.append(title, close);
|
|
10894
11115
|
dialog.append(header, content, stamp);
|
|
10895
11116
|
const removed = /* @__PURE__ */ new Map();
|
|
10896
11117
|
const listed = [];
|
|
10897
11118
|
const listing = (record2) => JSON.stringify([record2.status, record2.mark, record2.retiredAt, record2.approvedAt]);
|
|
10898
11119
|
const listings = (given) => new Map([given].flat().map((record2) => [record2.id, listing(record2)]));
|
|
10899
11120
|
let held;
|
|
11121
|
+
const folds = { open: detailsOpen, cards: /* @__PURE__ */ new Set() };
|
|
10900
11122
|
const relisted = (evidence) => {
|
|
10901
11123
|
let record2 = evidence;
|
|
10902
11124
|
for (const { ids, as: as2, at: at2 } of listed) {
|
|
@@ -10965,11 +11187,19 @@ ${claims(evidence)}`;
|
|
|
10965
11187
|
(e2) => removed.has(e2.id) && e2.status !== "revoked" ? { ...e2, status: "revoked", revokedAt: removed.get(e2.id) } : relisted(standing(e2))
|
|
10966
11188
|
)
|
|
10967
11189
|
);
|
|
11190
|
+
const listable = records.filter((e2) => e2.visibility === "public" && e2.status !== "revoked");
|
|
11191
|
+
title.replaceChildren(heading, ...listable.length > 1 ? [all] : []);
|
|
11192
|
+
if (listable.length > 1) {
|
|
11193
|
+
const label = `View all on ${listable[0].verifierName} (opens in a new tab)`;
|
|
11194
|
+
outward(all, subjectUrl(listable[0]));
|
|
11195
|
+
all.title = label;
|
|
11196
|
+
all.setAttribute("aria-label", label);
|
|
11197
|
+
}
|
|
10968
11198
|
const key2 = JSON.stringify(records.map((e2) => [e2, statusLabel(e2, Date.now())]));
|
|
10969
11199
|
if (key2 === drawn) return;
|
|
10970
11200
|
drawn = key2;
|
|
10971
11201
|
retries.clear();
|
|
10972
|
-
render(content, records, actions, (retry) => retries.add(retry));
|
|
11202
|
+
render(content, records, actions, (retry) => retries.add(retry), folds);
|
|
10973
11203
|
};
|
|
10974
11204
|
const watch = (given) => {
|
|
10975
11205
|
clearTimeout(expiryTimer);
|
|
@@ -11048,13 +11278,15 @@ ${claims(evidence)}`;
|
|
|
11048
11278
|
/* The block scrolls and its frame does not, so the copy button stays in its corner. */
|
|
11049
11279
|
.code { position: relative; margin: 10px 0; }
|
|
11050
11280
|
pre { margin: 0; padding: 10px 64px 10px 12px; border: 1px solid #e0e6df; border-radius: 8px; background: #f6f8f5; font: 12px/1.5 ui-monospace, monospace; white-space: pre; overflow-x: auto; }
|
|
11051
|
-
.code .action { position: absolute; top:
|
|
11281
|
+
.code .action { position: absolute; top: 9px; right: 9px; padding: 3px 8px; font-size: 11px; }
|
|
11052
11282
|
label { display: grid; gap: 4px; margin-top: 12px; font-weight: 600; }
|
|
11053
11283
|
input[type=url], input[type=email], input[type=tel], input[type=text], textarea { width: 100%; padding: 8px 10px; border: 1px solid #cfd8d2; border-radius: 8px; font: 13px/1.4 system-ui, sans-serif; color: inherit; background: #fff; }
|
|
11054
11284
|
textarea { font-family: ui-monospace, monospace; font-size: 12px; resize: vertical; }
|
|
11055
11285
|
fieldset { margin: 16px 0 0; padding: 10px 14px; border: 1px solid #e0e6df; border-radius: 10px; }
|
|
11056
11286
|
legend { padding: 0 4px; color: #6b786f; font-size: 11px; font-weight: 550; }
|
|
11057
11287
|
fieldset label { display: flex; align-items: baseline; gap: 8px; margin-top: 4px; font-weight: 500; }
|
|
11288
|
+
/* A radio has no baseline to speak of, so it is set in the middle of the label's first line. */
|
|
11289
|
+
fieldset input { flex-shrink: 0; align-self: flex-start; width: 13px; height: 13px; font: inherit; margin-top: 4px; margin-top: calc((1lh - 13px) / 2); margin-bottom: 0; }
|
|
11058
11290
|
.error { color: #9b2c33; }
|
|
11059
11291
|
`;
|
|
11060
11292
|
function codeBlock(code) {
|
|
@@ -11116,7 +11348,7 @@ ${claims(evidence)}`;
|
|
|
11116
11348
|
root.adoptedStyleSheets = [sheet2];
|
|
11117
11349
|
const dialog = node("dialog");
|
|
11118
11350
|
const heading = node("h2", "Verify an account");
|
|
11119
|
-
const close = node("button", "
|
|
11351
|
+
const close = node("button", "", "icon");
|
|
11120
11352
|
const header = node("header");
|
|
11121
11353
|
const stamp = node("footer");
|
|
11122
11354
|
const content = node("div", "Loading\u2026", "steps");
|
|
@@ -11124,6 +11356,7 @@ ${claims(evidence)}`;
|
|
|
11124
11356
|
dialog.setAttribute("aria-labelledby", heading.id);
|
|
11125
11357
|
close.type = "button";
|
|
11126
11358
|
close.setAttribute("aria-label", "Close");
|
|
11359
|
+
close.append(closeMark());
|
|
11127
11360
|
content.setAttribute("aria-live", "polite");
|
|
11128
11361
|
stamp.append(stampLink(), node("span", version));
|
|
11129
11362
|
header.append(heading, close);
|
|
@@ -11133,9 +11366,10 @@ ${claims(evidence)}`;
|
|
|
11133
11366
|
openDialogs2.set(opener, dialog);
|
|
11134
11367
|
let returning = false;
|
|
11135
11368
|
if (back) {
|
|
11136
|
-
const before = node("button", "
|
|
11369
|
+
const before = node("button", "", "icon");
|
|
11137
11370
|
before.type = "button";
|
|
11138
11371
|
before.setAttribute("aria-label", "Back");
|
|
11372
|
+
before.append(backMark());
|
|
11139
11373
|
header.className = "backed";
|
|
11140
11374
|
header.replaceChildren(before, heading, close);
|
|
11141
11375
|
before.onclick = () => {
|
|
@@ -11410,7 +11644,7 @@ ${claims(evidence)}`;
|
|
|
11410
11644
|
const external = accountCard(
|
|
11411
11645
|
logo2 ? [logo2, document.createTextNode(flow.provider.name)] : [document.createTextNode(flow.provider.name)],
|
|
11412
11646
|
externalName(flow.external),
|
|
11413
|
-
externalId(flow.external),
|
|
11647
|
+
externalIdGroups(flow.external) ?? externalId(flow.external),
|
|
11414
11648
|
externalLink(flow.external)
|
|
11415
11649
|
);
|
|
11416
11650
|
const parts = [subjectCard(flow.local), linkMark(), external];
|
|
@@ -11561,15 +11795,19 @@ ${claims(evidence)}`;
|
|
|
11561
11795
|
},
|
|
11562
11796
|
latestGroup.get(element),
|
|
11563
11797
|
accounts,
|
|
11564
|
-
managers.get(element)
|
|
11798
|
+
managers.get(element),
|
|
11799
|
+
openHosts.has(element)
|
|
11565
11800
|
);
|
|
11566
11801
|
}
|
|
11567
11802
|
}
|
|
11568
11803
|
var stackedHosts = /* @__PURE__ */ new WeakSet();
|
|
11569
11804
|
var quietHosts = /* @__PURE__ */ new WeakSet();
|
|
11805
|
+
var openHosts = /* @__PURE__ */ new WeakSet();
|
|
11570
11806
|
var stackedAccounts = 4;
|
|
11571
11807
|
var peekedAccounts = 8;
|
|
11572
|
-
function arrange(element, { stacked, peek }) {
|
|
11808
|
+
function arrange(element, { stacked, peek, detailsOpen }) {
|
|
11809
|
+
if (detailsOpen) openHosts.add(element);
|
|
11810
|
+
else openHosts.delete(element);
|
|
11573
11811
|
if (stacked) stackedHosts.add(element);
|
|
11574
11812
|
else stackedHosts.delete(element);
|
|
11575
11813
|
if (peek === false) quietHosts.add(element);
|
|
@@ -11577,34 +11815,14 @@ ${claims(evidence)}`;
|
|
|
11577
11815
|
}
|
|
11578
11816
|
var live = (evidence) => evidence.status === "verified" && evidence.expiresAt > Date.now();
|
|
11579
11817
|
function accounts(records) {
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
11587
|
-
|
|
11588
|
-
const verified = sorted.filter(live);
|
|
11589
|
-
const base = verified[0] ?? sorted.reduce((a2, b2) => b2.approvedAt > a2.approvedAt ? b2 : a2);
|
|
11590
|
-
const external = [...base.attestations.external];
|
|
11591
|
-
for (const other of verified.slice(1))
|
|
11592
|
-
for (const attestation of other.attestations.external)
|
|
11593
|
-
if (!external.some((shown3) => shown3.method === attestation.method))
|
|
11594
|
-
external.push(attestation);
|
|
11595
|
-
return {
|
|
11596
|
-
...base,
|
|
11597
|
-
connectedAt: when(sorted[0]),
|
|
11598
|
-
attestations: { ...base.attestations, external },
|
|
11599
|
-
links: sorted.filter((e2) => e2.status !== "revoked").map((e2) => e2.id),
|
|
11600
|
-
// Every record the card speaks for, so its signature mark answers for all of them.
|
|
11601
|
-
sources: verified.length ? verified : [base]
|
|
11602
|
-
};
|
|
11603
|
-
}).sort((a2, b2) => place2(a2) - place2(b2) || a2.connectedAt - b2.connectedAt);
|
|
11604
|
-
}
|
|
11605
|
-
function place2(account) {
|
|
11606
|
-
if (account.status === "retired") return 3;
|
|
11607
|
-
return account.mark === "preferred" ? 0 : account.mark === "unused" ? 2 : 1;
|
|
11818
|
+
return accountsOf(records, Date.now()).map(({ lead, held, verified, external, connectedAt }) => ({
|
|
11819
|
+
...lead,
|
|
11820
|
+
connectedAt,
|
|
11821
|
+
attestations: { ...lead.attestations, external },
|
|
11822
|
+
links: held.filter((e2) => e2.status !== "revoked").map((e2) => e2.id),
|
|
11823
|
+
// Every record the card speaks for, so its signature mark answers for all of them.
|
|
11824
|
+
sources: verified.length ? verified : [lead]
|
|
11825
|
+
}));
|
|
11608
11826
|
}
|
|
11609
11827
|
function presentGroup(element, records, load2) {
|
|
11610
11828
|
const ordered = accounts(records.map(standing));
|
|
@@ -11617,6 +11835,8 @@ ${claims(evidence)}`;
|
|
|
11617
11835
|
const badge = renderBadge(element, lead, {
|
|
11618
11836
|
more: Math.max(verified.length - 1, 0),
|
|
11619
11837
|
linked: lead.visibility === "public",
|
|
11838
|
+
// A modified click follows the link, and must reach what a plain one shows: every account.
|
|
11839
|
+
...ordered.length > 1 ? { href: subjectUrl(lead) } : {},
|
|
11620
11840
|
rows: stacked ? verified.slice(1, stackedAccounts) : peek ? verified.slice(1, peekedAccounts) : [],
|
|
11621
11841
|
peek
|
|
11622
11842
|
});
|
|
@@ -12017,7 +12237,8 @@ ${claims(evidence)}`;
|
|
|
12017
12237
|
"handoff-url",
|
|
12018
12238
|
"connect",
|
|
12019
12239
|
"stacked",
|
|
12020
|
-
"peek"
|
|
12240
|
+
"peek",
|
|
12241
|
+
"details-open"
|
|
12021
12242
|
];
|
|
12022
12243
|
handed;
|
|
12023
12244
|
/**
|
|
@@ -12071,7 +12292,8 @@ ${claims(evidence)}`;
|
|
|
12071
12292
|
const handoffUrl = this.getAttribute("handoff-url");
|
|
12072
12293
|
const arrangement = {
|
|
12073
12294
|
stacked: this.getAttribute("stacked") !== null,
|
|
12074
|
-
peek: this.getAttribute("peek") !== "off"
|
|
12295
|
+
peek: this.getAttribute("peek") !== "off",
|
|
12296
|
+
detailsOpen: this.getAttribute("details-open") !== null
|
|
12075
12297
|
};
|
|
12076
12298
|
if (backendUrl && (handoffUrl !== null || this.getAttribute("connect") !== null)) {
|
|
12077
12299
|
const client = init({ backendUrl, handoffUrl: handoffUrl ?? void 0 });
|