@thessor/widget 0.1.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 +94 -0
- package/dist/index.d.ts +28 -0
- package/dist/logo.d.ts +2 -0
- package/dist/styles.d.ts +1 -0
- package/dist/theme.d.ts +7 -0
- package/dist/thessor-widget.js +578 -0
- package/dist/thessor-widget.js.map +7 -0
- package/dist/thessor-widget.umd.js +403 -0
- package/dist/thessor-widget.umd.js.map +7 -0
- package/dist/types.d.ts +8 -0
- package/package.json +42 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
"use strict";(()=>{var c=`
|
|
2
|
+
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap');
|
|
3
|
+
|
|
4
|
+
:host {
|
|
5
|
+
all: initial;
|
|
6
|
+
display: inline-block;
|
|
7
|
+
font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
8
|
+
-webkit-font-smoothing: antialiased;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
* {
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.root {
|
|
16
|
+
position: relative;
|
|
17
|
+
display: inline-block;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.badge {
|
|
21
|
+
display: inline-flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
gap: 11px;
|
|
24
|
+
padding: 10px 14px;
|
|
25
|
+
border-radius: 10px;
|
|
26
|
+
border: 1px solid var(--tw-border, rgba(0, 0, 0, 0.12));
|
|
27
|
+
background: var(--tw-bg, #ffffff);
|
|
28
|
+
color: var(--tw-fg, #16171a);
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
font-size: 13px;
|
|
31
|
+
font-weight: 500;
|
|
32
|
+
line-height: 1.2;
|
|
33
|
+
user-select: none;
|
|
34
|
+
transition: border-color 150ms ease, background 150ms ease;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.badge:hover {
|
|
38
|
+
border-color: var(--tw-border-hover, rgba(0, 0, 0, 0.22));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.badge:focus-visible {
|
|
42
|
+
outline: 2px solid #6c8cf5;
|
|
43
|
+
outline-offset: 2px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:host([data-theme='dark']) .badge,
|
|
47
|
+
.root.theme-dark .badge {
|
|
48
|
+
--tw-bg: #17181c;
|
|
49
|
+
--tw-fg: #f3f3f5;
|
|
50
|
+
--tw-border: rgba(255, 255, 255, 0.14);
|
|
51
|
+
--tw-border-hover: rgba(255, 255, 255, 0.26);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.dot {
|
|
55
|
+
width: 8px;
|
|
56
|
+
height: 8px;
|
|
57
|
+
border-radius: 50%;
|
|
58
|
+
background: #2fbf6c;
|
|
59
|
+
flex-shrink: 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.dot.dot-muted {
|
|
63
|
+
background: #9a9aa2;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.dot.dot-loading {
|
|
67
|
+
animation: pulse 1.4s ease-in-out infinite;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.logo {
|
|
71
|
+
display: inline-flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
flex-shrink: 0;
|
|
74
|
+
height: 16px;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.logo-img {
|
|
78
|
+
display: block;
|
|
79
|
+
height: 100%;
|
|
80
|
+
width: auto;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.logo-dark {
|
|
84
|
+
display: none;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
:host([data-theme='dark']) .logo-light,
|
|
88
|
+
.root.theme-dark .logo-light {
|
|
89
|
+
display: none;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
:host([data-theme='dark']) .logo-dark,
|
|
93
|
+
.root.theme-dark .logo-dark {
|
|
94
|
+
display: block;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.label {
|
|
98
|
+
white-space: nowrap;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.label .muted-text {
|
|
102
|
+
color: var(--tw-fg);
|
|
103
|
+
opacity: 0.6;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* --- Proof panel --- */
|
|
107
|
+
|
|
108
|
+
.panel-wrapper {
|
|
109
|
+
display: grid;
|
|
110
|
+
grid-template-rows: 0fr;
|
|
111
|
+
transition: grid-template-rows 220ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
112
|
+
position: absolute;
|
|
113
|
+
top: calc(100% + 8px);
|
|
114
|
+
left: 0;
|
|
115
|
+
width: max-content;
|
|
116
|
+
min-width: 320px;
|
|
117
|
+
max-width: min(380px, 92vw);
|
|
118
|
+
z-index: 2147483000;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.panel-wrapper.open {
|
|
122
|
+
grid-template-rows: 1fr;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.panel-inner {
|
|
126
|
+
overflow: hidden;
|
|
127
|
+
min-height: 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.panel {
|
|
131
|
+
background: #0b0b0e;
|
|
132
|
+
color: #f3f3f5;
|
|
133
|
+
border-radius: 14px;
|
|
134
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
135
|
+
padding: 16px;
|
|
136
|
+
opacity: 0;
|
|
137
|
+
transform: scale(0.96);
|
|
138
|
+
transform-origin: top left;
|
|
139
|
+
transition: opacity 220ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
140
|
+
transform 220ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
141
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.panel-wrapper.open .panel {
|
|
145
|
+
opacity: 1;
|
|
146
|
+
transform: scale(1);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@media (prefers-reduced-motion: reduce) {
|
|
150
|
+
.panel-wrapper,
|
|
151
|
+
.panel {
|
|
152
|
+
transition: none !important;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.panel-header {
|
|
157
|
+
display: flex;
|
|
158
|
+
align-items: center;
|
|
159
|
+
justify-content: space-between;
|
|
160
|
+
margin-bottom: 14px;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.panel-title {
|
|
164
|
+
font-size: 13px;
|
|
165
|
+
font-weight: 600;
|
|
166
|
+
letter-spacing: 0.01em;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.live-indicator {
|
|
170
|
+
display: inline-flex;
|
|
171
|
+
align-items: center;
|
|
172
|
+
gap: 6px;
|
|
173
|
+
font-size: 11px;
|
|
174
|
+
color: #6adf9a;
|
|
175
|
+
font-weight: 500;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.live-dot {
|
|
179
|
+
width: 6px;
|
|
180
|
+
height: 6px;
|
|
181
|
+
border-radius: 50%;
|
|
182
|
+
background: #2fbf6c;
|
|
183
|
+
box-shadow: 0 0 0 0 rgba(47, 191, 108, 0.5);
|
|
184
|
+
animation: live-pulse 2s ease-out infinite;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
@keyframes live-pulse {
|
|
188
|
+
0% {
|
|
189
|
+
box-shadow: 0 0 0 0 rgba(47, 191, 108, 0.45);
|
|
190
|
+
}
|
|
191
|
+
70% {
|
|
192
|
+
box-shadow: 0 0 0 6px rgba(47, 191, 108, 0);
|
|
193
|
+
}
|
|
194
|
+
100% {
|
|
195
|
+
box-shadow: 0 0 0 0 rgba(47, 191, 108, 0);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@media (prefers-reduced-motion: reduce) {
|
|
200
|
+
.live-dot {
|
|
201
|
+
animation: none;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* stage chain */
|
|
206
|
+
|
|
207
|
+
.stage-chain {
|
|
208
|
+
display: grid;
|
|
209
|
+
grid-template-columns: auto 1fr auto 1fr auto 1fr auto;
|
|
210
|
+
row-gap: 8px;
|
|
211
|
+
margin-bottom: 16px;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.stage-dot {
|
|
215
|
+
grid-row: 1;
|
|
216
|
+
align-self: center;
|
|
217
|
+
width: 10px;
|
|
218
|
+
height: 10px;
|
|
219
|
+
border-radius: 50%;
|
|
220
|
+
flex-shrink: 0;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.stage-track {
|
|
224
|
+
grid-row: 1;
|
|
225
|
+
align-self: center;
|
|
226
|
+
height: 2px;
|
|
227
|
+
min-width: 14px;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.stage-label {
|
|
231
|
+
grid-row: 2;
|
|
232
|
+
font-size: 10px;
|
|
233
|
+
text-align: center;
|
|
234
|
+
color: rgba(255, 255, 255, 0.6);
|
|
235
|
+
line-height: 1.3;
|
|
236
|
+
padding: 0 2px;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* data rows */
|
|
240
|
+
|
|
241
|
+
.rows {
|
|
242
|
+
display: flex;
|
|
243
|
+
flex-direction: column;
|
|
244
|
+
gap: 9px;
|
|
245
|
+
padding: 12px 0;
|
|
246
|
+
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
|
247
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.row {
|
|
251
|
+
display: flex;
|
|
252
|
+
align-items: baseline;
|
|
253
|
+
justify-content: space-between;
|
|
254
|
+
gap: 12px;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.row-label {
|
|
258
|
+
font-size: 11px;
|
|
259
|
+
color: rgba(255, 255, 255, 0.5);
|
|
260
|
+
flex-shrink: 0;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.row-value {
|
|
264
|
+
font-family: 'IBM Plex Mono', ui-monospace, monospace;
|
|
265
|
+
font-size: 11px;
|
|
266
|
+
color: #f3f3f5;
|
|
267
|
+
text-align: right;
|
|
268
|
+
overflow-wrap: anywhere;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/* footer */
|
|
272
|
+
|
|
273
|
+
.panel-footer {
|
|
274
|
+
display: flex;
|
|
275
|
+
align-items: center;
|
|
276
|
+
justify-content: space-between;
|
|
277
|
+
margin-top: 12px;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.view-link {
|
|
281
|
+
font-size: 12px;
|
|
282
|
+
color: #a3b4f7;
|
|
283
|
+
text-decoration: none;
|
|
284
|
+
font-weight: 500;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.view-link:hover {
|
|
288
|
+
text-decoration: underline;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.watermark {
|
|
292
|
+
font-size: 10px;
|
|
293
|
+
color: rgba(255, 255, 255, 0.28);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* skeleton */
|
|
297
|
+
|
|
298
|
+
.skeleton-line {
|
|
299
|
+
height: 10px;
|
|
300
|
+
border-radius: 4px;
|
|
301
|
+
background: linear-gradient(
|
|
302
|
+
90deg,
|
|
303
|
+
rgba(255, 255, 255, 0.06) 25%,
|
|
304
|
+
rgba(255, 255, 255, 0.14) 37%,
|
|
305
|
+
rgba(255, 255, 255, 0.06) 63%
|
|
306
|
+
);
|
|
307
|
+
background-size: 400% 100%;
|
|
308
|
+
animation: shimmer 1.4s ease infinite;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
@keyframes shimmer {
|
|
312
|
+
0% {
|
|
313
|
+
background-position: 100% 50%;
|
|
314
|
+
}
|
|
315
|
+
100% {
|
|
316
|
+
background-position: 0 50%;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
@keyframes pulse {
|
|
321
|
+
0%, 100% {
|
|
322
|
+
opacity: 1;
|
|
323
|
+
}
|
|
324
|
+
50% {
|
|
325
|
+
opacity: 0.4;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
@media (prefers-reduced-motion: reduce) {
|
|
330
|
+
.skeleton-line,
|
|
331
|
+
.dot-loading {
|
|
332
|
+
animation: none;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.error-message {
|
|
337
|
+
font-size: 12px;
|
|
338
|
+
color: rgba(255, 255, 255, 0.65);
|
|
339
|
+
padding: 8px 0 4px;
|
|
340
|
+
line-height: 1.5;
|
|
341
|
+
}
|
|
342
|
+
`;var g="data:image/png;base64,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";var h="data:image/png;base64,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";var f=g,u=h;function x(i){let a=i.match(/rgba?\(([^)]+)\)/);if(!a||!a[1])return null;let e=a[1].split(",").map(n=>parseFloat(n.trim())),[t,o,r,s]=e;return t===void 0||o===void 0||r===void 0||[t,o,r].some(n=>Number.isNaN(n))||s===0?null:(.2126*t+.7152*o+.0722*r)/255}function m(i){let a=i.getAttribute("data-theme");if(a==="light"||a==="dark")return a;let e=i.parentElement;for(;e;){let t=x(getComputedStyle(e).backgroundColor);if(t!==null)return t<.5?"dark":"light";e=e.parentElement}return"light"}var p=[{label:"Hashed",color:"#6C8CF5"},{label:"Signed (ML-DSA-65)",color:"#8E84F2"},{label:"Merkle checkpoint",color:"#A186EF"},{label:"Bitcoin",color:"#B189EC"}],y="https://api.thessor.com/verify",$="https://thessor.com/verify";function l(i){let a=document.createElement("div");return a.textContent=i,a.innerHTML}function k(i){let a=new Date(i);return Number.isNaN(a.getTime())?i:a.toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"})}function b(){let i="";p.forEach((e,t)=>{i+=`<span class="stage-dot" style="background:${e.color}"></span>`;let o=p[t+1];o&&(i+=`<span class="stage-track" style="background:linear-gradient(to right, ${e.color}, ${o.color})"></span>`)});let a=p.map((e,t)=>`<span class="stage-label" style="grid-column:${t*2+1}">${l(e.label)}</span>`).join("");return i+a}var d=class extends HTMLElement{constructor(){super();this.state="loading";this.proof=null;this.isOpen=!1;this.abortController=null;this.hasRendered=!1;this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.applyTheme(),this.fetchProof()}disconnectedCallback(){this.abortController?.abort()}attributeChangedCallback(e){this.hasRendered&&(e==="data-theme"&&this.applyTheme(),e==="decision-id"&&this.fetchProof())}applyTheme(){let e=m(this),t=this.shadow.querySelector(".root");t?.classList.toggle("theme-dark",e==="dark"),t?.classList.toggle("theme-light",e==="light")}async fetchProof(){let e=this.getAttribute("decision-id");if(this.abortController?.abort(),!e){this.setState("error");return}this.setState("loading");let t=new AbortController;this.abortController=t;try{let o=await fetch(`${y}/${encodeURIComponent(e)}`,{signal:t.signal});if(!o.ok)throw new Error(`Request failed with status ${o.status}`);let r=await o.json();this.proof=r,this.setState("success")}catch(o){if(o instanceof DOMException&&o.name==="AbortError")return;this.proof=null,this.setState("error")}}setState(e){this.state=e,this.renderBadgeContent(),this.renderPanelContent()}togglePanel(){this.isOpen=!this.isOpen,this.shadow.querySelector(".panel-wrapper")?.classList.toggle("open",this.isOpen),this.shadow.querySelector(".badge")?.setAttribute("aria-expanded",String(this.isOpen))}render(){this.shadow.innerHTML=`
|
|
343
|
+
<style>${c}</style>
|
|
344
|
+
<div class="root">
|
|
345
|
+
<button type="button" class="badge" part="badge" aria-expanded="false" aria-haspopup="true">
|
|
346
|
+
<span class="dot dot-loading"></span>
|
|
347
|
+
<span class="label">Verified \xB7 Sealed by Thessor</span>
|
|
348
|
+
<span class="logo">
|
|
349
|
+
<img class="logo-img logo-light" src="${f}" alt="Thessor" />
|
|
350
|
+
<img class="logo-img logo-dark" src="${u}" alt="Thessor" />
|
|
351
|
+
</span>
|
|
352
|
+
</button>
|
|
353
|
+
<div class="panel-wrapper">
|
|
354
|
+
<div class="panel-inner">
|
|
355
|
+
<div class="panel" role="region" aria-label="Thessor verification proof">
|
|
356
|
+
<div class="panel-content"></div>
|
|
357
|
+
</div>
|
|
358
|
+
</div>
|
|
359
|
+
</div>
|
|
360
|
+
</div>
|
|
361
|
+
`,this.shadow.querySelector(".badge")?.addEventListener("click",()=>this.togglePanel()),this.hasRendered=!0,this.renderBadgeContent(),this.renderPanelContent()}renderBadgeContent(){let e=this.shadow.querySelector(".dot"),t=this.shadow.querySelector(".label");!e||!t||(e.className="dot",this.state==="error"?(e.classList.add("dot-muted"),t.innerHTML='<span class="muted-text">Unable to verify</span>'):(this.state==="loading"&&e.classList.add("dot-loading"),t.textContent="Verified \xB7 Sealed by Thessor"))}renderPanelContent(){let e=this.shadow.querySelector(".panel-content");if(!e)return;let t=l(this.getAttribute("decision-id")??""),o=`
|
|
362
|
+
<div class="panel-header">
|
|
363
|
+
<span class="panel-title">Verification Proof</span>
|
|
364
|
+
<span class="live-indicator"><span class="live-dot"></span>Verified</span>
|
|
365
|
+
</div>
|
|
366
|
+
`,r=n=>`
|
|
367
|
+
<div class="panel-footer">
|
|
368
|
+
${n?`<a class="view-link" href="${$}/${t}" target="_blank" rel="noopener noreferrer">View full proof \u2192</a>`:"<span></span>"}
|
|
369
|
+
<span class="watermark">thessor.com</span>
|
|
370
|
+
</div>
|
|
371
|
+
`;if(this.state==="loading"){e.innerHTML=`
|
|
372
|
+
${o}
|
|
373
|
+
<div class="stage-chain">${b()}</div>
|
|
374
|
+
<div class="rows">
|
|
375
|
+
<div class="skeleton-line" style="width: 90%"></div>
|
|
376
|
+
<div class="skeleton-line" style="width: 70%"></div>
|
|
377
|
+
<div class="skeleton-line" style="width: 55%"></div>
|
|
378
|
+
</div>
|
|
379
|
+
${r(!1)}
|
|
380
|
+
`;return}if(this.state==="error"){e.innerHTML=`
|
|
381
|
+
${o}
|
|
382
|
+
<p class="error-message">We couldn't reach Thessor to verify this credential right now. This doesn't necessarily mean it's invalid \u2014 please try again shortly.</p>
|
|
383
|
+
${r(!!this.getAttribute("decision-id"))}
|
|
384
|
+
`;return}let s=this.proof;s&&(e.innerHTML=`
|
|
385
|
+
${o}
|
|
386
|
+
<div class="stage-chain">${b()}</div>
|
|
387
|
+
<div class="rows">
|
|
388
|
+
<div class="row">
|
|
389
|
+
<span class="row-label">Envelope ID</span>
|
|
390
|
+
<span class="row-value">${l(s.envelope_id)}</span>
|
|
391
|
+
</div>
|
|
392
|
+
<div class="row">
|
|
393
|
+
<span class="row-label">Sealed</span>
|
|
394
|
+
<span class="row-value">${l(k(s.created_at))}</span>
|
|
395
|
+
</div>
|
|
396
|
+
<div class="row">
|
|
397
|
+
<span class="row-label">Signature suite</span>
|
|
398
|
+
<span class="row-value">${l(s.signature_suite)}</span>
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
401
|
+
${r(!0)}
|
|
402
|
+
`)}};d.observedAttributes=["decision-id","data-theme"];customElements.get("thessor-badge")||customElements.define("thessor-badge",d);})();
|
|
403
|
+
//# sourceMappingURL=thessor-widget.umd.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/styles.ts", "../src/logo.ts", "../src/theme.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["export const styles = `\n@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap');\n\n:host {\n all: initial;\n display: inline-block;\n font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;\n -webkit-font-smoothing: antialiased;\n}\n\n* {\n box-sizing: border-box;\n}\n\n.root {\n position: relative;\n display: inline-block;\n}\n\n.badge {\n display: inline-flex;\n align-items: center;\n gap: 11px;\n padding: 10px 14px;\n border-radius: 10px;\n border: 1px solid var(--tw-border, rgba(0, 0, 0, 0.12));\n background: var(--tw-bg, #ffffff);\n color: var(--tw-fg, #16171a);\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.2;\n user-select: none;\n transition: border-color 150ms ease, background 150ms ease;\n}\n\n.badge:hover {\n border-color: var(--tw-border-hover, rgba(0, 0, 0, 0.22));\n}\n\n.badge:focus-visible {\n outline: 2px solid #6c8cf5;\n outline-offset: 2px;\n}\n\n:host([data-theme='dark']) .badge,\n.root.theme-dark .badge {\n --tw-bg: #17181c;\n --tw-fg: #f3f3f5;\n --tw-border: rgba(255, 255, 255, 0.14);\n --tw-border-hover: rgba(255, 255, 255, 0.26);\n}\n\n.dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #2fbf6c;\n flex-shrink: 0;\n}\n\n.dot.dot-muted {\n background: #9a9aa2;\n}\n\n.dot.dot-loading {\n animation: pulse 1.4s ease-in-out infinite;\n}\n\n.logo {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n height: 16px;\n}\n\n.logo-img {\n display: block;\n height: 100%;\n width: auto;\n}\n\n.logo-dark {\n display: none;\n}\n\n:host([data-theme='dark']) .logo-light,\n.root.theme-dark .logo-light {\n display: none;\n}\n\n:host([data-theme='dark']) .logo-dark,\n.root.theme-dark .logo-dark {\n display: block;\n}\n\n.label {\n white-space: nowrap;\n}\n\n.label .muted-text {\n color: var(--tw-fg);\n opacity: 0.6;\n}\n\n/* --- Proof panel --- */\n\n.panel-wrapper {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows 220ms cubic-bezier(0.4, 0, 0.2, 1);\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n width: max-content;\n min-width: 320px;\n max-width: min(380px, 92vw);\n z-index: 2147483000;\n}\n\n.panel-wrapper.open {\n grid-template-rows: 1fr;\n}\n\n.panel-inner {\n overflow: hidden;\n min-height: 0;\n}\n\n.panel {\n background: #0b0b0e;\n color: #f3f3f5;\n border-radius: 14px;\n border: 1px solid rgba(255, 255, 255, 0.08);\n padding: 16px;\n opacity: 0;\n transform: scale(0.96);\n transform-origin: top left;\n transition: opacity 220ms cubic-bezier(0.4, 0, 0.2, 1),\n transform 220ms cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);\n}\n\n.panel-wrapper.open .panel {\n opacity: 1;\n transform: scale(1);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .panel-wrapper,\n .panel {\n transition: none !important;\n }\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 14px;\n}\n\n.panel-title {\n font-size: 13px;\n font-weight: 600;\n letter-spacing: 0.01em;\n}\n\n.live-indicator {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: #6adf9a;\n font-weight: 500;\n}\n\n.live-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #2fbf6c;\n box-shadow: 0 0 0 0 rgba(47, 191, 108, 0.5);\n animation: live-pulse 2s ease-out infinite;\n}\n\n@keyframes live-pulse {\n 0% {\n box-shadow: 0 0 0 0 rgba(47, 191, 108, 0.45);\n }\n 70% {\n box-shadow: 0 0 0 6px rgba(47, 191, 108, 0);\n }\n 100% {\n box-shadow: 0 0 0 0 rgba(47, 191, 108, 0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .live-dot {\n animation: none;\n }\n}\n\n/* stage chain */\n\n.stage-chain {\n display: grid;\n grid-template-columns: auto 1fr auto 1fr auto 1fr auto;\n row-gap: 8px;\n margin-bottom: 16px;\n}\n\n.stage-dot {\n grid-row: 1;\n align-self: center;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.stage-track {\n grid-row: 1;\n align-self: center;\n height: 2px;\n min-width: 14px;\n}\n\n.stage-label {\n grid-row: 2;\n font-size: 10px;\n text-align: center;\n color: rgba(255, 255, 255, 0.6);\n line-height: 1.3;\n padding: 0 2px;\n}\n\n/* data rows */\n\n.rows {\n display: flex;\n flex-direction: column;\n gap: 9px;\n padding: 12px 0;\n border-top: 1px solid rgba(255, 255, 255, 0.08);\n border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n}\n\n.row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 12px;\n}\n\n.row-label {\n font-size: 11px;\n color: rgba(255, 255, 255, 0.5);\n flex-shrink: 0;\n}\n\n.row-value {\n font-family: 'IBM Plex Mono', ui-monospace, monospace;\n font-size: 11px;\n color: #f3f3f5;\n text-align: right;\n overflow-wrap: anywhere;\n}\n\n/* footer */\n\n.panel-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-top: 12px;\n}\n\n.view-link {\n font-size: 12px;\n color: #a3b4f7;\n text-decoration: none;\n font-weight: 500;\n}\n\n.view-link:hover {\n text-decoration: underline;\n}\n\n.watermark {\n font-size: 10px;\n color: rgba(255, 255, 255, 0.28);\n}\n\n/* skeleton */\n\n.skeleton-line {\n height: 10px;\n border-radius: 4px;\n background: linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0.06) 25%,\n rgba(255, 255, 255, 0.14) 37%,\n rgba(255, 255, 255, 0.06) 63%\n );\n background-size: 400% 100%;\n animation: shimmer 1.4s ease infinite;\n}\n\n@keyframes shimmer {\n 0% {\n background-position: 100% 50%;\n }\n 100% {\n background-position: 0 50%;\n }\n}\n\n@keyframes pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.4;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .skeleton-line,\n .dot-loading {\n animation: none;\n }\n}\n\n.error-message {\n font-size: 12px;\n color: rgba(255, 255, 255, 0.65);\n padding: 8px 0 4px;\n line-height: 1.5;\n}\n`;\n", "import logoBlack from './assets/thessor-logo-black.png';\nimport logoWhite from './assets/thessor-logo-white.png';\n\n// Real Thessor cube-grid mark, bundled as inlined data URIs so the widget\n// stays a single file (no separate asset requests when loaded via CDN).\nexport const THESSOR_LOGO_LIGHT = logoBlack; // black mark, for light-background hosts\nexport const THESSOR_LOGO_DARK = logoWhite; // white mark, for dark-background hosts\n", "import type { ThemeMode } from './types';\n\n/**\n * Coarse perceptual lightness from an rgb()/rgba() computed-style string.\n * Not the sRGB-linearized WCAG formula \u2014 we only need a light/dark call,\n * not an accessibility contrast ratio.\n */\nfunction parseRgbLightness(color: string): number | null {\n const match = color.match(/rgba?\\(([^)]+)\\)/);\n if (!match || !match[1]) return null;\n const parts = match[1].split(',').map((p) => parseFloat(p.trim()));\n const [r, g, b, a] = parts;\n if (r === undefined || g === undefined || b === undefined) return null;\n if ([r, g, b].some((n) => Number.isNaN(n))) return null;\n if (a === 0) return null;\n return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;\n}\n\n/**\n * Walks up from the host element looking for the nearest ancestor with a\n * non-transparent background-color to decide light vs. dark. A\n * `data-theme` attribute on the badge itself always wins.\n */\nexport function detectHostTheme(el: HTMLElement): ThemeMode {\n const override = el.getAttribute('data-theme');\n if (override === 'light' || override === 'dark') return override;\n\n let node: Element | null = el.parentElement;\n while (node) {\n const lightness = parseRgbLightness(getComputedStyle(node).backgroundColor);\n if (lightness !== null) return lightness < 0.5 ? 'dark' : 'light';\n node = node.parentElement;\n }\n return 'light';\n}\n", "import { styles } from './styles';\nimport { THESSOR_LOGO_LIGHT, THESSOR_LOGO_DARK } from './logo';\nimport { detectHostTheme } from './theme';\nimport type { BadgeState, ProofData } from './types';\n\nconst STAGES: Array<{ label: string; color: string }> = [\n { label: 'Hashed', color: '#6C8CF5' },\n { label: 'Signed (ML-DSA-65)', color: '#8E84F2' },\n { label: 'Merkle checkpoint', color: '#A186EF' },\n { label: 'Bitcoin', color: '#B189EC' },\n];\n\nconst API_BASE = 'https://api.thessor.com/verify';\nconst PROOF_BASE = 'https://thessor.com/verify';\n\nfunction escapeHtml(value: string): string {\n const div = document.createElement('div');\n div.textContent = value;\n return div.innerHTML;\n}\n\nfunction formatTimestamp(iso: string): string {\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) return iso;\n return date.toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' });\n}\n\nfunction renderStageChainMarkup(): string {\n let row = '';\n STAGES.forEach((stage, i) => {\n row += `<span class=\"stage-dot\" style=\"background:${stage.color}\"></span>`;\n const next = STAGES[i + 1];\n if (next) {\n row += `<span class=\"stage-track\" style=\"background:linear-gradient(to right, ${stage.color}, ${next.color})\"></span>`;\n }\n });\n const labels = STAGES.map(\n (stage, i) => `<span class=\"stage-label\" style=\"grid-column:${i * 2 + 1}\">${escapeHtml(stage.label)}</span>`\n ).join('');\n return row + labels;\n}\n\n/**\n * Framework-agnostic verification badge. Renders a pill showing Thessor's\n * verification status; clicking it expands an inline proof panel populated\n * from `GET /verify/{decision-id}`.\n *\n * Usage: <thessor-badge decision-id=\"env_...\"></thessor-badge>\n * Theme override: <thessor-badge decision-id=\"...\" data-theme=\"dark\">\n */\nexport class ThessorBadge extends HTMLElement {\n static observedAttributes = ['decision-id', 'data-theme'];\n\n private shadow: ShadowRoot;\n private state: BadgeState = 'loading';\n private proof: ProofData | null = null;\n private isOpen = false;\n private abortController: AbortController | null = null;\n private hasRendered = false;\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'open' });\n }\n\n connectedCallback(): void {\n this.render();\n this.applyTheme();\n void this.fetchProof();\n }\n\n disconnectedCallback(): void {\n this.abortController?.abort();\n }\n\n attributeChangedCallback(name: string): void {\n if (!this.hasRendered) return;\n if (name === 'data-theme') this.applyTheme();\n if (name === 'decision-id') void this.fetchProof();\n }\n\n private applyTheme(): void {\n const theme = detectHostTheme(this);\n const root = this.shadow.querySelector('.root');\n root?.classList.toggle('theme-dark', theme === 'dark');\n root?.classList.toggle('theme-light', theme === 'light');\n }\n\n private async fetchProof(): Promise<void> {\n const id = this.getAttribute('decision-id');\n this.abortController?.abort();\n\n if (!id) {\n this.setState('error');\n return;\n }\n\n this.setState('loading');\n const controller = new AbortController();\n this.abortController = controller;\n\n try {\n const res = await fetch(`${API_BASE}/${encodeURIComponent(id)}`, { signal: controller.signal });\n if (!res.ok) throw new Error(`Request failed with status ${res.status}`);\n const data = (await res.json()) as ProofData;\n this.proof = data;\n this.setState('success');\n } catch (err) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n this.proof = null;\n this.setState('error');\n }\n }\n\n private setState(state: BadgeState): void {\n this.state = state;\n this.renderBadgeContent();\n this.renderPanelContent();\n }\n\n private togglePanel(): void {\n this.isOpen = !this.isOpen;\n this.shadow.querySelector('.panel-wrapper')?.classList.toggle('open', this.isOpen);\n this.shadow.querySelector('.badge')?.setAttribute('aria-expanded', String(this.isOpen));\n }\n\n private render(): void {\n this.shadow.innerHTML = `\n <style>${styles}</style>\n <div class=\"root\">\n <button type=\"button\" class=\"badge\" part=\"badge\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"dot dot-loading\"></span>\n <span class=\"label\">Verified \u00B7 Sealed by Thessor</span>\n <span class=\"logo\">\n <img class=\"logo-img logo-light\" src=\"${THESSOR_LOGO_LIGHT}\" alt=\"Thessor\" />\n <img class=\"logo-img logo-dark\" src=\"${THESSOR_LOGO_DARK}\" alt=\"Thessor\" />\n </span>\n </button>\n <div class=\"panel-wrapper\">\n <div class=\"panel-inner\">\n <div class=\"panel\" role=\"region\" aria-label=\"Thessor verification proof\">\n <div class=\"panel-content\"></div>\n </div>\n </div>\n </div>\n </div>\n `;\n this.shadow.querySelector('.badge')?.addEventListener('click', () => this.togglePanel());\n this.hasRendered = true;\n this.renderBadgeContent();\n this.renderPanelContent();\n }\n\n private renderBadgeContent(): void {\n const dot = this.shadow.querySelector('.dot');\n const label = this.shadow.querySelector('.label');\n if (!dot || !label) return;\n\n dot.className = 'dot';\n if (this.state === 'error') {\n dot.classList.add('dot-muted');\n label.innerHTML = `<span class=\"muted-text\">Unable to verify</span>`;\n } else {\n if (this.state === 'loading') dot.classList.add('dot-loading');\n label.textContent = 'Verified \u00B7 Sealed by Thessor';\n }\n }\n\n private renderPanelContent(): void {\n const content = this.shadow.querySelector('.panel-content');\n if (!content) return;\n\n const id = escapeHtml(this.getAttribute('decision-id') ?? '');\n const header = `\n <div class=\"panel-header\">\n <span class=\"panel-title\">Verification Proof</span>\n <span class=\"live-indicator\"><span class=\"live-dot\"></span>Verified</span>\n </div>\n `;\n const footer = (linkable: boolean) => `\n <div class=\"panel-footer\">\n ${\n linkable\n ? `<a class=\"view-link\" href=\"${PROOF_BASE}/${id}\" target=\"_blank\" rel=\"noopener noreferrer\">View full proof \u2192</a>`\n : '<span></span>'\n }\n <span class=\"watermark\">thessor.com</span>\n </div>\n `;\n\n if (this.state === 'loading') {\n content.innerHTML = `\n ${header}\n <div class=\"stage-chain\">${renderStageChainMarkup()}</div>\n <div class=\"rows\">\n <div class=\"skeleton-line\" style=\"width: 90%\"></div>\n <div class=\"skeleton-line\" style=\"width: 70%\"></div>\n <div class=\"skeleton-line\" style=\"width: 55%\"></div>\n </div>\n ${footer(false)}\n `;\n return;\n }\n\n if (this.state === 'error') {\n content.innerHTML = `\n ${header}\n <p class=\"error-message\">We couldn't reach Thessor to verify this credential right now. This doesn't necessarily mean it's invalid \u2014 please try again shortly.</p>\n ${footer(Boolean(this.getAttribute('decision-id')))}\n `;\n return;\n }\n\n const proof = this.proof;\n if (!proof) return;\n\n content.innerHTML = `\n ${header}\n <div class=\"stage-chain\">${renderStageChainMarkup()}</div>\n <div class=\"rows\">\n <div class=\"row\">\n <span class=\"row-label\">Envelope ID</span>\n <span class=\"row-value\">${escapeHtml(proof.envelope_id)}</span>\n </div>\n <div class=\"row\">\n <span class=\"row-label\">Sealed</span>\n <span class=\"row-value\">${escapeHtml(formatTimestamp(proof.created_at))}</span>\n </div>\n <div class=\"row\">\n <span class=\"row-label\">Signature suite</span>\n <span class=\"row-value\">${escapeHtml(proof.signature_suite)}</span>\n </div>\n </div>\n ${footer(true)}\n `;\n }\n}\n\nif (!customElements.get('thessor-badge')) {\n customElements.define('thessor-badge', ThessorBadge);\n}\n"],
|
|
5
|
+
"mappings": "mBAAO,IAAMA,EAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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",
|
|
6
|
+
"names": ["styles", "THESSOR_LOGO_LIGHT", "thessor_logo_black_default", "THESSOR_LOGO_DARK", "thessor_logo_white_default", "parseRgbLightness", "color", "match", "parts", "p", "r", "g", "b", "a", "detectHostTheme", "el", "override", "node", "lightness", "STAGES", "API_BASE", "PROOF_BASE", "escapeHtml", "value", "div", "formatTimestamp", "iso", "date", "renderStageChainMarkup", "row", "stage", "i", "next", "labels", "ThessorBadge", "name", "theme", "detectHostTheme", "root", "id", "controller", "res", "data", "err", "state", "styles", "THESSOR_LOGO_LIGHT", "THESSOR_LOGO_DARK", "dot", "label", "content", "header", "footer", "linkable", "proof"]
|
|
7
|
+
}
|
package/dist/types.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thessor/widget",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Framework-agnostic verification badge web component for Thessor.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/thessor-widget.js",
|
|
7
|
+
"module": "dist/thessor-widget.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"unpkg": "dist/thessor-widget.umd.js",
|
|
10
|
+
"jsdelivr": "dist/thessor-widget.umd.js",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/thessor-widget.js",
|
|
15
|
+
"default": "./dist/thessor-widget.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"sideEffects": true,
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "node scripts/build.mjs && tsc -p tsconfig.json --emitDeclarationOnly",
|
|
24
|
+
"dev": "node scripts/build.mjs --watch",
|
|
25
|
+
"demo": "npx --yes serve -l 4173 ."
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"web-components",
|
|
29
|
+
"custom-elements",
|
|
30
|
+
"thessor",
|
|
31
|
+
"verification",
|
|
32
|
+
"badge"
|
|
33
|
+
],
|
|
34
|
+
"license": "UNLICENSED",
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"esbuild": "^0.28.1",
|
|
40
|
+
"typescript": "^5.6.0"
|
|
41
|
+
}
|
|
42
|
+
}
|