@continuous-excellence/ze-great-dashboard-aws 0.13.0 → 0.13.2
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/client/.vite/manifest.json +2 -2
- package/client/assets/index-BgvnHC8t.js +3 -0
- package/client/assets/index-BgvnHC8t.js.map +1 -0
- package/client/assets/index-TlrdchAy.css +1 -0
- package/client/index.html +2 -2
- package/package.json +1 -1
- package/client/assets/index-D8cI_ztS.css +0 -1
- package/client/assets/index-cbQ9A1zL.js +0 -3
- package/client/assets/index-cbQ9A1zL.js.map +0 -1
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{z as e}from"zod";import{StrictMode as t,useEffect as n,useRef as r,useState as i,useSyncExternalStore as a}from"react";import{createRoot as o}from"react-dom/client";import{Fragment as s,jsx as c,jsxs as l}from"react/jsx-runtime";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var u=/^(\d+)(ms|s|m|h)$/,d={ms:1,s:1e3,m:6e4,h:36e5};function f(e){let t=u.exec(e);if(!t)return null;let[,n,r]=t;if(n===void 0||r===void 0)return null;let i=Number(n);return i<=0?null:i*d[r]}var p=e.string().refine(e=>f(e)!==null,{message:`must be a positive duration like "30s", "5m", or "1h"`}).brand(),ee=e.object({x:e.number().int().min(0),y:e.number().int().min(0),w:e.number().int().min(1).max(12),h:e.number().int().min(1)}),te=e.string().min(1),m=[`radial`,`runway`,`orbit`,`signal-field`,`telemetry-bloom`,`release-transit`,`status-weather`],ne=e.enum([...m,`off`]),re=e.looseObject({label:e.string().min(1).optional(),id:e.string().min(1),type:e.string().min(1),source:e.string().min(1).optional(),display:te.optional(),position:ee.optional(),refresh:p.optional(),running_animation:ne.optional(),link:e.url().optional(),url:e.url().optional(),json_path:e.string().regex(/^\$(?:\.[A-Za-z_][A-Za-z0-9_]*|\[\d+\])*$/,`must be a simple JSON path`).optional()}),ie=e.looseObject({type:e.string().min(1),token_env:e.string().min(1).optional()}),ae=e.object({refresh:p.optional(),panels:e.array(re).min(1).superRefine((e,t)=>{let n=new Map;e.forEach((e,r)=>{let i=n.get(e.id);if(i===void 0){n.set(e.id,r);return}t.addIssue({code:`custom`,path:[r,`id`],message:`duplicate panel id "${e.id}" (already used by panel at index ${i})`})})})}),oe=e.object({issuer:e.url(),client_id:e.string().min(1).optional(),allow:e.object({groups:e.array(e.string().min(1)).optional(),subjects:e.array(e.string().min(1)).optional()}).optional()});e.object({sources:e.record(e.string().min(1),ie).default({}),boards:e.record(e.string().min(1),ae),auth:oe.optional()});function se(e){let t=e.panelOverrideMillis??e.boardDefaultMillis;return Math.max(t,e.adapterFloorMillis)}var h=e.object({assetPath:e.string().min(1),proxyPath:e.string().min(1),board:e.string().min(1),clientVersion:e.string().min(1),auth:e.object({issuer:e.string().min(1),clientId:e.string().min(1).optional()}).optional()}),ce=h.pick({assetPath:!0,clientVersion:!0});function le(t=globalThis.window?.env){let n=h.safeParse(t);if(!n.success)throw Error(`window.env is missing or invalid \u2014 the server did not inject usable configuration.
|
|
2
|
+
${e.prettifyError(n.error)}`);return n.data}var ue=e.enum([`unreachable`,`unauthorized`,`not-found`,`no-runs`,`upstream-error`]),de=e.object({kind:ue,message:e.string()}),fe=e.discriminatedUnion(`state`,[e.object({panelId:e.string().min(1),state:e.literal(`ok`),observedAt:e.iso.datetime(),link:e.url().nullable(),signal:e.unknown()}),e.object({panelId:e.string().min(1),state:e.literal(`error`),observedAt:e.iso.datetime(),link:e.url().nullable(),error:de})]),g=e.object({type:e.literal(`pipeline-status`),status:e.enum([`passed`,`failed`,`running`,`cancelled`,`unknown`]),rawStatus:e.string(),name:e.string().min(1),branch:e.string().min(1).optional(),durationMs:e.number().int().nonnegative().optional(),runStartedAt:e.iso.datetime().optional(),estimatedDurationMs:e.number().int().positive().optional(),sourceUpdatedAt:e.iso.datetime().optional()}),_=e.object({label:e.string().min(1),status:g.shape.status,detail:e.string().min(1),link:e.url().nullable()}),v=e.object({type:e.literal(`pull-request-health`),status:g.shape.status,summary:e.string().min(1),workflows:e.array(_),pullRequests:e.array(_)}),pe=e.object({type:e.literal(`http-value`),value:e.union([e.string(),e.number(),e.boolean()])}),y={board:`_board_76d7l_1`,header:`_header_76d7l_11`,title:`_title_76d7l_18`,grid:`_grid_76d7l_24`,footer:`_footer_76d7l_34`},b={diagnostics:`_diagnostics_lseur_1`,button:`_button_lseur_5`,area:`_area_lseur_14`,warning:`_warning_lseur_31`,panels:`_panels_lseur_35`,actions:`_actions_lseur_43`};function me({log:e}){let[t,n]=i(!1);a(e.subscribe,e.snapshot,e.snapshot);let r=e.count(),o=e.summary();return l(`section`,{className:b.diagnostics,children:[l(`button`,{className:b.button,type:`button`,"aria-expanded":t,onClick:()=>n(!t),children:[`Diagnostics (`,r,`)`]}),t&&l(`div`,{className:b.area,children:[l(`p`,{children:[`Client `,e.clientVersion(),` · assets `,e.assetPath()]}),l(`p`,{children:[o.retained.eventCount,` retained browser-local events across`,` `,o.retained.sessionCount,` session`,o.retained.sessionCount===1?``:`s`,o.retained.firstEventAt&&o.retained.lastEventAt?` (${he(o.retained.firstEventAt,o.retained.lastEventAt)})`:``,`. They are never uploaded.`]}),o.retained.evidenceMayBeIncomplete&&l(`p`,{className:b.warning,role:`alert`,children:[`Earlier evidence was pruned: `,o.retained.retention.eventsPrunedByCount,` at the 2,000-event cap and `,o.retained.retention.eventsPrunedByAge,` by the 7-day age limit. “No failures” applies only to the retained window.`]}),l(`p`,{children:[`Update failures: `,o.failures.clientUpdate,`; board fetch failures:`,` `,o.failures.boardFetch,`.`]}),o.panels.length>0&&c(`div`,{className:b.panels,children:o.panels.map(e=>l(`p`,{children:[c(`strong`,{children:e.panelId}),` — `,e.requests,` requests`,Object.keys(e.httpStatuses).length?`; HTTP ${Object.entries(e.httpStatuses).map(([e,t])=>`${e}×${t}`).join(`, `)}`:``,`; parse/network failures `,e.parseFailures,`/`,e.networkFailures,`; visible changes `,e.visibleStateChanges,`; latest`,` `,e.latestRendered?`${e.latestRendered.state}${e.latestRendered.status?`/${e.latestRendered.status}`:``}`:`not rendered`,`.`]},e.panelId))}),l(`div`,{className:b.actions,children:[c(`button`,{className:b.button,type:`button`,onClick:()=>{let t=new Blob([JSON.stringify(e.export(),null,2)],{type:`application/json`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`dashboard-diagnostics-${new Date().toISOString().replaceAll(`:`,`-`)}.json`,r.click(),URL.revokeObjectURL(n)},children:`Download`}),c(`button`,{className:b.button,type:`button`,onClick:()=>{window.confirm(`Clear this browser’s retained dashboard diagnostics?`)&&e.clear()},children:`Clear`})]})]})]})}function he(e,t){return e===t?e:`${e} to ${t}`}function ge(e,t){let n=new Map,r=new Set,i=0,a=0;for(let t of e){if(r.add(t.sessionId),t.kind===`client-update-failure`&&i++,(t.kind===`board-fetch-failure`||t.kind===`board-fetch-parse-failure`)&&a++,!(`panelId`in t))continue;let e=n.get(t.panelId)??{panelId:t.panelId,requests:0,httpStatuses:{},parseFailures:0,networkFailures:0,visibleStateChanges:0};if(t.kind===`panel-fetch-start`&&e.requests++,t.kind===`panel-fetch-response`&&t.status!==void 0){let n=String(t.status);e.httpStatuses[n]=(e.httpStatuses[n]??0)+1}t.kind===`panel-fetch-parse-failure`&&e.parseFailures++,t.kind===`panel-fetch-failure`&&e.networkFailures++,t.kind===`panel-rendered`&&(e.visibleStateChanges++,e.latestRendered=t.rendered),n.set(t.panelId,e)}let o=e.map(e=>e.at).sort(),s=t.eventsPrunedByAge+t.eventsPrunedByCount;return{retained:{eventCount:e.length,firstEventAt:o[0],lastEventAt:o.at(-1),sessionCount:r.size,retention:t,evidenceMayBeIncomplete:s>0},failures:{clientUpdate:i,boardFetch:a},panels:[...n.values()].sort((e,t)=>e.panelId.localeCompare(t.panelId))}}var x=`ze-great-dashboard.diagnostics.v1`,_e=2e3,ve=6048e5,ye=[`session-start`,`client-update-check`,`client-update-failure`,`client-update-detected`,`board-fetch-start`,`board-fetch-response`,`board-fetch-parse-failure`,`board-fetch-failure`,`panel-fetch-start`,`panel-fetch-response`,`panel-fetch-parse-failure`,`panel-fetch-failure`,`panel-rendered`],be=class{env;storage;now;events=[];retention=C();revision=0;listeners=new Set;sessionId=crypto.randomUUID?.()??`${Date.now()}-${Math.random()}`;constructor(e,t=Ce(),n=()=>new Date){this.env=e,this.storage=t,this.now=n,this.events=this.read(),this.record({kind:`session-start`})}record(e){let t=w([...this.events,{...e,schemaVersion:1,at:this.now().toISOString(),sessionId:this.sessionId,board:this.env.board}],this.now(),this.retention);this.events=t.events,this.retention=t.retention,this.persist(),this.revision++,this.notify()}count=()=>this.events.length;clientVersion=()=>this.env.clientVersion;assetPath=()=>this.env.assetPath;snapshot=()=>this.revision;summary=()=>ge(this.events,this.retention);clear(){this.events=[],this.retention=C();try{this.storage?.removeItem(x)}catch{}this.revision++,this.notify()}subscribe=e=>(this.listeners.add(e),()=>{this.listeners.delete(e)});export=()=>({schemaVersion:1,exportedAt:this.now().toISOString(),client:{version:this.env.clientVersion,assetPath:this.env.assetPath,board:this.env.board,sessionId:this.sessionId},events:this.events,summary:this.summary()});read(){try{let e=this.storage?.getItem(x);if(!e)return[];let t=JSON.parse(e);if(t.schemaVersion!==1||!Array.isArray(t.events)||!t.events.every(Se))return this.storage?.removeItem(x),[];let n=w(t.events.map(e=>({...e,schemaVersion:1})),this.now(),xe(t.retention));return this.retention=n.retention,n.events}catch{try{this.storage?.removeItem(x)}catch{}return[]}}persist(){try{this.storage?.setItem(x,JSON.stringify({schemaVersion:1,events:this.events,retention:this.retention}))}catch{}}notify(){for(let e of this.listeners)e()}};function S(e){let t=Object.fromEntries([[`cacheControl`,`cache-control`],[`etag`,`etag`],[`lastModified`,`last-modified`],[`date`,`date`],[`age`,`age`]].flatMap(([t,n])=>{let r=e.get(n);return r?[[t,r]]:[]}));return Object.keys(t).length?t:void 0}function C(){return{eventsPrunedByAge:0,eventsPrunedByCount:0}}function xe(e){if(!e||typeof e!=`object`)return C();let t=e;return{eventsPrunedByAge:typeof t.eventsPrunedByAge==`number`&&t.eventsPrunedByAge>=0?t.eventsPrunedByAge:0,eventsPrunedByCount:typeof t.eventsPrunedByCount==`number`&&t.eventsPrunedByCount>=0?t.eventsPrunedByCount:0}}function w(e,t,n){let r=t.valueOf()-ve,i=e.filter(e=>Number.isFinite(new Date(e.at).valueOf())&&new Date(e.at).valueOf()>=r),a=e.length-i.length,o=Math.max(0,i.length-_e);return{events:i.slice(-2e3),retention:{eventsPrunedByAge:n.eventsPrunedByAge+a,eventsPrunedByCount:n.eventsPrunedByCount+o}}}function Se(e){if(!e||typeof e!=`object`)return!1;let t=e;return(t.schemaVersion===void 0||t.schemaVersion===1)&&typeof t.at==`string`&&Number.isFinite(new Date(t.at).valueOf())&&typeof t.sessionId==`string`&&typeof t.board==`string`&&ye.includes(t.kind)}function Ce(){try{return window.localStorage}catch{return}}var T={panel:`_panel_1gq90_1`,content:`_content_1gq90_21`,error:`_error_1gq90_35`,wide:`_wide_1gq90_38`,primary:`_primary_1gq90_41`,compact:`_compact_1gq90_48`,label:`_label_1gq90_58`,hint:`_hint_1gq90_68`,branch:`_branch_1gq90_73`,observed:`_observed_1gq90_77`,stale:`_stale_1gq90_82`,status:`_status_1gq90_85`,passed:`_passed_1gq90_93`,failed:`_failed_1gq90_96`,running:`_running_1gq90_99`,cancelled:`_cancelled_1gq90_102`,unknown:`_unknown_1gq90_103`,link:`_link_1gq90_106`,shallow:`_shallow_1gq90_125`};function E({label:e,hint:t,wide:n=!1}){return l(`section`,{className:`${T.panel} ${n?T.wide:``}`,"data-panel":!0,"data-panel-id":`placeholder`,children:[c(`h2`,{className:T.label,children:e}),c(`p`,{className:T.hint,children:t})]})}var we={fact:`_fact_17pw7_1`};function Te(e){let t=e.position;if(t)return{"--panel-column":`${t.x+1} / span ${t.w}`,"--panel-row":`${t.y+1} / span ${t.h}`}}function D({children:e}){return c(`p`,{className:T.hint,children:e})}function O({children:e,status:t}){return c(`p`,{className:`${T.status} ${t?T[t]:``}`,children:e})}function Ee({children:e,title:t}){return c(`span`,{className:T.branch,title:t,children:e})}function De({children:e,stale:t=!1}){return c(`p`,{className:`${T.hint} ${T.observed} ${t?T.stale:``}`,children:e})}function k({panel:e,envelope:t,error:n=!1,field:r,children:i}){let a=e.display===`primary`||e.display===`compact`?e.display:`supporting`,o=e.position?.h!==void 0&&e.position.h<=2;return l(`section`,{className:`${T.panel} ${T[a]} ${o?T.shallow:``} ${n?T.error:``}`,style:Te(e),"aria-busy":!t||void 0,"data-panel":!0,"data-panel-id":e.id,"data-display":a,"data-shallow":o,"data-error":n||void 0,children:[r,l(`div`,{className:T.content,"data-panel-content":!0,children:[c(`h2`,{className:T.label,children:e.label??e.id}),i,c(Oe,{panelId:e.id,link:t?.link})]})]})}function Oe({panelId:e,link:t}){return t?l(`a`,{className:T.link,href:t,target:`_blank`,rel:`noopener noreferrer`,"aria-label":`View source for ${e} (opens in a new tab)`,"data-panel-link":!0,children:[`View source `,c(`span`,{"aria-hidden":`true`,children:`↗`})]}):null}function A({value:e,label:t=`As of`}){let n=new Date(e),r=n.toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`}),i=Date.now()-n.getTime(),a=i>3e5,o=ke(i);return l(De,{stale:a,children:[c(`span`,{"aria-hidden":`true`,children:`◷`}),` `,t,` `,r,` · `,o]})}function ke(e){if(e<6e4)return`just now`;let t=Math.floor(e/6e4);return t<60?`${t}m ago`:`${Math.floor(t/60)}h ${t%60}m ago`}function Ae({panel:e,envelope:t}){if(!t)return c(k,{panel:e,children:c(D,{children:`Loading…`})});if(t.state===`error`)return l(k,{panel:e,envelope:t,error:!0,children:[c(O,{children:`⚠ Unable to read`}),c(D,{children:t.error.message}),c(A,{value:t.observedAt})]});let n=pe.safeParse(t.signal);return n.success?c(k,{panel:e,envelope:t,children:l(`div`,{className:we.fact,children:[c(O,{children:String(n.data.value)}),c(A,{value:t.observedAt})]})}):l(k,{panel:e,envelope:t,error:!0,children:[c(O,{children:`⚠ Invalid value`}),c(A,{value:t.observedAt})]})}var je={variant:`_variant_1lsfm_1`},j={frontier:`_frontier_9owsk_1`,now:`_now_9owsk_12`,routes:`_routes_9owsk_20`,route:`_route_9owsk_20`,trail:`_trail_9owsk_41`,packet:`_packet_9owsk_42`};function Me(){return l(s,{children:[c(`span`,{className:j.frontier,"data-running-part":`frontier`}),c(`span`,{className:j.now,"data-running-part":`transit-now`}),c(`span`,{className:j.routes,"data-running-part":`transit-routes`,children:[0,1,2].map(e=>c(`span`,{className:j.route},e))}),c(`span`,{className:j.trail,"data-running-part":`transit-trail`}),c(`span`,{className:j.packet,"data-running-part":`transit-packet`})]})}var M={field:`_field_pf9oz_1`,overdue:`_overdue_pf9oz_10`,timing:`_timing_pf9oz_13`,timingOverdue:`_timingOverdue_pf9oz_23`},N={haze:`_haze_nu2ru_1`,band:`_band_nu2ru_17`,bandOne:`_bandOne_nu2ru_30`,bandTwo:`_bandTwo_nu2ru_33`,bandThree:`_bandThree_nu2ru_37`,drift:`_drift_nu2ru_42`,driftOne:`_driftOne_nu2ru_51`,driftTwo:`_driftTwo_nu2ru_55`,driftThree:`_driftThree_nu2ru_64`,driftFour:`_driftFour_nu2ru_73`,driftFive:`_driftFive_nu2ru_82`};function Ne(){return l(s,{children:[c(`span`,{className:N.haze,"data-running-part":`weather-haze`}),c(`span`,{className:`${N.band} ${N.bandOne}`}),c(`span`,{className:`${N.band} ${N.bandTwo}`}),c(`span`,{className:`${N.band} ${N.bandThree}`}),c(`span`,{className:`${N.drift} ${N.driftOne}`}),c(`span`,{className:`${N.drift} ${N.driftTwo}`}),c(`span`,{className:`${N.drift} ${N.driftThree}`}),c(`span`,{className:`${N.drift} ${N.driftFour}`}),c(`span`,{className:`${N.drift} ${N.driftFive}`})]})}var P={anchor:`_anchor_scrah_1`,body:`_body_scrah_6`,"phased-marker":`_phased-marker_scrah_1`};function F({anchorClassName:e,bodyClassName:t,delay:n,anchorPart:r,bodyPart:i}){let a=n?{"--phased-marker-delay":n}:void 0;return c(`span`,{className:`${P.anchor} ${e??``}`,"data-running-part":r,children:c(`span`,{className:`${P.body} ${t??``}`,"data-running-part":i,style:a})})}var I={frontier:`_frontier_1fw3x_1`,lanes:`_lanes_1fw3x_12`,lane:`_lane_1fw3x_12`,markerAnchor:`_markerAnchor_1fw3x_28`,markerBody:`_markerBody_1fw3x_32`};function Pe(){return l(s,{children:[c(`span`,{className:I.frontier,"data-running-part":`frontier`}),c(`span`,{className:I.lanes,"data-running-part":`bloom-lanes`,children:[0,1,2,3].map(e=>c(`span`,{className:I.lane,"data-running-part":`bloom-lane`,children:c(F,{anchorClassName:I.markerAnchor,bodyClassName:I.markerBody,delay:[void 0,`-0.8s`,`-1.7s`,`-2.4s`][e],anchorPart:`bloom-marker-anchor`,bodyPart:`bloom-marker`})},e))})]})}function L(e){return[`telemetry-bloom`,`release-transit`,`status-weather`].includes(e)}function R({animation:e,progress:t,overdue:n,indeterminate:r}){let i={"--running-progress":`${t*100}%`};return l(`div`,{className:`${M.field} ${n?M.overdue:``}`,"data-animation":e,"data-running-field":!0,"data-indeterminate":r||void 0,"aria-hidden":`true`,style:i,children:[e===`telemetry-bloom`&&c(Pe,{}),e===`release-transit`&&c(Me,{}),e===`status-weather`&&c(Ne,{})]})}var Fe=20;function z(e,t){let n=Ie(!!e),r=e?new Date(e).valueOf():NaN,i=Number.isFinite(r)?Math.max(0,n-r):void 0,a=i!==void 0&&t!==void 0;return{elapsedMs:i,estimatedDurationMs:t,hasEstimate:a,overdue:a&&i>t,progress:a?Math.min(i/t,1):0}}function Ie(e){let[t,r]=i(()=>Date.now());return n(()=>{if(!e)return;r(Date.now());let t=window.setInterval(()=>r(Date.now()),Fe);return()=>window.clearInterval(t)},[e]),t}function B(e,t,n){return`${e===void 0?`Run in progress`:`Elapsed ${H(e)}`} · ${t===void 0?`Expected duration unavailable`:`Expected ≈ ${H(t)}`}${n?` · Over estimate`:``}`}function V(e,t,n){let r=e===void 0?`—`:U(e),i=t===void 0?`?`:`~${U(t)}`;return`${n?`⚠`:`\xA0`}${r}/${i}`}function H(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}h ${r}m`:r>0?`${r}m ${i}s`:`${i}s`}function U(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=`${r}:${String(i).padStart(2,`0`)}`;return n>0?`${n}:${a.padStart(5,`0`)}`:a}function W({elapsedMs:e,estimatedDurationMs:t,overdue:n}){return l(`p`,{className:`${M.timing} ${n?M.timingOverdue:``}`,children:[c(`span`,{className:`screen-reader-only`,children:B(e,t,n)}),c(`span`,{"aria-hidden":`true`,children:V(e,t,n)})]})}var G={progress:`_progress_trasc_1`,visual:`_visual_trasc_8`,timing:`_timing_trasc_12`,overdue:`_overdue_trasc_17`,readout:`_readout_trasc_23`,radial:`_radial_trasc_31`,sweep:`_sweep_trasc_1`,radialCore:`_radialCore_trasc_49`,runway:`_runway_trasc_56`,spark:`_spark_trasc_80`,orbit:`_orbit_trasc_91`,orbitCore:`_orbitCore_trasc_106`,particle:`_particle_trasc_113`,particleTwo:`_particleTwo_trasc_124`,indeterminate:`_indeterminate_trasc_128`,shift:`_shift_trasc_1`,signalField:`_signalField_trasc_136`,rail:`_rail_trasc_152`,lead:`_lead_trasc_158`,pulse:`_pulse_trasc_168`,pulseTwo:`_pulseTwo_trasc_179`,tracks:`_tracks_trasc_182`,sparkWide:`_sparkWide_trasc_1`,track:`_track_trasc_182`,markerAnchor:`_markerAnchor_trasc_306`,markerBody:`_markerBody_trasc_310`};function K({animation:e,timing:t}){let{elapsedMs:n,estimatedDurationMs:r,hasEstimate:i,overdue:a,progress:o}=t,u=e===`runway`||e===`signal-field`,d=B(n,r,a),f={"--running-progress":`${o*100}%`,"--running-degrees":`${o*360}deg`},p=e===`signal-field`?G.signalField:G[e];return l(`div`,{className:`${G.progress} ${p} ${a?G.overdue:``} ${i?``:G.indeterminate}`,style:f,"data-running-progress":e,"data-overdue":a||void 0,"data-indeterminate":!i||void 0,children:[l(`div`,{className:G.visual,"aria-hidden":`true`,"data-running-visual":!0,children:[e===`radial`&&c(`span`,{className:G.radialCore}),e===`runway`&&c(`span`,{className:G.spark}),e===`orbit`&&l(s,{children:[c(`span`,{className:G.orbitCore}),c(`span`,{className:G.particle}),c(`span`,{className:`${G.particle} ${G.particleTwo}`})]}),e===`signal-field`&&l(s,{children:[c(`span`,{className:G.rail}),c(`span`,{className:G.lead}),c(`span`,{className:G.pulse}),c(`span`,{className:`${G.pulse} ${G.pulseTwo}`}),c(`span`,{className:G.tracks,"data-running-part":`signal-tracks`,children:[0,1,2,3,4].map(e=>c(`span`,{className:G.track,"data-running-part":`signal-track`,children:c(F,{anchorClassName:G.markerAnchor,bodyClassName:G.markerBody,delay:[void 0,`-0.8s`,`-1.7s`,`-2.4s`,`-0.35s`][e],anchorPart:`signal-marker-anchor`,bodyPart:`signal-marker`})},e))})]})]}),c(`p`,{className:`${G.timing} ${u?G.readout:``}`,children:u?l(s,{children:[c(`span`,{className:`screen-reader-only`,children:d}),c(`span`,{"aria-hidden":`true`,children:V(n,r,a)})]}):d})]})}function Le(e){return[`radial`,`runway`,`orbit`,`signal-field`].includes(e)}var Re=2e4,ze=15e3,q=3e5,J=[`radial`,`runway`,`orbit`,`signal-field`,`telemetry-bloom`,`release-transit`,`status-weather`];function Be({panel:e}){let t=He(),n=e.running_animation===void 0||e.running_animation===`off`?void 0:e.running_animation,r=n?q:Re,i=Math.floor(t/r),a=n??J[i%J.length]??`radial`,o=i*r;return c(Ve,{panel:e,animation:a,runStartedAt:o,estimatedDurationMs:n?q:ze})}function Ve({panel:e,animation:t,runStartedAt:n,estimatedDurationMs:r}){let i=z(new Date(n).toISOString(),r),a=L(t);return l(k,{panel:e,field:a?c(R,{animation:t,progress:i.progress,overdue:i.overdue,indeterminate:!i.hasEstimate}):void 0,children:[c(O,{status:`running`,children:`↻ Running`}),l(`p`,{className:je.variant,children:[`Demo treatment · `,t]}),a?c(W,{elapsedMs:i.elapsedMs,estimatedDurationMs:r,overdue:i.overdue}):c(K,{animation:t,timing:i})]})}function He(){let[e,t]=i(()=>Date.now());return n(()=>{let e=window.setInterval(()=>t(Date.now()),1e3);return()=>window.clearInterval(e)},[]),e}var Ue={details:`_details_1isu9_1`};function We({panel:e,envelope:t}){if(!t)return c(k,{panel:e,children:c(D,{children:`Loading…`})});if(t.state===`error`)return l(k,{panel:e,envelope:t,error:!0,children:[l(O,{children:[`⚠ `,t.error.kind===`no-runs`?`No workflow runs`:`Unable to read`]}),c(D,{children:t.error.message}),c(A,{value:t.observedAt})]});let n=g.safeParse(t.signal);return n.success?c(Ge,{panel:e,envelope:t,signal:n.data}):l(k,{panel:e,envelope:t,error:!0,children:[c(O,{children:`⚠ Invalid signal`}),c(A,{value:t.observedAt})]})}function Ge({panel:e,envelope:t,signal:n}){let r=Je(n.status),[a]=i(Ke),o=e.running_animation??a,s=n.status===`running`&&o!==`off`,u=z(n.runStartedAt,n.estimatedDurationMs),d=s&&L(o),f=s&&Le(o);return c(k,{panel:e,envelope:t,field:d?c(R,{animation:o,progress:u.progress,overdue:u.overdue,indeterminate:!u.hasEstimate}):void 0,children:l(`div`,{className:Ue.details,children:[l(O,{status:n.status,children:[r.glyph,` `,r.label]}),l(D,{children:[n.name,` · `,n.rawStatus,n.branch&&l(Ee,{title:`Branch: ${n.branch}`,children:[c(`span`,{"aria-hidden":`true`,children:` · ⎇ `}),c(`span`,{className:`screen-reader-only`,children:`Branch: `}),n.branch]})]}),d&&c(W,{elapsedMs:u.elapsedMs,estimatedDurationMs:n.estimatedDurationMs,overdue:u.overdue}),f&&c(K,{animation:o,timing:u}),n.status!==`running`&&n.durationMs!==void 0&&l(D,{children:[`Took `,qe(n.durationMs)]}),n.sourceUpdatedAt&&c(A,{value:n.sourceUpdatedAt,label:`Run updated`}),c(A,{value:t.observedAt})]})})}function Ke(){return m[Math.floor(Math.random()*m.length)]??`telemetry-bloom`}function qe(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}h ${r}m`:r>0?`${r}m ${i}s`:`${i}s`}function Je(e){switch(e){case`passed`:return{glyph:`✓`,label:`Passed`};case`failed`:return{glyph:`✕`,label:`Failed`};case`running`:return{glyph:`↻`,label:`Running`};case`cancelled`:return{glyph:`⊘`,label:`Cancelled`};case`unknown`:return{glyph:`?`,label:`Unknown`}}}function Ye({panel:e,envelope:t}){if(!t)return c(k,{panel:e,children:c(D,{children:`Loading…`})});if(t.state===`error`)return l(k,{panel:e,envelope:t,error:!0,children:[c(O,{children:`⚠ Unable to read`}),c(D,{children:t.error.message}),c(A,{value:t.observedAt})]});let n=v.safeParse(t.signal);if(!n.success)return c(k,{panel:e,envelope:t,error:!0,children:c(O,{children:`⚠ Invalid signal`})});let r=Xe(n.data.status);return l(k,{panel:e,envelope:t,children:[l(O,{status:n.data.status,children:[r.glyph,` `,r.label]}),c(D,{children:n.data.summary}),c(A,{value:t.observedAt})]})}function Xe(e){switch(e){case`passed`:return{glyph:`✓`,label:`Healthy`};case`failed`:return{glyph:`✕`,label:`Failed`};case`running`:return{glyph:`↻`,label:`Running`};case`cancelled`:return{glyph:`⊘`,label:`Cancelled`};case`unknown`:return{glyph:`?`,label:`Unknown`}}}var Ze={"pipeline-status":We,"pull-request-health":Ye,"http-value":Ae,"pipeline-animation-demo":Be};function Qe({panel:e,envelope:t}){let n=Ze[e.type];return n?c(n,{panel:e,envelope:t}):c(E,{label:e.type,hint:`Not wired yet`,wide:!0})}var $e=6e4,et=1e4,tt=()=>globalThis.window.location.reload();function nt({env:e,diagnostics:t,fetcher:r,reload:i=tt}){n(()=>{let n=!1,a=!1,o,s=`${e.proxyPath}/client`,c=async()=>{if(n||a)return;a=!0;let l=new AbortController;o=l;let u=globalThis.setTimeout(()=>l.abort(),et);t.record({kind:`client-update-check`,path:s});try{let a=await(r??globalThis.fetch)(s,{cache:`no-store`,signal:l.signal});if(!a.ok)throw Error(`Client identity returned ${a.status}`);let o=ce.safeParse(await a.json());if(!o.success)throw Error(`Client identity response was invalid`);if(n)return;o.data.assetPath!==e.assetPath&&(t.record({kind:`client-update-detected`,path:s,current:{assetPath:e.assetPath,clientVersion:e.clientVersion},next:o.data}),i())}catch(e){!n&&!(e instanceof DOMException&&e.name===`AbortError`)&&t.record({kind:`client-update-failure`,path:s,message:e instanceof Error?e.message:String(e)})}finally{globalThis.clearTimeout(u),a=!1,o===l&&(o=void 0),n||globalThis.setTimeout(()=>void c(),$e)}};return c(),()=>{n=!0,o?.abort()}},[t,e.assetPath,e.clientVersion,e.proxyPath,r,i])}function Y(e,t){if(t.state===`error`)return{state:t.state,link:t.link};if(e.type===`pipeline-status`){let e=g.safeParse(t.signal);return{state:t.state,status:e.success?e.data.status:void 0,link:t.link}}if(e.type===`pull-request-health`){let e=v.safeParse(t.signal);return{state:t.state,status:e.success?e.data.status:void 0,link:t.link}}return{state:t.state,link:t.link}}function rt(e,t,n){if(!e)return!0;let r=Y(t,e),i=Y(t,n);return r.state!==i.state||r.status!==i.status||r.link!==i.link}function it({board:e,env:t,diagnostics:a}){let[o,s]=i({}),c=r({});return n(()=>{if(c.current={},s({}),!e)return;let n=!1,r=[];for(let i of e.panels){if(i.type!==`pipeline-status`&&i.type!==`pull-request-health`&&i.type!==`http-value`)continue;let o=!1,l=se({boardDefaultMillis:f(e.refresh??`60s`)??6e4,panelOverrideMillis:i.refresh?f(i.refresh)??void 0:void 0,adapterFloorMillis:0}),u=`${t.proxyPath}/panel/${encodeURIComponent(t.board)}/${encodeURIComponent(i.id)}`,d=()=>{n||o||(o=!0,a.record({kind:`panel-fetch-start`,panelId:i.id,path:u}),fetch(u).then(async e=>{let t={kind:`panel-fetch-response`,panelId:i.id,path:u,status:e.status,cache:S(e.headers)};if(e.status===304){a.record(t);return}try{let n=at(await e.json());if(!n){a.record(t),a.record({kind:`panel-fetch-parse-failure`,panelId:i.id,path:u,message:`Response was not a valid signal envelope.`});return}return a.record({...t,envelope:n}),n}catch(e){throw a.record(t),a.record({kind:`panel-fetch-parse-failure`,panelId:i.id,path:u,message:X(e)}),new Z(e)}}).then(e=>{if(!n&&e){let t=c.current[i.id];rt(t,i,e)&&a.record({kind:`panel-rendered`,panelId:i.id,path:u,rendered:Y(i,e)}),c.current={...c.current,[i.id]:e},s(c.current)}}).catch(e=>{e instanceof Z||a.record({kind:`panel-fetch-failure`,panelId:i.id,path:u,message:X(e)})}).finally(()=>{o=!1}))};d(),r.push(window.setInterval(d,l))}return()=>{n=!0;for(let e of r)window.clearInterval(e)}},[e,a,t.board,t.proxyPath]),o}function X(e){return e instanceof Error?e.message:String(e)}var Z=class extends Error{constructor(e){super(X(e))}};function at(e){let t=fe.safeParse(e);return t.success?t.data:void 0}function ot({env:e}){let[t,a]=i(),[o,s]=i(),u=r(null);u.current||=new be(e);let d=u.current;nt({env:e,diagnostics:d});let f=it({board:o===e.board?t:void 0,env:e,diagnostics:d});return n(()=>{let t=!1;a(void 0),s(void 0);let n=`${e.proxyPath}/boards/${encodeURIComponent(e.board)}`;return d.record({kind:`board-fetch-start`,path:n}),fetch(n).then(async e=>{if(d.record({kind:`board-fetch-response`,path:n,status:e.status,cache:S(e.headers)}),!e.ok)throw Error(`Board configuration returned ${e.status}`);try{return await e.json()}catch(e){throw d.record({kind:`board-fetch-parse-failure`,path:n,message:Q(e)}),new $(e)}}).then(r=>{if(!t){a(r),s(e.board);let t=Array.isArray(r.panels)?r.panels:[];d.record({kind:`board-fetch-response`,path:n,boardSummary:{panelCount:t.length,panelIds:t.flatMap(e=>typeof e.id==`string`?[e.id]:[])}})}}).catch(r=>{r instanceof $||d.record({kind:`board-fetch-failure`,path:n,message:Q(r)}),t||(a({panels:[]}),s(e.board))}),()=>{t=!0}},[d,e.board,e.proxyPath]),l(`div`,{className:y.board,children:[c(`header`,{className:y.header,children:c(`h1`,{className:y.title,children:e.board})}),l(`main`,{className:y.grid,children:[!t&&c(E,{label:`board`,hint:`Loading configuration…`,wide:!0}),t?.panels.map(e=>c(Qe,{panel:e,envelope:f[e.id]},e.id))]}),l(`footer`,{className:y.footer,"data-board-footer":!0,children:[c(`span`,{children:`Signals are read live from their configured authorities.`}),c(me,{log:d})]})]})}function Q(e){return e instanceof Error?e.message:String(e)}var $=class extends Error{constructor(e){super(Q(e))}},st={error:`_error_yx1g9_1`};function ct({message:e}){return l(`div`,{className:st.error,role:`alert`,children:[c(`h1`,{children:`⚠️ Dashboard misconfigured`}),c(`p`,{children:`The page loaded, but the server did not hand it usable configuration.`}),c(`pre`,{children:e})]})}var lt=document.getElementById(`root`);if(!lt)throw Error(`No #root element in the document — the template is not the one we expect.`);var ut=o(lt);try{ut.render(c(t,{children:c(ot,{env:le()})}))}catch(e){ut.render(c(ct,{message:e instanceof Error?e.message:String(e)}))}
|
|
3
|
+
//# sourceMappingURL=index-BgvnHC8t.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BgvnHC8t.js","names":[],"sources":["../../../shared/dist/index.js","../../src/App.module.css","../../src/Diagnostics.module.css","../../src/Diagnostics.tsx","../../src/diagnostics-summary.ts","../../src/diagnostics.ts","../../src/PanelFrame.module.css","../../src/PanelPlaceholder.tsx","../../src/HttpValuePanel.module.css","../../src/panel-layout.ts","../../src/PanelFrame.tsx","../../src/ObservedAt.tsx","../../src/HttpValuePanel.tsx","../../src/PipelineAnimationDemoPanel.module.css","../../src/ReleaseTransitField.module.css","../../src/ReleaseTransitField.tsx","../../src/RunningField.module.css","../../src/StatusWeatherField.module.css","../../src/StatusWeatherField.tsx","../../src/PhasedProgressMarker.module.css","../../src/PhasedProgressMarker.tsx","../../src/TelemetryBloomField.module.css","../../src/TelemetryBloomField.tsx","../../src/RunningField.tsx","../../src/running-timing.ts","../../src/RunningFieldTiming.tsx","../../src/RunningProgress.module.css","../../src/RunningProgress.tsx","../../src/PipelineAnimationDemoPanel.tsx","../../src/PipelinePanel.module.css","../../src/PipelinePanel.tsx","../../src/PullRequestHealthPanel.tsx","../../src/panel-registry.tsx","../../src/useClientUpdate.ts","../../src/panel-diagnostics.ts","../../src/usePanelSignals.ts","../../src/App.tsx","../../src/ConfigError.module.css","../../src/ConfigError.tsx","../../src/main.tsx"],"sourcesContent":["// packages/shared/src/board-config.ts\nimport { z as z2 } from \"zod\";\n\n// packages/shared/src/duration.ts\nimport { z } from \"zod\";\nvar DURATION_PATTERN = /^(\\d+)(ms|s|m|h)$/;\nvar UNIT_MILLIS = {\n ms: 1,\n s: 1e3,\n m: 6e4,\n h: 36e5\n};\nfunction parseDuration(value) {\n const match = DURATION_PATTERN.exec(value);\n if (!match) return null;\n const [, rawAmount, rawUnit] = match;\n if (rawAmount === void 0 || rawUnit === void 0) return null;\n const amount = Number(rawAmount);\n if (amount <= 0) return null;\n return amount * UNIT_MILLIS[rawUnit];\n}\nvar durationSchema = z.string().refine((value) => parseDuration(value) !== null, {\n message: 'must be a positive duration like \"30s\", \"5m\", or \"1h\"'\n}).brand();\n\n// packages/shared/src/board-config.ts\nvar positionSchema = z2.object({\n x: z2.number().int().min(0),\n y: z2.number().int().min(0),\n w: z2.number().int().min(1).max(12),\n h: z2.number().int().min(1)\n});\nvar panelDisplayRoles = [\"primary\", \"supporting\", \"compact\"];\nvar panelDisplaySchema = z2.string().min(1);\nvar visibleRunningAnimations = [\n \"radial\",\n \"runway\",\n \"orbit\",\n \"signal-field\",\n \"telemetry-bloom\",\n \"release-transit\",\n \"status-weather\"\n];\nvar runningAnimationSchema = z2.enum([...visibleRunningAnimations, \"off\"]);\nvar panelSchema = z2.looseObject({\n /** Presentation-only wall label. `id` remains the stable proxy and allowlist address. */\n label: z2.string().min(1).optional(),\n id: z2.string().min(1),\n type: z2.string().min(1),\n source: z2.string().min(1).optional(),\n /** Semantic visual weight; position still controls the panel's explicit grid placement. */\n display: panelDisplaySchema.optional(),\n /** Advisory in v1 — a panel without a position renders in config order rather than not at all. */\n position: positionSchema.optional(),\n refresh: durationSchema.optional(),\n /** Optional active-run treatment. Omitted selects a visible treatment at random. */\n running_animation: runningAnimationSchema.optional(),\n /** A deliberate override only. Adapters derive links; hand-written ones drift. */\n link: z2.url().optional(),\n /** Source-agnostic endpoint used by the http-value signal. */\n url: z2.url().optional(),\n /** Small, deliberate JSON path subset: $.version, $.deployment.version, or $.response.docs[0].latestVersion. */\n json_path: z2.string().regex(/^\\$(?:\\.[A-Za-z_][A-Za-z0-9_]*|\\[\\d+\\])*$/, \"must be a simple JSON path\").optional()\n});\nvar sourceSchema = z2.looseObject({\n type: z2.string().min(1),\n /** Credentials are never in the config — only the name of the env var holding one. */\n token_env: z2.string().min(1).optional()\n});\nvar boardSchema = z2.object({\n refresh: durationSchema.optional(),\n panels: z2.array(panelSchema).min(1).superRefine((panels, ctx) => {\n const seen = /* @__PURE__ */ new Map();\n panels.forEach((panel, index) => {\n const firstIndex = seen.get(panel.id);\n if (firstIndex === void 0) {\n seen.set(panel.id, index);\n return;\n }\n ctx.addIssue({\n code: \"custom\",\n path: [index, \"id\"],\n message: `duplicate panel id \"${panel.id}\" (already used by panel at index ${firstIndex})`\n });\n });\n })\n});\nvar authSchema = z2.object({\n issuer: z2.url(),\n /** Absent in gateway mode — the gateway does the flow, the proxy still validates. */\n client_id: z2.string().min(1).optional(),\n allow: z2.object({\n groups: z2.array(z2.string().min(1)).optional(),\n subjects: z2.array(z2.string().min(1)).optional()\n }).optional()\n});\nvar boardConfigSchema = z2.object({\n sources: z2.record(z2.string().min(1), sourceSchema).default({}),\n boards: z2.record(z2.string().min(1), boardSchema),\n auth: authSchema.optional()\n});\nfunction resolveRefreshMillis(args) {\n const requested = args.panelOverrideMillis ?? args.boardDefaultMillis;\n return Math.max(requested, args.adapterFloorMillis);\n}\n\n// packages/shared/src/client-env.ts\nimport { z as z3 } from \"zod\";\nvar clientEnvSchema = z3.object({\n /** Where the immutable client assets live. The one variable that repoints the whole client. */\n assetPath: z3.string().min(1),\n /** Same-origin path the proxy is mounted at, so there is no CORS and no cookie problem. */\n proxyPath: z3.string().min(1),\n /** Which board this is, resolved server-side so the client parses no URLs. */\n board: z3.string().min(1),\n /** The client version being served, so two published versions are visibly distinguishable. */\n clientVersion: z3.string().min(1),\n /** Omitted entirely when unauthenticated — presence is what turns auth on. */\n auth: z3.object({\n issuer: z3.string().min(1),\n clientId: z3.string().min(1).optional()\n }).optional()\n});\nvar clientIdentitySchema = clientEnvSchema.pick({ assetPath: true, clientVersion: true });\nfunction readClientEnv(source = globalThis.window?.env) {\n const result = clientEnvSchema.safeParse(source);\n if (!result.success) {\n throw new Error(\n `window.env is missing or invalid \\u2014 the server did not inject usable configuration.\n${z3.prettifyError(result.error)}`\n );\n }\n return result.data;\n}\n\n// packages/shared/src/envelope.ts\nimport { z as z4 } from \"zod\";\nvar errorKindSchema = z4.enum([\n \"unreachable\",\n \"unauthorized\",\n \"not-found\",\n \"no-runs\",\n \"upstream-error\"\n]);\nvar envelopeErrorSchema = z4.object({\n kind: errorKindSchema,\n message: z4.string()\n});\nvar envelopeSchema = z4.discriminatedUnion(\"state\", [\n z4.object({\n panelId: z4.string().min(1),\n state: z4.literal(\"ok\"),\n /** From the upstream response `Date`. A cached value must never be shown without its age. */\n observedAt: z4.iso.datetime(),\n /** Adapter-derived. The authority for this panel; the dashboard itself asserts nothing. */\n link: z4.url().nullable(),\n signal: z4.unknown()\n }),\n z4.object({\n panelId: z4.string().min(1),\n state: z4.literal(\"error\"),\n /**\n * Populated even on error: knowing *when* a failure was observed is the difference between\n * \"broken just now\" and \"broken all morning\", and a panel that can't reach its source is\n * exactly when a viewer most wants to click through.\n */\n observedAt: z4.iso.datetime(),\n link: z4.url().nullable(),\n error: envelopeErrorSchema\n })\n]);\nvar pipelineStatusSchema = z4.object({\n type: z4.literal(\"pipeline-status\"),\n status: z4.enum([\"passed\", \"failed\", \"running\", \"cancelled\", \"unknown\"]),\n /** The source's unmodified status/result vocabulary, for an honest display. */\n rawStatus: z4.string(),\n name: z4.string().min(1),\n /** The branch represented by this status, when the upstream supplies or filters by one. */\n branch: z4.string().min(1).optional(),\n /** Elapsed execution time, supplied only after the upstream run has completed. */\n durationMs: z4.number().int().nonnegative().optional(),\n /** When an active run began, so the client can advance its elapsed display between polls. */\n runStartedAt: z4.iso.datetime().optional(),\n /** Advisory median duration from recent completed runs from the same source response. */\n estimatedDurationMs: z4.number().int().positive().optional(),\n /** When this workflow run was last updated by its source, distinct from our observation time. */\n sourceUpdatedAt: z4.iso.datetime().optional()\n});\nvar pullRequestHealthItemSchema = z4.object({\n label: z4.string().min(1),\n status: pipelineStatusSchema.shape.status,\n detail: z4.string().min(1),\n link: z4.url().nullable()\n});\nvar pullRequestHealthSchema = z4.object({\n type: z4.literal(\"pull-request-health\"),\n status: pipelineStatusSchema.shape.status,\n summary: z4.string().min(1),\n workflows: z4.array(pullRequestHealthItemSchema),\n pullRequests: z4.array(pullRequestHealthItemSchema)\n});\nvar httpValueSchema = z4.object({\n type: z4.literal(\"http-value\"),\n value: z4.union([z4.string(), z4.number(), z4.boolean()])\n});\nexport {\n authSchema,\n boardConfigSchema,\n boardSchema,\n clientEnvSchema,\n clientIdentitySchema,\n durationSchema,\n envelopeSchema,\n errorKindSchema,\n httpValueSchema,\n panelDisplayRoles,\n panelDisplaySchema,\n panelSchema,\n parseDuration,\n pipelineStatusSchema,\n positionSchema,\n pullRequestHealthSchema,\n readClientEnv,\n resolveRefreshMillis,\n runningAnimationSchema,\n sourceSchema,\n visibleRunningAnimations\n};\n",".board {\n display: flex;\n flex-direction: column;\n gap: var(--gap);\n height: 100dvh;\n min-height: 0;\n padding: var(--gap);\n overflow-x: hidden;\n overflow-y: auto;\n}\n.header {\n display: flex;\n align-items: baseline;\n border-bottom: 1px solid var(--edge);\n padding-bottom: var(--gap);\n flex: 0 0 auto;\n}\n.title {\n margin: 0;\n font-size: 1.75em;\n font-weight: 650;\n letter-spacing: -0.01em;\n}\n.grid {\n display: grid;\n grid-template-columns: repeat(12, 1fr);\n grid-template-rows: repeat(12, minmax(0, 1fr));\n grid-auto-rows: minmax(0, 1fr);\n gap: var(--gap);\n flex: 1;\n min-height: 0;\n align-content: stretch;\n}\n.footer {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n color: var(--ink-muted);\n font-size: 0.75em;\n flex: 0 0 auto;\n}\n@media (max-width: 60rem) {\n .board {\n height: auto;\n min-height: 100dvh;\n overflow: visible;\n }\n .grid {\n grid-template-columns: 1fr;\n grid-auto-rows: auto;\n flex: 0 0 auto;\n min-height: auto;\n }\n}\n",".diagnostics {\n position: relative;\n}\n\n.button {\n border: 1px solid var(--edge);\n border-radius: 0.25rem;\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font: inherit;\n padding: 0.3em 0.55em;\n}\n\n.area {\n position: absolute;\n z-index: 1;\n right: 0;\n bottom: calc(100% + 0.5rem);\n width: min(24rem, 90vw);\n padding: 0.75rem;\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n background: var(--surface-raised);\n box-shadow: 0 0.5rem 1.5rem #0008;\n}\n\n.area p {\n margin: 0 0 0.5rem;\n}\n\n.warning {\n color: var(--status-warning);\n}\n\n.panels {\n max-height: 12rem;\n overflow-y: auto;\n border-top: 1px solid var(--edge);\n margin: 0.5rem 0;\n padding-top: 0.5rem;\n}\n\n.actions {\n display: flex;\n gap: 0.5rem;\n}\n","import { useState, useSyncExternalStore } from 'react'\nimport styles from './Diagnostics.module.css'\nimport type { BrowserDiagnosticStore } from './diagnostics.ts'\n\nexport function Diagnostics({ log }: { log: BrowserDiagnosticStore }) {\n const [open, setOpen] = useState(false)\n useSyncExternalStore(log.subscribe, log.snapshot, log.snapshot)\n const count = log.count()\n const summary = log.summary()\n const download = () => {\n const blob = new Blob([JSON.stringify(log.export(), null, 2)], { type: 'application/json' })\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = `dashboard-diagnostics-${new Date().toISOString().replaceAll(':', '-')}.json`\n link.click()\n URL.revokeObjectURL(url)\n }\n const clear = () => {\n if (!window.confirm('Clear this browser’s retained dashboard diagnostics?')) return\n log.clear()\n }\n\n return (\n <section className={styles.diagnostics}>\n <button\n className={styles.button}\n type=\"button\"\n aria-expanded={open}\n onClick={() => setOpen(!open)}\n >\n Diagnostics ({count})\n </button>\n {open && (\n <div className={styles.area}>\n <p>\n Client {log.clientVersion()} · assets {log.assetPath()}\n </p>\n <p>\n {summary.retained.eventCount} retained browser-local events across{' '}\n {summary.retained.sessionCount} session{summary.retained.sessionCount === 1 ? '' : 's'}\n {summary.retained.firstEventAt && summary.retained.lastEventAt\n ? ` (${formatWindow(summary.retained.firstEventAt, summary.retained.lastEventAt)})`\n : ''}\n . They are never uploaded.\n </p>\n {summary.retained.evidenceMayBeIncomplete && (\n <p className={styles.warning} role=\"alert\">\n Earlier evidence was pruned: {summary.retained.retention.eventsPrunedByCount} at the\n 2,000-event cap and {summary.retained.retention.eventsPrunedByAge} by the 7-day age\n limit. “No failures” applies only to the retained window.\n </p>\n )}\n <p>\n Update failures: {summary.failures.clientUpdate}; board fetch failures:{' '}\n {summary.failures.boardFetch}.\n </p>\n {summary.panels.length > 0 && (\n <div className={styles.panels}>\n {summary.panels.map((panel) => (\n <p key={panel.panelId}>\n <strong>{panel.panelId}</strong> — {panel.requests} requests\n {Object.keys(panel.httpStatuses).length\n ? `; HTTP ${Object.entries(panel.httpStatuses)\n .map(([status, count]) => `${status}×${count}`)\n .join(', ')}`\n : ''}\n ; parse/network failures {panel.parseFailures}/{panel.networkFailures}; visible\n changes {panel.visibleStateChanges}; latest{' '}\n {panel.latestRendered\n ? `${panel.latestRendered.state}${panel.latestRendered.status ? `/${panel.latestRendered.status}` : ''}`\n : 'not rendered'}\n .\n </p>\n ))}\n </div>\n )}\n <div className={styles.actions}>\n <button className={styles.button} type=\"button\" onClick={download}>\n Download\n </button>\n <button className={styles.button} type=\"button\" onClick={clear}>\n Clear\n </button>\n </div>\n </div>\n )}\n </section>\n )\n}\n\nfunction formatWindow(first: string, last: string) {\n return first === last ? first : `${first} to ${last}`\n}\n","import type {\n DiagnosticEvent,\n DiagnosticRetention,\n RenderedPanelDiagnostic,\n} from './diagnostics.ts'\n\nexport type PanelDiagnosticsSummary = {\n panelId: string\n requests: number\n httpStatuses: Record<string, number>\n parseFailures: number\n networkFailures: number\n visibleStateChanges: number\n latestRendered?: RenderedPanelDiagnostic\n}\n\nexport type DiagnosticsSummary = {\n retained: {\n eventCount: number\n firstEventAt?: string\n lastEventAt?: string\n sessionCount: number\n retention: DiagnosticRetention\n evidenceMayBeIncomplete: boolean\n }\n failures: {\n clientUpdate: number\n boardFetch: number\n }\n panels: PanelDiagnosticsSummary[]\n}\n\n/** Summarizes retained browser evidence only; omitted history is disclosed through retention. */\nexport function summarizeDiagnostics(\n events: readonly DiagnosticEvent[],\n retention: DiagnosticRetention,\n): DiagnosticsSummary {\n const panels = new Map<string, PanelDiagnosticsSummary>()\n const sessions = new Set<string>()\n let clientUpdate = 0\n let boardFetch = 0\n\n for (const event of events) {\n sessions.add(event.sessionId)\n if (event.kind === 'client-update-failure') clientUpdate++\n if (event.kind === 'board-fetch-failure' || event.kind === 'board-fetch-parse-failure')\n boardFetch++\n if (!('panelId' in event)) continue\n\n const panel = panels.get(event.panelId) ?? {\n panelId: event.panelId,\n requests: 0,\n httpStatuses: {},\n parseFailures: 0,\n networkFailures: 0,\n visibleStateChanges: 0,\n }\n if (event.kind === 'panel-fetch-start') panel.requests++\n if (event.kind === 'panel-fetch-response') {\n if (event.status !== undefined) {\n const status = String(event.status)\n panel.httpStatuses[status] = (panel.httpStatuses[status] ?? 0) + 1\n }\n }\n if (event.kind === 'panel-fetch-parse-failure') panel.parseFailures++\n if (event.kind === 'panel-fetch-failure') panel.networkFailures++\n if (event.kind === 'panel-rendered') {\n panel.visibleStateChanges++\n panel.latestRendered = event.rendered\n }\n panels.set(event.panelId, panel)\n }\n\n const timestamps = events.map((event) => event.at).sort()\n const discarded = retention.eventsPrunedByAge + retention.eventsPrunedByCount\n return {\n retained: {\n eventCount: events.length,\n firstEventAt: timestamps[0],\n lastEventAt: timestamps.at(-1),\n sessionCount: sessions.size,\n retention,\n evidenceMayBeIncomplete: discarded > 0,\n },\n failures: { clientUpdate, boardFetch },\n panels: [...panels.values()].sort((left, right) => left.panelId.localeCompare(right.panelId)),\n }\n}\n","import type { ClientEnv, Envelope } from '@ze-great-dashboard/shared'\nimport { type DiagnosticsSummary, summarizeDiagnostics } from './diagnostics-summary.ts'\n\nconst storageKey = 'ze-great-dashboard.diagnostics.v1'\nexport const diagnosticsSchemaVersion = 1\nconst maximumEvents = 2_000\nconst maximumAgeMillis = 7 * 24 * 60 * 60 * 1_000\nconst diagnosticKinds = [\n 'session-start',\n 'client-update-check',\n 'client-update-failure',\n 'client-update-detected',\n 'board-fetch-start',\n 'board-fetch-response',\n 'board-fetch-parse-failure',\n 'board-fetch-failure',\n 'panel-fetch-start',\n 'panel-fetch-response',\n 'panel-fetch-parse-failure',\n 'panel-fetch-failure',\n 'panel-rendered',\n] as const\n\nexport type CacheMetadata = Partial<\n Record<'cacheControl' | 'etag' | 'lastModified' | 'date' | 'age', string>\n>\n\ntype EventMetadata = {\n schemaVersion: typeof diagnosticsSchemaVersion\n at: string\n sessionId: string\n board: string\n}\n\nexport type RenderedPanelDiagnostic = {\n state: Envelope['state']\n status?: string\n link: string | null\n}\n\nexport type DiagnosticEventInput =\n | { kind: 'session-start' }\n | { kind: 'client-update-check'; path: string }\n | { kind: 'client-update-failure'; path: string; message: string }\n | {\n kind: 'client-update-detected'\n path: string\n current: { assetPath: string; clientVersion: string }\n next: { assetPath: string; clientVersion: string }\n }\n | { kind: 'board-fetch-start'; path: string }\n | {\n kind: 'board-fetch-response'\n path: string\n status?: number\n cache?: CacheMetadata\n boardSummary?: { panelCount: number; panelIds: string[] }\n }\n | { kind: 'board-fetch-parse-failure'; path: string; message: string }\n | { kind: 'board-fetch-failure'; path: string; message: string }\n | { kind: 'panel-fetch-start'; panelId: string; path: string }\n | {\n kind: 'panel-fetch-response'\n panelId: string\n path: string\n status?: number\n cache?: CacheMetadata\n envelope?: Envelope\n }\n | { kind: 'panel-fetch-parse-failure'; panelId: string; path: string; message: string }\n | { kind: 'panel-fetch-failure'; panelId: string; path: string; message: string }\n | {\n kind: 'panel-rendered'\n panelId: string\n path: string\n rendered: RenderedPanelDiagnostic\n }\n\nexport type DiagnosticEvent = DiagnosticEventInput extends infer Event\n ? Event extends DiagnosticEventInput\n ? Event & EventMetadata\n : never\n : never\n\n/** The only interface client features need in order to emit browser diagnostics. */\nexport interface DiagnosticSink {\n record(event: DiagnosticEventInput): void\n}\n\ntype PersistedDiagnosticEvent = Omit<DiagnosticEvent, 'schemaVersion'> & { schemaVersion?: number }\nexport type DiagnosticRetention = {\n eventsPrunedByAge: number\n eventsPrunedByCount: number\n}\n\ntype StoredDiagnostics = {\n schemaVersion: number\n events: PersistedDiagnosticEvent[]\n retention?: Partial<DiagnosticRetention>\n}\n\ntype StorageLike = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>\n\n/** Browser-local diagnostic evidence. It deliberately has no server or shared-contract counterpart. */\nexport class BrowserDiagnosticStore implements DiagnosticSink {\n private events: DiagnosticEvent[] = []\n private retention: DiagnosticRetention = emptyRetention()\n private revision = 0\n private readonly listeners = new Set<() => void>()\n private readonly sessionId = crypto.randomUUID?.() ?? `${Date.now()}-${Math.random()}`\n\n constructor(\n private readonly env: ClientEnv,\n private readonly storage: StorageLike | undefined = storageOrUndefined(),\n private readonly now: () => Date = () => new Date(),\n ) {\n this.events = this.read()\n this.record({ kind: 'session-start' })\n }\n\n record(event: DiagnosticEventInput) {\n const pruned = prune(\n [\n ...this.events,\n {\n ...event,\n schemaVersion: diagnosticsSchemaVersion,\n at: this.now().toISOString(),\n sessionId: this.sessionId,\n board: this.env.board,\n },\n ],\n this.now(),\n this.retention,\n )\n this.events = pruned.events\n this.retention = pruned.retention\n this.persist()\n this.revision++\n this.notify()\n }\n\n count = () => {\n return this.events.length\n }\n\n clientVersion = () => this.env.clientVersion\n\n assetPath = () => this.env.assetPath\n\n snapshot = () => this.revision\n\n summary = (): DiagnosticsSummary => summarizeDiagnostics(this.events, this.retention)\n\n clear() {\n this.events = []\n this.retention = emptyRetention()\n try {\n this.storage?.removeItem(storageKey)\n } catch {\n // Diagnostics must not interrupt the radiator when browser storage is unavailable.\n }\n this.revision++\n this.notify()\n }\n\n subscribe = (listener: () => void) => {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n export = () => {\n return {\n schemaVersion: diagnosticsSchemaVersion,\n exportedAt: this.now().toISOString(),\n client: {\n version: this.env.clientVersion,\n assetPath: this.env.assetPath,\n board: this.env.board,\n sessionId: this.sessionId,\n },\n events: this.events,\n summary: this.summary(),\n }\n }\n\n private read(): DiagnosticEvent[] {\n try {\n const raw = this.storage?.getItem(storageKey)\n if (!raw) return []\n const parsed = JSON.parse(raw) as Partial<StoredDiagnostics>\n if (parsed.schemaVersion !== diagnosticsSchemaVersion || !Array.isArray(parsed.events)) {\n this.storage?.removeItem(storageKey)\n return []\n }\n if (!parsed.events.every(isDiagnosticEvent)) {\n this.storage?.removeItem(storageKey)\n return []\n }\n // v1 retained events predate per-event versions. Their containing store was already v1, so\n // retain them and normalize on the next write rather than discarding viewer evidence.\n const pruned = prune(\n parsed.events.map(\n (event) => ({ ...event, schemaVersion: diagnosticsSchemaVersion }) as DiagnosticEvent,\n ),\n this.now(),\n validRetention(parsed.retention),\n )\n this.retention = pruned.retention\n return pruned.events\n } catch {\n try {\n this.storage?.removeItem(storageKey)\n } catch {\n // Storage can fail on both reads and writes (for example, private browsing policies).\n }\n return []\n }\n }\n\n private persist() {\n try {\n this.storage?.setItem(\n storageKey,\n JSON.stringify({\n schemaVersion: diagnosticsSchemaVersion,\n events: this.events,\n retention: this.retention,\n }),\n )\n } catch {\n // Keep the in-memory record for this page, but never make diagnostics a rendering failure.\n }\n }\n\n private notify() {\n for (const listener of this.listeners) listener()\n }\n}\n\nexport function cacheMetadata(headers: Headers): CacheMetadata | undefined {\n const entries = [\n ['cacheControl', 'cache-control'],\n ['etag', 'etag'],\n ['lastModified', 'last-modified'],\n ['date', 'date'],\n ['age', 'age'],\n ] as const\n const metadata = Object.fromEntries(\n entries.flatMap(([key, header]) => {\n const value = headers.get(header)\n return value ? [[key, value]] : []\n }),\n ) as CacheMetadata\n return Object.keys(metadata).length ? metadata : undefined\n}\n\nfunction emptyRetention(): DiagnosticRetention {\n return { eventsPrunedByAge: 0, eventsPrunedByCount: 0 }\n}\n\nfunction validRetention(value: unknown): DiagnosticRetention {\n if (!value || typeof value !== 'object') return emptyRetention()\n const retention = value as Partial<DiagnosticRetention>\n return {\n eventsPrunedByAge:\n typeof retention.eventsPrunedByAge === 'number' && retention.eventsPrunedByAge >= 0\n ? retention.eventsPrunedByAge\n : 0,\n eventsPrunedByCount:\n typeof retention.eventsPrunedByCount === 'number' && retention.eventsPrunedByCount >= 0\n ? retention.eventsPrunedByCount\n : 0,\n }\n}\n\nfunction prune(events: DiagnosticEvent[], now: Date, priorRetention: DiagnosticRetention) {\n const cutoff = now.valueOf() - maximumAgeMillis\n const current = events.filter(\n (event) =>\n Number.isFinite(new Date(event.at).valueOf()) && new Date(event.at).valueOf() >= cutoff,\n )\n const discardedByAge = events.length - current.length\n const discardedByCount = Math.max(0, current.length - maximumEvents)\n return {\n events: current.slice(-maximumEvents),\n retention: {\n eventsPrunedByAge: priorRetention.eventsPrunedByAge + discardedByAge,\n eventsPrunedByCount: priorRetention.eventsPrunedByCount + discardedByCount,\n },\n }\n}\n\nfunction isDiagnosticEvent(value: unknown): value is PersistedDiagnosticEvent {\n if (!value || typeof value !== 'object') return false\n const event = value as Partial<DiagnosticEvent>\n return (\n (event.schemaVersion === undefined || event.schemaVersion === diagnosticsSchemaVersion) &&\n typeof event.at === 'string' &&\n Number.isFinite(new Date(event.at).valueOf()) &&\n typeof event.sessionId === 'string' &&\n typeof event.board === 'string' &&\n diagnosticKinds.includes(event.kind as (typeof diagnosticKinds)[number])\n )\n}\n\nfunction storageOrUndefined(): StorageLike | undefined {\n try {\n return window.localStorage\n } catch {\n return undefined\n }\n}\n",".panel {\n grid-column: var(--panel-column, span 6);\n grid-row: var(--panel-row, auto);\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 0.25em;\n min-width: 0;\n min-height: 0;\n padding: var(--gap);\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n background: var(--surface-raised);\n position: relative;\n isolation: isolate;\n overflow: hidden;\n line-height: 1.2;\n container-name: panel;\n container-type: inline-size;\n}\n.content {\n position: relative;\n z-index: 1;\n display: flex;\n flex: 0 1 auto;\n flex-direction: column;\n justify-content: center;\n gap: 0.25em;\n min-width: 0;\n min-height: 0;\n}\n.content:has([data-running-progress=\"signal-field\"]) {\n flex: 1 1 auto;\n}\n.error {\n border-color: var(--status-serious);\n}\n.wide {\n grid-column: span 12;\n}\n.primary {\n padding: 0.65em;\n gap: 0.1em;\n}\n.primary .content {\n gap: 0.1em;\n}\n.compact {\n min-height: 3.5em;\n padding: 0.2em;\n gap: 0;\n line-height: 1.05;\n justify-content: flex-start;\n}\n.compact .content {\n gap: 0;\n}\n.label {\n margin: 0;\n font-size: 1em;\n font-weight: 600;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n color: var(--ink-secondary);\n}\n.compact .label {\n font-size: 0.8em;\n}\n.hint {\n margin: 0;\n font-size: 0.75em;\n color: var(--ink-muted);\n}\n.branch {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: nowrap;\n}\n.observed {\n display: flex;\n gap: 0.35em;\n align-items: center;\n}\n.stale {\n color: var(--status-warning);\n}\n.status {\n margin: 0;\n font-size: 1.35em;\n font-weight: 650;\n}\n.compact .status {\n font-size: 1.1em;\n}\n.passed {\n color: var(--status-good);\n}\n.failed {\n color: var(--status-critical);\n}\n.running {\n color: var(--status-warning);\n}\n.cancelled,\n.unknown {\n color: var(--ink-secondary);\n}\n.link {\n align-self: flex-start;\n margin-top: 0.2em;\n color: var(--ink-secondary);\n font-size: 0.75em;\n font-weight: 600;\n text-underline-offset: 0.18em;\n}\n.link:hover {\n color: var(--ink-primary);\n}\n.primary :is(.hint, .observed, .link),\n.compact :is(.hint, .observed, .link) {\n font-size: 0.65em;\n}\n.compact .link {\n margin-top: 0;\n}\n@container panel (min-width: 48rem) {\n .primary.shallow {\n padding: 0.45em 0.65em;\n }\n .primary.shallow .content {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: baseline;\n column-gap: 0.7em;\n row-gap: 0.15em;\n }\n .primary.shallow .status {\n flex: 0 0 auto;\n font-size: 1em;\n }\n .primary.shallow :is(.label, .observed, .link) {\n flex: 0 0 auto;\n }\n}\n@container panel (min-width: 12rem) {\n .compact.shallow .content {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: baseline;\n column-gap: 0.7em;\n row-gap: 0.15em;\n }\n .compact.shallow :is(.label, .observed, .link) {\n flex: 0 0 auto;\n }\n}\n@media (max-width: 60rem) {\n .panel {\n grid-column: 1 / -1;\n grid-row: auto;\n min-height: 6em;\n }\n .primary .content,\n .compact .content {\n flex-direction: column;\n align-items: stretch;\n }\n}\n","/**\n * A panel-shaped hole, so the grid can be looked at and argued with before any signal exists.\n * Replaced by real panels in Stage 2 — nothing here is meant to survive.\n */\nexport function PanelPlaceholder({\n label,\n hint,\n wide = false,\n}: {\n label: string\n hint: string\n wide?: boolean\n}) {\n return (\n <section\n className={`${styles.panel} ${wide ? styles.wide : ''}`}\n data-panel\n data-panel-id=\"placeholder\"\n >\n <h2 className={styles.label}>{label}</h2>\n <p className={styles.hint}>{hint}</p>\n </section>\n )\n}\n\nimport styles from './PanelFrame.module.css'\n",".fact {\n display: contents;\n}\n@container panel (min-width: 48rem) {\n :global([data-display=\"compact\"][data-shallow=\"true\"]) .fact > * {\n margin: 0;\n }\n}\n@container panel (min-width: 12rem) {\n :global([data-display=\"compact\"][data-shallow=\"true\"]) .fact > * {\n margin: 0;\n }\n}\n","import type { Panel } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\n\n/** Convert the advisory board position into CSS grid placement. */\nexport function panelLayout(panel: Panel): CSSProperties | undefined {\n const position = panel.position\n if (!position) return undefined\n\n return {\n '--panel-column': `${position.x + 1} / span ${position.w}`,\n '--panel-row': `${position.y + 1} / span ${position.h}`,\n } as CSSProperties\n}\n","import type { Envelope, Panel } from '@ze-great-dashboard/shared'\nimport type { ReactNode } from 'react'\nimport styles from './PanelFrame.module.css'\nimport { panelLayout } from './panel-layout.ts'\n\ntype PanelStatusKind = 'passed' | 'failed' | 'running' | 'cancelled' | 'unknown'\n\nexport function PanelHint({ children }: { children: ReactNode }) {\n return <p className={styles.hint}>{children}</p>\n}\n\nexport function PanelStatus({\n children,\n status,\n}: {\n children: ReactNode\n status?: PanelStatusKind\n}) {\n return <p className={`${styles.status} ${status ? styles[status] : ''}`}>{children}</p>\n}\n\nexport function PanelBranch({ children, title }: { children: ReactNode; title: string }) {\n return (\n <span className={styles.branch} title={title}>\n {children}\n </span>\n )\n}\n\nexport function PanelObserved({\n children,\n stale = false,\n}: {\n children: ReactNode\n stale?: boolean\n}) {\n return (\n <p className={`${styles.hint} ${styles.observed} ${stale ? styles.stale : ''}`}>{children}</p>\n )\n}\n\nexport function PanelFrame({\n panel,\n envelope,\n error = false,\n field,\n children,\n}: {\n panel: Panel\n envelope?: Envelope\n error?: boolean\n /** Decorative active-run layer. It is intentionally a sibling of readable panel content. */\n field?: ReactNode\n children: ReactNode\n}) {\n const display =\n panel.display === 'primary' || panel.display === 'compact' ? panel.display : 'supporting'\n const shallow = panel.position?.h !== undefined && panel.position.h <= 2\n return (\n <section\n className={`${styles.panel} ${styles[display]} ${shallow ? styles.shallow : ''} ${error ? styles.error : ''}`}\n style={panelLayout(panel)}\n aria-busy={envelope ? undefined : true}\n data-panel\n data-panel-id={panel.id}\n data-display={display}\n data-shallow={shallow}\n data-error={error || undefined}\n >\n {field}\n <div className={styles.content} data-panel-content>\n <h2 className={styles.label}>{panel.label ?? panel.id}</h2>\n {children}\n <PanelSourceLink panelId={panel.id} link={envelope?.link} />\n </div>\n </section>\n )\n}\n\nfunction PanelSourceLink({ panelId, link }: { panelId: string; link?: string | null }) {\n if (!link) return null\n\n return (\n <a\n className={styles.link}\n href={link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`View source for ${panelId} (opens in a new tab)`}\n data-panel-link\n >\n View source <span aria-hidden=\"true\">↗</span>\n </a>\n )\n}\n","import { PanelObserved } from './PanelFrame.tsx'\n\nexport function ObservedAt({ value, label = 'As of' }: { value: string; label?: string }) {\n const observed = new Date(value)\n const formatted = observed.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n const age = Date.now() - observed.getTime()\n const stale = age > 5 * 60 * 1000\n const ageText = formatAge(age)\n return (\n <PanelObserved stale={stale}>\n <span aria-hidden=\"true\">◷</span> {label} {formatted} · {ageText}\n </PanelObserved>\n )\n}\n\nexport function formatAge(milliseconds: number) {\n if (milliseconds < 60_000) return 'just now'\n const minutes = Math.floor(milliseconds / 60_000)\n if (minutes < 60) return `${minutes}m ago`\n const hours = Math.floor(minutes / 60)\n return `${hours}h ${minutes % 60}m ago`\n}\n","import type { Panel } from '@ze-great-dashboard/shared'\nimport { type Envelope, httpValueSchema } from '@ze-great-dashboard/shared'\nimport styles from './HttpValuePanel.module.css'\nimport { ObservedAt } from './ObservedAt.tsx'\nimport { PanelFrame, PanelHint, PanelStatus } from './PanelFrame.tsx'\n\nexport function HttpValuePanel({\n panel,\n envelope,\n}: {\n panel: Panel\n envelope: Envelope | undefined\n}) {\n if (!envelope)\n return (\n <PanelFrame panel={panel}>\n <PanelHint>Loading…</PanelHint>\n </PanelFrame>\n )\n if (envelope.state === 'error')\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <PanelStatus>⚠ Unable to read</PanelStatus>\n <PanelHint>{envelope.error.message}</PanelHint>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n const signal = httpValueSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <PanelStatus>⚠ Invalid value</PanelStatus>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n return (\n <PanelFrame panel={panel} envelope={envelope}>\n <div className={styles.fact}>\n <PanelStatus>{String(signal.data.value)}</PanelStatus>\n <ObservedAt value={envelope.observedAt} />\n </div>\n </PanelFrame>\n )\n}\n",".variant {\n margin: 0;\n color: var(--ink-muted);\n font-size: 0.72em;\n text-transform: capitalize;\n transition: color 180ms ease;\n}\n@media (prefers-reduced-motion: reduce) {\n .variant {\n transition: none;\n }\n}\n",".frontier {\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--running-progress);\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, currentColor 16%, transparent),\n transparent\n );\n border-right: 1px solid color-mix(in srgb, currentColor 75%, transparent);\n}\n.now {\n position: absolute;\n top: 10%;\n bottom: 10%;\n left: 70%;\n width: 1px;\n background: color-mix(in srgb, var(--ink-primary) 45%, transparent);\n}\n.routes {\n position: absolute;\n inset: 18% 8%;\n display: grid;\n align-content: space-between;\n}\n.route {\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, var(--ink-muted) 45%, transparent),\n transparent\n );\n}\n.route:nth-child(2) {\n transform: translateX(8%);\n}\n.route:nth-child(3) {\n transform: translateX(-6%);\n}\n.trail,\n.packet {\n position: absolute;\n top: 50%;\n left: -10%;\n border-radius: 999px;\n animation: packet 4.8s ease-in-out infinite alternate;\n}\n.trail {\n width: 18%;\n height: 2px;\n background: linear-gradient(90deg, transparent, currentColor);\n opacity: 0.65;\n}\n.packet {\n width: 0.48em;\n height: 0.48em;\n background: currentColor;\n box-shadow: 0 0 0.65em currentColor;\n}\n@container (max-width: 40rem) {\n .routes,\n .trail,\n .packet,\n .now {\n display: none;\n }\n .frontier {\n width: 0.28em;\n border-right: 0;\n background: currentColor;\n }\n}\n@media (max-width: 42rem) {\n .routes,\n .trail,\n .packet,\n .now {\n display: none;\n }\n}\n@keyframes packet {\n from {\n transform: translate(-10vw, -50%);\n }\n to {\n transform: translate(120cqw, -50%);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .trail,\n .packet {\n animation: none;\n }\n .frontier {\n transition: none;\n }\n}\n","import styles from './ReleaseTransitField.module.css'\n\nexport function ReleaseTransitField() {\n return (\n <>\n <span className={styles.frontier} data-running-part=\"frontier\" />\n <span className={styles.now} data-running-part=\"transit-now\" />\n <span className={styles.routes} data-running-part=\"transit-routes\">\n {[0, 1, 2].map((route) => (\n <span className={styles.route} key={route} />\n ))}\n </span>\n <span className={styles.trail} data-running-part=\"transit-trail\" />\n <span className={styles.packet} data-running-part=\"transit-packet\" />\n </>\n )\n}\n",".field {\n position: absolute;\n z-index: 0;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n container-type: size;\n color: var(--status-warning);\n}\n.overdue {\n color: var(--status-serious);\n}\n.timing {\n width: 12ch;\n margin: 0;\n color: var(--ink-secondary);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.72em;\n font-variant-numeric: tabular-nums;\n text-align: end;\n white-space: nowrap;\n}\n.timingOverdue {\n color: var(--status-serious);\n}\n",".haze {\n position: absolute;\n inset: -15%;\n background:\n radial-gradient(\n ellipse at 18% 44%,\n color-mix(in srgb, currentColor 19%, transparent),\n transparent 42%\n ),\n radial-gradient(\n ellipse at 74% 63%,\n color-mix(in srgb, currentColor 12%, transparent),\n transparent 38%\n );\n animation: haze 15s ease-in-out infinite alternate;\n}\n.band {\n position: absolute;\n right: -15%;\n left: -15%;\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, currentColor 32%, transparent),\n transparent\n );\n animation: band 10s ease-in-out infinite alternate;\n}\n.bandOne {\n top: 32%;\n}\n.bandTwo {\n top: 67%;\n animation-delay: -4s;\n}\n.bandThree {\n top: 49%;\n animation-delay: -7s;\n opacity: 0.55;\n}\n.drift {\n position: absolute;\n width: 0.5em;\n height: 0.5em;\n border: 1px solid color-mix(in srgb, currentColor 78%, transparent);\n border-radius: 50%;\n box-shadow: 0 0 0.55em color-mix(in srgb, currentColor 55%, transparent);\n animation: drift 11s ease-in-out infinite alternate;\n}\n.driftOne {\n top: 25%;\n left: 12%;\n}\n.driftTwo {\n top: 72%;\n left: 58%;\n width: 0.34em;\n height: 0.34em;\n animation-duration: 14s;\n animation-delay: -4s;\n opacity: 0.6;\n}\n.driftThree {\n top: 18%;\n left: 74%;\n width: 0.7em;\n height: 0.7em;\n animation-duration: 17s;\n animation-delay: -9s;\n opacity: 0.55;\n}\n.driftFour {\n top: 58%;\n left: 31%;\n width: 0.42em;\n height: 0.42em;\n animation-duration: 9s;\n animation-delay: -2s;\n opacity: 0.75;\n}\n.driftFive {\n top: 84%;\n left: 83%;\n width: 0.58em;\n height: 0.58em;\n animation-duration: 13s;\n animation-delay: -6s;\n opacity: 0.45;\n}\n@container (max-width: 40rem) {\n .drift,\n .band {\n display: none;\n }\n .haze {\n inset: auto 0 0 auto;\n width: 2.5em;\n height: 2.5em;\n opacity: 0.65;\n }\n}\n@media (max-width: 42rem) {\n .drift,\n .band {\n display: none;\n }\n}\n@keyframes haze {\n to {\n transform: translate(9%, -4%);\n }\n}\n@keyframes band {\n to {\n transform: translateX(8%);\n opacity: 0.45;\n }\n}\n@keyframes drift {\n to {\n transform: translate(10cqw, -2em);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .haze,\n .band,\n .drift {\n animation: none;\n }\n}\n","import styles from './StatusWeatherField.module.css'\n\nexport function StatusWeatherField() {\n return (\n <>\n <span className={styles.haze} data-running-part=\"weather-haze\" />\n <span className={`${styles.band} ${styles.bandOne}`} />\n <span className={`${styles.band} ${styles.bandTwo}`} />\n <span className={`${styles.band} ${styles.bandThree}`} />\n <span className={`${styles.drift} ${styles.driftOne}`} />\n <span className={`${styles.drift} ${styles.driftTwo}`} />\n <span className={`${styles.drift} ${styles.driftThree}`} />\n <span className={`${styles.drift} ${styles.driftFour}`} />\n <span className={`${styles.drift} ${styles.driftFive}`} />\n </>\n )\n}\n",".anchor {\n position: absolute;\n top: 50%;\n left: var(--running-progress);\n}\n.body {\n position: absolute;\n inset: 0;\n animation: phased-marker 3.2s ease-in-out infinite alternate;\n animation-delay: var(--phased-marker-delay, 0s);\n will-change: transform;\n}\n@keyframes phased-marker {\n from {\n transform: translate(-10em, -50%);\n }\n to {\n transform: translate(-50%, -50%);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .body {\n animation: none;\n }\n}\n","import type { CSSProperties } from 'react'\nimport styles from './PhasedProgressMarker.module.css'\n\n/**\n * A progress-anchored decorative marker. The anchor owns live progress geometry; the body owns\n * its independent phase animation, so a timing render cannot replace its transform.\n */\nexport function PhasedProgressMarker({\n anchorClassName,\n bodyClassName,\n delay,\n anchorPart,\n bodyPart,\n}: {\n anchorClassName: string | undefined\n bodyClassName: string | undefined\n delay?: string\n anchorPart?: string\n bodyPart: string\n}) {\n const style = delay ? ({ '--phased-marker-delay': delay } as CSSProperties) : undefined\n return (\n <span className={`${styles.anchor} ${anchorClassName ?? ''}`} data-running-part={anchorPart}>\n <span\n className={`${styles.body} ${bodyClassName ?? ''}`}\n data-running-part={bodyPart}\n style={style}\n />\n </span>\n )\n}\n",".frontier {\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--running-progress);\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, currentColor 16%, transparent),\n transparent\n );\n border-right: 1px solid color-mix(in srgb, currentColor 75%, transparent);\n}\n.lanes {\n position: absolute;\n inset: 13% 7%;\n display: grid;\n align-content: space-between;\n}\n.lane {\n position: relative;\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, var(--edge) 90%, transparent),\n transparent\n );\n}\n.markerAnchor {\n width: 0.42em;\n height: 0.25em;\n}\n.markerBody {\n border-radius: 999px;\n background: currentColor;\n box-shadow: 0 0 0.6em currentColor;\n}\n.lane:nth-child(2) .markerBody {\n opacity: 0.7;\n}\n.lane:nth-child(3) .markerBody {\n opacity: 0.5;\n}\n.lane:nth-child(4) .markerBody {\n opacity: 0.8;\n}\n@container (max-width: 40rem) {\n .lanes {\n display: none;\n }\n .frontier {\n width: 0.28em;\n border-right: 0;\n background: currentColor;\n }\n}\n@media (max-width: 42rem) {\n .lanes {\n display: none;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .frontier {\n transition: none;\n }\n}\n","import { PhasedProgressMarker } from './PhasedProgressMarker.tsx'\nimport styles from './TelemetryBloomField.module.css'\n\nexport function TelemetryBloomField() {\n return (\n <>\n <span className={styles.frontier} data-running-part=\"frontier\" />\n <span className={styles.lanes} data-running-part=\"bloom-lanes\">\n {[0, 1, 2, 3].map((lane) => (\n <span className={styles.lane} key={lane} data-running-part=\"bloom-lane\">\n <PhasedProgressMarker\n anchorClassName={styles.markerAnchor}\n bodyClassName={styles.markerBody}\n delay={[undefined, '-0.8s', '-1.7s', '-2.4s'][lane]}\n anchorPart=\"bloom-marker-anchor\"\n bodyPart=\"bloom-marker\"\n />\n </span>\n ))}\n </span>\n </>\n )\n}\n","import type { RunningAnimation } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\nimport { ReleaseTransitField } from './ReleaseTransitField.tsx'\nimport styles from './RunningField.module.css'\nimport { StatusWeatherField } from './StatusWeatherField.tsx'\nimport { TelemetryBloomField } from './TelemetryBloomField.tsx'\n\nexport type RunningFieldAnimation = Extract<\n RunningAnimation,\n 'telemetry-bloom' | 'release-transit' | 'status-weather'\n>\n\nexport function isRunningFieldAnimation(\n animation: Exclude<RunningAnimation, 'off'>,\n): animation is RunningFieldAnimation {\n return ['telemetry-bloom', 'release-transit', 'status-weather'].includes(animation)\n}\n\nexport function RunningField({\n animation,\n progress,\n overdue,\n indeterminate,\n}: {\n animation: RunningFieldAnimation\n progress: number\n overdue: boolean\n indeterminate: boolean\n}) {\n const style = {\n '--running-progress': `${progress * 100}%`,\n } as CSSProperties\n return (\n <div\n className={`${styles.field} ${overdue ? styles.overdue : ''}`}\n data-animation={animation}\n data-running-field\n data-indeterminate={indeterminate || undefined}\n aria-hidden=\"true\"\n style={style}\n >\n {animation === 'telemetry-bloom' && <TelemetryBloomField />}\n {animation === 'release-transit' && <ReleaseTransitField />}\n {animation === 'status-weather' && <StatusWeatherField />}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\n\nconst VISUAL_TICK_MS = 20\n\nexport type RunningTiming = {\n elapsedMs: number | undefined\n estimatedDurationMs: number | undefined\n hasEstimate: boolean\n overdue: boolean\n progress: number\n}\n\nexport function useRunningTiming(\n runStartedAt?: string,\n estimatedDurationMs?: number,\n): RunningTiming {\n const now = useClock(Boolean(runStartedAt))\n const startedAt = runStartedAt ? new Date(runStartedAt).valueOf() : Number.NaN\n const elapsedMs = Number.isFinite(startedAt) ? Math.max(0, now - startedAt) : undefined\n const hasEstimate = elapsedMs !== undefined && estimatedDurationMs !== undefined\n const overdue = hasEstimate && elapsedMs > estimatedDurationMs\n const progress = hasEstimate ? Math.min(elapsedMs / estimatedDurationMs, 1) : 0\n return { elapsedMs, estimatedDurationMs, hasEstimate, overdue, progress }\n}\n\nfunction useClock(enabled: boolean) {\n const [now, setNow] = useState(() => Date.now())\n useEffect(() => {\n if (!enabled) return\n setNow(Date.now())\n // The timing text rounds to seconds, but progress gets display-cadence intermediate positions.\n // This avoids the visible sawtooth created by a coarse timer and CSS transition.\n const interval = window.setInterval(() => setNow(Date.now()), VISUAL_TICK_MS)\n return () => window.clearInterval(interval)\n }, [enabled])\n return now\n}\n\nexport function timingDescription(\n elapsedMs: number | undefined,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n) {\n const elapsed =\n elapsedMs === undefined ? 'Run in progress' : `Elapsed ${formatDuration(elapsedMs)}`\n const expected =\n estimatedDurationMs === undefined\n ? 'Expected duration unavailable'\n : `Expected ≈ ${formatDuration(estimatedDurationMs)}`\n return `${elapsed} · ${expected}${overdue ? ' · Over estimate' : ''}`\n}\n\nexport function compactTiming(\n elapsedMs: number | undefined,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n) {\n const elapsed = elapsedMs === undefined ? '—' : formatClockDuration(elapsedMs)\n const expected =\n estimatedDurationMs === undefined ? '?' : `~${formatClockDuration(estimatedDurationMs)}`\n return `${overdue ? '⚠' : '\\u00a0'}${elapsed}/${expected}`\n}\n\nfunction formatDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n if (hours > 0) return `${hours}h ${minutes}m`\n if (minutes > 0) return `${minutes}m ${seconds}s`\n return `${seconds}s`\n}\n\nfunction formatClockDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n const clock = `${minutes}:${String(seconds).padStart(2, '0')}`\n return hours > 0 ? `${hours}:${clock.padStart(5, '0')}` : clock\n}\n","import styles from './RunningField.module.css'\nimport { compactTiming, timingDescription } from './running-timing.ts'\n\n/** The sole readable timing projection for panel-scale decorative fields. */\nexport function RunningFieldTiming({\n elapsedMs,\n estimatedDurationMs,\n overdue,\n}: {\n elapsedMs: number | undefined\n estimatedDurationMs: number | undefined\n overdue: boolean\n}) {\n return (\n <p className={`${styles.timing} ${overdue ? styles.timingOverdue : ''}`}>\n <span className=\"screen-reader-only\">\n {timingDescription(elapsedMs, estimatedDurationMs, overdue)}\n </span>\n <span aria-hidden=\"true\">{compactTiming(elapsedMs, estimatedDurationMs, overdue)}</span>\n </p>\n )\n}\n",".progress {\n display: flex;\n align-items: center;\n gap: 0.6em;\n min-width: 0;\n color: var(--status-warning);\n}\n.visual {\n position: relative;\n flex: 0 0 auto;\n}\n.timing {\n margin: 0;\n color: var(--ink-secondary);\n font-size: 0.72em;\n}\n.overdue {\n color: var(--status-serious);\n}\n.overdue .timing {\n color: var(--status-serious);\n}\n.readout {\n width: 12ch;\n flex: 0 0 12ch;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-variant-numeric: tabular-nums;\n text-align: end;\n white-space: nowrap;\n}\n.radial .visual {\n width: 2.35em;\n height: 2.35em;\n border: 0.14em solid var(--edge);\n border-radius: 50%;\n background: conic-gradient(var(--status-warning) var(--running-progress), var(--edge) 0);\n box-shadow:\n inset 0 0 0 0.22em var(--surface-raised),\n 0 0 0.55em color-mix(in srgb, var(--status-warning) 45%, transparent);\n}\n.radial .visual::after {\n content: \"\";\n position: absolute;\n inset: -0.14em;\n border-radius: 50%;\n border-top: 0.14em solid var(--status-warning);\n animation: sweep 1.7s linear infinite;\n}\n.radialCore {\n position: absolute;\n inset: 0.68em;\n border-radius: 50%;\n background: var(--status-warning);\n box-shadow: 0 0 0.45em var(--status-warning);\n}\n.runway {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-self: stretch;\n container-type: inline-size;\n}\n.runway .visual {\n width: min(12em, 36vw);\n height: 0.8em;\n overflow: hidden;\n border: 1px solid var(--edge);\n border-radius: 999px;\n background: linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);\n}\n.runway .visual::after {\n content: \"\";\n position: absolute;\n top: -0.25em;\n bottom: -0.25em;\n left: calc(var(--running-progress) - 0.06em);\n width: 0.12em;\n background: var(--ink-primary);\n box-shadow: 0 0 0.45em var(--ink-primary);\n}\n.spark {\n position: absolute;\n top: 50%;\n left: -0.5em;\n width: 0.35em;\n height: 0.35em;\n border-radius: 50%;\n background: var(--ink-primary);\n box-shadow: 0 0 0.4em var(--status-warning);\n animation: spark 1.5s linear infinite;\n}\n.orbit .visual {\n width: 2.4em;\n height: 2.4em;\n border: 1px solid var(--edge);\n border-radius: 50%;\n}\n.orbit .visual::before {\n content: \"\";\n position: absolute;\n inset: 0.18em;\n border: 0.12em solid transparent;\n border-top-color: var(--status-warning);\n border-radius: 50%;\n transform: rotate(var(--running-degrees));\n}\n.orbitCore {\n position: absolute;\n inset: 0.75em;\n border-radius: 50%;\n background: var(--status-warning);\n box-shadow: 0 0 0.45em var(--status-warning);\n}\n.particle {\n position: absolute;\n top: 0.25em;\n left: calc(50% - 0.16em);\n width: 0.32em;\n height: 0.32em;\n border-radius: 50%;\n background: var(--ink-primary);\n transform-origin: 0.16em 0.95em;\n animation: orbit 1.8s linear infinite;\n}\n.particleTwo {\n animation-delay: -0.9s;\n background: var(--status-warning);\n}\n.indeterminate .visual {\n background-image: repeating-linear-gradient(\n 135deg,\n color-mix(in srgb, var(--status-warning) 70%, transparent) 0 0.25em,\n var(--edge) 0.25em 0.5em\n );\n animation: shift 1s linear infinite;\n}\n.signalField {\n container-type: size;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-self: stretch;\n flex: 1 1 auto;\n min-height: 2.8em;\n}\n.signalField .visual {\n width: auto;\n height: 1em;\n overflow: hidden;\n border: 1px solid var(--edge);\n border-radius: 999px;\n background: var(--surface);\n}\n.rail {\n position: absolute;\n inset: 0;\n background: linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);\n opacity: 0.75;\n}\n.lead {\n position: absolute;\n top: -0.2em;\n bottom: -0.2em;\n left: calc(var(--running-progress) - 0.08em);\n width: 0.16em;\n border-radius: 999px;\n background: var(--ink-primary);\n box-shadow: 0 0 0.5em var(--status-warning);\n}\n.pulse {\n position: absolute;\n top: 50%;\n left: -0.5em;\n width: 0.3em;\n height: 0.3em;\n border-radius: 50%;\n background: var(--ink-primary);\n box-shadow: 0 0 0.4em var(--status-warning);\n animation: pulse 2.4s ease-in-out infinite alternate;\n}\n.pulseTwo {\n animation-delay: -1.2s;\n}\n.tracks {\n display: none;\n}\n@container (min-width: 26rem) {\n .runway .visual {\n flex: 1 1 auto;\n width: auto;\n height: clamp(1.1em, 7cqw, 2.7em);\n box-shadow: inset 0 0 1em color-mix(in srgb, var(--status-warning) 16%, transparent);\n }\n .runway .visual::after {\n left: calc(var(--running-progress) - 0.08em);\n width: 0.16em;\n }\n .spark {\n animation-name: sparkWide;\n }\n}\n@container (max-width: 18rem) {\n .signalField {\n flex: 0 1 auto;\n min-height: 0;\n }\n .signalField .visual {\n width: 2.65em;\n height: 1.15em;\n }\n .signalField .rail {\n background: var(--edge);\n }\n .signalField .lead {\n top: 0.2em;\n bottom: 0.2em;\n width: 0.38em;\n border-radius: 50%;\n }\n .pulse {\n display: none;\n }\n}\n@container (max-height: 5rem) {\n .signalField {\n flex: 0 1 auto;\n min-height: 0;\n }\n .signalField .visual {\n width: 2.65em;\n height: 1.15em;\n }\n .signalField .rail {\n background: var(--edge);\n }\n .signalField .lead {\n top: 0.2em;\n bottom: 0.2em;\n width: 0.38em;\n border-radius: 50%;\n }\n .pulse {\n display: none;\n }\n}\n/* A size-contained signal field cannot use its own intrinsic height as a query input: its\n auto-sized content would always satisfy the compact branch. Width is the stable panel-scale\n discriminator; the field's parent already controls its available height. */\n@container (min-width: 26rem) {\n .signalField .visual {\n height: 100%;\n min-height: 8em;\n border-radius: 0.25em;\n background: linear-gradient(\n 180deg,\n color-mix(in srgb, var(--edge) 60%, transparent),\n transparent\n );\n }\n .signalField .visual::before {\n content: \"\";\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--running-progress);\n background:\n repeating-linear-gradient(\n 0deg,\n transparent 0 0.55em,\n color-mix(in srgb, var(--status-warning) 16%, transparent) 0.55em 0.6em\n ),\n linear-gradient(\n 90deg,\n color-mix(in srgb, var(--status-warning) 19%, transparent),\n color-mix(in srgb, var(--status-warning) 7%, transparent)\n );\n box-shadow: inset -0.8em 0 1em color-mix(in srgb, var(--status-warning) 22%, transparent);\n }\n .signalField .rail {\n top: 50%;\n bottom: auto;\n height: 1px;\n }\n .signalField .lead {\n top: calc(50% - 0.45em);\n bottom: auto;\n height: 0.9em;\n }\n .pulse {\n display: none;\n }\n .tracks {\n position: absolute;\n inset: 0.8em 0;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n }\n .track {\n position: relative;\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, var(--edge) 85%, transparent),\n transparent\n );\n }\n .markerAnchor {\n width: 0.38em;\n height: 0.22em;\n }\n .markerBody {\n border-radius: 0.06em;\n background: var(--status-warning);\n box-shadow: 0 0 0.4em var(--status-warning);\n }\n .track:nth-child(2) .markerBody {\n animation-delay: -0.8s;\n opacity: 0.7;\n }\n .track:nth-child(3) .markerBody {\n animation-delay: -1.7s;\n opacity: 0.45;\n }\n .track:nth-child(4) .markerBody {\n animation-delay: -2.4s;\n opacity: 0.7;\n }\n .track:nth-child(5) .markerBody {\n animation-delay: -0.35s;\n opacity: 0.55;\n }\n}\n@keyframes sweep {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes spark {\n to {\n transform: translateX(13em);\n }\n}\n@keyframes sparkWide {\n to {\n transform: translateX(100cqw);\n }\n}\n@keyframes orbit {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes shift {\n to {\n background-position: 1em 0;\n }\n}\n@keyframes pulse {\n from {\n transform: translate(-0.5em, -50%);\n }\n to {\n transform: translate(calc(var(--running-progress) + 0.5em), -50%);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .radial .visual::after,\n .spark,\n .runway .visual::after,\n .particle,\n .pulse,\n .lead,\n .signalField .visual::before,\n .indeterminate .visual {\n animation: none;\n }\n}\n","import type { RunningAnimation } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\nimport { PhasedProgressMarker } from './PhasedProgressMarker.tsx'\nimport styles from './RunningProgress.module.css'\nimport { compactTiming, type RunningTiming, timingDescription } from './running-timing.ts'\n\nexport function RunningProgress({\n animation,\n timing,\n}: {\n animation: LegacyRunningAnimation\n timing: RunningTiming\n}) {\n const { elapsedMs, estimatedDurationMs, hasEstimate, overdue, progress } = timing\n const usesReadout = animation === 'runway' || animation === 'signal-field'\n const timingText = timingDescription(elapsedMs, estimatedDurationMs, overdue)\n const style = {\n '--running-progress': `${progress * 100}%`,\n '--running-degrees': `${progress * 360}deg`,\n } as CSSProperties\n const animationStyle = animation === 'signal-field' ? styles.signalField : styles[animation]\n\n return (\n <div\n className={`${styles.progress} ${animationStyle} ${overdue ? styles.overdue : ''} ${hasEstimate ? '' : styles.indeterminate}`}\n style={style}\n data-running-progress={animation}\n data-overdue={overdue || undefined}\n data-indeterminate={!hasEstimate || undefined}\n >\n <div className={styles.visual} aria-hidden=\"true\" data-running-visual>\n {animation === 'radial' && <span className={styles.radialCore} />}\n {animation === 'runway' && <span className={styles.spark} />}\n {animation === 'orbit' && (\n <>\n <span className={styles.orbitCore} />\n <span className={styles.particle} />\n <span className={`${styles.particle} ${styles.particleTwo}`} />\n </>\n )}\n {animation === 'signal-field' && (\n <>\n <span className={styles.rail} />\n <span className={styles.lead} />\n <span className={styles.pulse} />\n <span className={`${styles.pulse} ${styles.pulseTwo}`} />\n <span className={styles.tracks} data-running-part=\"signal-tracks\">\n {[0, 1, 2, 3, 4].map((track) => (\n <span className={styles.track} key={track} data-running-part=\"signal-track\">\n <PhasedProgressMarker\n anchorClassName={styles.markerAnchor}\n bodyClassName={styles.markerBody}\n delay={[undefined, '-0.8s', '-1.7s', '-2.4s', '-0.35s'][track]}\n anchorPart=\"signal-marker-anchor\"\n bodyPart=\"signal-marker\"\n />\n </span>\n ))}\n </span>\n </>\n )}\n </div>\n <p className={`${styles.timing} ${usesReadout ? styles.readout : ''}`}>\n {usesReadout ? (\n <>\n <span className=\"screen-reader-only\">{timingText}</span>\n <span aria-hidden=\"true\">{compactTiming(elapsedMs, estimatedDurationMs, overdue)}</span>\n </>\n ) : (\n timingText\n )}\n </p>\n </div>\n )\n}\n\n/** The compact, inline treatments retained for existing boards. */\nexport type LegacyRunningAnimation = Extract<\n RunningAnimation,\n 'radial' | 'runway' | 'orbit' | 'signal-field'\n>\n\nexport function isLegacyRunningAnimation(\n animation: RunningAnimation,\n): animation is LegacyRunningAnimation {\n return ['radial', 'runway', 'orbit', 'signal-field'].includes(animation)\n}\n","import type { Panel } from '@ze-great-dashboard/shared'\nimport { useEffect, useState } from 'react'\nimport { PanelFrame, PanelStatus } from './PanelFrame.tsx'\nimport styles from './PipelineAnimationDemoPanel.module.css'\nimport { isRunningFieldAnimation, RunningField } from './RunningField.tsx'\nimport { RunningFieldTiming } from './RunningFieldTiming.tsx'\nimport { RunningProgress } from './RunningProgress.tsx'\nimport { useRunningTiming } from './running-timing.ts'\n\nconst RUN_DURATION_MS = 20_000\nconst ESTIMATED_DURATION_MS = 15_000\nconst REVIEW_DURATION_MS = 300_000\nconst variants = [\n 'radial',\n 'runway',\n 'orbit',\n 'signal-field',\n 'telemetry-bloom',\n 'release-transit',\n 'status-weather',\n] as const\n\n/**\n * A local comparison aid for the active-run treatments. It deliberately creates no signal or\n * diagnostic evidence: its state is derived only from the wall clock and repeats forever.\n */\nexport function PipelineAnimationDemoPanel({ panel }: { panel: Panel }) {\n const now = useClock()\n // A configured visible treatment turns the local comparison aid into a stable review panel.\n // `off` retains the rotating default: the demo exists to render a treatment.\n const fixedAnimation =\n panel.running_animation === undefined || panel.running_animation === 'off'\n ? undefined\n : panel.running_animation\n const durationMs = fixedAnimation ? REVIEW_DURATION_MS : RUN_DURATION_MS\n const runNumber = Math.floor(now / durationMs)\n const animation = fixedAnimation ?? variants[runNumber % variants.length] ?? 'radial'\n const runStartedAt = runNumber * durationMs\n\n return (\n <DemoRun\n panel={panel}\n animation={animation}\n runStartedAt={runStartedAt}\n estimatedDurationMs={fixedAnimation ? REVIEW_DURATION_MS : ESTIMATED_DURATION_MS}\n />\n )\n}\n\nfunction DemoRun({\n panel,\n animation,\n runStartedAt,\n estimatedDurationMs,\n}: {\n panel: Panel\n animation: (typeof variants)[number]\n runStartedAt: number\n estimatedDurationMs: number\n}) {\n const startedAt = new Date(runStartedAt).toISOString()\n const timing = useRunningTiming(startedAt, estimatedDurationMs)\n const usesField = isRunningFieldAnimation(animation)\n return (\n <PanelFrame\n panel={panel}\n field={\n usesField ? (\n <RunningField\n animation={animation}\n progress={timing.progress}\n overdue={timing.overdue}\n indeterminate={!timing.hasEstimate}\n />\n ) : undefined\n }\n >\n <PanelStatus status=\"running\">↻ Running</PanelStatus>\n <p className={styles.variant}>Demo treatment · {animation}</p>\n {usesField ? (\n <RunningFieldTiming\n elapsedMs={timing.elapsedMs}\n estimatedDurationMs={estimatedDurationMs}\n overdue={timing.overdue}\n />\n ) : (\n <RunningProgress animation={animation} timing={timing} />\n )}\n </PanelFrame>\n )\n}\n\nfunction useClock() {\n const [now, setNow] = useState(() => Date.now())\n useEffect(() => {\n const interval = window.setInterval(() => setNow(Date.now()), 1_000)\n return () => window.clearInterval(interval)\n }, [])\n return now\n}\n",".details {\n display: contents;\n}\n@container panel (min-width: 48rem) {\n :global([data-display=\"primary\"][data-shallow=\"true\"]) .details > * {\n margin: 0;\n }\n}\n","import {\n type Envelope,\n type Panel,\n type PipelineStatus,\n pipelineStatusSchema,\n visibleRunningAnimations,\n} from '@ze-great-dashboard/shared'\nimport { useState } from 'react'\nimport { ObservedAt } from './ObservedAt.tsx'\nimport { PanelBranch, PanelFrame, PanelHint, PanelStatus } from './PanelFrame.tsx'\nimport styles from './PipelinePanel.module.css'\nimport { isRunningFieldAnimation, RunningField } from './RunningField.tsx'\nimport { RunningFieldTiming } from './RunningFieldTiming.tsx'\nimport { isLegacyRunningAnimation, RunningProgress } from './RunningProgress.tsx'\nimport { useRunningTiming } from './running-timing.ts'\n\nexport function PipelinePanel({\n panel,\n envelope,\n}: {\n panel: Panel\n envelope: Envelope | undefined\n}) {\n if (!envelope)\n return (\n <PanelFrame panel={panel}>\n <PanelHint>Loading…</PanelHint>\n </PanelFrame>\n )\n if (envelope.state === 'error') {\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <PanelStatus>\n ⚠ {envelope.error.kind === 'no-runs' ? 'No workflow runs' : 'Unable to read'}\n </PanelStatus>\n <PanelHint>{envelope.error.message}</PanelHint>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n }\n\n const signal = pipelineStatusSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <PanelStatus>⚠ Invalid signal</PanelStatus>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n return <PipelineSignalPanel panel={panel} envelope={envelope} signal={signal.data} />\n}\n\nfunction PipelineSignalPanel({\n panel,\n envelope,\n signal,\n}: {\n panel: Panel\n envelope: Envelope\n signal: PipelineStatus\n}) {\n const presentation = statusPresentation(signal.status)\n // Keep an omitted treatment stable for this panel's lifetime; timing updates must not reshuffle it.\n const [defaultAnimation] = useState(selectDefaultRunningAnimation)\n const animation = panel.running_animation ?? defaultAnimation\n const activeRun = signal.status === 'running' && animation !== 'off'\n const timing = useRunningTiming(signal.runStartedAt, signal.estimatedDurationMs)\n const usesField = activeRun && isRunningFieldAnimation(animation)\n const usesLegacyProgress = activeRun && isLegacyRunningAnimation(animation)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n field={\n usesField ? (\n <RunningField\n animation={animation}\n progress={timing.progress}\n overdue={timing.overdue}\n indeterminate={!timing.hasEstimate}\n />\n ) : undefined\n }\n >\n <div className={styles.details}>\n <PanelStatus status={signal.status}>\n {presentation.glyph} {presentation.label}\n </PanelStatus>\n <PanelHint>\n {signal.name} · {signal.rawStatus}\n {signal.branch && (\n <PanelBranch title={`Branch: ${signal.branch}`}>\n <span aria-hidden=\"true\"> · ⎇ </span>\n <span className=\"screen-reader-only\">Branch: </span>\n {signal.branch}\n </PanelBranch>\n )}\n </PanelHint>\n {usesField && (\n <RunningFieldTiming\n elapsedMs={timing.elapsedMs}\n estimatedDurationMs={signal.estimatedDurationMs}\n overdue={timing.overdue}\n />\n )}\n {usesLegacyProgress && <RunningProgress animation={animation} timing={timing} />}\n {signal.status !== 'running' && signal.durationMs !== undefined && (\n <PanelHint>Took {formatDuration(signal.durationMs)}</PanelHint>\n )}\n {signal.sourceUpdatedAt && (\n <ObservedAt value={signal.sourceUpdatedAt} label=\"Run updated\" />\n )}\n <ObservedAt value={envelope.observedAt} />\n </div>\n </PanelFrame>\n )\n}\n\nfunction selectDefaultRunningAnimation() {\n return (\n visibleRunningAnimations[Math.floor(Math.random() * visibleRunningAnimations.length)] ??\n 'telemetry-bloom'\n )\n}\n\nfunction formatDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0) return `${hours}h ${minutes}m`\n if (minutes > 0) return `${minutes}m ${seconds}s`\n return `${seconds}s`\n}\n\nfunction statusPresentation(status: 'passed' | 'failed' | 'running' | 'cancelled' | 'unknown') {\n switch (status) {\n case 'passed':\n return { glyph: '✓', label: 'Passed' }\n case 'failed':\n return { glyph: '✕', label: 'Failed' }\n case 'running':\n return { glyph: '↻', label: 'Running' }\n case 'cancelled':\n return { glyph: '⊘', label: 'Cancelled' }\n case 'unknown':\n return { glyph: '?', label: 'Unknown' }\n }\n}\n","import { type Envelope, type Panel, pullRequestHealthSchema } from '@ze-great-dashboard/shared'\nimport { ObservedAt } from './ObservedAt.tsx'\nimport { PanelFrame, PanelHint, PanelStatus } from './PanelFrame.tsx'\n\nexport function PullRequestHealthPanel({\n panel,\n envelope,\n}: {\n panel: Panel\n envelope: Envelope | undefined\n}) {\n if (!envelope)\n return (\n <PanelFrame panel={panel}>\n <PanelHint>Loading…</PanelHint>\n </PanelFrame>\n )\n if (envelope.state === 'error')\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <PanelStatus>⚠ Unable to read</PanelStatus>\n <PanelHint>{envelope.error.message}</PanelHint>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n const signal = pullRequestHealthSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <PanelStatus>⚠ Invalid signal</PanelStatus>\n </PanelFrame>\n )\n const presentation = statusPresentation(signal.data.status)\n return (\n <PanelFrame panel={panel} envelope={envelope}>\n <PanelStatus status={signal.data.status}>\n {presentation.glyph} {presentation.label}\n </PanelStatus>\n <PanelHint>{signal.data.summary}</PanelHint>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n}\n\nfunction statusPresentation(status: 'passed' | 'failed' | 'running' | 'cancelled' | 'unknown') {\n switch (status) {\n case 'passed':\n return { glyph: '✓', label: 'Healthy' }\n case 'failed':\n return { glyph: '✕', label: 'Failed' }\n case 'running':\n return { glyph: '↻', label: 'Running' }\n case 'cancelled':\n return { glyph: '⊘', label: 'Cancelled' }\n case 'unknown':\n return { glyph: '?', label: 'Unknown' }\n }\n}\n","import type { Envelope, Panel } from '@ze-great-dashboard/shared'\nimport type { ComponentType } from 'react'\nimport { HttpValuePanel } from './HttpValuePanel.tsx'\nimport { PanelPlaceholder } from './PanelPlaceholder.tsx'\nimport { PipelineAnimationDemoPanel } from './PipelineAnimationDemoPanel.tsx'\nimport { PipelinePanel } from './PipelinePanel.tsx'\nimport { PullRequestHealthPanel } from './PullRequestHealthPanel.tsx'\n\ntype PanelRendererProps = {\n panel: Panel\n envelope: Envelope | undefined\n}\n\n/** The one client-side dispatch point for panel types. */\nexport const panelRenderers: Record<string, ComponentType<PanelRendererProps>> = {\n 'pipeline-status': PipelinePanel,\n 'pull-request-health': PullRequestHealthPanel,\n 'http-value': HttpValuePanel,\n 'pipeline-animation-demo': PipelineAnimationDemoPanel,\n}\n\nexport function PanelRenderer({ panel, envelope }: PanelRendererProps) {\n const Renderer = panelRenderers[panel.type]\n return Renderer ? (\n <Renderer panel={panel} envelope={envelope} />\n ) : (\n <PanelPlaceholder label={panel.type} hint=\"Not wired yet\" wide />\n )\n}\n","import { type ClientEnv, clientIdentitySchema } from '@ze-great-dashboard/shared'\nimport { useEffect } from 'react'\nimport type { DiagnosticSink } from './diagnostics.ts'\n\nconst clientUpdateIntervalMillis = 60_000\nconst clientUpdateTimeoutMillis = 10_000\nconst defaultReload = () => globalThis.window.location.reload()\n\nexport function useClientUpdate({\n env,\n diagnostics,\n fetcher,\n reload = defaultReload,\n}: {\n env: ClientEnv\n diagnostics: DiagnosticSink\n fetcher?: typeof fetch\n reload?: () => void\n}) {\n useEffect(() => {\n let cancelled = false\n let inFlight = false\n let activeController: AbortController | undefined\n const path = `${env.proxyPath}/client`\n\n const check = async () => {\n if (cancelled || inFlight) return\n inFlight = true\n const controller = new AbortController()\n activeController = controller\n const timeout = globalThis.setTimeout(() => controller.abort(), clientUpdateTimeoutMillis)\n diagnostics.record({ kind: 'client-update-check', path })\n try {\n const response = await (fetcher ?? globalThis.fetch)(path, {\n cache: 'no-store',\n signal: controller.signal,\n })\n if (!response.ok) throw new Error(`Client identity returned ${response.status}`)\n const parsed = clientIdentitySchema.safeParse(await response.json())\n if (!parsed.success) throw new Error('Client identity response was invalid')\n if (cancelled) return\n // assetPath is the server's immutable deployment selector. clientVersion is a label and\n // can change independently without changing the code the browser should load.\n if (parsed.data.assetPath !== env.assetPath) {\n diagnostics.record({\n kind: 'client-update-detected',\n path,\n current: { assetPath: env.assetPath, clientVersion: env.clientVersion },\n next: parsed.data,\n })\n reload()\n }\n } catch (error) {\n if (!cancelled && !(error instanceof DOMException && error.name === 'AbortError')) {\n diagnostics.record({\n kind: 'client-update-failure',\n path,\n message: error instanceof Error ? error.message : String(error),\n })\n }\n } finally {\n globalThis.clearTimeout(timeout)\n inFlight = false\n if (activeController === controller) activeController = undefined\n if (!cancelled) globalThis.setTimeout(() => void check(), clientUpdateIntervalMillis)\n }\n }\n\n void check()\n return () => {\n cancelled = true\n activeController?.abort()\n }\n }, [diagnostics, env.assetPath, env.clientVersion, env.proxyPath, fetcher, reload])\n}\n","import {\n type Envelope,\n type Panel,\n pipelineStatusSchema,\n pullRequestHealthSchema,\n} from '@ze-great-dashboard/shared'\nimport type { RenderedPanelDiagnostic } from './diagnostics.ts'\n\n/**\n * The compact public fact a viewer saw. Keep new panel projections here beside their\n * presentation boundary; this is intentionally not a source or server event contract.\n */\nexport function projectPanelDiagnostic(panel: Panel, envelope: Envelope): RenderedPanelDiagnostic {\n if (envelope.state === 'error') return { state: envelope.state, link: envelope.link }\n\n if (panel.type === 'pipeline-status') {\n const signal = pipelineStatusSchema.safeParse(envelope.signal)\n return {\n state: envelope.state,\n status: signal.success ? signal.data.status : undefined,\n link: envelope.link,\n }\n }\n\n if (panel.type === 'pull-request-health') {\n const signal = pullRequestHealthSchema.safeParse(envelope.signal)\n return {\n state: envelope.state,\n status: signal.success ? signal.data.status : undefined,\n link: envelope.link,\n }\n }\n\n return { state: envelope.state, link: envelope.link }\n}\n\nexport function panelDiagnosticChanged(\n previous: Envelope | undefined,\n panel: Panel,\n next: Envelope,\n) {\n if (!previous) return true\n const before = projectPanelDiagnostic(panel, previous)\n const after = projectPanelDiagnostic(panel, next)\n return (\n before.state !== after.state || before.status !== after.status || before.link !== after.link\n )\n}\n","import {\n type Board,\n type ClientEnv,\n type Envelope,\n envelopeSchema,\n parseDuration,\n resolveRefreshMillis,\n} from '@ze-great-dashboard/shared'\nimport { useEffect, useRef, useState } from 'react'\nimport { cacheMetadata, type DiagnosticSink } from './diagnostics.ts'\nimport { panelDiagnosticChanged, projectPanelDiagnostic } from './panel-diagnostics.ts'\n\nexport function usePanelSignals({\n board,\n env,\n diagnostics,\n}: {\n board: Board | undefined\n env: ClientEnv\n diagnostics: DiagnosticSink\n}) {\n const [signals, setSignals] = useState<Record<string, Envelope | undefined>>({})\n const signalsRef = useRef<Record<string, Envelope | undefined>>({})\n\n useEffect(() => {\n signalsRef.current = {}\n setSignals({})\n if (!board) return\n\n let cancelled = false\n const timers: number[] = []\n for (const panel of board.panels) {\n if (\n panel.type !== 'pipeline-status' &&\n panel.type !== 'pull-request-health' &&\n panel.type !== 'http-value'\n )\n continue\n let inFlight = false\n const refreshMillis = resolveRefreshMillis({\n boardDefaultMillis: parseDuration(board.refresh ?? '60s') ?? 60_000,\n panelOverrideMillis: panel.refresh\n ? (parseDuration(panel.refresh) ?? undefined)\n : undefined,\n adapterFloorMillis: 0,\n })\n const path = `${env.proxyPath}/panel/${encodeURIComponent(env.board)}/${encodeURIComponent(panel.id)}`\n const refresh = () => {\n if (cancelled || inFlight) return\n inFlight = true\n diagnostics.record({ kind: 'panel-fetch-start', panelId: panel.id, path })\n fetch(path)\n .then(async (response) => {\n const transport = {\n kind: 'panel-fetch-response' as const,\n panelId: panel.id,\n path,\n status: response.status,\n cache: cacheMetadata(response.headers),\n }\n if (response.status === 304) {\n diagnostics.record(transport)\n return undefined\n }\n try {\n const value: unknown = await response.json()\n const envelope = parseEnvelope(value)\n if (!envelope) {\n diagnostics.record(transport)\n diagnostics.record({\n kind: 'panel-fetch-parse-failure',\n panelId: panel.id,\n path,\n message: 'Response was not a valid signal envelope.',\n })\n return undefined\n }\n diagnostics.record({ ...transport, envelope })\n return envelope\n } catch (error) {\n diagnostics.record(transport)\n diagnostics.record({\n kind: 'panel-fetch-parse-failure',\n panelId: panel.id,\n path,\n message: errorMessage(error),\n })\n throw new DiagnosticParseFailure(error)\n }\n })\n .then((envelope) => {\n if (!cancelled && envelope) {\n const previous = signalsRef.current[panel.id]\n if (panelDiagnosticChanged(previous, panel, envelope)) {\n diagnostics.record({\n kind: 'panel-rendered',\n panelId: panel.id,\n path,\n rendered: projectPanelDiagnostic(panel, envelope),\n })\n }\n signalsRef.current = { ...signalsRef.current, [panel.id]: envelope }\n setSignals(signalsRef.current)\n }\n })\n .catch((error) => {\n if (!(error instanceof DiagnosticParseFailure)) {\n diagnostics.record({\n kind: 'panel-fetch-failure',\n panelId: panel.id,\n path,\n message: errorMessage(error),\n })\n }\n })\n .finally(() => {\n inFlight = false\n })\n }\n refresh()\n timers.push(window.setInterval(refresh, refreshMillis))\n }\n return () => {\n cancelled = true\n for (const timer of timers) window.clearInterval(timer)\n }\n }, [board, diagnostics, env.board, env.proxyPath])\n\n return signals\n}\n\nfunction errorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error)\n}\n\nclass DiagnosticParseFailure extends Error {\n constructor(error: unknown) {\n super(errorMessage(error))\n }\n}\n\nfunction parseEnvelope(value: unknown): Envelope | undefined {\n const result = envelopeSchema.safeParse(value)\n return result.success ? result.data : undefined\n}\n","import type { Board, ClientEnv } from '@ze-great-dashboard/shared'\nimport { useEffect, useRef, useState } from 'react'\nimport styles from './App.module.css'\nimport { Diagnostics } from './Diagnostics.tsx'\nimport { BrowserDiagnosticStore, cacheMetadata } from './diagnostics.ts'\nimport { PanelPlaceholder } from './PanelPlaceholder.tsx'\nimport { PanelRenderer } from './panel-registry.tsx'\nimport { useClientUpdate } from './useClientUpdate.ts'\nimport { usePanelSignals } from './usePanelSignals.ts'\n\n/**\n * The board shell.\n *\n * Stage 1 has no data: there is no proxy endpoint to poll yet. What this proves is the plumbing —\n * that the client was handed its configuration by the server and knows which version of itself it\n * is. The version readout is what makes two published versions visibly different, which is the\n * whole point of the Stage 1 exit criterion.\n */\nexport function App({ env }: { env: ClientEnv }) {\n const [board, setBoard] = useState<Board>()\n const [loadedBoardName, setLoadedBoardName] = useState<string>()\n const diagnosticsRef = useRef<BrowserDiagnosticStore | null>(null)\n if (!diagnosticsRef.current) diagnosticsRef.current = new BrowserDiagnosticStore(env)\n const diagnostics = diagnosticsRef.current\n useClientUpdate({ env, diagnostics })\n const signals = usePanelSignals({\n board: loadedBoardName === env.board ? board : undefined,\n env,\n diagnostics,\n })\n\n useEffect(() => {\n let cancelled = false\n setBoard(undefined)\n setLoadedBoardName(undefined)\n const path = `${env.proxyPath}/boards/${encodeURIComponent(env.board)}`\n diagnostics.record({ kind: 'board-fetch-start', path })\n fetch(path)\n .then(async (response) => {\n diagnostics.record({\n kind: 'board-fetch-response',\n path,\n status: response.status,\n cache: cacheMetadata(response.headers),\n })\n if (!response.ok) throw new Error(`Board configuration returned ${response.status}`)\n try {\n return await response.json()\n } catch (error) {\n diagnostics.record({\n kind: 'board-fetch-parse-failure',\n path,\n message: errorMessage(error),\n })\n throw new DiagnosticParseFailure(error)\n }\n })\n .then((value: unknown) => {\n if (!cancelled) {\n setBoard(value as Board)\n setLoadedBoardName(env.board)\n const panels = Array.isArray((value as { panels?: unknown }).panels)\n ? (value as { panels: Array<{ id?: unknown }> }).panels\n : []\n diagnostics.record({\n kind: 'board-fetch-response',\n path,\n boardSummary: {\n panelCount: panels.length,\n panelIds: panels.flatMap((panel) => (typeof panel.id === 'string' ? [panel.id] : [])),\n },\n })\n }\n })\n .catch((error) => {\n if (!(error instanceof DiagnosticParseFailure)) {\n diagnostics.record({ kind: 'board-fetch-failure', path, message: errorMessage(error) })\n }\n if (!cancelled) {\n setBoard({ panels: [] })\n setLoadedBoardName(env.board)\n }\n })\n return () => {\n cancelled = true\n }\n }, [diagnostics, env.board, env.proxyPath])\n\n return (\n <div className={styles.board}>\n <header className={styles.header}>\n <h1 className={styles.title}>{env.board}</h1>\n </header>\n\n <main className={styles.grid}>\n {!board && <PanelPlaceholder label=\"board\" hint=\"Loading configuration…\" wide />}\n {board?.panels.map((panel) => (\n <PanelRenderer key={panel.id} panel={panel} envelope={signals[panel.id]} />\n ))}\n </main>\n\n <footer className={styles.footer} data-board-footer>\n <span>Signals are read live from their configured authorities.</span>\n <Diagnostics log={diagnostics} />\n </footer>\n </div>\n )\n}\n\nfunction errorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error)\n}\n\nclass DiagnosticParseFailure extends Error {\n constructor(error: unknown) {\n super(errorMessage(error))\n }\n}\n",".error {\n margin: 0 auto;\n max-width: 60ch;\n padding: 2rem;\n color: var(--ink-primary);\n}\n.error pre {\n padding: 1rem;\n border-radius: var(--radius);\n border: 1px solid var(--status-critical);\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font-size: 0.75em;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n","import styles from './ConfigError.module.css'\n\nexport function ConfigError({ message }: { message: string }) {\n return (\n <div className={styles.error} role=\"alert\">\n <h1>⚠️ Dashboard misconfigured</h1>\n <p>The page loaded, but the server did not hand it usable configuration.</p>\n <pre>{message}</pre>\n </div>\n )\n}\n","import { readClientEnv } from '@ze-great-dashboard/shared'\nimport { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { App } from './App.tsx'\nimport { ConfigError } from './ConfigError.tsx'\nimport './styles.css'\n\nconst container = document.getElementById('root')\nif (!container) {\n throw new Error('No #root element in the document — the template is not the one we expect.')\n}\n\nconst root = createRoot(container)\n\ntry {\n root.render(\n <StrictMode>\n <App env={readClientEnv()} />\n </StrictMode>,\n )\n} catch (error) {\n // A radiator that fails silently is worse than one that says what's wrong. If configuration\n // never arrived, say so on screen rather than rendering an empty board.\n root.render(<ConfigError message={error instanceof Error ? error.message : String(error)} />)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
._board_76d7l_1{gap:var(--gap);height:100dvh;min-height:0;padding:var(--gap);flex-direction:column;display:flex;overflow:hidden auto}._header_76d7l_11{border-bottom:1px solid var(--edge);padding-bottom:var(--gap);flex:none;align-items:baseline;display:flex}._title_76d7l_18{letter-spacing:-.01em;margin:0;font-size:1.75em;font-weight:650}._grid_76d7l_24{gap:var(--gap);flex:1;grid-template-rows:repeat(12,minmax(0,1fr));grid-template-columns:repeat(12,1fr);grid-auto-rows:minmax(0,1fr);align-content:stretch;min-height:0;display:grid}._footer_76d7l_34{color:var(--ink-muted);flex-wrap:wrap;flex:none;justify-content:space-between;align-items:center;gap:.5rem;font-size:.75em;display:flex}@media (width<=60rem){._board_76d7l_1{height:auto;min-height:100dvh;overflow:visible}._grid_76d7l_24{flex:none;grid-template-columns:1fr;grid-auto-rows:auto;min-height:auto}}._diagnostics_lseur_1{position:relative}._button_lseur_5{border:1px solid var(--edge);background:var(--surface-raised);color:var(--ink-secondary);font:inherit;border-radius:.25rem;padding:.3em .55em}._area_lseur_14{z-index:1;border:1px solid var(--edge);border-radius:var(--radius);background:var(--surface-raised);width:min(24rem,90vw);padding:.75rem;position:absolute;bottom:calc(100% + .5rem);right:0;box-shadow:0 .5rem 1.5rem #0008}._area_lseur_14 p{margin:0 0 .5rem}._warning_lseur_31{color:var(--status-warning)}._panels_lseur_35{border-top:1px solid var(--edge);max-height:12rem;margin:.5rem 0;padding-top:.5rem;overflow-y:auto}._actions_lseur_43{gap:.5rem;display:flex}._panel_1gq90_1{grid-column:var(--panel-column,span 6);grid-row:var(--panel-row,auto);min-width:0;min-height:0;padding:var(--gap);border:1px solid var(--edge);border-radius:var(--radius);background:var(--surface-raised);isolation:isolate;flex-direction:column;justify-content:center;gap:.25em;line-height:1.2;display:flex;position:relative;overflow:hidden;container:panel/inline-size}._content_1gq90_21{z-index:1;flex-direction:column;flex:0 auto;justify-content:center;gap:.25em;min-width:0;min-height:0;display:flex;position:relative}._content_1gq90_21:has([data-running-progress=signal-field]){flex:auto}._error_1gq90_35{border-color:var(--status-serious)}._wide_1gq90_38{grid-column:span 12}._primary_1gq90_41{gap:.1em;padding:.65em}._primary_1gq90_41 ._content_1gq90_21{gap:.1em}._compact_1gq90_48{justify-content:flex-start;gap:0;min-height:3.5em;padding:.2em;line-height:1.05}._compact_1gq90_48 ._content_1gq90_21{gap:0}._label_1gq90_58{color:var(--ink-secondary);margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:1em;font-weight:600}._compact_1gq90_48 ._label_1gq90_58{font-size:.8em}._hint_1gq90_68{color:var(--ink-muted);margin:0;font-size:.75em}._branch_1gq90_73{white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}._observed_1gq90_77{align-items:center;gap:.35em;display:flex}._stale_1gq90_82{color:var(--status-warning)}._status_1gq90_85{margin:0;font-size:1.35em;font-weight:650}._compact_1gq90_48 ._status_1gq90_85{font-size:1.1em}._passed_1gq90_93{color:var(--status-good)}._failed_1gq90_96{color:var(--status-critical)}._running_1gq90_99{color:var(--status-warning)}._cancelled_1gq90_102,._unknown_1gq90_103{color:var(--ink-secondary)}._link_1gq90_106{color:var(--ink-secondary);text-underline-offset:.18em;align-self:flex-start;margin-top:.2em;font-size:.75em;font-weight:600}._link_1gq90_106:hover{color:var(--ink-primary)}._primary_1gq90_41 :is(._hint_1gq90_68,._observed_1gq90_77,._link_1gq90_106),._compact_1gq90_48 :is(._hint_1gq90_68,._observed_1gq90_77,._link_1gq90_106){font-size:.65em}._compact_1gq90_48 ._link_1gq90_106{margin-top:0}@container panel (width>=48rem){._primary_1gq90_41._shallow_1gq90_125{padding:.45em .65em}._primary_1gq90_41._shallow_1gq90_125 ._content_1gq90_21{flex-flow:wrap;align-items:baseline;gap:.15em .7em}._primary_1gq90_41._shallow_1gq90_125 ._status_1gq90_85{flex:none;font-size:1em}._primary_1gq90_41._shallow_1gq90_125 :is(._label_1gq90_58,._observed_1gq90_77,._link_1gq90_106){flex:none}}@container panel (width>=12rem){._compact_1gq90_48._shallow_1gq90_125 ._content_1gq90_21{flex-flow:wrap;align-items:baseline;gap:.15em .7em}._compact_1gq90_48._shallow_1gq90_125 :is(._label_1gq90_58,._observed_1gq90_77,._link_1gq90_106){flex:none}}@media (width<=60rem){._panel_1gq90_1{grid-area:auto/1/auto/-1;min-height:6em}._primary_1gq90_41 ._content_1gq90_21,._compact_1gq90_48 ._content_1gq90_21{flex-direction:column;align-items:stretch}}._fact_17pw7_1{display:contents}@container panel (width>=48rem){[data-display=compact][data-shallow=true] ._fact_17pw7_1>*{margin:0}}@container panel (width>=12rem){[data-display=compact][data-shallow=true] ._fact_17pw7_1>*{margin:0}}._variant_1lsfm_1{color:var(--ink-muted);text-transform:capitalize;margin:0;font-size:.72em;transition:color .18s}@media (prefers-reduced-motion:reduce){._variant_1lsfm_1{transition:none}}._frontier_9owsk_1{width:var(--running-progress);background:linear-gradient(90deg, color-mix(in srgb, currentColor 16%, transparent), transparent);border-right:1px solid color-mix(in srgb, currentColor 75%, transparent);position:absolute;inset:0 auto 0 0}._now_9owsk_12{background:color-mix(in srgb, var(--ink-primary) 45%, transparent);width:1px;position:absolute;top:10%;bottom:10%;left:70%}._routes_9owsk_20{align-content:space-between;display:grid;position:absolute;inset:18% 8%}._route_9owsk_20{background:linear-gradient(90deg, transparent, color-mix(in srgb, var(--ink-muted) 45%, transparent), transparent);height:1px}._route_9owsk_20:nth-child(2){transform:translate(8%)}._route_9owsk_20:nth-child(3){transform:translate(-6%)}._trail_9owsk_41,._packet_9owsk_42{border-radius:999px;animation:4.8s ease-in-out infinite alternate _packet_9owsk_42;position:absolute;top:50%;left:-10%}._trail_9owsk_41{opacity:.65;background:linear-gradient(90deg,#0000,currentColor);width:18%;height:2px}._packet_9owsk_42{background:currentColor;width:.48em;height:.48em;box-shadow:0 0 .65em}@container (width<=40rem){._routes_9owsk_20,._trail_9owsk_41,._packet_9owsk_42,._now_9owsk_12{display:none}._frontier_9owsk_1{background:currentColor;border-right:0;width:.28em}}@media (width<=42rem){._routes_9owsk_20,._trail_9owsk_41,._packet_9owsk_42,._now_9owsk_12{display:none}}@keyframes _packet_9owsk_42{0%{transform:translate(-10vw,-50%)}to{transform:translate(120cqw,-50%)}}@media (prefers-reduced-motion:reduce){._trail_9owsk_41,._packet_9owsk_42{animation:none}._frontier_9owsk_1{transition:none}}._field_pf9oz_1{z-index:0;pointer-events:none;color:var(--status-warning);position:absolute;inset:0;overflow:hidden;container-type:size}._overdue_pf9oz_10{color:var(--status-serious)}._timing_pf9oz_13{width:12ch;color:var(--ink-secondary);font-variant-numeric:tabular-nums;text-align:end;white-space:nowrap;margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.72em}._timingOverdue_pf9oz_23{color:var(--status-serious)}._haze_nu2ru_1{background:radial-gradient(ellipse at 18% 44%, color-mix(in srgb, currentColor 19%, transparent), transparent 42%), radial-gradient(ellipse at 74% 63%, color-mix(in srgb, currentColor 12%, transparent), transparent 38%);animation:15s ease-in-out infinite alternate _haze_nu2ru_1;position:absolute;inset:-15%}._band_nu2ru_17{background:linear-gradient(90deg, transparent, color-mix(in srgb, currentColor 32%, transparent), transparent);height:1px;animation:10s ease-in-out infinite alternate _band_nu2ru_17;position:absolute;left:-15%;right:-15%}._bandOne_nu2ru_30{top:32%}._bandTwo_nu2ru_33{animation-delay:-4s;top:67%}._bandThree_nu2ru_37{opacity:.55;animation-delay:-7s;top:49%}._drift_nu2ru_42{border:1px solid color-mix(in srgb, currentColor 78%, transparent);width:.5em;height:.5em;box-shadow:0 0 .55em color-mix(in srgb, currentColor 55%, transparent);border-radius:50%;animation:11s ease-in-out infinite alternate _drift_nu2ru_42;position:absolute}._driftOne_nu2ru_51{top:25%;left:12%}._driftTwo_nu2ru_55{opacity:.6;width:.34em;height:.34em;animation-duration:14s;animation-delay:-4s;top:72%;left:58%}._driftThree_nu2ru_64{opacity:.55;width:.7em;height:.7em;animation-duration:17s;animation-delay:-9s;top:18%;left:74%}._driftFour_nu2ru_73{opacity:.75;width:.42em;height:.42em;animation-duration:9s;animation-delay:-2s;top:58%;left:31%}._driftFive_nu2ru_82{opacity:.45;width:.58em;height:.58em;animation-duration:13s;animation-delay:-6s;top:84%;left:83%}@container (width<=40rem){._drift_nu2ru_42,._band_nu2ru_17{display:none}._haze_nu2ru_1{opacity:.65;width:2.5em;height:2.5em;inset:auto 0 0 auto}}@media (width<=42rem){._drift_nu2ru_42,._band_nu2ru_17{display:none}}@keyframes _haze_nu2ru_1{to{transform:translate(9%,-4%)}}@keyframes _band_nu2ru_17{to{opacity:.45;transform:translate(8%)}}@keyframes _drift_nu2ru_42{to{transform:translate(10cqw,-2em)}}@media (prefers-reduced-motion:reduce){._haze_nu2ru_1,._band_nu2ru_17,._drift_nu2ru_42{animation:none}}._anchor_scrah_1{top:50%;left:var(--running-progress);position:absolute}._body_scrah_6{animation:3.2s ease-in-out infinite alternate _phased-marker_scrah_1;animation-delay:var(--phased-marker-delay,0s);will-change:transform;position:absolute;inset:0}@keyframes _phased-marker_scrah_1{0%{transform:translate(-10em,-50%)}to{transform:translate(-50%,-50%)}}@media (prefers-reduced-motion:reduce){._body_scrah_6{animation:none}}._frontier_1fw3x_1{width:var(--running-progress);background:linear-gradient(90deg, color-mix(in srgb, currentColor 16%, transparent), transparent);border-right:1px solid color-mix(in srgb, currentColor 75%, transparent);position:absolute;inset:0 auto 0 0}._lanes_1fw3x_12{align-content:space-between;display:grid;position:absolute;inset:13% 7%}._lane_1fw3x_12{background:linear-gradient(90deg, transparent, color-mix(in srgb, var(--edge) 90%, transparent), transparent);height:1px;position:relative}._markerAnchor_1fw3x_28{width:.42em;height:.25em}._markerBody_1fw3x_32{background:currentColor;border-radius:999px;box-shadow:0 0 .6em}._lane_1fw3x_12:nth-child(2) ._markerBody_1fw3x_32{opacity:.7}._lane_1fw3x_12:nth-child(3) ._markerBody_1fw3x_32{opacity:.5}._lane_1fw3x_12:nth-child(4) ._markerBody_1fw3x_32{opacity:.8}@container (width<=40rem){._lanes_1fw3x_12{display:none}._frontier_1fw3x_1{background:currentColor;border-right:0;width:.28em}}@media (width<=42rem){._lanes_1fw3x_12{display:none}}@media (prefers-reduced-motion:reduce){._frontier_1fw3x_1{transition:none}}._progress_trasc_1{min-width:0;color:var(--status-warning);align-items:center;gap:.6em;display:flex}._visual_trasc_8{flex:none;position:relative}._timing_trasc_12{color:var(--ink-secondary);margin:0;font-size:.72em}._overdue_trasc_17,._overdue_trasc_17 ._timing_trasc_12{color:var(--status-serious)}._readout_trasc_23{font-variant-numeric:tabular-nums;text-align:end;white-space:nowrap;flex:0 0 12ch;width:12ch;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}._radial_trasc_31 ._visual_trasc_8{border:.14em solid var(--edge);background:conic-gradient(var(--status-warning) var(--running-progress), var(--edge) 0);width:2.35em;height:2.35em;box-shadow:inset 0 0 0 .22em var(--surface-raised), 0 0 .55em color-mix(in srgb, var(--status-warning) 45%, transparent);border-radius:50%}._radial_trasc_31 ._visual_trasc_8:after{content:"";border-top:.14em solid var(--status-warning);border-radius:50%;animation:1.7s linear infinite _sweep_trasc_1;position:absolute;inset:-.14em}._radialCore_trasc_49{background:var(--status-warning);box-shadow:0 0 .45em var(--status-warning);border-radius:50%;position:absolute;inset:.68em}._runway_trasc_56{grid-template-columns:minmax(0,1fr) auto;align-self:stretch;display:grid;container-type:inline-size}._runway_trasc_56 ._visual_trasc_8{border:1px solid var(--edge);background:linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);border-radius:999px;width:min(12em,36vw);height:.8em;overflow:hidden}._runway_trasc_56 ._visual_trasc_8:after{content:"";top:-.25em;bottom:-.25em;left:calc(var(--running-progress) - .06em);background:var(--ink-primary);width:.12em;box-shadow:0 0 .45em var(--ink-primary);position:absolute}._spark_trasc_80{background:var(--ink-primary);width:.35em;height:.35em;box-shadow:0 0 .4em var(--status-warning);border-radius:50%;animation:1.5s linear infinite _spark_trasc_80;position:absolute;top:50%;left:-.5em}._orbit_trasc_91 ._visual_trasc_8{border:1px solid var(--edge);border-radius:50%;width:2.4em;height:2.4em}._orbit_trasc_91 ._visual_trasc_8:before{content:"";border:.12em solid #0000;border-top-color:var(--status-warning);transform:rotate(var(--running-degrees));border-radius:50%;position:absolute;inset:.18em}._orbitCore_trasc_106{background:var(--status-warning);box-shadow:0 0 .45em var(--status-warning);border-radius:50%;position:absolute;inset:.75em}._particle_trasc_113{background:var(--ink-primary);transform-origin:.16em .95em;border-radius:50%;width:.32em;height:.32em;animation:1.8s linear infinite _orbit_trasc_91;position:absolute;top:.25em;left:calc(50% - .16em)}._particleTwo_trasc_124{background:var(--status-warning);animation-delay:-.9s}._indeterminate_trasc_128 ._visual_trasc_8{background-image:repeating-linear-gradient(135deg, color-mix(in srgb, var(--status-warning) 70%, transparent) 0 .25em, var(--edge) .25em .5em);animation:1s linear infinite _shift_trasc_1}._signalField_trasc_136{flex:auto;grid-template-columns:minmax(0,1fr) auto;align-self:stretch;min-height:2.8em;display:grid;container-type:size}._signalField_trasc_136 ._visual_trasc_8{border:1px solid var(--edge);background:var(--surface);border-radius:999px;width:auto;height:1em;overflow:hidden}._rail_trasc_152{background:linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);opacity:.75;position:absolute;inset:0}._lead_trasc_158{top:-.2em;bottom:-.2em;left:calc(var(--running-progress) - .08em);background:var(--ink-primary);width:.16em;box-shadow:0 0 .5em var(--status-warning);border-radius:999px;position:absolute}._pulse_trasc_168{background:var(--ink-primary);width:.3em;height:.3em;box-shadow:0 0 .4em var(--status-warning);border-radius:50%;animation:2.4s ease-in-out infinite alternate _pulse_trasc_168;position:absolute;top:50%;left:-.5em}._pulseTwo_trasc_179{animation-delay:-1.2s}._tracks_trasc_182{display:none}@container (width>=26rem){._runway_trasc_56 ._visual_trasc_8{width:auto;height:clamp(1.1em,7cqw,2.7em);box-shadow:inset 0 0 1em color-mix(in srgb, var(--status-warning) 16%, transparent);flex:auto}._runway_trasc_56 ._visual_trasc_8:after{left:calc(var(--running-progress) - .08em);width:.16em}._spark_trasc_80{animation-name:_sparkWide_trasc_1}}@container (width<=18rem){._signalField_trasc_136{flex:0 auto;min-height:0}._signalField_trasc_136 ._visual_trasc_8{width:2.65em;height:1.15em}._signalField_trasc_136 ._rail_trasc_152{background:var(--edge)}._signalField_trasc_136 ._lead_trasc_158{border-radius:50%;width:.38em;top:.2em;bottom:.2em}._pulse_trasc_168{display:none}}@container (height<=5rem){._signalField_trasc_136{flex:0 auto;min-height:0}._signalField_trasc_136 ._visual_trasc_8{width:2.65em;height:1.15em}._signalField_trasc_136 ._rail_trasc_152{background:var(--edge)}._signalField_trasc_136 ._lead_trasc_158{border-radius:50%;width:.38em;top:.2em;bottom:.2em}._pulse_trasc_168{display:none}}@container (width>=26rem){._signalField_trasc_136 ._visual_trasc_8{background:linear-gradient(180deg, color-mix(in srgb, var(--edge) 60%, transparent), transparent);border-radius:.25em;height:100%;min-height:8em}._signalField_trasc_136 ._visual_trasc_8:before{content:"";width:var(--running-progress);background:repeating-linear-gradient(0deg, transparent 0 .55em, color-mix(in srgb, var(--status-warning) 16%, transparent) .55em .6em), linear-gradient(90deg, color-mix(in srgb, var(--status-warning) 19%, transparent), color-mix(in srgb, var(--status-warning) 7%, transparent));box-shadow:inset -.8em 0 1em color-mix(in srgb, var(--status-warning) 22%, transparent);position:absolute;inset:0 auto 0 0}._signalField_trasc_136 ._rail_trasc_152{height:1px;top:50%;bottom:auto}._signalField_trasc_136 ._lead_trasc_158{height:.9em;top:calc(50% - .45em);bottom:auto}._pulse_trasc_168{display:none}._tracks_trasc_182{flex-direction:column;justify-content:space-between;display:flex;position:absolute;inset:.8em 0}._track_trasc_182{background:linear-gradient(90deg, transparent, color-mix(in srgb, var(--edge) 85%, transparent), transparent);height:1px;position:relative}._markerAnchor_trasc_306{width:.38em;height:.22em}._markerBody_trasc_310{background:var(--status-warning);box-shadow:0 0 .4em var(--status-warning);border-radius:.06em}._track_trasc_182:nth-child(2) ._markerBody_trasc_310{opacity:.7;animation-delay:-.8s}._track_trasc_182:nth-child(3) ._markerBody_trasc_310{opacity:.45;animation-delay:-1.7s}._track_trasc_182:nth-child(4) ._markerBody_trasc_310{opacity:.7;animation-delay:-2.4s}._track_trasc_182:nth-child(5) ._markerBody_trasc_310{opacity:.55;animation-delay:-.35s}}@keyframes _sweep_trasc_1{to{transform:rotate(360deg)}}@keyframes _spark_trasc_80{to{transform:translate(13em)}}@keyframes _sparkWide_trasc_1{to{transform:translate(100cqw)}}@keyframes _orbit_trasc_91{to{transform:rotate(360deg)}}@keyframes _shift_trasc_1{to{background-position:1em 0}}@keyframes _pulse_trasc_168{0%{transform:translate(-.5em,-50%)}to{transform:translate(calc(var(--running-progress) + .5em), -50%)}}@media (prefers-reduced-motion:reduce){._radial_trasc_31 ._visual_trasc_8:after,._spark_trasc_80,._runway_trasc_56 ._visual_trasc_8:after,._particle_trasc_113,._pulse_trasc_168,._lead_trasc_158,._signalField_trasc_136 ._visual_trasc_8:before,._indeterminate_trasc_128 ._visual_trasc_8{animation:none}}._details_1isu9_1{display:contents}@container panel (width>=48rem){[data-display=primary][data-shallow=true] ._details_1isu9_1>*{margin:0}}._error_yx1g9_1{max-width:60ch;color:var(--ink-primary);margin:0 auto;padding:2rem}._error_yx1g9_1 pre{border-radius:var(--radius);border:1px solid var(--status-critical);background:var(--surface-raised);color:var(--ink-secondary);white-space:pre-wrap;overflow-wrap:anywhere;padding:1rem;font-size:.75em}:root{--surface:#12140f;--surface-raised:#1a1a19;--ink-primary:#fff;--ink-secondary:#c3c2b7;--ink-muted:#898781;--edge:#2f312b;--status-good:#0ca30c;--status-warning:#fab219;--status-serious:#ec835a;--status-critical:#d03b3b;--gap:1rem;--radius:.5rem;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}*{box-sizing:border-box}html,body{height:100%;margin:0}body{background:var(--surface);color:var(--ink-primary);font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Helvetica,Arial,sans-serif;font-size:clamp(16px,1.1vw + .5rem,28px);line-height:1.4;overflow-x:hidden}.screen-reader-only{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}
|
package/client/index.html
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
<title>Trust Dashboard</title>
|
|
12
12
|
|
|
13
13
|
<script type="importmap">{"imports":{"react":"https://esm.sh/react@19.2.8","react/":"https://esm.sh/react@19.2.8/","react-dom":"https://esm.sh/react-dom@19.2.8","react-dom/":"https://esm.sh/react-dom@19.2.8/","scheduler":"https://esm.sh/scheduler@0.27.0","scheduler/":"https://esm.sh/scheduler@0.27.0/","zod":"https://esm.sh/zod@4.4.3","zod/":"https://esm.sh/zod@4.4.3/"}}</script>
|
|
14
|
-
<script type="module" crossorigin src="/__ASSET_PATH__/assets/index-
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/__ASSET_PATH__/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/__ASSET_PATH__/assets/index-BgvnHC8t.js"></script>
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/__ASSET_PATH__/assets/index-TlrdchAy.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._diagnostics_lseur_1{position:relative}._button_lseur_5{border:1px solid var(--edge);background:var(--surface-raised);color:var(--ink-secondary);font:inherit;border-radius:.25rem;padding:.3em .55em}._area_lseur_14{z-index:1;border:1px solid var(--edge);border-radius:var(--radius);background:var(--surface-raised);width:min(24rem,90vw);padding:.75rem;position:absolute;bottom:calc(100% + .5rem);right:0;box-shadow:0 .5rem 1.5rem #0008}._area_lseur_14 p{margin:0 0 .5rem}._warning_lseur_31{color:var(--status-warning)}._panels_lseur_35{border-top:1px solid var(--edge);max-height:12rem;margin:.5rem 0;padding-top:.5rem;overflow-y:auto}._actions_lseur_43{gap:.5rem;display:flex}:root{--surface:#12140f;--surface-raised:#1a1a19;--ink-primary:#fff;--ink-secondary:#c3c2b7;--ink-muted:#898781;--edge:#2f312b;--status-good:#0ca30c;--status-warning:#fab219;--status-serious:#ec835a;--status-critical:#d03b3b;--gap:1rem;--radius:.5rem;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}*{box-sizing:border-box}.screen-reader-only{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}html,body{height:100%;margin:0}body{background:var(--surface);color:var(--ink-primary);font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Helvetica,Arial,sans-serif;font-size:clamp(16px,1.1vw + .5rem,28px);line-height:1.4;overflow-x:hidden}.board{gap:var(--gap);height:100dvh;min-height:0;padding:var(--gap);flex-direction:column;display:flex;overflow:hidden auto}.board__header{border-bottom:1px solid var(--edge);padding-bottom:var(--gap);flex:none;align-items:baseline;display:flex}.board__title{letter-spacing:-.01em;margin:0;font-size:1.75em;font-weight:650}.board__grid{gap:var(--gap);flex:1;grid-template-rows:repeat(12,minmax(0,1fr));grid-template-columns:repeat(12,1fr);grid-auto-rows:minmax(0,1fr);align-content:stretch;min-height:0;display:grid}.panel{grid-column:var(--panel-column,span 6);grid-row:var(--panel-row,auto);min-width:0;min-height:0;padding:var(--gap);border:1px solid var(--edge);border-radius:var(--radius);background:var(--surface-raised);isolation:isolate;flex-direction:column;justify-content:center;gap:.25em;line-height:1.2;display:flex;position:relative;overflow:hidden;container:panel/inline-size}.panel__content{z-index:1;flex-direction:column;flex:0 auto;justify-content:center;gap:.25em;min-width:0;min-height:0;display:flex;position:relative}.panel__content:has(.running-progress--signal-field){flex:auto}.panel--wide{grid-column:span 12}.panel__label{color:var(--ink-secondary);margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:1em;font-weight:600}.panel__hint{color:var(--ink-muted);margin:0;font-size:.75em}.panel__branch{white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.panel__observed{align-items:center;gap:.35em;display:flex}.panel__observed--stale{color:var(--status-warning)}.panel__status{margin:0;font-size:1.35em;font-weight:650}.panel__status--passed{color:var(--status-good)}.panel__status--failed{color:var(--status-critical)}.panel__status--running{color:var(--status-warning)}.panel__status--cancelled,.panel__status--unknown{color:var(--ink-secondary)}.running-field{z-index:0;pointer-events:none;color:var(--status-warning);position:absolute;inset:0;overflow:hidden;container-type:size}.running-field__timing{width:12ch;color:var(--ink-secondary);font-variant-numeric:tabular-nums;text-align:end;white-space:nowrap;margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.72em}.running-field__timing--overdue,.running-field--overdue{color:var(--status-serious)}.running-field__bloom-frontier,.running-field__transit-frontier{width:var(--running-progress);background:linear-gradient(90deg, color-mix(in srgb, currentColor 16%, transparent), transparent);border-right:1px solid color-mix(in srgb, currentColor 75%, transparent);position:absolute;inset:0 auto 0 0}.running-field__bloom-lanes{align-content:space-between;display:grid;position:absolute;inset:13% 7%}.running-field__bloom-lane{background:linear-gradient(90deg, transparent, color-mix(in srgb, var(--edge) 90%, transparent), transparent);height:1px;position:relative}.running-field__bloom-marker{top:50%;left:var(--running-progress);background:currentColor;border-radius:999px;width:.42em;height:.25em;animation:3.2s ease-in-out infinite alternate bloom-marker;position:absolute;box-shadow:0 0 .6em}.running-field__bloom-lane:nth-child(2) .running-field__bloom-marker{opacity:.7;animation-delay:-.8s}.running-field__bloom-lane:nth-child(3) .running-field__bloom-marker{opacity:.5;animation-delay:-1.7s}.running-field__bloom-lane:nth-child(4) .running-field__bloom-marker{opacity:.8;animation-delay:-2.4s}.running-field__transit-routes{align-content:space-between;display:grid;position:absolute;inset:18% 8%}.running-field__transit-route{background:linear-gradient(90deg, transparent, color-mix(in srgb, var(--ink-muted) 45%, transparent), transparent);height:1px}.running-field__transit-route:nth-child(2){transform:translate(8%)}.running-field__transit-route:nth-child(3){transform:translate(-6%)}.running-field__transit-now{background:color-mix(in srgb, var(--ink-primary) 45%, transparent);width:1px;position:absolute;top:10%;bottom:10%;left:70%}.running-field__transit-trail,.running-field__transit-packet{border-radius:999px;animation:4.8s ease-in-out infinite alternate transit-packet;position:absolute;top:50%;left:-10%}.running-field__transit-trail{opacity:.65;background:linear-gradient(90deg,#0000,currentColor);width:18%;height:2px}.running-field__transit-packet{background:currentColor;width:.48em;height:.48em;box-shadow:0 0 .65em}.running-field__weather-haze{background:radial-gradient(ellipse at 18% 44%, color-mix(in srgb, currentColor 19%, transparent), transparent 42%), radial-gradient(ellipse at 74% 63%, color-mix(in srgb, currentColor 12%, transparent), transparent 38%);animation:15s ease-in-out infinite alternate weather-haze;position:absolute;inset:-15%}.running-field__weather-band{background:linear-gradient(90deg, transparent, color-mix(in srgb, currentColor 32%, transparent), transparent);height:1px;animation:10s ease-in-out infinite alternate weather-band;position:absolute;left:-15%;right:-15%}.running-field__weather-band--one{top:32%}.running-field__weather-band--two{animation-delay:-4s;top:67%}.running-field__weather-band--three{opacity:.55;animation-delay:-7s;top:49%}.running-field__weather-drift{border:1px solid color-mix(in srgb, currentColor 78%, transparent);width:.5em;height:.5em;box-shadow:0 0 .55em color-mix(in srgb, currentColor 55%, transparent);border-radius:50%;animation:11s ease-in-out infinite alternate weather-drift;position:absolute}.running-field__weather-drift--one{top:25%;left:12%}.running-field__weather-drift--two{opacity:.6;width:.34em;height:.34em;animation-duration:14s;animation-delay:-4s;top:72%;left:58%}.running-field__weather-drift--three{opacity:.55;width:.7em;height:.7em;animation-duration:17s;animation-delay:-9s;top:18%;left:74%}.running-field__weather-drift--four{opacity:.75;width:.42em;height:.42em;animation-duration:9s;animation-delay:-2s;top:58%;left:31%}.running-field__weather-drift--five{opacity:.45;width:.58em;height:.58em;animation-duration:13s;animation-delay:-6s;top:84%;left:83%}@container (width<=40rem){.running-field__bloom-lanes,.running-field__transit-routes,.running-field__transit-trail,.running-field__transit-packet,.running-field__weather-drift,.running-field__weather-band{display:none}.running-field__bloom-frontier,.running-field__transit-frontier{background:currentColor;border-right:0;width:.28em}.running-field__weather-haze{opacity:.65;width:2.5em;height:2.5em;inset:auto 0 0 auto}.running-field__transit-now{display:none}}@media (width<=42rem){.running-field__bloom-lanes,.running-field__transit-routes,.running-field__transit-trail,.running-field__transit-packet,.running-field__weather-drift,.running-field__weather-band,.running-field__transit-now{display:none}}.running-progress{min-width:0;color:var(--status-warning);align-items:center;gap:.6em;display:flex}.running-progress__visual{flex:none;position:relative}.running-progress__timing{color:var(--ink-secondary);margin:0;font-size:.72em}.running-progress__timing--readout{width:12ch;color:var(--ink-secondary);font-variant-numeric:tabular-nums;text-align:end;white-space:nowrap;flex:0 0 12ch;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.running-progress--radial .running-progress__visual{border:.14em solid var(--edge);background:conic-gradient(var(--status-warning) var(--running-progress), var(--edge) 0);width:2.35em;height:2.35em;box-shadow:inset 0 0 0 .22em var(--surface-raised), 0 0 .55em color-mix(in srgb, var(--status-warning) 45%, transparent);border-radius:50%}.running-progress--radial .running-progress__visual:after{content:"";border-top:.14em solid var(--status-warning);border-radius:50%;animation:1.7s linear infinite running-sweep;position:absolute;inset:-.14em}.running-progress--radial .running-progress__radial-core{background:var(--status-warning);box-shadow:0 0 .45em var(--status-warning);border-radius:50%;position:absolute;inset:.68em}.running-progress--runway .running-progress__visual{border:1px solid var(--edge);background:linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);border-radius:999px;width:min(12em,36vw);height:.8em;overflow:hidden}.running-progress--runway .running-progress__visual:after{content:"";top:-.25em;bottom:-.25em;left:calc(var(--running-progress) - .06em);background:var(--ink-primary);width:.12em;box-shadow:0 0 .45em var(--ink-primary);position:absolute}.running-progress--runway .running-progress__runway-spark{background:var(--ink-primary);width:.35em;height:.35em;box-shadow:0 0 .4em var(--status-warning);border-radius:50%;animation:1.5s linear infinite runway-spark;position:absolute;top:50%;left:-.5em}.running-progress--runway{grid-template-columns:minmax(0,1fr) auto;align-self:stretch;display:grid;container-type:inline-size}@container (width>=26rem){.running-progress--runway .running-progress__visual{width:auto;height:clamp(1.1em,7cqw,2.7em);box-shadow:inset 0 0 1em color-mix(in srgb, var(--status-warning) 16%, transparent);flex:auto}.running-progress--runway .running-progress__visual:after{left:calc(var(--running-progress) - .08em);width:.16em}.running-progress--runway .running-progress__runway-spark{animation-name:runway-spark-wide}}.running-progress--orbit .running-progress__visual{border:1px solid var(--edge);border-radius:50%;width:2.4em;height:2.4em}.running-progress--orbit .running-progress__visual:before{content:"";border:.12em solid #0000;border-top-color:var(--status-warning);transform:rotate(var(--running-degrees));border-radius:50%;position:absolute;inset:.18em}.running-progress__orbit-core{background:var(--status-warning);box-shadow:0 0 .45em var(--status-warning);border-radius:50%;position:absolute;inset:.75em}.running-progress__orbit-particle{background:var(--ink-primary);transform-origin:.16em .95em;border-radius:50%;width:.32em;height:.32em;animation:1.8s linear infinite orbit-particle;position:absolute;top:.25em;left:calc(50% - .16em)}.running-progress__orbit-particle--two{background:var(--status-warning);animation-delay:-.9s}.running-progress--indeterminate .running-progress__visual{background-image:repeating-linear-gradient(135deg, color-mix(in srgb, var(--status-warning) 70%, transparent) 0 .25em, var(--edge) .25em .5em);animation:1s linear infinite indeterminate-shift}.running-progress--overdue,.running-progress--overdue .running-progress__timing{color:var(--status-serious)}.running-progress--signal-field{flex:auto;grid-template-columns:minmax(0,1fr) auto;align-self:stretch;min-height:2.8em;display:grid;container-type:size}.running-progress--signal-field .running-progress__visual{border:1px solid var(--edge);background:var(--surface);border-radius:999px;width:auto;height:1em;overflow:hidden}.running-progress__signal-rail{background:linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);opacity:.75;position:absolute;inset:0}.running-progress__signal-lead{top:-.2em;bottom:-.2em;left:calc(var(--running-progress) - .08em);background:var(--ink-primary);width:.16em;box-shadow:0 0 .5em var(--status-warning);border-radius:999px;position:absolute}.running-progress__signal-pulse{background:var(--ink-primary);width:.3em;height:.3em;box-shadow:0 0 .4em var(--status-warning);border-radius:50%;animation:2.4s ease-in-out infinite alternate signal-pulse;position:absolute;top:50%;left:-.5em}.running-progress__signal-pulse--two{animation-delay:-1.2s}.running-progress__signal-tracks{display:none}@container (width<=18rem){.running-progress--signal-field{flex:0 auto;min-height:0}.running-progress--signal-field .running-progress__visual{width:2.65em;height:1.15em}.running-progress--signal-field .running-progress__signal-rail{background:var(--edge)}.running-progress--signal-field .running-progress__signal-lead{border-radius:50%;width:.38em;top:.2em;bottom:.2em}.running-progress--signal-field .running-progress__signal-pulse{display:none}}@container (height<=5rem){.running-progress--signal-field{flex:0 auto;min-height:0}.running-progress--signal-field .running-progress__visual{width:2.65em;height:1.15em}.running-progress--signal-field .running-progress__signal-rail{background:var(--edge)}.running-progress--signal-field .running-progress__signal-lead{border-radius:50%;width:.38em;top:.2em;bottom:.2em}.running-progress--signal-field .running-progress__signal-pulse{display:none}}@container (width>=26rem) and (height>=10rem){.running-progress--signal-field .running-progress__visual{background:linear-gradient(180deg, color-mix(in srgb, var(--edge) 60%, transparent), transparent);border-radius:.25em;height:100%;min-height:8em}.running-progress--signal-field .running-progress__visual:before{content:"";width:var(--running-progress);background:repeating-linear-gradient(0deg, transparent 0 .55em, color-mix(in srgb, var(--status-warning) 16%, transparent) .55em .6em), linear-gradient(90deg, color-mix(in srgb, var(--status-warning) 19%, transparent), color-mix(in srgb, var(--status-warning) 7%, transparent));box-shadow:inset -.8em 0 1em color-mix(in srgb, var(--status-warning) 22%, transparent);position:absolute;inset:0 auto 0 0}.running-progress--signal-field .running-progress__signal-rail{background:linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);height:1px;top:50%;bottom:auto}.running-progress--signal-field .running-progress__signal-lead{height:.9em;top:calc(50% - .45em);bottom:auto}.running-progress--signal-field .running-progress__signal-pulse{display:none}.running-progress--signal-field .running-progress__signal-tracks{flex-direction:column;justify-content:space-between;display:flex;position:absolute;inset:.8em 0}.running-progress--signal-field .running-progress__signal-track{background:linear-gradient(90deg, transparent, color-mix(in srgb, var(--edge) 85%, transparent), transparent);height:1px;position:relative}.running-progress--signal-field .running-progress__signal-marker{top:50%;left:var(--running-progress);width:.38em;height:.22em;position:absolute}.running-progress__signal-marker-dot{background:var(--status-warning);box-shadow:0 0 .4em var(--status-warning);will-change:transform;border-radius:.06em;animation:3.2s ease-in-out infinite alternate bloom-marker;position:absolute;inset:0}.running-progress--signal-field .running-progress__signal-track:nth-child(2) .running-progress__signal-marker-dot{opacity:.7;animation-delay:-.8s}.running-progress--signal-field .running-progress__signal-track:nth-child(3) .running-progress__signal-marker-dot{opacity:.45;animation-delay:-1.7s}.running-progress--signal-field .running-progress__signal-track:nth-child(4) .running-progress__signal-marker-dot{opacity:.7;animation-delay:-2.4s}.running-progress--signal-field .running-progress__signal-track:nth-child(5) .running-progress__signal-marker-dot{opacity:.55;animation-delay:-.35s}}.pipeline-animation-demo__variant{color:var(--ink-muted);text-transform:capitalize;margin:0;font-size:.72em;transition:color .18s}@keyframes running-sweep{to{transform:rotate(360deg)}}@keyframes runway-spark{to{transform:translate(13em)}}@keyframes runway-spark-wide{to{transform:translate(100cqw)}}@keyframes orbit-particle{to{transform:rotate(360deg)}}@keyframes indeterminate-shift{to{background-position:1em 0}}@keyframes signal-pulse{0%{transform:translate(-.5em,-50%)}to{transform:translate(calc(var(--running-progress) + .5em), -50%)}}@keyframes signal-arrival{0%{transform:translate(-12em,-50%)}to{transform:translate(-50%,-50%)}}@keyframes bloom-marker{0%{transform:translate(-10em,-50%)}to{transform:translate(-50%,-50%)}}@keyframes transit-packet{0%{transform:translate(-10vw,-50%)}to{transform:translate(120cqw,-50%)}}@keyframes weather-haze{to{transform:translate(9%,-4%)}}@keyframes weather-band{to{opacity:.45;transform:translate(8%)}}@keyframes weather-drift{to{transform:translate(10cqw,-2em)}}@media (prefers-reduced-motion:reduce){.running-progress--radial .running-progress__visual:after,.running-progress--runway .running-progress__runway-spark,.running-progress--runway .running-progress__visual:after,.running-progress--orbit .running-progress__orbit-particle,.running-progress--signal-field .running-progress__signal-pulse,.running-progress--signal-field .running-progress__signal-lead,.running-progress--signal-field .running-progress__signal-marker-dot,.running-progress--signal-field .running-progress__visual:before,.running-progress--indeterminate .running-progress__visual,.pipeline-animation-demo__variant{transition:none;animation:none}.running-field__bloom-marker,.running-field__transit-trail,.running-field__transit-packet,.running-field__weather-haze,.running-field__weather-band,.running-field__weather-drift{animation:none}.running-field__bloom-frontier,.running-field__transit-frontier,.running-field__bloom-marker{transition:none}}.panel--error{border-color:var(--status-serious)}.panel__link{color:var(--ink-secondary);text-underline-offset:.18em;align-self:flex-start;margin-top:.2em;font-size:.75em;font-weight:600}.panel__link:hover{color:var(--ink-primary)}.panel--primary .panel__status{font-size:1.35em}.panel--primary{gap:.1em;padding:.65em}.panel--primary .panel__content{gap:.1em}.panel--primary .panel__hint,.panel--primary .panel__observed,.panel--primary .panel__link{font-size:.65em}.panel--compact{justify-content:flex-start;gap:0;min-height:3.5em;padding:.2em;line-height:1.05}.panel--compact .panel__content{gap:0}.panel--compact .panel__label{font-size:.8em}.panel--compact .panel__status{font-size:1.1em}.panel--compact .panel__hint,.panel--compact .panel__observed,.panel--compact .panel__link{font-size:.65em}.panel--compact .panel__link{margin-top:0}@container panel (width>=48rem){.panel--primary.panel--shallow{padding:.45em .65em}.panel--primary.panel--shallow .panel__content,.panel--compact.panel--shallow .panel__content{flex-flow:wrap;align-items:baseline;gap:.15em .7em}.pipeline-panel__details,.http-value-panel__fact{display:contents}.panel--primary.panel--shallow .pipeline-panel__details>*,.panel--compact.panel--shallow .http-value-panel__fact>*{margin:0}.panel--primary.panel--shallow .panel__status{flex:none;font-size:1em}.panel--primary.panel--shallow .panel__label,.panel--compact.panel--shallow .panel__label,.panel--primary.panel--shallow .panel__observed,.panel--compact.panel--shallow .panel__observed,.panel--primary.panel--shallow .panel__link,.panel--compact.panel--shallow .panel__link{flex:none}}@container panel (width>=12rem){.panel--compact.panel--shallow .panel__content{flex-flow:wrap;align-items:baseline;gap:.15em .7em}.http-value-panel__fact{display:contents}.panel--compact.panel--shallow .http-value-panel__fact>*{margin:0}.panel--compact.panel--shallow .panel__label,.panel--compact.panel--shallow .panel__observed,.panel--compact.panel--shallow .panel__link{flex:none}}.board__footer{color:var(--ink-muted);flex-wrap:wrap;flex:none;justify-content:space-between;align-items:center;gap:.5rem;font-size:.75em;display:flex}.config-error{max-width:60ch;color:var(--ink-primary);margin:0 auto;padding:2rem}.config-error pre{border-radius:var(--radius);border:1px solid var(--status-critical);background:var(--surface-raised);color:var(--ink-secondary);white-space:pre-wrap;overflow-wrap:anywhere;padding:1rem;font-size:.75em}@media (width<=60rem){.board{height:auto;min-height:100dvh;overflow:visible}.board__grid{flex:none;grid-template-columns:1fr;grid-auto-rows:auto;min-height:auto}.panel{grid-area:auto/1/auto/-1;min-height:6em}.panel--primary .panel__content,.panel--compact .panel__content{flex-direction:column;align-items:stretch}}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{z as e}from"zod";import{StrictMode as t,useEffect as n,useRef as r,useState as i,useSyncExternalStore as a}from"react";import{createRoot as o}from"react-dom/client";import{Fragment as s,jsx as c,jsxs as l}from"react/jsx-runtime";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var u=/^(\d+)(ms|s|m|h)$/,d={ms:1,s:1e3,m:6e4,h:36e5};function f(e){let t=u.exec(e);if(!t)return null;let[,n,r]=t;if(n===void 0||r===void 0)return null;let i=Number(n);return i<=0?null:i*d[r]}var p=e.string().refine(e=>f(e)!==null,{message:`must be a positive duration like "30s", "5m", or "1h"`}).brand(),ee=e.object({x:e.number().int().min(0),y:e.number().int().min(0),w:e.number().int().min(1).max(12),h:e.number().int().min(1)}),m=e.string().min(1),h=[`radial`,`runway`,`orbit`,`signal-field`,`telemetry-bloom`,`release-transit`,`status-weather`],te=e.enum([...h,`off`]),g=e.looseObject({label:e.string().min(1).optional(),id:e.string().min(1),type:e.string().min(1),source:e.string().min(1).optional(),display:m.optional(),position:ee.optional(),refresh:p.optional(),running_animation:te.optional(),link:e.url().optional(),url:e.url().optional(),json_path:e.string().regex(/^\$(?:\.[A-Za-z_][A-Za-z0-9_]*|\[\d+\])*$/,`must be a simple JSON path`).optional()}),_=e.looseObject({type:e.string().min(1),token_env:e.string().min(1).optional()}),ne=e.object({refresh:p.optional(),panels:e.array(g).min(1).superRefine((e,t)=>{let n=new Map;e.forEach((e,r)=>{let i=n.get(e.id);if(i===void 0){n.set(e.id,r);return}t.addIssue({code:`custom`,path:[r,`id`],message:`duplicate panel id "${e.id}" (already used by panel at index ${i})`})})})}),re=e.object({issuer:e.url(),client_id:e.string().min(1).optional(),allow:e.object({groups:e.array(e.string().min(1)).optional(),subjects:e.array(e.string().min(1)).optional()}).optional()});e.object({sources:e.record(e.string().min(1),_).default({}),boards:e.record(e.string().min(1),ne),auth:re.optional()});function ie(e){let t=e.panelOverrideMillis??e.boardDefaultMillis;return Math.max(t,e.adapterFloorMillis)}var v=e.object({assetPath:e.string().min(1),proxyPath:e.string().min(1),board:e.string().min(1),clientVersion:e.string().min(1),auth:e.object({issuer:e.string().min(1),clientId:e.string().min(1).optional()}).optional()}),ae=v.pick({assetPath:!0,clientVersion:!0});function y(t=globalThis.window?.env){let n=v.safeParse(t);if(!n.success)throw Error(`window.env is missing or invalid \u2014 the server did not inject usable configuration.
|
|
2
|
-
${e.prettifyError(n.error)}`);return n.data}var oe=e.enum([`unreachable`,`unauthorized`,`not-found`,`no-runs`,`upstream-error`]),se=e.object({kind:oe,message:e.string()}),ce=e.discriminatedUnion(`state`,[e.object({panelId:e.string().min(1),state:e.literal(`ok`),observedAt:e.iso.datetime(),link:e.url().nullable(),signal:e.unknown()}),e.object({panelId:e.string().min(1),state:e.literal(`error`),observedAt:e.iso.datetime(),link:e.url().nullable(),error:se})]),b=e.object({type:e.literal(`pipeline-status`),status:e.enum([`passed`,`failed`,`running`,`cancelled`,`unknown`]),rawStatus:e.string(),name:e.string().min(1),branch:e.string().min(1).optional(),durationMs:e.number().int().nonnegative().optional(),runStartedAt:e.iso.datetime().optional(),estimatedDurationMs:e.number().int().positive().optional(),sourceUpdatedAt:e.iso.datetime().optional()}),x=e.object({label:e.string().min(1),status:b.shape.status,detail:e.string().min(1),link:e.url().nullable()}),S=e.object({type:e.literal(`pull-request-health`),status:b.shape.status,summary:e.string().min(1),workflows:e.array(x),pullRequests:e.array(x)}),le=e.object({type:e.literal(`http-value`),value:e.union([e.string(),e.number(),e.boolean()])}),C={diagnostics:`_diagnostics_lseur_1`,button:`_button_lseur_5`,area:`_area_lseur_14`,warning:`_warning_lseur_31`,panels:`_panels_lseur_35`,actions:`_actions_lseur_43`};function ue({log:e}){let[t,n]=i(!1);a(e.subscribe,e.snapshot,e.snapshot);let r=e.count(),o=e.summary();return l(`section`,{className:C.diagnostics,children:[l(`button`,{className:C.button,type:`button`,"aria-expanded":t,onClick:()=>n(!t),children:[`Diagnostics (`,r,`)`]}),t&&l(`div`,{className:C.area,children:[l(`p`,{children:[`Client `,e.clientVersion(),` · assets `,e.assetPath()]}),l(`p`,{children:[o.retained.eventCount,` retained browser-local events across`,` `,o.retained.sessionCount,` session`,o.retained.sessionCount===1?``:`s`,o.retained.firstEventAt&&o.retained.lastEventAt?` (${de(o.retained.firstEventAt,o.retained.lastEventAt)})`:``,`. They are never uploaded.`]}),o.retained.evidenceMayBeIncomplete&&l(`p`,{className:C.warning,role:`alert`,children:[`Earlier evidence was pruned: `,o.retained.retention.eventsPrunedByCount,` at the 2,000-event cap and `,o.retained.retention.eventsPrunedByAge,` by the 7-day age limit. “No failures” applies only to the retained window.`]}),l(`p`,{children:[`Update failures: `,o.failures.clientUpdate,`; board fetch failures:`,` `,o.failures.boardFetch,`.`]}),o.panels.length>0&&c(`div`,{className:C.panels,children:o.panels.map(e=>l(`p`,{children:[c(`strong`,{children:e.panelId}),` — `,e.requests,` requests`,Object.keys(e.httpStatuses).length?`; HTTP ${Object.entries(e.httpStatuses).map(([e,t])=>`${e}×${t}`).join(`, `)}`:``,`; parse/network failures `,e.parseFailures,`/`,e.networkFailures,`; visible changes `,e.visibleStateChanges,`; latest`,` `,e.latestRendered?`${e.latestRendered.state}${e.latestRendered.status?`/${e.latestRendered.status}`:``}`:`not rendered`,`.`]},e.panelId))}),l(`div`,{className:C.actions,children:[c(`button`,{className:C.button,type:`button`,onClick:()=>{let t=new Blob([JSON.stringify(e.export(),null,2)],{type:`application/json`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`dashboard-diagnostics-${new Date().toISOString().replaceAll(`:`,`-`)}.json`,r.click(),URL.revokeObjectURL(n)},children:`Download`}),c(`button`,{className:C.button,type:`button`,onClick:()=>{window.confirm(`Clear this browser’s retained dashboard diagnostics?`)&&e.clear()},children:`Clear`})]})]})]})}function de(e,t){return e===t?e:`${e} to ${t}`}function fe(e,t){let n=new Map,r=new Set,i=0,a=0;for(let t of e){if(r.add(t.sessionId),t.kind===`client-update-failure`&&i++,(t.kind===`board-fetch-failure`||t.kind===`board-fetch-parse-failure`)&&a++,!(`panelId`in t))continue;let e=n.get(t.panelId)??{panelId:t.panelId,requests:0,httpStatuses:{},parseFailures:0,networkFailures:0,visibleStateChanges:0};if(t.kind===`panel-fetch-start`&&e.requests++,t.kind===`panel-fetch-response`&&t.status!==void 0){let n=String(t.status);e.httpStatuses[n]=(e.httpStatuses[n]??0)+1}t.kind===`panel-fetch-parse-failure`&&e.parseFailures++,t.kind===`panel-fetch-failure`&&e.networkFailures++,t.kind===`panel-rendered`&&(e.visibleStateChanges++,e.latestRendered=t.rendered),n.set(t.panelId,e)}let o=e.map(e=>e.at).sort(),s=t.eventsPrunedByAge+t.eventsPrunedByCount;return{retained:{eventCount:e.length,firstEventAt:o[0],lastEventAt:o.at(-1),sessionCount:r.size,retention:t,evidenceMayBeIncomplete:s>0},failures:{clientUpdate:i,boardFetch:a},panels:[...n.values()].sort((e,t)=>e.panelId.localeCompare(t.panelId))}}var w=`ze-great-dashboard.diagnostics.v1`,pe=2e3,me=6048e5,he=[`session-start`,`client-update-check`,`client-update-failure`,`client-update-detected`,`board-fetch-start`,`board-fetch-response`,`board-fetch-parse-failure`,`board-fetch-failure`,`panel-fetch-start`,`panel-fetch-response`,`panel-fetch-parse-failure`,`panel-fetch-failure`,`panel-rendered`],ge=class{env;storage;now;events=[];retention=E();revision=0;listeners=new Set;sessionId=crypto.randomUUID?.()??`${Date.now()}-${Math.random()}`;constructor(e,t=ye(),n=()=>new Date){this.env=e,this.storage=t,this.now=n,this.events=this.read(),this.record({kind:`session-start`})}record(e){let t=D([...this.events,{...e,schemaVersion:1,at:this.now().toISOString(),sessionId:this.sessionId,board:this.env.board}],this.now(),this.retention);this.events=t.events,this.retention=t.retention,this.persist(),this.revision++,this.notify()}count=()=>this.events.length;clientVersion=()=>this.env.clientVersion;assetPath=()=>this.env.assetPath;snapshot=()=>this.revision;summary=()=>fe(this.events,this.retention);clear(){this.events=[],this.retention=E();try{this.storage?.removeItem(w)}catch{}this.revision++,this.notify()}subscribe=e=>(this.listeners.add(e),()=>{this.listeners.delete(e)});export=()=>({schemaVersion:1,exportedAt:this.now().toISOString(),client:{version:this.env.clientVersion,assetPath:this.env.assetPath,board:this.env.board,sessionId:this.sessionId},events:this.events,summary:this.summary()});read(){try{let e=this.storage?.getItem(w);if(!e)return[];let t=JSON.parse(e);if(t.schemaVersion!==1||!Array.isArray(t.events)||!t.events.every(ve))return this.storage?.removeItem(w),[];let n=D(t.events.map(e=>({...e,schemaVersion:1})),this.now(),_e(t.retention));return this.retention=n.retention,n.events}catch{try{this.storage?.removeItem(w)}catch{}return[]}}persist(){try{this.storage?.setItem(w,JSON.stringify({schemaVersion:1,events:this.events,retention:this.retention}))}catch{}}notify(){for(let e of this.listeners)e()}};function T(e){let t=Object.fromEntries([[`cacheControl`,`cache-control`],[`etag`,`etag`],[`lastModified`,`last-modified`],[`date`,`date`],[`age`,`age`]].flatMap(([t,n])=>{let r=e.get(n);return r?[[t,r]]:[]}));return Object.keys(t).length?t:void 0}function E(){return{eventsPrunedByAge:0,eventsPrunedByCount:0}}function _e(e){if(!e||typeof e!=`object`)return E();let t=e;return{eventsPrunedByAge:typeof t.eventsPrunedByAge==`number`&&t.eventsPrunedByAge>=0?t.eventsPrunedByAge:0,eventsPrunedByCount:typeof t.eventsPrunedByCount==`number`&&t.eventsPrunedByCount>=0?t.eventsPrunedByCount:0}}function D(e,t,n){let r=t.valueOf()-me,i=e.filter(e=>Number.isFinite(new Date(e.at).valueOf())&&new Date(e.at).valueOf()>=r),a=e.length-i.length,o=Math.max(0,i.length-pe);return{events:i.slice(-2e3),retention:{eventsPrunedByAge:n.eventsPrunedByAge+a,eventsPrunedByCount:n.eventsPrunedByCount+o}}}function ve(e){if(!e||typeof e!=`object`)return!1;let t=e;return(t.schemaVersion===void 0||t.schemaVersion===1)&&typeof t.at==`string`&&Number.isFinite(new Date(t.at).valueOf())&&typeof t.sessionId==`string`&&typeof t.board==`string`&&he.includes(t.kind)}function ye(){try{return window.localStorage}catch{return}}function O({label:e,hint:t,wide:n=!1}){return l(`section`,{className:n?`panel panel--wide`:`panel`,children:[c(`h2`,{className:`panel__label`,children:e}),c(`p`,{className:`panel__hint`,children:t})]})}function k({value:e,label:t=`As of`}){let n=new Date(e),r=n.toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`}),i=Date.now()-n.getTime(),a=i>3e5,o=A(i);return l(`p`,{className:`panel__hint panel__observed${a?` panel__observed--stale`:``}`,children:[c(`span`,{"aria-hidden":`true`,children:`◷`}),` `,t,` `,r,` · `,o]})}function A(e){if(e<6e4)return`just now`;let t=Math.floor(e/6e4);return t<60?`${t}m ago`:`${Math.floor(t/60)}h ${t%60}m ago`}function j(e){let t=e.position;if(t)return{"--panel-column":`${t.x+1} / span ${t.w}`,"--panel-row":`${t.y+1} / span ${t.h}`}}function M({panel:e,envelope:t,error:n=!1,field:r,children:i}){let a=e.display===`primary`||e.display===`compact`?e.display:`supporting`,o=e.position?.h!==void 0&&e.position.h<=2;return l(`section`,{className:`panel panel--${a}${o?` panel--shallow`:``}${n?` panel--error`:``}`,style:j(e),"aria-busy":!t||void 0,children:[r,l(`div`,{className:`panel__content`,children:[c(`h2`,{className:`panel__label`,children:e.label??e.id}),i,c(N,{panelId:e.id,link:t?.link})]})]})}function N({panelId:e,link:t}){return t?l(`a`,{className:`panel__link`,href:t,target:`_blank`,rel:`noopener noreferrer`,"aria-label":`View source for ${e} (opens in a new tab)`,children:[`View source `,c(`span`,{"aria-hidden":`true`,children:`↗`})]}):null}function P({panel:e,envelope:t}){if(!t)return c(M,{panel:e,children:c(`p`,{className:`panel__hint`,children:`Loading…`})});if(t.state===`error`)return l(M,{panel:e,envelope:t,error:!0,children:[c(`p`,{className:`panel__status`,children:`⚠ Unable to read`}),c(`p`,{className:`panel__hint`,children:t.error.message}),c(k,{value:t.observedAt})]});let n=le.safeParse(t.signal);return n.success?c(M,{panel:e,envelope:t,children:l(`div`,{className:`http-value-panel__fact`,children:[c(`p`,{className:`panel__status`,children:String(n.data.value)}),c(k,{value:t.observedAt})]})}):l(M,{panel:e,envelope:t,error:!0,children:[c(`p`,{className:`panel__status`,children:`⚠ Invalid value`}),c(k,{value:t.observedAt})]})}function F(e){return[`telemetry-bloom`,`release-transit`,`status-weather`].includes(e)}function I({animation:e,progress:t,overdue:n,indeterminate:r}){let i={"--running-progress":`${t*100}%`};return l(`div`,{className:`running-field running-field--${e}${`${n?` running-field--overdue`:``}${r?` running-field--indeterminate`:``}`}`,"data-animation":e,"aria-hidden":`true`,style:i,children:[e===`telemetry-bloom`&&l(s,{children:[c(`span`,{className:`running-field__bloom-frontier`}),c(`span`,{className:`running-field__bloom-lanes`,children:[0,1,2,3].map(e=>c(`span`,{className:`running-field__bloom-lane`,children:c(`span`,{className:`running-field__bloom-marker`})},e))})]}),e===`release-transit`&&l(s,{children:[c(`span`,{className:`running-field__transit-frontier`}),c(`span`,{className:`running-field__transit-now`}),c(`span`,{className:`running-field__transit-routes`,children:[0,1,2].map(e=>c(`span`,{className:`running-field__transit-route`},e))}),c(`span`,{className:`running-field__transit-trail`}),c(`span`,{className:`running-field__transit-packet`})]}),e===`status-weather`&&l(s,{children:[c(`span`,{className:`running-field__weather-haze`}),c(`span`,{className:`running-field__weather-band running-field__weather-band--one`}),c(`span`,{className:`running-field__weather-band running-field__weather-band--two`}),c(`span`,{className:`running-field__weather-band running-field__weather-band--three`}),c(`span`,{className:`running-field__weather-drift running-field__weather-drift--one`}),c(`span`,{className:`running-field__weather-drift running-field__weather-drift--two`}),c(`span`,{className:`running-field__weather-drift running-field__weather-drift--three`}),c(`span`,{className:`running-field__weather-drift running-field__weather-drift--four`}),c(`span`,{className:`running-field__weather-drift running-field__weather-drift--five`})]})]})}var be=20;function L(e,t){let n=xe(!!e),r=e?new Date(e).valueOf():NaN,i=Number.isFinite(r)?Math.max(0,n-r):void 0,a=i!==void 0&&t!==void 0;return{elapsedMs:i,hasEstimate:a,overdue:a&&i>t,progress:a?Math.min(i/t,1):0}}function xe(e){let[t,r]=i(()=>Date.now());return n(()=>{if(!e)return;r(Date.now());let t=window.setInterval(()=>r(Date.now()),be);return()=>window.clearInterval(t)},[e]),t}function R(e,t,n){return`${e===void 0?`Run in progress`:`Elapsed ${B(e)}`} · ${t===void 0?`Expected duration unavailable`:`Expected ≈ ${B(t)}`}${n?` · Over estimate`:``}`}function z(e,t,n){let r=e===void 0?`—`:V(e),i=t===void 0?`?`:`~${V(t)}`;return`${n?`⚠`:`\xA0`}${r}/${i}`}function B(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}h ${r}m`:r>0?`${r}m ${i}s`:`${i}s`}function V(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=`${r}:${String(i).padStart(2,`0`)}`;return n>0?`${n}:${a.padStart(5,`0`)}`:a}function H({elapsedMs:e,estimatedDurationMs:t,overdue:n}){return l(`p`,{className:`running-field__timing${n?` running-field__timing--overdue`:``}`,children:[c(`span`,{className:`screen-reader-only`,children:R(e,t,n)}),c(`span`,{"aria-hidden":`true`,children:z(e,t,n)})]})}function U({animation:e,runStartedAt:t,estimatedDurationMs:n}){let{elapsedMs:r,hasEstimate:i,overdue:a,progress:o}=L(t,n),u=e===`runway`||e===`signal-field`,d=R(r,n,a),f={"--running-progress":`${o*100}%`,"--running-degrees":`${o*360}deg`};return l(`div`,{className:`running-progress running-progress--${e}${a?` running-progress--overdue`:``}${i?``:` running-progress--indeterminate`}`,style:f,children:[l(`div`,{className:`running-progress__visual`,"aria-hidden":`true`,children:[e===`radial`&&c(`span`,{className:`running-progress__radial-core`}),e===`runway`&&c(`span`,{className:`running-progress__runway-spark`}),e===`orbit`&&l(s,{children:[c(`span`,{className:`running-progress__orbit-core`}),c(`span`,{className:`running-progress__orbit-particle running-progress__orbit-particle--one`}),c(`span`,{className:`running-progress__orbit-particle running-progress__orbit-particle--two`})]}),e===`signal-field`&&l(s,{children:[c(`span`,{className:`running-progress__signal-rail`}),c(`span`,{className:`running-progress__signal-lead`}),c(`span`,{className:`running-progress__signal-pulse running-progress__signal-pulse--one`}),c(`span`,{className:`running-progress__signal-pulse running-progress__signal-pulse--two`}),c(`span`,{className:`running-progress__signal-tracks`,children:[0,1,2,3,4].map(e=>c(`span`,{className:`running-progress__signal-track`,children:c(`span`,{className:`running-progress__signal-marker`,children:c(`span`,{className:`running-progress__signal-marker-dot`})})},e))})]})]}),c(`p`,{className:`running-progress__timing${u?` running-progress__timing--readout`:``}`,children:u?l(s,{children:[c(`span`,{className:`screen-reader-only`,children:d}),c(`span`,{"aria-hidden":`true`,children:z(r,n,a)})]}):d})]})}function Se(e){return[`radial`,`runway`,`orbit`,`signal-field`].includes(e)}var W=2e4,G=15e3,K=[`radial`,`runway`,`orbit`,`signal-field`,`telemetry-bloom`,`release-transit`,`status-weather`];function Ce({panel:e}){let t=Te(),n=Math.floor(t/W),r=K[n%K.length]??`radial`,i=n*W;return c(we,{panel:e,animation:r,runStartedAt:i})}function we({panel:e,animation:t,runStartedAt:n}){let r=new Date(n).toISOString(),i=L(r,G),a=F(t);return l(M,{panel:e,field:a?c(I,{animation:t,progress:i.progress,overdue:i.overdue,indeterminate:!i.hasEstimate}):void 0,children:[c(`p`,{className:`panel__status panel__status--running`,children:`↻ Running`}),l(`p`,{className:`pipeline-animation-demo__variant`,children:[`Demo treatment · `,t]}),a?c(H,{elapsedMs:i.elapsedMs,estimatedDurationMs:G,overdue:i.overdue}):c(U,{animation:t,runStartedAt:r,estimatedDurationMs:G})]})}function Te(){let[e,t]=i(()=>Date.now());return n(()=>{let e=window.setInterval(()=>t(Date.now()),1e3);return()=>window.clearInterval(e)},[]),e}function Ee({panel:e,envelope:t}){if(!t)return c(M,{panel:e,children:c(`p`,{className:`panel__hint`,children:`Loading…`})});if(t.state===`error`)return l(M,{panel:e,envelope:t,error:!0,children:[l(`p`,{className:`panel__status`,children:[`⚠ `,t.error.kind===`no-runs`?`No workflow runs`:`Unable to read`]}),c(`p`,{className:`panel__hint`,children:t.error.message}),c(k,{value:t.observedAt})]});let n=b.safeParse(t.signal);return n.success?c(De,{panel:e,envelope:t,signal:n.data}):l(M,{panel:e,envelope:t,error:!0,children:[c(`p`,{className:`panel__status`,children:`⚠ Invalid signal`}),c(k,{value:t.observedAt})]})}function De({panel:e,envelope:t,signal:n}){let r=Ae(n.status),[a]=i(Oe),o=e.running_animation??a,s=n.status===`running`&&o!==`off`,u=L(n.runStartedAt,n.estimatedDurationMs),d=s&&F(o),f=s&&Se(o);return c(M,{panel:e,envelope:t,field:d?c(I,{animation:o,progress:u.progress,overdue:u.overdue,indeterminate:!u.hasEstimate}):void 0,children:l(`div`,{className:`pipeline-panel__details`,children:[l(`p`,{className:`panel__status panel__status--${n.status}`,children:[r.glyph,` `,r.label]}),l(`p`,{className:`panel__hint`,children:[n.name,` · `,n.rawStatus,n.branch&&l(`span`,{className:`panel__branch`,title:`Branch: ${n.branch}`,children:[c(`span`,{"aria-hidden":`true`,children:` · ⎇ `}),c(`span`,{className:`screen-reader-only`,children:`Branch: `}),n.branch]})]}),d&&c(H,{elapsedMs:u.elapsedMs,estimatedDurationMs:n.estimatedDurationMs,overdue:u.overdue}),f&&c(U,{animation:o,runStartedAt:n.runStartedAt,estimatedDurationMs:n.estimatedDurationMs}),n.status!==`running`&&n.durationMs!==void 0&&l(`p`,{className:`panel__hint`,children:[`Took `,ke(n.durationMs)]}),n.sourceUpdatedAt&&c(k,{value:n.sourceUpdatedAt,label:`Run updated`}),c(k,{value:t.observedAt})]})})}function Oe(){return h[Math.floor(Math.random()*h.length)]??`telemetry-bloom`}function ke(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}h ${r}m`:r>0?`${r}m ${i}s`:`${i}s`}function Ae(e){switch(e){case`passed`:return{glyph:`✓`,label:`Passed`};case`failed`:return{glyph:`✕`,label:`Failed`};case`running`:return{glyph:`↻`,label:`Running`};case`cancelled`:return{glyph:`⊘`,label:`Cancelled`};case`unknown`:return{glyph:`?`,label:`Unknown`}}}function je({panel:e,envelope:t}){if(!t)return c(M,{panel:e,children:c(`p`,{className:`panel__hint`,children:`Loading…`})});if(t.state===`error`)return l(M,{panel:e,envelope:t,error:!0,children:[c(`p`,{className:`panel__status`,children:`⚠ Unable to read`}),c(`p`,{className:`panel__hint`,children:t.error.message}),c(k,{value:t.observedAt})]});let n=S.safeParse(t.signal);if(!n.success)return c(M,{panel:e,envelope:t,error:!0,children:c(`p`,{className:`panel__status`,children:`⚠ Invalid signal`})});let r=Me(n.data.status);return l(M,{panel:e,envelope:t,children:[l(`p`,{className:`panel__status panel__status--${n.data.status}`,children:[r.glyph,` `,r.label]}),c(`p`,{className:`panel__hint`,children:n.data.summary}),c(k,{value:t.observedAt})]})}function Me(e){switch(e){case`passed`:return{glyph:`✓`,label:`Healthy`};case`failed`:return{glyph:`✕`,label:`Failed`};case`running`:return{glyph:`↻`,label:`Running`};case`cancelled`:return{glyph:`⊘`,label:`Cancelled`};case`unknown`:return{glyph:`?`,label:`Unknown`}}}var Ne={"pipeline-status":Ee,"pull-request-health":je,"http-value":P,"pipeline-animation-demo":Ce};function Pe({panel:e,envelope:t}){let n=Ne[e.type];return n?c(n,{panel:e,envelope:t}):c(O,{label:e.type,hint:`Not wired yet`,wide:!0})}var Fe=6e4,Ie=1e4,Le=()=>globalThis.window.location.reload();function Re({env:e,diagnostics:t,fetcher:r,reload:i=Le}){n(()=>{let n=!1,a=!1,o,s=`${e.proxyPath}/client`,c=async()=>{if(n||a)return;a=!0;let l=new AbortController;o=l;let u=globalThis.setTimeout(()=>l.abort(),Ie);t.record({kind:`client-update-check`,path:s});try{let a=await(r??globalThis.fetch)(s,{cache:`no-store`,signal:l.signal});if(!a.ok)throw Error(`Client identity returned ${a.status}`);let o=ae.safeParse(await a.json());if(!o.success)throw Error(`Client identity response was invalid`);if(n)return;o.data.assetPath!==e.assetPath&&(t.record({kind:`client-update-detected`,path:s,current:{assetPath:e.assetPath,clientVersion:e.clientVersion},next:o.data}),i())}catch(e){!n&&!(e instanceof DOMException&&e.name===`AbortError`)&&t.record({kind:`client-update-failure`,path:s,message:e instanceof Error?e.message:String(e)})}finally{globalThis.clearTimeout(u),a=!1,o===l&&(o=void 0),n||globalThis.setTimeout(()=>void c(),Fe)}};return c(),()=>{n=!0,o?.abort()}},[t,e.assetPath,e.clientVersion,e.proxyPath,r,i])}function q(e,t){if(t.state===`error`)return{state:t.state,link:t.link};if(e.type===`pipeline-status`){let e=b.safeParse(t.signal);return{state:t.state,status:e.success?e.data.status:void 0,link:t.link}}if(e.type===`pull-request-health`){let e=S.safeParse(t.signal);return{state:t.state,status:e.success?e.data.status:void 0,link:t.link}}return{state:t.state,link:t.link}}function ze(e,t,n){if(!e)return!0;let r=q(t,e),i=q(t,n);return r.state!==i.state||r.status!==i.status||r.link!==i.link}function Be({board:e,env:t,diagnostics:a}){let[o,s]=i({}),c=r({});return n(()=>{if(c.current={},s({}),!e)return;let n=!1,r=[];for(let i of e.panels){if(i.type!==`pipeline-status`&&i.type!==`pull-request-health`&&i.type!==`http-value`)continue;let o=!1,l=ie({boardDefaultMillis:f(e.refresh??`60s`)??6e4,panelOverrideMillis:i.refresh?f(i.refresh)??void 0:void 0,adapterFloorMillis:0}),u=`${t.proxyPath}/panel/${encodeURIComponent(t.board)}/${encodeURIComponent(i.id)}`,d=()=>{n||o||(o=!0,a.record({kind:`panel-fetch-start`,panelId:i.id,path:u}),fetch(u).then(async e=>{let t={kind:`panel-fetch-response`,panelId:i.id,path:u,status:e.status,cache:T(e.headers)};if(e.status===304){a.record(t);return}try{let n=Ve(await e.json());if(!n){a.record(t),a.record({kind:`panel-fetch-parse-failure`,panelId:i.id,path:u,message:`Response was not a valid signal envelope.`});return}return a.record({...t,envelope:n}),n}catch(e){throw a.record(t),a.record({kind:`panel-fetch-parse-failure`,panelId:i.id,path:u,message:J(e)}),new Y(e)}}).then(e=>{if(!n&&e){let t=c.current[i.id];ze(t,i,e)&&a.record({kind:`panel-rendered`,panelId:i.id,path:u,rendered:q(i,e)}),c.current={...c.current,[i.id]:e},s(c.current)}}).catch(e=>{e instanceof Y||a.record({kind:`panel-fetch-failure`,panelId:i.id,path:u,message:J(e)})}).finally(()=>{o=!1}))};d(),r.push(window.setInterval(d,l))}return()=>{n=!0;for(let e of r)window.clearInterval(e)}},[e,a,t.board,t.proxyPath]),o}function J(e){return e instanceof Error?e.message:String(e)}var Y=class extends Error{constructor(e){super(J(e))}};function Ve(e){let t=ce.safeParse(e);return t.success?t.data:void 0}function He({env:e}){let[t,a]=i(),[o,s]=i(),u=r(null);u.current||=new ge(e);let d=u.current;Re({env:e,diagnostics:d});let f=Be({board:o===e.board?t:void 0,env:e,diagnostics:d});return n(()=>{let t=!1;a(void 0),s(void 0);let n=`${e.proxyPath}/boards/${encodeURIComponent(e.board)}`;return d.record({kind:`board-fetch-start`,path:n}),fetch(n).then(async e=>{if(d.record({kind:`board-fetch-response`,path:n,status:e.status,cache:T(e.headers)}),!e.ok)throw Error(`Board configuration returned ${e.status}`);try{return await e.json()}catch(e){throw d.record({kind:`board-fetch-parse-failure`,path:n,message:X(e)}),new Z(e)}}).then(r=>{if(!t){a(r),s(e.board);let t=Array.isArray(r.panels)?r.panels:[];d.record({kind:`board-fetch-response`,path:n,boardSummary:{panelCount:t.length,panelIds:t.flatMap(e=>typeof e.id==`string`?[e.id]:[])}})}}).catch(r=>{r instanceof Z||d.record({kind:`board-fetch-failure`,path:n,message:X(r)}),t||(a({panels:[]}),s(e.board))}),()=>{t=!0}},[d,e.board,e.proxyPath]),l(`div`,{className:`board`,children:[c(`header`,{className:`board__header`,children:c(`h1`,{className:`board__title`,children:e.board})}),l(`main`,{className:`board__grid`,children:[!t&&c(O,{label:`board`,hint:`Loading configuration…`,wide:!0}),t?.panels.map(e=>c(Pe,{panel:e,envelope:f[e.id]},e.id))]}),l(`footer`,{className:`board__footer`,children:[c(`span`,{children:`Signals are read live from their configured authorities.`}),c(ue,{log:d})]})]})}function X(e){return e instanceof Error?e.message:String(e)}var Z=class extends Error{constructor(e){super(X(e))}};function Ue({message:e}){return l(`div`,{className:`config-error`,role:`alert`,children:[c(`h1`,{children:`⚠️ Dashboard misconfigured`}),c(`p`,{children:`The page loaded, but the server did not hand it usable configuration.`}),c(`pre`,{children:e})]})}var Q=document.getElementById(`root`);if(!Q)throw Error(`No #root element in the document — the template is not the one we expect.`);var $=o(Q);try{$.render(c(t,{children:c(He,{env:y()})}))}catch(e){$.render(c(Ue,{message:e instanceof Error?e.message:String(e)}))}
|
|
3
|
-
//# sourceMappingURL=index-cbQ9A1zL.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-cbQ9A1zL.js","names":[],"sources":["../../../shared/dist/index.js","../../src/Diagnostics.module.css","../../src/Diagnostics.tsx","../../src/diagnostics-summary.ts","../../src/diagnostics.ts","../../src/PanelPlaceholder.tsx","../../src/ObservedAt.tsx","../../src/panel-layout.ts","../../src/PanelFrame.tsx","../../src/HttpValuePanel.tsx","../../src/RunningField.tsx","../../src/running-timing.ts","../../src/RunningFieldTiming.tsx","../../src/RunningProgress.tsx","../../src/PipelineAnimationDemoPanel.tsx","../../src/PipelinePanel.tsx","../../src/PullRequestHealthPanel.tsx","../../src/panel-registry.tsx","../../src/useClientUpdate.ts","../../src/panel-diagnostics.ts","../../src/usePanelSignals.ts","../../src/App.tsx","../../src/ConfigError.tsx","../../src/main.tsx"],"sourcesContent":["// packages/shared/src/board-config.ts\nimport { z as z2 } from \"zod\";\n\n// packages/shared/src/duration.ts\nimport { z } from \"zod\";\nvar DURATION_PATTERN = /^(\\d+)(ms|s|m|h)$/;\nvar UNIT_MILLIS = {\n ms: 1,\n s: 1e3,\n m: 6e4,\n h: 36e5\n};\nfunction parseDuration(value) {\n const match = DURATION_PATTERN.exec(value);\n if (!match) return null;\n const [, rawAmount, rawUnit] = match;\n if (rawAmount === void 0 || rawUnit === void 0) return null;\n const amount = Number(rawAmount);\n if (amount <= 0) return null;\n return amount * UNIT_MILLIS[rawUnit];\n}\nvar durationSchema = z.string().refine((value) => parseDuration(value) !== null, {\n message: 'must be a positive duration like \"30s\", \"5m\", or \"1h\"'\n}).brand();\n\n// packages/shared/src/board-config.ts\nvar positionSchema = z2.object({\n x: z2.number().int().min(0),\n y: z2.number().int().min(0),\n w: z2.number().int().min(1).max(12),\n h: z2.number().int().min(1)\n});\nvar panelDisplayRoles = [\"primary\", \"supporting\", \"compact\"];\nvar panelDisplaySchema = z2.string().min(1);\nvar visibleRunningAnimations = [\n \"radial\",\n \"runway\",\n \"orbit\",\n \"signal-field\",\n \"telemetry-bloom\",\n \"release-transit\",\n \"status-weather\"\n];\nvar runningAnimationSchema = z2.enum([...visibleRunningAnimations, \"off\"]);\nvar panelSchema = z2.looseObject({\n /** Presentation-only wall label. `id` remains the stable proxy and allowlist address. */\n label: z2.string().min(1).optional(),\n id: z2.string().min(1),\n type: z2.string().min(1),\n source: z2.string().min(1).optional(),\n /** Semantic visual weight; position still controls the panel's explicit grid placement. */\n display: panelDisplaySchema.optional(),\n /** Advisory in v1 — a panel without a position renders in config order rather than not at all. */\n position: positionSchema.optional(),\n refresh: durationSchema.optional(),\n /** Optional active-run treatment. Omitted selects a visible treatment at random. */\n running_animation: runningAnimationSchema.optional(),\n /** A deliberate override only. Adapters derive links; hand-written ones drift. */\n link: z2.url().optional(),\n /** Source-agnostic endpoint used by the http-value signal. */\n url: z2.url().optional(),\n /** Small, deliberate JSON path subset: $.version, $.deployment.version, or $.response.docs[0].latestVersion. */\n json_path: z2.string().regex(/^\\$(?:\\.[A-Za-z_][A-Za-z0-9_]*|\\[\\d+\\])*$/, \"must be a simple JSON path\").optional()\n});\nvar sourceSchema = z2.looseObject({\n type: z2.string().min(1),\n /** Credentials are never in the config — only the name of the env var holding one. */\n token_env: z2.string().min(1).optional()\n});\nvar boardSchema = z2.object({\n refresh: durationSchema.optional(),\n panels: z2.array(panelSchema).min(1).superRefine((panels, ctx) => {\n const seen = /* @__PURE__ */ new Map();\n panels.forEach((panel, index) => {\n const firstIndex = seen.get(panel.id);\n if (firstIndex === void 0) {\n seen.set(panel.id, index);\n return;\n }\n ctx.addIssue({\n code: \"custom\",\n path: [index, \"id\"],\n message: `duplicate panel id \"${panel.id}\" (already used by panel at index ${firstIndex})`\n });\n });\n })\n});\nvar authSchema = z2.object({\n issuer: z2.url(),\n /** Absent in gateway mode — the gateway does the flow, the proxy still validates. */\n client_id: z2.string().min(1).optional(),\n allow: z2.object({\n groups: z2.array(z2.string().min(1)).optional(),\n subjects: z2.array(z2.string().min(1)).optional()\n }).optional()\n});\nvar boardConfigSchema = z2.object({\n sources: z2.record(z2.string().min(1), sourceSchema).default({}),\n boards: z2.record(z2.string().min(1), boardSchema),\n auth: authSchema.optional()\n});\nfunction resolveRefreshMillis(args) {\n const requested = args.panelOverrideMillis ?? args.boardDefaultMillis;\n return Math.max(requested, args.adapterFloorMillis);\n}\n\n// packages/shared/src/client-env.ts\nimport { z as z3 } from \"zod\";\nvar clientEnvSchema = z3.object({\n /** Where the immutable client assets live. The one variable that repoints the whole client. */\n assetPath: z3.string().min(1),\n /** Same-origin path the proxy is mounted at, so there is no CORS and no cookie problem. */\n proxyPath: z3.string().min(1),\n /** Which board this is, resolved server-side so the client parses no URLs. */\n board: z3.string().min(1),\n /** The client version being served, so two published versions are visibly distinguishable. */\n clientVersion: z3.string().min(1),\n /** Omitted entirely when unauthenticated — presence is what turns auth on. */\n auth: z3.object({\n issuer: z3.string().min(1),\n clientId: z3.string().min(1).optional()\n }).optional()\n});\nvar clientIdentitySchema = clientEnvSchema.pick({ assetPath: true, clientVersion: true });\nfunction readClientEnv(source = globalThis.window?.env) {\n const result = clientEnvSchema.safeParse(source);\n if (!result.success) {\n throw new Error(\n `window.env is missing or invalid \\u2014 the server did not inject usable configuration.\n${z3.prettifyError(result.error)}`\n );\n }\n return result.data;\n}\n\n// packages/shared/src/envelope.ts\nimport { z as z4 } from \"zod\";\nvar errorKindSchema = z4.enum([\n \"unreachable\",\n \"unauthorized\",\n \"not-found\",\n \"no-runs\",\n \"upstream-error\"\n]);\nvar envelopeErrorSchema = z4.object({\n kind: errorKindSchema,\n message: z4.string()\n});\nvar envelopeSchema = z4.discriminatedUnion(\"state\", [\n z4.object({\n panelId: z4.string().min(1),\n state: z4.literal(\"ok\"),\n /** From the upstream response `Date`. A cached value must never be shown without its age. */\n observedAt: z4.iso.datetime(),\n /** Adapter-derived. The authority for this panel; the dashboard itself asserts nothing. */\n link: z4.url().nullable(),\n signal: z4.unknown()\n }),\n z4.object({\n panelId: z4.string().min(1),\n state: z4.literal(\"error\"),\n /**\n * Populated even on error: knowing *when* a failure was observed is the difference between\n * \"broken just now\" and \"broken all morning\", and a panel that can't reach its source is\n * exactly when a viewer most wants to click through.\n */\n observedAt: z4.iso.datetime(),\n link: z4.url().nullable(),\n error: envelopeErrorSchema\n })\n]);\nvar pipelineStatusSchema = z4.object({\n type: z4.literal(\"pipeline-status\"),\n status: z4.enum([\"passed\", \"failed\", \"running\", \"cancelled\", \"unknown\"]),\n /** The source's unmodified status/result vocabulary, for an honest display. */\n rawStatus: z4.string(),\n name: z4.string().min(1),\n /** The branch represented by this status, when the upstream supplies or filters by one. */\n branch: z4.string().min(1).optional(),\n /** Elapsed execution time, supplied only after the upstream run has completed. */\n durationMs: z4.number().int().nonnegative().optional(),\n /** When an active run began, so the client can advance its elapsed display between polls. */\n runStartedAt: z4.iso.datetime().optional(),\n /** Advisory median duration from recent completed runs from the same source response. */\n estimatedDurationMs: z4.number().int().positive().optional(),\n /** When this workflow run was last updated by its source, distinct from our observation time. */\n sourceUpdatedAt: z4.iso.datetime().optional()\n});\nvar pullRequestHealthItemSchema = z4.object({\n label: z4.string().min(1),\n status: pipelineStatusSchema.shape.status,\n detail: z4.string().min(1),\n link: z4.url().nullable()\n});\nvar pullRequestHealthSchema = z4.object({\n type: z4.literal(\"pull-request-health\"),\n status: pipelineStatusSchema.shape.status,\n summary: z4.string().min(1),\n workflows: z4.array(pullRequestHealthItemSchema),\n pullRequests: z4.array(pullRequestHealthItemSchema)\n});\nvar httpValueSchema = z4.object({\n type: z4.literal(\"http-value\"),\n value: z4.union([z4.string(), z4.number(), z4.boolean()])\n});\nexport {\n authSchema,\n boardConfigSchema,\n boardSchema,\n clientEnvSchema,\n clientIdentitySchema,\n durationSchema,\n envelopeSchema,\n errorKindSchema,\n httpValueSchema,\n panelDisplayRoles,\n panelDisplaySchema,\n panelSchema,\n parseDuration,\n pipelineStatusSchema,\n positionSchema,\n pullRequestHealthSchema,\n readClientEnv,\n resolveRefreshMillis,\n runningAnimationSchema,\n sourceSchema,\n visibleRunningAnimations\n};\n",".diagnostics {\n position: relative;\n}\n\n.button {\n border: 1px solid var(--edge);\n border-radius: 0.25rem;\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font: inherit;\n padding: 0.3em 0.55em;\n}\n\n.area {\n position: absolute;\n z-index: 1;\n right: 0;\n bottom: calc(100% + 0.5rem);\n width: min(24rem, 90vw);\n padding: 0.75rem;\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n background: var(--surface-raised);\n box-shadow: 0 0.5rem 1.5rem #0008;\n}\n\n.area p {\n margin: 0 0 0.5rem;\n}\n\n.warning {\n color: var(--status-warning);\n}\n\n.panels {\n max-height: 12rem;\n overflow-y: auto;\n border-top: 1px solid var(--edge);\n margin: 0.5rem 0;\n padding-top: 0.5rem;\n}\n\n.actions {\n display: flex;\n gap: 0.5rem;\n}\n","import { useState, useSyncExternalStore } from 'react'\nimport styles from './Diagnostics.module.css'\nimport type { BrowserDiagnosticStore } from './diagnostics.ts'\n\nexport function Diagnostics({ log }: { log: BrowserDiagnosticStore }) {\n const [open, setOpen] = useState(false)\n useSyncExternalStore(log.subscribe, log.snapshot, log.snapshot)\n const count = log.count()\n const summary = log.summary()\n const download = () => {\n const blob = new Blob([JSON.stringify(log.export(), null, 2)], { type: 'application/json' })\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = `dashboard-diagnostics-${new Date().toISOString().replaceAll(':', '-')}.json`\n link.click()\n URL.revokeObjectURL(url)\n }\n const clear = () => {\n if (!window.confirm('Clear this browser’s retained dashboard diagnostics?')) return\n log.clear()\n }\n\n return (\n <section className={styles.diagnostics}>\n <button\n className={styles.button}\n type=\"button\"\n aria-expanded={open}\n onClick={() => setOpen(!open)}\n >\n Diagnostics ({count})\n </button>\n {open && (\n <div className={styles.area}>\n <p>\n Client {log.clientVersion()} · assets {log.assetPath()}\n </p>\n <p>\n {summary.retained.eventCount} retained browser-local events across{' '}\n {summary.retained.sessionCount} session{summary.retained.sessionCount === 1 ? '' : 's'}\n {summary.retained.firstEventAt && summary.retained.lastEventAt\n ? ` (${formatWindow(summary.retained.firstEventAt, summary.retained.lastEventAt)})`\n : ''}\n . They are never uploaded.\n </p>\n {summary.retained.evidenceMayBeIncomplete && (\n <p className={styles.warning} role=\"alert\">\n Earlier evidence was pruned: {summary.retained.retention.eventsPrunedByCount} at the\n 2,000-event cap and {summary.retained.retention.eventsPrunedByAge} by the 7-day age\n limit. “No failures” applies only to the retained window.\n </p>\n )}\n <p>\n Update failures: {summary.failures.clientUpdate}; board fetch failures:{' '}\n {summary.failures.boardFetch}.\n </p>\n {summary.panels.length > 0 && (\n <div className={styles.panels}>\n {summary.panels.map((panel) => (\n <p key={panel.panelId}>\n <strong>{panel.panelId}</strong> — {panel.requests} requests\n {Object.keys(panel.httpStatuses).length\n ? `; HTTP ${Object.entries(panel.httpStatuses)\n .map(([status, count]) => `${status}×${count}`)\n .join(', ')}`\n : ''}\n ; parse/network failures {panel.parseFailures}/{panel.networkFailures}; visible\n changes {panel.visibleStateChanges}; latest{' '}\n {panel.latestRendered\n ? `${panel.latestRendered.state}${panel.latestRendered.status ? `/${panel.latestRendered.status}` : ''}`\n : 'not rendered'}\n .\n </p>\n ))}\n </div>\n )}\n <div className={styles.actions}>\n <button className={styles.button} type=\"button\" onClick={download}>\n Download\n </button>\n <button className={styles.button} type=\"button\" onClick={clear}>\n Clear\n </button>\n </div>\n </div>\n )}\n </section>\n )\n}\n\nfunction formatWindow(first: string, last: string) {\n return first === last ? first : `${first} to ${last}`\n}\n","import type {\n DiagnosticEvent,\n DiagnosticRetention,\n RenderedPanelDiagnostic,\n} from './diagnostics.ts'\n\nexport type PanelDiagnosticsSummary = {\n panelId: string\n requests: number\n httpStatuses: Record<string, number>\n parseFailures: number\n networkFailures: number\n visibleStateChanges: number\n latestRendered?: RenderedPanelDiagnostic\n}\n\nexport type DiagnosticsSummary = {\n retained: {\n eventCount: number\n firstEventAt?: string\n lastEventAt?: string\n sessionCount: number\n retention: DiagnosticRetention\n evidenceMayBeIncomplete: boolean\n }\n failures: {\n clientUpdate: number\n boardFetch: number\n }\n panels: PanelDiagnosticsSummary[]\n}\n\n/** Summarizes retained browser evidence only; omitted history is disclosed through retention. */\nexport function summarizeDiagnostics(\n events: readonly DiagnosticEvent[],\n retention: DiagnosticRetention,\n): DiagnosticsSummary {\n const panels = new Map<string, PanelDiagnosticsSummary>()\n const sessions = new Set<string>()\n let clientUpdate = 0\n let boardFetch = 0\n\n for (const event of events) {\n sessions.add(event.sessionId)\n if (event.kind === 'client-update-failure') clientUpdate++\n if (event.kind === 'board-fetch-failure' || event.kind === 'board-fetch-parse-failure')\n boardFetch++\n if (!('panelId' in event)) continue\n\n const panel = panels.get(event.panelId) ?? {\n panelId: event.panelId,\n requests: 0,\n httpStatuses: {},\n parseFailures: 0,\n networkFailures: 0,\n visibleStateChanges: 0,\n }\n if (event.kind === 'panel-fetch-start') panel.requests++\n if (event.kind === 'panel-fetch-response') {\n if (event.status !== undefined) {\n const status = String(event.status)\n panel.httpStatuses[status] = (panel.httpStatuses[status] ?? 0) + 1\n }\n }\n if (event.kind === 'panel-fetch-parse-failure') panel.parseFailures++\n if (event.kind === 'panel-fetch-failure') panel.networkFailures++\n if (event.kind === 'panel-rendered') {\n panel.visibleStateChanges++\n panel.latestRendered = event.rendered\n }\n panels.set(event.panelId, panel)\n }\n\n const timestamps = events.map((event) => event.at).sort()\n const discarded = retention.eventsPrunedByAge + retention.eventsPrunedByCount\n return {\n retained: {\n eventCount: events.length,\n firstEventAt: timestamps[0],\n lastEventAt: timestamps.at(-1),\n sessionCount: sessions.size,\n retention,\n evidenceMayBeIncomplete: discarded > 0,\n },\n failures: { clientUpdate, boardFetch },\n panels: [...panels.values()].sort((left, right) => left.panelId.localeCompare(right.panelId)),\n }\n}\n","import type { ClientEnv, Envelope } from '@ze-great-dashboard/shared'\nimport { type DiagnosticsSummary, summarizeDiagnostics } from './diagnostics-summary.ts'\n\nconst storageKey = 'ze-great-dashboard.diagnostics.v1'\nexport const diagnosticsSchemaVersion = 1\nconst maximumEvents = 2_000\nconst maximumAgeMillis = 7 * 24 * 60 * 60 * 1_000\nconst diagnosticKinds = [\n 'session-start',\n 'client-update-check',\n 'client-update-failure',\n 'client-update-detected',\n 'board-fetch-start',\n 'board-fetch-response',\n 'board-fetch-parse-failure',\n 'board-fetch-failure',\n 'panel-fetch-start',\n 'panel-fetch-response',\n 'panel-fetch-parse-failure',\n 'panel-fetch-failure',\n 'panel-rendered',\n] as const\n\nexport type CacheMetadata = Partial<\n Record<'cacheControl' | 'etag' | 'lastModified' | 'date' | 'age', string>\n>\n\ntype EventMetadata = {\n schemaVersion: typeof diagnosticsSchemaVersion\n at: string\n sessionId: string\n board: string\n}\n\nexport type RenderedPanelDiagnostic = {\n state: Envelope['state']\n status?: string\n link: string | null\n}\n\nexport type DiagnosticEventInput =\n | { kind: 'session-start' }\n | { kind: 'client-update-check'; path: string }\n | { kind: 'client-update-failure'; path: string; message: string }\n | {\n kind: 'client-update-detected'\n path: string\n current: { assetPath: string; clientVersion: string }\n next: { assetPath: string; clientVersion: string }\n }\n | { kind: 'board-fetch-start'; path: string }\n | {\n kind: 'board-fetch-response'\n path: string\n status?: number\n cache?: CacheMetadata\n boardSummary?: { panelCount: number; panelIds: string[] }\n }\n | { kind: 'board-fetch-parse-failure'; path: string; message: string }\n | { kind: 'board-fetch-failure'; path: string; message: string }\n | { kind: 'panel-fetch-start'; panelId: string; path: string }\n | {\n kind: 'panel-fetch-response'\n panelId: string\n path: string\n status?: number\n cache?: CacheMetadata\n envelope?: Envelope\n }\n | { kind: 'panel-fetch-parse-failure'; panelId: string; path: string; message: string }\n | { kind: 'panel-fetch-failure'; panelId: string; path: string; message: string }\n | {\n kind: 'panel-rendered'\n panelId: string\n path: string\n rendered: RenderedPanelDiagnostic\n }\n\nexport type DiagnosticEvent = DiagnosticEventInput extends infer Event\n ? Event extends DiagnosticEventInput\n ? Event & EventMetadata\n : never\n : never\n\n/** The only interface client features need in order to emit browser diagnostics. */\nexport interface DiagnosticSink {\n record(event: DiagnosticEventInput): void\n}\n\ntype PersistedDiagnosticEvent = Omit<DiagnosticEvent, 'schemaVersion'> & { schemaVersion?: number }\nexport type DiagnosticRetention = {\n eventsPrunedByAge: number\n eventsPrunedByCount: number\n}\n\ntype StoredDiagnostics = {\n schemaVersion: number\n events: PersistedDiagnosticEvent[]\n retention?: Partial<DiagnosticRetention>\n}\n\ntype StorageLike = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>\n\n/** Browser-local diagnostic evidence. It deliberately has no server or shared-contract counterpart. */\nexport class BrowserDiagnosticStore implements DiagnosticSink {\n private events: DiagnosticEvent[] = []\n private retention: DiagnosticRetention = emptyRetention()\n private revision = 0\n private readonly listeners = new Set<() => void>()\n private readonly sessionId = crypto.randomUUID?.() ?? `${Date.now()}-${Math.random()}`\n\n constructor(\n private readonly env: ClientEnv,\n private readonly storage: StorageLike | undefined = storageOrUndefined(),\n private readonly now: () => Date = () => new Date(),\n ) {\n this.events = this.read()\n this.record({ kind: 'session-start' })\n }\n\n record(event: DiagnosticEventInput) {\n const pruned = prune(\n [\n ...this.events,\n {\n ...event,\n schemaVersion: diagnosticsSchemaVersion,\n at: this.now().toISOString(),\n sessionId: this.sessionId,\n board: this.env.board,\n },\n ],\n this.now(),\n this.retention,\n )\n this.events = pruned.events\n this.retention = pruned.retention\n this.persist()\n this.revision++\n this.notify()\n }\n\n count = () => {\n return this.events.length\n }\n\n clientVersion = () => this.env.clientVersion\n\n assetPath = () => this.env.assetPath\n\n snapshot = () => this.revision\n\n summary = (): DiagnosticsSummary => summarizeDiagnostics(this.events, this.retention)\n\n clear() {\n this.events = []\n this.retention = emptyRetention()\n try {\n this.storage?.removeItem(storageKey)\n } catch {\n // Diagnostics must not interrupt the radiator when browser storage is unavailable.\n }\n this.revision++\n this.notify()\n }\n\n subscribe = (listener: () => void) => {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n export = () => {\n return {\n schemaVersion: diagnosticsSchemaVersion,\n exportedAt: this.now().toISOString(),\n client: {\n version: this.env.clientVersion,\n assetPath: this.env.assetPath,\n board: this.env.board,\n sessionId: this.sessionId,\n },\n events: this.events,\n summary: this.summary(),\n }\n }\n\n private read(): DiagnosticEvent[] {\n try {\n const raw = this.storage?.getItem(storageKey)\n if (!raw) return []\n const parsed = JSON.parse(raw) as Partial<StoredDiagnostics>\n if (parsed.schemaVersion !== diagnosticsSchemaVersion || !Array.isArray(parsed.events)) {\n this.storage?.removeItem(storageKey)\n return []\n }\n if (!parsed.events.every(isDiagnosticEvent)) {\n this.storage?.removeItem(storageKey)\n return []\n }\n // v1 retained events predate per-event versions. Their containing store was already v1, so\n // retain them and normalize on the next write rather than discarding viewer evidence.\n const pruned = prune(\n parsed.events.map(\n (event) => ({ ...event, schemaVersion: diagnosticsSchemaVersion }) as DiagnosticEvent,\n ),\n this.now(),\n validRetention(parsed.retention),\n )\n this.retention = pruned.retention\n return pruned.events\n } catch {\n try {\n this.storage?.removeItem(storageKey)\n } catch {\n // Storage can fail on both reads and writes (for example, private browsing policies).\n }\n return []\n }\n }\n\n private persist() {\n try {\n this.storage?.setItem(\n storageKey,\n JSON.stringify({\n schemaVersion: diagnosticsSchemaVersion,\n events: this.events,\n retention: this.retention,\n }),\n )\n } catch {\n // Keep the in-memory record for this page, but never make diagnostics a rendering failure.\n }\n }\n\n private notify() {\n for (const listener of this.listeners) listener()\n }\n}\n\nexport function cacheMetadata(headers: Headers): CacheMetadata | undefined {\n const entries = [\n ['cacheControl', 'cache-control'],\n ['etag', 'etag'],\n ['lastModified', 'last-modified'],\n ['date', 'date'],\n ['age', 'age'],\n ] as const\n const metadata = Object.fromEntries(\n entries.flatMap(([key, header]) => {\n const value = headers.get(header)\n return value ? [[key, value]] : []\n }),\n ) as CacheMetadata\n return Object.keys(metadata).length ? metadata : undefined\n}\n\nfunction emptyRetention(): DiagnosticRetention {\n return { eventsPrunedByAge: 0, eventsPrunedByCount: 0 }\n}\n\nfunction validRetention(value: unknown): DiagnosticRetention {\n if (!value || typeof value !== 'object') return emptyRetention()\n const retention = value as Partial<DiagnosticRetention>\n return {\n eventsPrunedByAge:\n typeof retention.eventsPrunedByAge === 'number' && retention.eventsPrunedByAge >= 0\n ? retention.eventsPrunedByAge\n : 0,\n eventsPrunedByCount:\n typeof retention.eventsPrunedByCount === 'number' && retention.eventsPrunedByCount >= 0\n ? retention.eventsPrunedByCount\n : 0,\n }\n}\n\nfunction prune(events: DiagnosticEvent[], now: Date, priorRetention: DiagnosticRetention) {\n const cutoff = now.valueOf() - maximumAgeMillis\n const current = events.filter(\n (event) =>\n Number.isFinite(new Date(event.at).valueOf()) && new Date(event.at).valueOf() >= cutoff,\n )\n const discardedByAge = events.length - current.length\n const discardedByCount = Math.max(0, current.length - maximumEvents)\n return {\n events: current.slice(-maximumEvents),\n retention: {\n eventsPrunedByAge: priorRetention.eventsPrunedByAge + discardedByAge,\n eventsPrunedByCount: priorRetention.eventsPrunedByCount + discardedByCount,\n },\n }\n}\n\nfunction isDiagnosticEvent(value: unknown): value is PersistedDiagnosticEvent {\n if (!value || typeof value !== 'object') return false\n const event = value as Partial<DiagnosticEvent>\n return (\n (event.schemaVersion === undefined || event.schemaVersion === diagnosticsSchemaVersion) &&\n typeof event.at === 'string' &&\n Number.isFinite(new Date(event.at).valueOf()) &&\n typeof event.sessionId === 'string' &&\n typeof event.board === 'string' &&\n diagnosticKinds.includes(event.kind as (typeof diagnosticKinds)[number])\n )\n}\n\nfunction storageOrUndefined(): StorageLike | undefined {\n try {\n return window.localStorage\n } catch {\n return undefined\n }\n}\n","/**\n * A panel-shaped hole, so the grid can be looked at and argued with before any signal exists.\n * Replaced by real panels in Stage 2 — nothing here is meant to survive.\n */\nexport function PanelPlaceholder({\n label,\n hint,\n wide = false,\n}: {\n label: string\n hint: string\n wide?: boolean\n}) {\n return (\n <section className={wide ? 'panel panel--wide' : 'panel'}>\n <h2 className=\"panel__label\">{label}</h2>\n <p className=\"panel__hint\">{hint}</p>\n </section>\n )\n}\n","export function ObservedAt({ value, label = 'As of' }: { value: string; label?: string }) {\n const observed = new Date(value)\n const formatted = observed.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n const age = Date.now() - observed.getTime()\n const stale = age > 5 * 60 * 1000\n const ageText = formatAge(age)\n return (\n <p className={`panel__hint panel__observed${stale ? ' panel__observed--stale' : ''}`}>\n <span aria-hidden=\"true\">◷</span> {label} {formatted} · {ageText}\n </p>\n )\n}\n\nexport function formatAge(milliseconds: number) {\n if (milliseconds < 60_000) return 'just now'\n const minutes = Math.floor(milliseconds / 60_000)\n if (minutes < 60) return `${minutes}m ago`\n const hours = Math.floor(minutes / 60)\n return `${hours}h ${minutes % 60}m ago`\n}\n","import type { Panel } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\n\n/** Convert the advisory board position into CSS grid placement. */\nexport function panelLayout(panel: Panel): CSSProperties | undefined {\n const position = panel.position\n if (!position) return undefined\n\n return {\n '--panel-column': `${position.x + 1} / span ${position.w}`,\n '--panel-row': `${position.y + 1} / span ${position.h}`,\n } as CSSProperties\n}\n","import type { Envelope, Panel } from '@ze-great-dashboard/shared'\nimport type { ReactNode } from 'react'\nimport { panelLayout } from './panel-layout.ts'\n\nexport function PanelFrame({\n panel,\n envelope,\n error = false,\n field,\n children,\n}: {\n panel: Panel\n envelope?: Envelope\n error?: boolean\n /** Decorative active-run layer. It is intentionally a sibling of readable panel content. */\n field?: ReactNode\n children: ReactNode\n}) {\n const display =\n panel.display === 'primary' || panel.display === 'compact' ? panel.display : 'supporting'\n const shallow = panel.position?.h !== undefined && panel.position.h <= 2\n return (\n <section\n className={`panel panel--${display}${shallow ? ' panel--shallow' : ''}${error ? ' panel--error' : ''}`}\n style={panelLayout(panel)}\n aria-busy={envelope ? undefined : true}\n >\n {field}\n <div className=\"panel__content\">\n <h2 className=\"panel__label\">{panel.label ?? panel.id}</h2>\n {children}\n <PanelSourceLink panelId={panel.id} link={envelope?.link} />\n </div>\n </section>\n )\n}\n\nfunction PanelSourceLink({ panelId, link }: { panelId: string; link?: string | null }) {\n if (!link) return null\n\n return (\n <a\n className=\"panel__link\"\n href={link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`View source for ${panelId} (opens in a new tab)`}\n >\n View source <span aria-hidden=\"true\">↗</span>\n </a>\n )\n}\n","import type { Panel } from '@ze-great-dashboard/shared'\nimport { type Envelope, httpValueSchema } from '@ze-great-dashboard/shared'\nimport { ObservedAt } from './ObservedAt.tsx'\nimport { PanelFrame } from './PanelFrame.tsx'\n\nexport function HttpValuePanel({\n panel,\n envelope,\n}: {\n panel: Panel\n envelope: Envelope | undefined\n}) {\n if (!envelope)\n return (\n <PanelFrame panel={panel}>\n <p className=\"panel__hint\">Loading…</p>\n </PanelFrame>\n )\n if (envelope.state === 'error')\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <p className=\"panel__status\">⚠ Unable to read</p>\n <p className=\"panel__hint\">{envelope.error.message}</p>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n const signal = httpValueSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <p className=\"panel__status\">⚠ Invalid value</p>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n return (\n <PanelFrame panel={panel} envelope={envelope}>\n <div className=\"http-value-panel__fact\">\n <p className=\"panel__status\">{String(signal.data.value)}</p>\n <ObservedAt value={envelope.observedAt} />\n </div>\n </PanelFrame>\n )\n}\n","import type { RunningAnimation } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\n\nexport type RunningFieldAnimation = Extract<\n RunningAnimation,\n 'telemetry-bloom' | 'release-transit' | 'status-weather'\n>\n\nexport function isRunningFieldAnimation(\n animation: Exclude<RunningAnimation, 'off'>,\n): animation is RunningFieldAnimation {\n return ['telemetry-bloom', 'release-transit', 'status-weather'].includes(animation)\n}\n\nexport function RunningField({\n animation,\n progress,\n overdue,\n indeterminate,\n}: {\n animation: RunningFieldAnimation\n progress: number\n overdue: boolean\n indeterminate: boolean\n}) {\n const style = {\n '--running-progress': `${progress * 100}%`,\n } as CSSProperties\n const state = `${overdue ? ' running-field--overdue' : ''}${indeterminate ? ' running-field--indeterminate' : ''}`\n\n return (\n <div\n className={`running-field running-field--${animation}${state}`}\n data-animation={animation}\n aria-hidden=\"true\"\n style={style}\n >\n {animation === 'telemetry-bloom' && (\n <>\n <span className=\"running-field__bloom-frontier\" />\n <span className=\"running-field__bloom-lanes\">\n {[0, 1, 2, 3].map((lane) => (\n <span className=\"running-field__bloom-lane\" key={lane}>\n <span className=\"running-field__bloom-marker\" />\n </span>\n ))}\n </span>\n </>\n )}\n {animation === 'release-transit' && (\n <>\n <span className=\"running-field__transit-frontier\" />\n <span className=\"running-field__transit-now\" />\n <span className=\"running-field__transit-routes\">\n {[0, 1, 2].map((route) => (\n <span className=\"running-field__transit-route\" key={route} />\n ))}\n </span>\n <span className=\"running-field__transit-trail\" />\n <span className=\"running-field__transit-packet\" />\n </>\n )}\n {animation === 'status-weather' && (\n <>\n <span className=\"running-field__weather-haze\" />\n <span className=\"running-field__weather-band running-field__weather-band--one\" />\n <span className=\"running-field__weather-band running-field__weather-band--two\" />\n <span className=\"running-field__weather-band running-field__weather-band--three\" />\n <span className=\"running-field__weather-drift running-field__weather-drift--one\" />\n <span className=\"running-field__weather-drift running-field__weather-drift--two\" />\n <span className=\"running-field__weather-drift running-field__weather-drift--three\" />\n <span className=\"running-field__weather-drift running-field__weather-drift--four\" />\n <span className=\"running-field__weather-drift running-field__weather-drift--five\" />\n </>\n )}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\n\nconst VISUAL_TICK_MS = 20\n\nexport function useRunningTiming(runStartedAt?: string, estimatedDurationMs?: number) {\n const now = useClock(Boolean(runStartedAt))\n const startedAt = runStartedAt ? new Date(runStartedAt).valueOf() : Number.NaN\n const elapsedMs = Number.isFinite(startedAt) ? Math.max(0, now - startedAt) : undefined\n const hasEstimate = elapsedMs !== undefined && estimatedDurationMs !== undefined\n const overdue = hasEstimate && elapsedMs > estimatedDurationMs\n const progress = hasEstimate ? Math.min(elapsedMs / estimatedDurationMs, 1) : 0\n return { elapsedMs, hasEstimate, overdue, progress }\n}\n\nfunction useClock(enabled: boolean) {\n const [now, setNow] = useState(() => Date.now())\n useEffect(() => {\n if (!enabled) return\n setNow(Date.now())\n // The timing text rounds to seconds, but progress gets display-cadence intermediate positions.\n // This avoids the visible sawtooth created by a coarse timer and CSS transition.\n const interval = window.setInterval(() => setNow(Date.now()), VISUAL_TICK_MS)\n return () => window.clearInterval(interval)\n }, [enabled])\n return now\n}\n\nexport function timingDescription(\n elapsedMs: number | undefined,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n) {\n const elapsed =\n elapsedMs === undefined ? 'Run in progress' : `Elapsed ${formatDuration(elapsedMs)}`\n const expected =\n estimatedDurationMs === undefined\n ? 'Expected duration unavailable'\n : `Expected ≈ ${formatDuration(estimatedDurationMs)}`\n return `${elapsed} · ${expected}${overdue ? ' · Over estimate' : ''}`\n}\n\nexport function compactTiming(\n elapsedMs: number | undefined,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n) {\n const elapsed = elapsedMs === undefined ? '—' : formatClockDuration(elapsedMs)\n const expected =\n estimatedDurationMs === undefined ? '?' : `~${formatClockDuration(estimatedDurationMs)}`\n return `${overdue ? '⚠' : '\\u00a0'}${elapsed}/${expected}`\n}\n\nfunction formatDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n if (hours > 0) return `${hours}h ${minutes}m`\n if (minutes > 0) return `${minutes}m ${seconds}s`\n return `${seconds}s`\n}\n\nfunction formatClockDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n const clock = `${minutes}:${String(seconds).padStart(2, '0')}`\n return hours > 0 ? `${hours}:${clock.padStart(5, '0')}` : clock\n}\n","import { compactTiming, timingDescription } from './running-timing.ts'\n\n/** The sole readable timing projection for panel-scale decorative fields. */\nexport function RunningFieldTiming({\n elapsedMs,\n estimatedDurationMs,\n overdue,\n}: {\n elapsedMs: number | undefined\n estimatedDurationMs: number | undefined\n overdue: boolean\n}) {\n return (\n <p className={`running-field__timing${overdue ? ' running-field__timing--overdue' : ''}`}>\n <span className=\"screen-reader-only\">\n {timingDescription(elapsedMs, estimatedDurationMs, overdue)}\n </span>\n <span aria-hidden=\"true\">{compactTiming(elapsedMs, estimatedDurationMs, overdue)}</span>\n </p>\n )\n}\n","import type { RunningAnimation } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\nimport { compactTiming, timingDescription, useRunningTiming } from './running-timing.ts'\n\nexport function RunningProgress({\n animation,\n runStartedAt,\n estimatedDurationMs,\n}: {\n animation: LegacyRunningAnimation\n runStartedAt?: string\n estimatedDurationMs?: number\n}) {\n const { elapsedMs, hasEstimate, overdue, progress } = useRunningTiming(\n runStartedAt,\n estimatedDurationMs,\n )\n const usesReadout = animation === 'runway' || animation === 'signal-field'\n const timingText = timingDescription(elapsedMs, estimatedDurationMs, overdue)\n const style = {\n '--running-progress': `${progress * 100}%`,\n '--running-degrees': `${progress * 360}deg`,\n } as CSSProperties\n\n return (\n <div\n className={`running-progress running-progress--${animation}${overdue ? ' running-progress--overdue' : ''}${hasEstimate ? '' : ' running-progress--indeterminate'}`}\n style={style}\n >\n <div className=\"running-progress__visual\" aria-hidden=\"true\">\n {animation === 'radial' && <span className=\"running-progress__radial-core\" />}\n {animation === 'runway' && <span className=\"running-progress__runway-spark\" />}\n {animation === 'orbit' && (\n <>\n <span className=\"running-progress__orbit-core\" />\n <span className=\"running-progress__orbit-particle running-progress__orbit-particle--one\" />\n <span className=\"running-progress__orbit-particle running-progress__orbit-particle--two\" />\n </>\n )}\n {animation === 'signal-field' && (\n <>\n <span className=\"running-progress__signal-rail\" />\n <span className=\"running-progress__signal-lead\" />\n <span className=\"running-progress__signal-pulse running-progress__signal-pulse--one\" />\n <span className=\"running-progress__signal-pulse running-progress__signal-pulse--two\" />\n <span className=\"running-progress__signal-tracks\">\n {[0, 1, 2, 3, 4].map((track) => (\n <span className=\"running-progress__signal-track\" key={track}>\n <span className=\"running-progress__signal-marker\">\n <span className=\"running-progress__signal-marker-dot\" />\n </span>\n </span>\n ))}\n </span>\n </>\n )}\n </div>\n <p\n className={`running-progress__timing${usesReadout ? ' running-progress__timing--readout' : ''}`}\n >\n {usesReadout ? (\n <>\n <span className=\"screen-reader-only\">{timingText}</span>\n <span aria-hidden=\"true\">{compactTiming(elapsedMs, estimatedDurationMs, overdue)}</span>\n </>\n ) : (\n timingText\n )}\n </p>\n </div>\n )\n}\n\n/** The compact, inline treatments retained for existing boards. */\nexport type LegacyRunningAnimation = Extract<\n RunningAnimation,\n 'radial' | 'runway' | 'orbit' | 'signal-field'\n>\n\nexport function isLegacyRunningAnimation(\n animation: RunningAnimation,\n): animation is LegacyRunningAnimation {\n return ['radial', 'runway', 'orbit', 'signal-field'].includes(animation)\n}\n","import type { Panel } from '@ze-great-dashboard/shared'\nimport { useEffect, useState } from 'react'\nimport { PanelFrame } from './PanelFrame.tsx'\nimport { isRunningFieldAnimation, RunningField } from './RunningField.tsx'\nimport { RunningFieldTiming } from './RunningFieldTiming.tsx'\nimport { RunningProgress } from './RunningProgress.tsx'\nimport { useRunningTiming } from './running-timing.ts'\n\nconst RUN_DURATION_MS = 20_000\nconst ESTIMATED_DURATION_MS = 15_000\nconst variants = [\n 'radial',\n 'runway',\n 'orbit',\n 'signal-field',\n 'telemetry-bloom',\n 'release-transit',\n 'status-weather',\n] as const\n\n/**\n * A local comparison aid for the active-run treatments. It deliberately creates no signal or\n * diagnostic evidence: its state is derived only from the wall clock and repeats forever.\n */\nexport function PipelineAnimationDemoPanel({ panel }: { panel: Panel }) {\n const now = useClock()\n const runNumber = Math.floor(now / RUN_DURATION_MS)\n const animation = variants[runNumber % variants.length] ?? 'radial'\n const runStartedAt = runNumber * RUN_DURATION_MS\n\n return <DemoRun panel={panel} animation={animation} runStartedAt={runStartedAt} />\n}\n\nfunction DemoRun({\n panel,\n animation,\n runStartedAt,\n}: {\n panel: Panel\n animation: (typeof variants)[number]\n runStartedAt: number\n}) {\n const startedAt = new Date(runStartedAt).toISOString()\n const timing = useRunningTiming(startedAt, ESTIMATED_DURATION_MS)\n const usesField = isRunningFieldAnimation(animation)\n return (\n <PanelFrame\n panel={panel}\n field={\n usesField ? (\n <RunningField\n animation={animation}\n progress={timing.progress}\n overdue={timing.overdue}\n indeterminate={!timing.hasEstimate}\n />\n ) : undefined\n }\n >\n <p className=\"panel__status panel__status--running\">↻ Running</p>\n <p className=\"pipeline-animation-demo__variant\">Demo treatment · {animation}</p>\n {usesField ? (\n <RunningFieldTiming\n elapsedMs={timing.elapsedMs}\n estimatedDurationMs={ESTIMATED_DURATION_MS}\n overdue={timing.overdue}\n />\n ) : (\n <RunningProgress\n animation={animation}\n runStartedAt={startedAt}\n estimatedDurationMs={ESTIMATED_DURATION_MS}\n />\n )}\n </PanelFrame>\n )\n}\n\nfunction useClock() {\n const [now, setNow] = useState(() => Date.now())\n useEffect(() => {\n const interval = window.setInterval(() => setNow(Date.now()), 1_000)\n return () => window.clearInterval(interval)\n }, [])\n return now\n}\n","import {\n type Envelope,\n type Panel,\n type PipelineStatus,\n pipelineStatusSchema,\n visibleRunningAnimations,\n} from '@ze-great-dashboard/shared'\nimport { useState } from 'react'\nimport { ObservedAt } from './ObservedAt.tsx'\nimport { PanelFrame } from './PanelFrame.tsx'\nimport { isRunningFieldAnimation, RunningField } from './RunningField.tsx'\nimport { RunningFieldTiming } from './RunningFieldTiming.tsx'\nimport { isLegacyRunningAnimation, RunningProgress } from './RunningProgress.tsx'\nimport { useRunningTiming } from './running-timing.ts'\n\nexport function PipelinePanel({\n panel,\n envelope,\n}: {\n panel: Panel\n envelope: Envelope | undefined\n}) {\n if (!envelope)\n return (\n <PanelFrame panel={panel}>\n <p className=\"panel__hint\">Loading…</p>\n </PanelFrame>\n )\n if (envelope.state === 'error') {\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <p className=\"panel__status\">\n ⚠ {envelope.error.kind === 'no-runs' ? 'No workflow runs' : 'Unable to read'}\n </p>\n <p className=\"panel__hint\">{envelope.error.message}</p>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n }\n\n const signal = pipelineStatusSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <p className=\"panel__status\">⚠ Invalid signal</p>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n return <PipelineSignalPanel panel={panel} envelope={envelope} signal={signal.data} />\n}\n\nfunction PipelineSignalPanel({\n panel,\n envelope,\n signal,\n}: {\n panel: Panel\n envelope: Envelope\n signal: PipelineStatus\n}) {\n const presentation = statusPresentation(signal.status)\n // Keep an omitted treatment stable for this panel's lifetime; timing updates must not reshuffle it.\n const [defaultAnimation] = useState(selectDefaultRunningAnimation)\n const animation = panel.running_animation ?? defaultAnimation\n const activeRun = signal.status === 'running' && animation !== 'off'\n const timing = useRunningTiming(signal.runStartedAt, signal.estimatedDurationMs)\n const usesField = activeRun && isRunningFieldAnimation(animation)\n const usesLegacyProgress = activeRun && isLegacyRunningAnimation(animation)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n field={\n usesField ? (\n <RunningField\n animation={animation}\n progress={timing.progress}\n overdue={timing.overdue}\n indeterminate={!timing.hasEstimate}\n />\n ) : undefined\n }\n >\n <div className=\"pipeline-panel__details\">\n <p className={`panel__status panel__status--${signal.status}`}>\n {presentation.glyph} {presentation.label}\n </p>\n <p className=\"panel__hint\">\n {signal.name} · {signal.rawStatus}\n {signal.branch && (\n <span className=\"panel__branch\" title={`Branch: ${signal.branch}`}>\n <span aria-hidden=\"true\"> · ⎇ </span>\n <span className=\"screen-reader-only\">Branch: </span>\n {signal.branch}\n </span>\n )}\n </p>\n {usesField && (\n <RunningFieldTiming\n elapsedMs={timing.elapsedMs}\n estimatedDurationMs={signal.estimatedDurationMs}\n overdue={timing.overdue}\n />\n )}\n {usesLegacyProgress && (\n <RunningProgress\n animation={animation}\n runStartedAt={signal.runStartedAt}\n estimatedDurationMs={signal.estimatedDurationMs}\n />\n )}\n {signal.status !== 'running' && signal.durationMs !== undefined && (\n <p className=\"panel__hint\">Took {formatDuration(signal.durationMs)}</p>\n )}\n {signal.sourceUpdatedAt && (\n <ObservedAt value={signal.sourceUpdatedAt} label=\"Run updated\" />\n )}\n <ObservedAt value={envelope.observedAt} />\n </div>\n </PanelFrame>\n )\n}\n\nfunction selectDefaultRunningAnimation() {\n return (\n visibleRunningAnimations[Math.floor(Math.random() * visibleRunningAnimations.length)] ??\n 'telemetry-bloom'\n )\n}\n\nfunction formatDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0) return `${hours}h ${minutes}m`\n if (minutes > 0) return `${minutes}m ${seconds}s`\n return `${seconds}s`\n}\n\nfunction statusPresentation(status: 'passed' | 'failed' | 'running' | 'cancelled' | 'unknown') {\n switch (status) {\n case 'passed':\n return { glyph: '✓', label: 'Passed' }\n case 'failed':\n return { glyph: '✕', label: 'Failed' }\n case 'running':\n return { glyph: '↻', label: 'Running' }\n case 'cancelled':\n return { glyph: '⊘', label: 'Cancelled' }\n case 'unknown':\n return { glyph: '?', label: 'Unknown' }\n }\n}\n","import { type Envelope, type Panel, pullRequestHealthSchema } from '@ze-great-dashboard/shared'\nimport { ObservedAt } from './ObservedAt.tsx'\nimport { PanelFrame } from './PanelFrame.tsx'\n\nexport function PullRequestHealthPanel({\n panel,\n envelope,\n}: {\n panel: Panel\n envelope: Envelope | undefined\n}) {\n if (!envelope)\n return (\n <PanelFrame panel={panel}>\n <p className=\"panel__hint\">Loading…</p>\n </PanelFrame>\n )\n if (envelope.state === 'error')\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <p className=\"panel__status\">⚠ Unable to read</p>\n <p className=\"panel__hint\">{envelope.error.message}</p>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n const signal = pullRequestHealthSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame panel={panel} envelope={envelope} error>\n <p className=\"panel__status\">⚠ Invalid signal</p>\n </PanelFrame>\n )\n const presentation = statusPresentation(signal.data.status)\n return (\n <PanelFrame panel={panel} envelope={envelope}>\n <p className={`panel__status panel__status--${signal.data.status}`}>\n {presentation.glyph} {presentation.label}\n </p>\n <p className=\"panel__hint\">{signal.data.summary}</p>\n <ObservedAt value={envelope.observedAt} />\n </PanelFrame>\n )\n}\n\nfunction statusPresentation(status: 'passed' | 'failed' | 'running' | 'cancelled' | 'unknown') {\n switch (status) {\n case 'passed':\n return { glyph: '✓', label: 'Healthy' }\n case 'failed':\n return { glyph: '✕', label: 'Failed' }\n case 'running':\n return { glyph: '↻', label: 'Running' }\n case 'cancelled':\n return { glyph: '⊘', label: 'Cancelled' }\n case 'unknown':\n return { glyph: '?', label: 'Unknown' }\n }\n}\n","import type { Envelope, Panel } from '@ze-great-dashboard/shared'\nimport type { ComponentType } from 'react'\nimport { HttpValuePanel } from './HttpValuePanel.tsx'\nimport { PanelPlaceholder } from './PanelPlaceholder.tsx'\nimport { PipelineAnimationDemoPanel } from './PipelineAnimationDemoPanel.tsx'\nimport { PipelinePanel } from './PipelinePanel.tsx'\nimport { PullRequestHealthPanel } from './PullRequestHealthPanel.tsx'\n\ntype PanelRendererProps = {\n panel: Panel\n envelope: Envelope | undefined\n}\n\n/** The one client-side dispatch point for panel types. */\nexport const panelRenderers: Record<string, ComponentType<PanelRendererProps>> = {\n 'pipeline-status': PipelinePanel,\n 'pull-request-health': PullRequestHealthPanel,\n 'http-value': HttpValuePanel,\n 'pipeline-animation-demo': PipelineAnimationDemoPanel,\n}\n\nexport function PanelRenderer({ panel, envelope }: PanelRendererProps) {\n const Renderer = panelRenderers[panel.type]\n return Renderer ? (\n <Renderer panel={panel} envelope={envelope} />\n ) : (\n <PanelPlaceholder label={panel.type} hint=\"Not wired yet\" wide />\n )\n}\n","import { type ClientEnv, clientIdentitySchema } from '@ze-great-dashboard/shared'\nimport { useEffect } from 'react'\nimport type { DiagnosticSink } from './diagnostics.ts'\n\nconst clientUpdateIntervalMillis = 60_000\nconst clientUpdateTimeoutMillis = 10_000\nconst defaultReload = () => globalThis.window.location.reload()\n\nexport function useClientUpdate({\n env,\n diagnostics,\n fetcher,\n reload = defaultReload,\n}: {\n env: ClientEnv\n diagnostics: DiagnosticSink\n fetcher?: typeof fetch\n reload?: () => void\n}) {\n useEffect(() => {\n let cancelled = false\n let inFlight = false\n let activeController: AbortController | undefined\n const path = `${env.proxyPath}/client`\n\n const check = async () => {\n if (cancelled || inFlight) return\n inFlight = true\n const controller = new AbortController()\n activeController = controller\n const timeout = globalThis.setTimeout(() => controller.abort(), clientUpdateTimeoutMillis)\n diagnostics.record({ kind: 'client-update-check', path })\n try {\n const response = await (fetcher ?? globalThis.fetch)(path, {\n cache: 'no-store',\n signal: controller.signal,\n })\n if (!response.ok) throw new Error(`Client identity returned ${response.status}`)\n const parsed = clientIdentitySchema.safeParse(await response.json())\n if (!parsed.success) throw new Error('Client identity response was invalid')\n if (cancelled) return\n // assetPath is the server's immutable deployment selector. clientVersion is a label and\n // can change independently without changing the code the browser should load.\n if (parsed.data.assetPath !== env.assetPath) {\n diagnostics.record({\n kind: 'client-update-detected',\n path,\n current: { assetPath: env.assetPath, clientVersion: env.clientVersion },\n next: parsed.data,\n })\n reload()\n }\n } catch (error) {\n if (!cancelled && !(error instanceof DOMException && error.name === 'AbortError')) {\n diagnostics.record({\n kind: 'client-update-failure',\n path,\n message: error instanceof Error ? error.message : String(error),\n })\n }\n } finally {\n globalThis.clearTimeout(timeout)\n inFlight = false\n if (activeController === controller) activeController = undefined\n if (!cancelled) globalThis.setTimeout(() => void check(), clientUpdateIntervalMillis)\n }\n }\n\n void check()\n return () => {\n cancelled = true\n activeController?.abort()\n }\n }, [diagnostics, env.assetPath, env.clientVersion, env.proxyPath, fetcher, reload])\n}\n","import {\n type Envelope,\n type Panel,\n pipelineStatusSchema,\n pullRequestHealthSchema,\n} from '@ze-great-dashboard/shared'\nimport type { RenderedPanelDiagnostic } from './diagnostics.ts'\n\n/**\n * The compact public fact a viewer saw. Keep new panel projections here beside their\n * presentation boundary; this is intentionally not a source or server event contract.\n */\nexport function projectPanelDiagnostic(panel: Panel, envelope: Envelope): RenderedPanelDiagnostic {\n if (envelope.state === 'error') return { state: envelope.state, link: envelope.link }\n\n if (panel.type === 'pipeline-status') {\n const signal = pipelineStatusSchema.safeParse(envelope.signal)\n return {\n state: envelope.state,\n status: signal.success ? signal.data.status : undefined,\n link: envelope.link,\n }\n }\n\n if (panel.type === 'pull-request-health') {\n const signal = pullRequestHealthSchema.safeParse(envelope.signal)\n return {\n state: envelope.state,\n status: signal.success ? signal.data.status : undefined,\n link: envelope.link,\n }\n }\n\n return { state: envelope.state, link: envelope.link }\n}\n\nexport function panelDiagnosticChanged(\n previous: Envelope | undefined,\n panel: Panel,\n next: Envelope,\n) {\n if (!previous) return true\n const before = projectPanelDiagnostic(panel, previous)\n const after = projectPanelDiagnostic(panel, next)\n return (\n before.state !== after.state || before.status !== after.status || before.link !== after.link\n )\n}\n","import {\n type Board,\n type ClientEnv,\n type Envelope,\n envelopeSchema,\n parseDuration,\n resolveRefreshMillis,\n} from '@ze-great-dashboard/shared'\nimport { useEffect, useRef, useState } from 'react'\nimport { cacheMetadata, type DiagnosticSink } from './diagnostics.ts'\nimport { panelDiagnosticChanged, projectPanelDiagnostic } from './panel-diagnostics.ts'\n\nexport function usePanelSignals({\n board,\n env,\n diagnostics,\n}: {\n board: Board | undefined\n env: ClientEnv\n diagnostics: DiagnosticSink\n}) {\n const [signals, setSignals] = useState<Record<string, Envelope | undefined>>({})\n const signalsRef = useRef<Record<string, Envelope | undefined>>({})\n\n useEffect(() => {\n signalsRef.current = {}\n setSignals({})\n if (!board) return\n\n let cancelled = false\n const timers: number[] = []\n for (const panel of board.panels) {\n if (\n panel.type !== 'pipeline-status' &&\n panel.type !== 'pull-request-health' &&\n panel.type !== 'http-value'\n )\n continue\n let inFlight = false\n const refreshMillis = resolveRefreshMillis({\n boardDefaultMillis: parseDuration(board.refresh ?? '60s') ?? 60_000,\n panelOverrideMillis: panel.refresh\n ? (parseDuration(panel.refresh) ?? undefined)\n : undefined,\n adapterFloorMillis: 0,\n })\n const path = `${env.proxyPath}/panel/${encodeURIComponent(env.board)}/${encodeURIComponent(panel.id)}`\n const refresh = () => {\n if (cancelled || inFlight) return\n inFlight = true\n diagnostics.record({ kind: 'panel-fetch-start', panelId: panel.id, path })\n fetch(path)\n .then(async (response) => {\n const transport = {\n kind: 'panel-fetch-response' as const,\n panelId: panel.id,\n path,\n status: response.status,\n cache: cacheMetadata(response.headers),\n }\n if (response.status === 304) {\n diagnostics.record(transport)\n return undefined\n }\n try {\n const value: unknown = await response.json()\n const envelope = parseEnvelope(value)\n if (!envelope) {\n diagnostics.record(transport)\n diagnostics.record({\n kind: 'panel-fetch-parse-failure',\n panelId: panel.id,\n path,\n message: 'Response was not a valid signal envelope.',\n })\n return undefined\n }\n diagnostics.record({ ...transport, envelope })\n return envelope\n } catch (error) {\n diagnostics.record(transport)\n diagnostics.record({\n kind: 'panel-fetch-parse-failure',\n panelId: panel.id,\n path,\n message: errorMessage(error),\n })\n throw new DiagnosticParseFailure(error)\n }\n })\n .then((envelope) => {\n if (!cancelled && envelope) {\n const previous = signalsRef.current[panel.id]\n if (panelDiagnosticChanged(previous, panel, envelope)) {\n diagnostics.record({\n kind: 'panel-rendered',\n panelId: panel.id,\n path,\n rendered: projectPanelDiagnostic(panel, envelope),\n })\n }\n signalsRef.current = { ...signalsRef.current, [panel.id]: envelope }\n setSignals(signalsRef.current)\n }\n })\n .catch((error) => {\n if (!(error instanceof DiagnosticParseFailure)) {\n diagnostics.record({\n kind: 'panel-fetch-failure',\n panelId: panel.id,\n path,\n message: errorMessage(error),\n })\n }\n })\n .finally(() => {\n inFlight = false\n })\n }\n refresh()\n timers.push(window.setInterval(refresh, refreshMillis))\n }\n return () => {\n cancelled = true\n for (const timer of timers) window.clearInterval(timer)\n }\n }, [board, diagnostics, env.board, env.proxyPath])\n\n return signals\n}\n\nfunction errorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error)\n}\n\nclass DiagnosticParseFailure extends Error {\n constructor(error: unknown) {\n super(errorMessage(error))\n }\n}\n\nfunction parseEnvelope(value: unknown): Envelope | undefined {\n const result = envelopeSchema.safeParse(value)\n return result.success ? result.data : undefined\n}\n","import type { Board, ClientEnv } from '@ze-great-dashboard/shared'\nimport { useEffect, useRef, useState } from 'react'\nimport { Diagnostics } from './Diagnostics.tsx'\nimport { BrowserDiagnosticStore, cacheMetadata } from './diagnostics.ts'\nimport { PanelPlaceholder } from './PanelPlaceholder.tsx'\nimport { PanelRenderer } from './panel-registry.tsx'\nimport { useClientUpdate } from './useClientUpdate.ts'\nimport { usePanelSignals } from './usePanelSignals.ts'\n\n/**\n * The board shell.\n *\n * Stage 1 has no data: there is no proxy endpoint to poll yet. What this proves is the plumbing —\n * that the client was handed its configuration by the server and knows which version of itself it\n * is. The version readout is what makes two published versions visibly different, which is the\n * whole point of the Stage 1 exit criterion.\n */\nexport function App({ env }: { env: ClientEnv }) {\n const [board, setBoard] = useState<Board>()\n const [loadedBoardName, setLoadedBoardName] = useState<string>()\n const diagnosticsRef = useRef<BrowserDiagnosticStore | null>(null)\n if (!diagnosticsRef.current) diagnosticsRef.current = new BrowserDiagnosticStore(env)\n const diagnostics = diagnosticsRef.current\n useClientUpdate({ env, diagnostics })\n const signals = usePanelSignals({\n board: loadedBoardName === env.board ? board : undefined,\n env,\n diagnostics,\n })\n\n useEffect(() => {\n let cancelled = false\n setBoard(undefined)\n setLoadedBoardName(undefined)\n const path = `${env.proxyPath}/boards/${encodeURIComponent(env.board)}`\n diagnostics.record({ kind: 'board-fetch-start', path })\n fetch(path)\n .then(async (response) => {\n diagnostics.record({\n kind: 'board-fetch-response',\n path,\n status: response.status,\n cache: cacheMetadata(response.headers),\n })\n if (!response.ok) throw new Error(`Board configuration returned ${response.status}`)\n try {\n return await response.json()\n } catch (error) {\n diagnostics.record({\n kind: 'board-fetch-parse-failure',\n path,\n message: errorMessage(error),\n })\n throw new DiagnosticParseFailure(error)\n }\n })\n .then((value: unknown) => {\n if (!cancelled) {\n setBoard(value as Board)\n setLoadedBoardName(env.board)\n const panels = Array.isArray((value as { panels?: unknown }).panels)\n ? (value as { panels: Array<{ id?: unknown }> }).panels\n : []\n diagnostics.record({\n kind: 'board-fetch-response',\n path,\n boardSummary: {\n panelCount: panels.length,\n panelIds: panels.flatMap((panel) => (typeof panel.id === 'string' ? [panel.id] : [])),\n },\n })\n }\n })\n .catch((error) => {\n if (!(error instanceof DiagnosticParseFailure)) {\n diagnostics.record({ kind: 'board-fetch-failure', path, message: errorMessage(error) })\n }\n if (!cancelled) {\n setBoard({ panels: [] })\n setLoadedBoardName(env.board)\n }\n })\n return () => {\n cancelled = true\n }\n }, [diagnostics, env.board, env.proxyPath])\n\n return (\n <div className=\"board\">\n <header className=\"board__header\">\n <h1 className=\"board__title\">{env.board}</h1>\n </header>\n\n <main className=\"board__grid\">\n {!board && <PanelPlaceholder label=\"board\" hint=\"Loading configuration…\" wide />}\n {board?.panels.map((panel) => (\n <PanelRenderer key={panel.id} panel={panel} envelope={signals[panel.id]} />\n ))}\n </main>\n\n <footer className=\"board__footer\">\n <span>Signals are read live from their configured authorities.</span>\n <Diagnostics log={diagnostics} />\n </footer>\n </div>\n )\n}\n\nfunction errorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error)\n}\n\nclass DiagnosticParseFailure extends Error {\n constructor(error: unknown) {\n super(errorMessage(error))\n }\n}\n","export function ConfigError({ message }: { message: string }) {\n return (\n <div className=\"config-error\" role=\"alert\">\n <h1>⚠️ Dashboard misconfigured</h1>\n <p>The page loaded, but the server did not hand it usable configuration.</p>\n <pre>{message}</pre>\n </div>\n )\n}\n","import { readClientEnv } from '@ze-great-dashboard/shared'\nimport { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { App } from './App.tsx'\nimport { ConfigError } from './ConfigError.tsx'\nimport './styles.css'\n\nconst container = document.getElementById('root')\nif (!container) {\n throw new Error('No #root element in the document — the template is not the one we expect.')\n}\n\nconst root = createRoot(container)\n\ntry {\n root.render(\n <StrictMode>\n <App env={readClientEnv()} />\n </StrictMode>,\n )\n} catch (error) {\n // A radiator that fails silently is worse than one that says what's wrong. If configuration\n // never arrived, say so on screen rather than rendering an empty board.\n root.render(<ConfigError message={error instanceof Error ? error.message : String(error)} />)\n}\n"],"mappings":"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"}
|