@bkazemi/verily 0.9.2 → 0.9.3
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
CHANGED
|
@@ -168,7 +168,7 @@ import { init } from '@bkazemi/verily';
|
|
|
168
168
|
const client = init({ backendUrl: '/api/verily' });
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
Without one, serve `node_modules/@bkazemi/verily/dist/verily.js` yourself, or load it from a CDN such as `https://cdn.jsdelivr.net/npm/@bkazemi/verily@0.9.
|
|
171
|
+
Without one, serve `node_modules/@bkazemi/verily/dist/verily.js` yourself, or load it from a CDN such as `https://cdn.jsdelivr.net/npm/@bkazemi/verily@0.9.3/dist/verily.js`. The script defines a global `Verily`.
|
|
172
172
|
|
|
173
173
|
Then place the badge wherever the account appears:
|
|
174
174
|
|
|
@@ -370,7 +370,7 @@ A static site only needs the script and the badge markup; the backend runs somew
|
|
|
370
370
|
|
|
371
371
|
```html
|
|
372
372
|
<script
|
|
373
|
-
src="https://cdn.jsdelivr.net/npm/@bkazemi/verily@0.9.
|
|
373
|
+
src="https://cdn.jsdelivr.net/npm/@bkazemi/verily@0.9.3/dist/verily.js"
|
|
374
374
|
defer
|
|
375
375
|
></script>
|
|
376
376
|
<verily-badge
|
|
@@ -115,6 +115,7 @@ renew) {
|
|
|
115
115
|
const header = node('header');
|
|
116
116
|
const stamp = node('footer');
|
|
117
117
|
const content = node('div', 'Loading…', 'steps');
|
|
118
|
+
const pane = node('div', '', 'pane');
|
|
118
119
|
heading.id = 'verily-connect-title';
|
|
119
120
|
dialog.setAttribute('aria-labelledby', heading.id);
|
|
120
121
|
close.type = 'button';
|
|
@@ -123,7 +124,8 @@ renew) {
|
|
|
123
124
|
content.setAttribute('aria-live', 'polite');
|
|
124
125
|
stamp.append(stampLink(), node('span', version));
|
|
125
126
|
header.append(heading, close);
|
|
126
|
-
|
|
127
|
+
pane.append(header, content, stamp);
|
|
128
|
+
dialog.append(pane);
|
|
127
129
|
root.append(dialog);
|
|
128
130
|
document.body.append(host);
|
|
129
131
|
openDialogs.set(opener, dialog);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Evidence, type ExternalAccount } from '../core/index.js';
|
|
2
2
|
/** The logotype as a link to the project, as both dialogs carry it in their footer. */
|
|
3
3
|
export declare function stampLink(): HTMLAnchorElement;
|
|
4
|
-
export declare const styles = "\n * { box-sizing: border-box; }\n dialog { width: min(460px, calc(100vw - 32px)); max-height: calc(100dvh - 40px); margin: auto; padding:
|
|
4
|
+
export declare const styles = "\n * { box-sizing: border-box; }\n dialog { width: min(460px, calc(100vw - 32px)); max-height: calc(100dvh - 40px); margin: auto; padding: 0; overflow: hidden; border: 1px solid #dce2de; border-radius: 16px; background: #fff; color: #23312b; box-shadow: 0 24px 90px #10201935; font: 13px/1.6 system-ui, sans-serif; }\n /* The pane scrolls inside the dialog, which clips its scrollbar to the rounded corners. */\n dialog[open] { display: flex; flex-direction: column; }\n .pane { min-height: 0; padding: 24px; overflow-y: auto; }\n dialog::backdrop { background: #15271f66; }\n header { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 20px; }\n h2 { margin: 0; font-size: 18px; font-weight: 650; letter-spacing: -.3px; }\n button { width: 32px; height: 32px; border: 1px solid #dce2de; border-radius: 8px; background: #fff; color: #52645a; font: 20px system-ui, sans-serif; cursor: pointer; }\n button:hover { background: #f2f5f1; }\n .icon { display: grid; place-items: center; padding: 0; }\n .icon svg { width: 16px; height: 16px; }\n .title { display: flex; align-items: center; gap: 6px; min-width: 0; }\n .all { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 8px; color: #52645a; }\n .all:hover { background: #f2f5f1; }\n .all svg { width: 16px; height: 16px; }\n a { color: #245f43; text-underline-offset: 3px; overflow-wrap: anywhere; }\n a:focus-visible, button:focus-visible, summary:focus-visible { outline: 2px solid #357ce5; outline-offset: 3px; }\n /* An element given its own display would otherwise go on showing while hidden. */\n [hidden] { display: none !important; }\n .summary { display: flex; align-items: center; gap: 8px; margin-top: 16px; }\n .mark { width: 36px; height: 36px; flex-shrink: 0; }\n .provider { width: 14px; height: 14px; }\n .state { font-size: 14px; font-weight: 650; line-height: 1.4; }\n .muted { color: #6b786f; font-size: 12px; }\n .account { position: relative; }\n .veiled > :not(.checking) { filter: blur(4px); opacity: .55; user-select: none; }\n .checking { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 8px; color: #23312b; font-size: 13px; font-weight: 600; }\n .spinner { width: 14px; height: 14px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin .7s linear infinite; }\n @keyframes spin { to { transform: rotate(360deg); } }\n @media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }\n /* The \"signed\" pill after the verifier's name, one size smaller than the line it sits on. */\n .summary .signed { display: inline-block; margin-left: 5px; padding: 0 6px; border: 1px solid #cfdcd3; border-radius: 999px; font-size: 10px; font-weight: 550; line-height: 1.3; text-decoration: none; vertical-align: 1px; }\n .summary a.signed:hover { background: #f2f5f1; }\n .summary .signed.bad { border-color: #b3261e; color: #b3261e; font-weight: 650; cursor: help; }\n .caution { display: inline-block; margin-left: 3px; color: #a15c00; vertical-align: -1.5px; }\n .caution svg { display: block; width: 10px; height: 10px; }\n .account { padding: 14px 16px; border: 1px solid #e0e6df; border-radius: 10px; margin-top: 12px; }\n .account h3 { display: flex; align-items: center; gap: 6px; margin: 0 0 3px; color: #6b786f; font-size: 11px; font-weight: 550; }\n .account a, .account strong { font-weight: 650; font-size: 14px; }\n /* The account's own name carries that weight; a link inside a line of prose does not. */\n .summary a, .method a, .additional a { font: inherit; }\n .reference { margin-top: 2px; }\n /* A fingerprint in fours: it breaks between groups, and copies as one unbroken word. */\n .fingerprint { font-family: ui-monospace, monospace; text-wrap: balance; }\n .fingerprint span { display: inline-block; margin-right: .5ch; }\n .method { margin-top: 8px; }\n /* In the corner the heading leaves empty, apart from everything that was checked. */\n .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; }\n .listing.preferred { border-color: #245f43; color: #245f43; }\n /* Quiet, as its pill is: the surface and the name step back, and the controls do not. */\n .account.retired { background: #f6f8f5; }\n .account.retired > a, .account.retired > strong, .account.retired > .named > a, .account.retired > .named > strong { color: #6b786f; }\n /* The name, then a dot and the account's creation date. The date wraps under a long name. */\n /* Clipped 4px left of the text, which hides the dot when the date wraps to a new line. */\n .named { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 14px; margin-left: -4px; padding-left: 4px; overflow-x: clip; }\n .since { position: relative; white-space: nowrap; }\n /* The dot sits in the gap before the date. */\n .since::before { content: \"\u00B7\"; position: absolute; left: -7px; transform: translateX(-50%); }\n .account.retired .mark { opacity: .45; }\n .group { margin: 20px 0 0; color: #6b786f; font-size: 11px; font-weight: 550; }\n summary.group { display: flex; align-items: center; gap: 4px; width: fit-content; border-radius: 4px; list-style: none; cursor: pointer; }\n summary::-webkit-details-marker { display: none; }\n .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; }\n .fold svg, summary svg { width: 12px; height: 12px; }\n .fold[aria-expanded=\"true\"] svg, details[open] > summary svg { transform: rotate(90deg); }\n @media (prefers-reduced-motion: no-preference) { .fold svg, summary svg { transition: transform .15s; } }\n /* The fold and what the holder may do share a line, until a question needs the whole of it. */\n .bar { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 10px; }\n .account .bar .row { margin: 0 0 0 auto; }\n .additional { margin-top: 2px; padding-left: 12px; }\n .joiner { display: block; width: 20px; height: 20px; margin: 8px auto -4px; color: #90a096; }\n 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; }\n dt { color: #6b786f; }\n dd { margin: 0; text-align: right; overflow-wrap: anywhere; }\n .explanation { margin-top: 16px; }\n .action { width: auto; height: auto; padding: 9px 14px; font: 600 13px/1.3 system-ui, sans-serif; color: #23312b; text-align: left; }\n .action.primary { border-color: #245f43; background: #245f43; color: #fff; }\n .action.primary:hover { background: #1d4f37; }\n .action:disabled { opacity: .6; cursor: progress; }\n .action.danger:hover { border-color: #b3261e; background: #fdecea; color: #b3261e; }\n .row { display: flex; justify-content: end; gap: 8px; margin-top: 16px; }\n .account .row { align-items: center; justify-content: start; flex-wrap: wrap; margin-top: 12px; }\n .account .action { padding: 5px 10px; font-size: 12px; }\n .account .action.dots { display: grid; place-items: center; align-self: stretch; width: 30px; padding: 0; }\n .dots svg { width: 16px; height: 16px; }\n /* Placed under its button each time it opens, above the dialog and clipped by none of it. */\n .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; }\n .menu:popover-open { display: grid; }\n .account .menu .action { border: 0; border-radius: 6px; padding: 6px 10px; font-weight: 550; }\n .menu .danger { color: #b3261e; }\n .menu hr { width: 100%; margin: 4px 0; border: 0; border-top: 1px solid #e5e9e3; }\n footer { display: flex; align-items: center; justify-content: start; gap: 6px; margin: 20px 0 -8px; color: #9aa9a0; font-size: 11px; }\n footer a { display: flex; color: inherit; }\n .logo { display: block; height: 13px; }\n \n @media (prefers-reduced-motion: no-preference) {\n .mark.current path:last-child { animation: verily-draw .8s cubic-bezier(.65, 0, .35, 1) .1s backwards; }\n }\n @keyframes verily-draw { from { stroke-dasharray: 0 176; } to { stroke-dasharray: 108 176; } }\n\n";
|
|
5
5
|
export declare function node<K extends keyof HTMLElementTagNameMap>(tag: K, text?: string, className?: string): HTMLElementTagNameMap[K];
|
|
6
6
|
/**
|
|
7
7
|
* Points an anchor out of the dialog. Every link here opens in a new tab: the dialog is
|
|
@@ -13,7 +13,10 @@ export function stampLink() {
|
|
|
13
13
|
const openDialogs = new WeakMap();
|
|
14
14
|
export const styles = `
|
|
15
15
|
* { box-sizing: border-box; }
|
|
16
|
-
dialog { width: min(460px, calc(100vw - 32px)); max-height: calc(100dvh - 40px); margin: auto; padding:
|
|
16
|
+
dialog { width: min(460px, calc(100vw - 32px)); max-height: calc(100dvh - 40px); margin: auto; padding: 0; overflow: hidden; border: 1px solid #dce2de; border-radius: 16px; background: #fff; color: #23312b; box-shadow: 0 24px 90px #10201935; font: 13px/1.6 system-ui, sans-serif; }
|
|
17
|
+
/* The pane scrolls inside the dialog, which clips its scrollbar to the rounded corners. */
|
|
18
|
+
dialog[open] { display: flex; flex-direction: column; }
|
|
19
|
+
.pane { min-height: 0; padding: 24px; overflow-y: auto; }
|
|
17
20
|
dialog::backdrop { background: #15271f66; }
|
|
18
21
|
header { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 20px; }
|
|
19
22
|
h2 { margin: 0; font-size: 18px; font-weight: 650; letter-spacing: -.3px; }
|
|
@@ -337,7 +340,7 @@ function actionsMenu(more, choices) {
|
|
|
337
340
|
if (bottom > innerHeight - edge)
|
|
338
341
|
menu.style.top = `${Math.max(edge, more.getBoundingClientRect().top - gap - height)}px`;
|
|
339
342
|
// It does not follow its button, so it does not stay open once the button moves.
|
|
340
|
-
menu.closest('
|
|
343
|
+
menu.closest('.pane')?.addEventListener('scroll', shut, { once: true });
|
|
341
344
|
choices[0].focus();
|
|
342
345
|
});
|
|
343
346
|
menu.addEventListener('click', shut);
|
|
@@ -766,6 +769,7 @@ detailsOpen = false) {
|
|
|
766
769
|
// What drew the record, under it. The record is about the pair, not about us.
|
|
767
770
|
const stamp = node('footer');
|
|
768
771
|
const content = node('div', 'Checking verification…');
|
|
772
|
+
const pane = node('div', '', 'pane');
|
|
769
773
|
heading.id = 'verily-dialog-title';
|
|
770
774
|
dialog.setAttribute('aria-labelledby', heading.id);
|
|
771
775
|
close.type = 'button';
|
|
@@ -778,7 +782,8 @@ detailsOpen = false) {
|
|
|
778
782
|
close.autofocus = true;
|
|
779
783
|
title.append(heading);
|
|
780
784
|
header.append(title, close);
|
|
781
|
-
|
|
785
|
+
pane.append(header, content, stamp);
|
|
786
|
+
dialog.append(pane);
|
|
782
787
|
/** Links removed from this dialog, shown as removed before the page hands over new records. */
|
|
783
788
|
const removed = new Map();
|
|
784
789
|
/**
|
package/dist/verily.js
CHANGED
|
@@ -10520,7 +10520,7 @@ ${claims(evidence)}`;
|
|
|
10520
10520
|
}
|
|
10521
10521
|
|
|
10522
10522
|
// src/version.ts
|
|
10523
|
-
var version = "v0.9.
|
|
10523
|
+
var version = "v0.9.3";
|
|
10524
10524
|
|
|
10525
10525
|
// src/browser/evidence-dialog.ts
|
|
10526
10526
|
function stampLink() {
|
|
@@ -10531,7 +10531,10 @@ ${claims(evidence)}`;
|
|
|
10531
10531
|
var openDialogs = /* @__PURE__ */ new WeakMap();
|
|
10532
10532
|
var styles2 = `
|
|
10533
10533
|
* { box-sizing: border-box; }
|
|
10534
|
-
dialog { width: min(460px, calc(100vw - 32px)); max-height: calc(100dvh - 40px); margin: auto; padding:
|
|
10534
|
+
dialog { width: min(460px, calc(100vw - 32px)); max-height: calc(100dvh - 40px); margin: auto; padding: 0; overflow: hidden; border: 1px solid #dce2de; border-radius: 16px; background: #fff; color: #23312b; box-shadow: 0 24px 90px #10201935; font: 13px/1.6 system-ui, sans-serif; }
|
|
10535
|
+
/* The pane scrolls inside the dialog, which clips its scrollbar to the rounded corners. */
|
|
10536
|
+
dialog[open] { display: flex; flex-direction: column; }
|
|
10537
|
+
.pane { min-height: 0; padding: 24px; overflow-y: auto; }
|
|
10535
10538
|
dialog::backdrop { background: #15271f66; }
|
|
10536
10539
|
header { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 20px; }
|
|
10537
10540
|
h2 { margin: 0; font-size: 18px; font-weight: 650; letter-spacing: -.3px; }
|
|
@@ -10799,7 +10802,7 @@ ${claims(evidence)}`;
|
|
|
10799
10802
|
const { height, bottom } = menu.getBoundingClientRect();
|
|
10800
10803
|
if (bottom > innerHeight - edge)
|
|
10801
10804
|
menu.style.top = `${Math.max(edge, more.getBoundingClientRect().top - gap - height)}px`;
|
|
10802
|
-
menu.closest("
|
|
10805
|
+
menu.closest(".pane")?.addEventListener("scroll", shut, { once: true });
|
|
10803
10806
|
choices[0].focus();
|
|
10804
10807
|
});
|
|
10805
10808
|
menu.addEventListener("click", shut);
|
|
@@ -11134,6 +11137,7 @@ ${record2.external.id}`;
|
|
|
11134
11137
|
const header = node("header");
|
|
11135
11138
|
const stamp = node("footer");
|
|
11136
11139
|
const content = node("div", "Checking verification\u2026");
|
|
11140
|
+
const pane = node("div", "", "pane");
|
|
11137
11141
|
heading.id = "verily-dialog-title";
|
|
11138
11142
|
dialog.setAttribute("aria-labelledby", heading.id);
|
|
11139
11143
|
close.type = "button";
|
|
@@ -11145,7 +11149,8 @@ ${record2.external.id}`;
|
|
|
11145
11149
|
close.autofocus = true;
|
|
11146
11150
|
title.append(heading);
|
|
11147
11151
|
header.append(title, close);
|
|
11148
|
-
|
|
11152
|
+
pane.append(header, content, stamp);
|
|
11153
|
+
dialog.append(pane);
|
|
11149
11154
|
const removed = /* @__PURE__ */ new Map();
|
|
11150
11155
|
const listed = [];
|
|
11151
11156
|
const listing = (record2) => JSON.stringify([record2.status, record2.mark, record2.retiredAt, record2.approvedAt]);
|
|
@@ -11385,6 +11390,7 @@ ${record2.external.id}`;
|
|
|
11385
11390
|
const header = node("header");
|
|
11386
11391
|
const stamp = node("footer");
|
|
11387
11392
|
const content = node("div", "Loading\u2026", "steps");
|
|
11393
|
+
const pane = node("div", "", "pane");
|
|
11388
11394
|
heading.id = "verily-connect-title";
|
|
11389
11395
|
dialog.setAttribute("aria-labelledby", heading.id);
|
|
11390
11396
|
close.type = "button";
|
|
@@ -11393,7 +11399,8 @@ ${record2.external.id}`;
|
|
|
11393
11399
|
content.setAttribute("aria-live", "polite");
|
|
11394
11400
|
stamp.append(stampLink(), node("span", version));
|
|
11395
11401
|
header.append(heading, close);
|
|
11396
|
-
|
|
11402
|
+
pane.append(header, content, stamp);
|
|
11403
|
+
dialog.append(pane);
|
|
11397
11404
|
root.append(dialog);
|
|
11398
11405
|
document.body.append(host);
|
|
11399
11406
|
openDialogs2.set(opener, dialog);
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED