@weatherboard/annotation 0.3.0 → 0.4.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/ADOPTING.md +49 -5
- package/dist/markers.cjs +11 -4
- package/dist/markers.cjs.map +3 -3
- package/dist/markers.d.cts +39 -2
- package/dist/markers.d.mts +39 -2
- package/dist/markers.d.ts +39 -2
- package/dist/markers.mjs +11 -4
- package/dist/markers.mjs.map +3 -3
- package/dist/read.cjs +1 -1
- package/dist/read.cjs.map +3 -3
- package/dist/read.d.cts +46 -1
- package/dist/read.d.mts +46 -1
- package/dist/read.d.ts +46 -1
- package/dist/read.mjs +1 -1
- package/dist/read.mjs.map +3 -3
- package/package.json +4 -4
package/ADOPTING.md
CHANGED
|
@@ -341,20 +341,36 @@ panel with the comment, who raised it, when, and what has happened to it.
|
|
|
341
341
|
|
|
342
342
|
```tsx
|
|
343
343
|
const { readToken } = readArming(); // from `ai_read`, stripped and stored
|
|
344
|
-
if (!readToken) return; // a link minted before markers shipped
|
|
345
344
|
|
|
346
345
|
const { createAnnotationReader } = await import("@weatherboard/annotation/read");
|
|
347
346
|
const { mountAnnotationMarkers } = await import("@weatherboard/annotation/markers");
|
|
348
347
|
|
|
349
348
|
const layer = mountAnnotationMarkers({
|
|
350
|
-
reader
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
349
|
+
// `reader` is a REQUIRED NULLABLE, not an optional. Mount whenever armed and
|
|
350
|
+
// pass null when there is no token — the count line then says so on the page.
|
|
351
|
+
// Returning early instead leaves an armed page blank, which is the one state
|
|
352
|
+
// this layer exists to make impossible. See "The count line is the feature".
|
|
353
|
+
reader: readToken
|
|
354
|
+
? createAnnotationReader({
|
|
355
|
+
endpoint: "https://<console>/ingest/annotations",
|
|
356
|
+
readToken,
|
|
357
|
+
})
|
|
358
|
+
: null,
|
|
354
359
|
});
|
|
355
360
|
await layer.refresh(); // and again after a route change
|
|
356
361
|
```
|
|
357
362
|
|
|
363
|
+
**Call `refresh()` even with a null reader.** It is what replaces the *"Looking
|
|
364
|
+
for annotations…"* line with *"No read credential, so annotations were not
|
|
365
|
+
requested."* Treating a null reader as "nothing to do" leaves an armed page
|
|
366
|
+
loading forever — a mistake that is not obvious from the signature, and one the
|
|
367
|
+
first adopter made.
|
|
368
|
+
|
|
369
|
+
**Treat an empty token as absent, not as a credential.** `createAnnotationReader`
|
|
370
|
+
throws on `""`, and `?ai_read=` with nothing after it is a query string anyone
|
|
371
|
+
can type. Guard on presence, or a stray character in a URL takes the whole mount
|
|
372
|
+
down and the toolbar with it.
|
|
373
|
+
|
|
358
374
|
**It is a second credential, not the capture token.** The console refuses a write
|
|
359
375
|
claim at the read endpoint and a read claim at the ingest, so handing
|
|
360
376
|
`captureToken` to the reader does not degrade to a read — it fails. The read
|
|
@@ -376,6 +392,34 @@ the read, whatever the answer: *"3 annotations here, 1 shown"*. Zero markers is
|
|
|
376
392
|
exactly what "working, nothing here" looks like and a dozen distinct causes
|
|
377
393
|
produce it, so a layer that drew only icons would be silent in every one.
|
|
378
394
|
|
|
395
|
+
**A finished capture is hidden, and the line says how many.** The console
|
|
396
|
+
suppresses `done` and `cancelled` by default, so the sentence gains a third
|
|
397
|
+
clause when it is holding something back — *"3 annotations here, 1 shown · 2
|
|
398
|
+
resolved"* — and the pill grows a button that re-reads with them included. You
|
|
399
|
+
do not have to wire either one up; both are in the layer.
|
|
400
|
+
|
|
401
|
+
The clause matters most on the page where `total` is **zero and history is
|
|
402
|
+
not**: without it, a component with three finished conversations behind it reads
|
|
403
|
+
*"No annotations on this page"*, and a reviewer who fixed something and came back
|
|
404
|
+
to check what they had said would find no evidence there had ever been anything.
|
|
405
|
+
`total` counts what the response is about, so a suppressed capture is outside it
|
|
406
|
+
and is never added in — that is what keeps *"5 annotations here, 2 shown"* from
|
|
407
|
+
appearing on a page where nothing is wrong.
|
|
408
|
+
|
|
409
|
+
Pass `showResolved: true` to start wide. The default is `false`, matching the
|
|
410
|
+
console's own default deliberately: a layer that always asked for everything
|
|
411
|
+
would move that decision to a place nobody reading the console's code would see.
|
|
412
|
+
|
|
413
|
+
**If you drive the reader yourself**, `read(path, { includeResolved })` is the
|
|
414
|
+
only way to see them, and the console honours **only** the literal
|
|
415
|
+
`?resolved=include` — `true`, `1`, `yes`, `Include` and a trailing space all get
|
|
416
|
+
the default silently. Use the option rather than building the query string.
|
|
417
|
+
|
|
418
|
+
**Overriding `labels.count`?** It now takes a third argument,
|
|
419
|
+
`(total, shown, resolvedHidden)`. A two-parameter override still compiles and
|
|
420
|
+
still works — and will not say what is being held back, which is the one thing
|
|
421
|
+
that argument is for.
|
|
422
|
+
|
|
379
423
|
**`refresh()` never rejects.** A refused CORS preflight arrives as `TypeError:
|
|
380
424
|
Failed to fetch` with no status and no body; it becomes a sentence in the count
|
|
381
425
|
line rather than an exception in your page.
|
package/dist/markers.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var B=Object.defineProperty;var te=Object.getOwnPropertyDescriptor;var re=Object.getOwnPropertyNames;var oe=Object.prototype.hasOwnProperty;var ae=(e,t)=>{for(var n in t)B(e,n,{get:t[n],enumerable:!0})},ie=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of re(t))!oe.call(e,o)&&o!==n&&B(e,o,{get:()=>t[o],enumerable:!(r=te(t,o))||r.enumerable});return e};var se=e=>ie(B({},"__esModule",{value:!0}),e);var me={};ae(me,{DEFAULT_MARKER_LABELS:()=>J,MARKERS_ID:()=>U,formatMarkerAge:()=>Q,freeSpot:()=>Z,mountAnnotationMarkers:()=>fe,placeMarkers:()=>ee});module.exports=se(me);var C="data-src";var H=8;function S(e){if(!e)return null;let t=e.lastIndexOf(":");if(t<=0)return null;let n=e.lastIndexOf(":",t-1);if(n<=0)return null;let r=e.slice(0,n),o=Number(e.slice(n+1,t)),i=Number(e.slice(t+1));return!r||!Number.isFinite(o)||!Number.isFinite(i)?null:{file:r,line:o,column:i}}function V(e,t=H){let n=[],r=e;for(;r&&n.length<t;){let o=S(r.getAttribute(C));if(o){let i=n[n.length-1];i&&i.file===o.file&&i.line===o.line||n.push(o)}r=r.parentElement}return n}function X(e){let t=e;for(;t;){if(S(t.getAttribute(C)))return t;t=t.parentElement}return null}function K(e,t){return e.file!==t.file||e.line!==t.line?!1:e.column===void 0||t.column===void 0?!0:e.column===t.column}function le(e,t){if(e.length===0)return!1;if(e.length<H){if(t.length!==e.length)return!1}else if(t.length<e.length)return!1;return e.every((n,r)=>{let o=t[r];return o!==void 0&&K(n,o)})}function ue(e,t){let n={file:e.file,line:e.line};e.column!==void 0&&(n.column=e.column);let r=t.querySelectorAll(`[${C}]`),o=[];for(let i=0;i<r.length;i++){let s=r[i],c=S(s.getAttribute(C));if(!c||!K(n,c))continue;let d=S(X(s.parentElement)?.getAttribute(C)??null);d&&K(d,c)||o.push(s)}return o}function W(e,t){switch(e.kind){case"route":{if(!e.path)return"none";let n=t.location?.pathname;return!n||n!==e.path?"none":t.body??"none"}case"dom-path":{if(!e.path)return"none";let n;try{n=t.querySelectorAll(e.path)}catch{return"none"}return n.length===0?"none":n.length>1?"ambiguous":n[0]}case"source-ref":{if(e.chain.length===0)return"none";let n=ue(e,t).filter(r=>le(e.chain,V(r)));return n.length===0?"none":n.length>1?"ambiguous":n[0]}default:return"none"}}var U="ai-annotation-markers",ce="2147483002",J={region:"Annotations on this page",count:(e,t,n)=>{let r=e===0?"No annotations on this page":`${e} annotation${e===1?"":"s"} here, ${t} shown`;return n>0?`${r} \xB7 ${n} resolved`:r},showResolved:e=>`Show ${e} resolved annotation${e===1?"":"s"}`,hideResolved:"Hide resolved annotations",loading:"Looking for annotations\u2026",refused:e=>e==="retired-link"?"This annotation link is an older format the console no longer accepts. Open Request changes again.":e==="rate-limited"?"The console is rate-limiting this page's reads. Wait a moment.":"The console refused this page's read.",unreachable:"Could not reach the console for this page's annotations.",noCredential:"No read credential, so annotations were not requested.",asOf:e=>`status as of ${e} ago`,freshnessUnknown:"the console cannot say how fresh these statuses are",close:"Close"},F={total:0,shown:0,ambiguous:0,unresolved:0,anchored:0,resolvedHidden:0,showingResolved:!1,clusters:0,asOf:"",line:""},de=`
|
|
2
2
|
:host{
|
|
3
3
|
--ai-bg:#fff;
|
|
4
4
|
--ai-fg:#18181b;
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
--ai-radius-pill:999px;
|
|
20
20
|
--ai-pin:22px;
|
|
21
21
|
--ai-edge:16px;
|
|
22
|
-
all:initial;position:fixed;inset:0;z-index:${
|
|
22
|
+
all:initial;position:fixed;inset:0;z-index:${ce};pointer-events:none;
|
|
23
23
|
font:13px/1.45 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
|
|
24
24
|
color:var(--ai-fg);color-scheme:light}
|
|
25
25
|
*,*::before,*::after{box-sizing:border-box}
|
|
@@ -28,7 +28,14 @@
|
|
|
28
28
|
position:absolute;left:var(--ai-edge);bottom:var(--ai-edge);pointer-events:auto;
|
|
29
29
|
background:var(--ai-invert-bg);color:var(--ai-invert-fg);
|
|
30
30
|
border-radius:var(--ai-radius-pill);
|
|
31
|
-
padding:var(--ai-space-2) var(--ai-space-5);max-width:min(60vw,420px)
|
|
31
|
+
padding:var(--ai-space-2) var(--ai-space-5);max-width:min(60vw,420px);
|
|
32
|
+
display:flex;align-items:center;gap:var(--ai-space-3);flex-wrap:wrap}
|
|
33
|
+
.toggle{
|
|
34
|
+
pointer-events:auto;font:inherit;font-size:12px;white-space:nowrap;
|
|
35
|
+
background:var(--ai-invert-bg);color:var(--ai-invert-fg);
|
|
36
|
+
border:1px solid var(--ai-invert-fg);border-radius:var(--ai-radius-pill);
|
|
37
|
+
padding:0 var(--ai-space-3);cursor:pointer}
|
|
38
|
+
.toggle:focus-visible{outline:2px solid var(--ai-invert-fg);outline-offset:2px}
|
|
32
39
|
.pin{
|
|
33
40
|
position:absolute;pointer-events:auto;
|
|
34
41
|
width:var(--ai-pin);height:var(--ai-pin);
|
|
@@ -53,5 +60,5 @@
|
|
|
53
60
|
background:var(--ai-bg);color:var(--ai-fg);border:1px solid var(--ai-line);
|
|
54
61
|
border-radius:var(--ai-radius-control);
|
|
55
62
|
padding:var(--ai-space-1) var(--ai-space-4);cursor:pointer}
|
|
56
|
-
`,
|
|
63
|
+
`,T=22,v=4,G=(e,t,n)=>Math.min(Math.max(e,t),n),Y=T+2,pe=128;function Z(e,t,n){let{left:r,top:o}=e,i=(s,c)=>t.some(d=>Math.abs(d.left-s)<T&&Math.abs(d.top-c)<T);for(let s=0;s<pe;s+=1){if(!i(r,o))return{left:r,top:o};if(o+=Y,o>n&&(o=v,r-=Y,r<v))break}return{left:e.left,top:e.top}}function u(e,t,n){let r=e.createElement(t);if(n)for(let o of Object.keys(n))r.setAttribute(o,n[o]??"");return r}function Q(e){let t=Math.max(0,Math.floor(e/1e3));if(t<60)return`${t}s`;let n=Math.floor(t/60);if(n<60)return`${n}m`;let r=Math.floor(n/60);if(r<24){let s=n%60;return s===0?`${r}h`:`${r}h ${s}m`}let o=Math.floor(r/24),i=r%24;return i===0?`${o}d`:`${o}d ${i}h`}function ee(e,t){let n=new Map,r=0,o=0;for(let i of e){let s=W(i.anchor,t);if(s==="ambiguous"){r+=1;continue}if(s==="none"){o+=1;continue}let c=n.get(s);c?c.push(i):n.set(s,[i])}return{clusters:[...n].map(([i,s])=>({element:i,markers:s})),ambiguous:r,unresolved:o}}function fe(e){let t={...J,...e.labels};if(e.armed===!1)return{refresh:()=>Promise.resolve(F),owns:()=>!1,last:()=>null,destroy:()=>{}};let n=e.doc??document,r=e.win??n.defaultView??window,o=e.now??Date.now,i=u(n,"div",{id:U}),s=i.attachShadow({mode:"open"}),c=u(n,"style");c.textContent=de,s.appendChild(c);let d=u(n,"style");s.appendChild(d);let O=u(n,"div",{class:"count",role:"status","aria-label":t.region}),k=u(n,"span",{class:"count-text"});k.textContent=t.loading,O.appendChild(k);let A=u(n,"button",{type:"button",class:"toggle",hidden:""});O.appendChild(A),s.appendChild(O);let h=u(n,"div",{class:"panel",role:"dialog","aria-modal":"false","aria-label":t.region,hidden:""});s.appendChild(h),n.body.appendChild(i);let M=null,E=[],N=!1,R=e.showResolved===!0;function _(a){if(R)A.textContent=t.hideResolved;else if(a>0)A.textContent=t.showResolved(a);else{A.setAttribute("hidden",""),A.textContent="";return}A.setAttribute("aria-pressed",R?"true":"false"),A.removeAttribute("hidden")}function P(){if(E.length===0){d.textContent="";return}let a=r.innerWidth||0,p=r.innerHeight||0,g=[],b=[];E.forEach(({element:w},l)=>{let y=w.getBoundingClientRect(),f=G(Math.round(y.right-11),v,Math.max(v,a-T-v)),m=G(Math.round(y.top-11),v,Math.max(v,p-T-v)),x=Z({left:f,top:m},g,p-T-v);g.push(x),b.push(`.pin[data-i="${l}"]{left:${x.left}px;top:${x.top}px}`)}),d.textContent=b.join("")}let L=()=>{N||P()};r.addEventListener("scroll",L,!0),r.addEventListener("resize",L);function I(){for(h.setAttribute("hidden","");h.firstChild;)h.removeChild(h.firstChild)}function ne(a,p){I();for(let f of a){let m=u(n,"div",{class:"entry"}),x=u(n,"p",{class:"who"}),D=f.createdAt?new Date(f.createdAt):null;x.textContent=D!==null&&!Number.isNaN(D.getTime())?`${f.reviewer} \xB7 ${D.toISOString().slice(0,10)}`:f.reviewer,m.appendChild(x);let j=u(n,"p",{class:"what"});j.textContent=f.comment,m.appendChild(j);let q=u(n,"p",{class:"state"});q.textContent=f.status.display,m.appendChild(q),h.appendChild(m)}let g=u(n,"p",{class:"fresh"}),b=M?.asOf??"",w=b===""?NaN:Date.parse(b);g.textContent=Number.isNaN(w)?t.freshnessUnknown:t.asOf(Q(o()-w)),h.appendChild(g);let l=u(n,"button",{type:"button",class:"close"});l.textContent=t.close,l.addEventListener("click",()=>I()),h.appendChild(l);let y=p.getBoundingClientRect();d.textContent=`${d.textContent??""}.panel{left:${Math.round(Math.max(8,y.right-320))}px;top:${Math.round(y.top+20)}px}`,h.removeAttribute("hidden")}function $(a,p){for(let{pin:l}of E)l.remove();if(E=[],I(),a===null){k.textContent=p??t.unreachable,_(0);let l={...F,showingResolved:R,line:k.textContent};return M=l,P(),l}let g=ee(a.annotations,n),b=0;g.clusters.forEach((l,y)=>{let f=l.element,m=u(n,"button",{type:"button",class:"pin","data-i":String(y),"aria-label":`${l.markers.length} annotation${l.markers.length===1?"":"s"}`});m.textContent=l.markers.length===1?"1":String(l.markers.length),m.addEventListener("click",x=>{x.preventDefault(),x.stopPropagation(),ne(l.markers,f)}),s.appendChild(m),E.push({pin:m,element:f}),b+=l.markers.length}),k.textContent=a.ok||a.reason===void 0?t.count(a.total,b,a.resolvedHidden):t.refused(a.reason),_(a.resolvedHidden);let w={total:a.total,shown:b,ambiguous:g.ambiguous,unresolved:g.unresolved,anchored:a.anchored,resolvedHidden:a.resolvedHidden,showingResolved:R,clusters:g.clusters.length,asOf:a.asOf,line:k.textContent??""};return M=w,P(),w}A.addEventListener("click",a=>{a.preventDefault(),a.stopPropagation(),!N&&(R=!R,_(M?.resolvedHidden??0),k.textContent=t.loading,z.refresh())});let z={async refresh(){if(N)return F;if(e.reader===null)return $(null,t.noCredential);let a=e.path??n.location?.pathname??"/";try{let p=await e.reader.read(a,{includeResolved:R});return $(p,null)}catch{return $(null,t.unreachable)}},owns(a){if(a===i)return!0;let p=a;return typeof p?.closest=="function"?p.closest(`#${U}`)===i:!1},last:()=>M,destroy(){N=!0,r.removeEventListener("scroll",L,!0),r.removeEventListener("resize",L);for(let{pin:a}of E)a.remove();E=[],i.remove()}};return z}
|
|
57
64
|
//# sourceMappingURL=markers.cjs.map
|