@xauyxau/hnch 1.17.0 → 1.17.1
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/dist/index.js +19 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import Dd from'yargs';import {hideBin}from'yargs/helpers';import vn,{useState,useEffect,useCallback,useMemo,useRef}from'react';import {render,useApp,useInput,Box,Text}from'ink';import*as _e from'yjs';import {Awareness}from'y-protocols/awareness';import {existsSync,readFileSync,writeFileSync,unlinkSync,mkdirSync,chmodSync}from'fs';import {homedir}from'os';import {join}from'path';import {randomUUID}from'crypto';import {createInterface}from'readline';import {WebsocketProvider}from'y-websocket';import xa from'ws';import Ri from'clipboardy';import {jsxs,jsx,Fragment}from'react/jsx-runtime';var Bt="hnch_abstain";function Z(e){return e===Bt}var Re="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",jt=Re.length,Dn=Math.floor(jt/2);function pt(e){let t=Re.indexOf(e);if(t===-1)throw new Error(`fractional-index: invalid character '${e}'`);return t}function Eo(e,t){return e.length>=t?e:e+"0".repeat(t-e.length)}function hs(e){let t=e.length-1;for(;t>0&&e[t]==="0";)t--;return e.slice(0,t+1)}function Ss(e,t){let n=e.length,o=Array.from({length:n+1}).fill(0),r=0;for(let s=n-1;s>=0;s--){let c=e[s]+t[s]+r;o[s+1]=c%jt,r=Math.floor(c/jt);}o[0]=r;let i=Array.from({length:n+1}).fill(0),a=0;for(let s=0;s<=n;s++){let c=o[s]+a*jt;i[s]=Math.floor(c/2),a=c%2;}return i.slice(1)}function On(e,t){let n=Re[Dn];if(e===null&&t===null)return n+n;if(t===null)return e+n+n+n+n;if(e===null)return xs(t);if(e>=t)throw new Error(`keyBetween: a must be < b (a='${e}', b='${t}')`);return ws(e,t)}function xs(e){for(let t=e.length-1;t>=0;t--){let n=pt(e[t]);if(n>0)return e.slice(0,t)+Re[n-1]+Re[Dn]}if(e.length>1)return e.slice(0,-1);throw new Error(`keyBetween: cannot generate key before '${e}' \u2014 use keyBetween(null, null) for the initial key`)}function ws(e,t){let n=Math.max(e.length,t.length),o=Eo(e,n).split("").map(c=>pt(c)),r=Eo(t,n).split("").map(c=>pt(c)),a=Ss(o,r).map(c=>Re[c]).join(""),s=hs(a);return s>e&&s<t?s:a>e&&a<t?a:Cs(e,t)}function Cs(e,t){for(let n=0;n<t.length;n++){let o=n<e.length?pt(e[n]):0;if(pt(t[n])===o+1)return (n<e.length?e.slice(0,n+1):e+Re[0])+Re[Dn]}throw new Error(`keyBetween: space exhausted between '${e}' and '${t}'`)}function Mn(e){let{revealedAt:t,skippedAt:n,discardedAt:o}=e;if(t===void 0&&n===void 0&&o===void 0)return null;let r=[];t!==void 0&&r.push({kind:"revealed",at:t}),n!==void 0&&r.push({kind:"skipped",at:n}),o!==void 0&&r.push({kind:"discarded",at:o});let i={revealed:0,skipped:1,discarded:2};return r.sort((a,s)=>a.at-s.at||i[a.kind]-i[s.kind]),r[0].kind}function mt(e){return e==="revealed"||e==="skipped"||e==="discarded"}function Ft(e){return e==="revealed"||e==="skipped"}function et(e){return !mt(e)}var ko="meta",Po="settings",No="participants",Do="rounds",Oo="agenda",ys=["roomUuid","createdAt","createdBy","sessionEndedAt"],vs=["name","defaultScale","hostParticipantId"],Is=["displayName","joinedAt","role","leftAt","removedBy","avatarColor"],bs=["id","title","description","ticketId","state","source","externalId","sortKey","createdAt","consumedAt","consumedByRoundId"],As=["id","title","description","ticketId","parentRoundId","scale","timerStartedAt","revealedAt","skippedAt","discardedAt","discardedBy","createdBy","createdAt","agendaItemId"];function Vt(e){return e.getMap(ko)}function Wt(e){return e.getMap(Po)}function Te(e){return e.getMap(No)}function Un(e){return e.getArray(Do)}function gt(e){return e.getArray(Oo)}function ht(e,t){let n={};for(let o of t){let r=e.get(o);r!==void 0&&(n[o]=r);}return n}function Rs(e){return ht(Vt(e),ys)}function Ts(e){return ht(Wt(e),vs)}function Es(e){let t=Te(e),n=[];return t.forEach((o,r)=>{let i=ht(o,Is);n.push({id:r,...i});}),n.sort((o,r)=>o.joinedAt-r.joinedAt||o.id.localeCompare(r.id)),n}function ks(e){let t={};return e.forEach((n,o)=>{t[o]=n;}),t}function Ps(e){let t=ht(e,As),n=e.get("votes"),o=n?ks(n):{},r=Mn(t),{revealedAt:i,skippedAt:a,discardedAt:s,...c}=t,l=r??(t.timerStartedAt!==void 0?"voting":"pending"),u=r==="revealed"?i:r==="skipped"?a:r==="discarded"?s:void 0;return u===void 0?{...c,votes:o,status:l}:{...c,votes:o,status:l,terminalAt:u}}function Ns(e){let t=Un(e),n=[];return t.forEach(o=>{n.push(Ps(o));}),n}function Ds(e){return ht(e,bs)}function Os(e){let t=gt(e),n=[];return t.forEach(o=>{n.push(Ds(o));}),n.sort((o,r)=>o.sortKey.localeCompare(r.sortKey)),n}function F(e){return {meta:Rs(e),settings:Ts(e),participants:Es(e),rounds:Ns(e),agenda:Os(e)}}function _n(e,t){if(Vt(e).has("roomUuid"))throw new Error("initDoc: doc already seeded");e.transact(()=>{let n=Vt(e);n.set("roomUuid",t.roomUuid),n.set("createdAt",t.createdAt),n.set("createdBy",t.participantId);let o=Wt(e);t.sessionName!==void 0&&o.set("name",t.sessionName),o.set("defaultScale",t.defaultScale),o.set("hostParticipantId",t.participantId);let r=new _e.Map;r.set("displayName",t.displayName),r.set("joinedAt",t.createdAt),t.avatarColor!==void 0&&r.set("avatarColor",t.avatarColor),Te(e).set(t.participantId,r);});}function $e(e,t){e.transact(()=>{let n=Te(e),o=n.get(t.participantId),r=o??new _e.Map;r.set("displayName",t.displayName),o===void 0&&r.set("joinedAt",t.joinedAt),t.avatarColor!==void 0&&r.set("avatarColor",t.avatarColor),r.delete("leftAt"),r.delete("removedBy"),o===void 0&&n.set(t.participantId,r);});}function Yt(e,t){e.transact(()=>{let n=Wt(e);for(let[o,r]of Object.entries(t))r===void 0?n.delete(o):n.set(o,r);});}function Jt(e,t){Yt(e,t);}function $n(e,t,n){e.transact(()=>{let o=Te(e),r=o.get(t),i=r??new _e.Map;i.set("displayName",n.displayName),i.set("joinedAt",n.joinedAt),n.role!==void 0&&i.set("role",n.role),n.avatarColor!==void 0&&i.set("avatarColor",n.avatarColor),r===void 0&&o.set(t,i);});}function Mo(e,t,n){e.transact(()=>{let r=Te(e).get(t);r&&r.set("avatarColor",n);});}function Uo(e,t){let n=t.scale??Wt(e).get("defaultScale");if(!n)throw new Error("appendRound: no scale (settings.defaultScale missing)");if(t.parentRoundId!==void 0){let o=Le(e,t.parentRoundId);if(o!==void 0&&o.get("discardedAt")!==void 0)throw new Error(`appendRound: parentRoundId ${t.parentRoundId} points at a discarded round`)}return e.transact(()=>{let o=new _e.Map;o.set("id",t.id),o.set("createdAt",t.createdAt),o.set("createdBy",t.createdBy),o.set("scale",n),t.title!==void 0&&o.set("title",t.title),t.description!==void 0&&o.set("description",t.description),t.ticketId!==void 0&&o.set("ticketId",t.ticketId),t.parentRoundId!==void 0&&o.set("parentRoundId",t.parentRoundId),t.agendaItemId!==void 0&&o.set("agendaItemId",t.agendaItemId),o.set("timerStartedAt",t.createdAt),o.set("votes",new _e.Map),Un(e).push([o]);}),t.id}function Ln(e,t,n){let o=Le(e,t);if(!o)throw new Error(`patchRoundDescriptor: round ${t} not found`);e.transact(()=>{n.title!==void 0&&o.set("title",n.title),n.description!==void 0&&o.set("description",n.description);});}function Le(e,t){let n=Un(e);for(let o=0;o<n.length;o+=1){let r=n.get(o);if(r.get("id")===t)return r}}function Hn(e){return Mn({revealedAt:e.get("revealedAt"),skippedAt:e.get("skippedAt"),discardedAt:e.get("discardedAt")})}function _o(e,t,n,o){let r=Le(e,t);if(!r)throw new Error(`castVote: round ${t} not found`);r.get("revealedAt")===void 0&&e.transact(()=>{r.get("votes").set(n,o);});}function Bn(e,t,n){let o=Le(e,t);if(!o)throw new Error(`clearVote: round ${t} not found`);o.get("revealedAt")===void 0&&e.transact(()=>{o.get("votes").delete(n);});}function $o(e,t,n,o){let r=t.get("agendaItemId");if(r===void 0)return;let i=Kt(e,r);i!==void 0&&i.get("state")==="pending"&&(i.set("state","consumed"),i.set("consumedAt",o),i.set("consumedByRoundId",n));}function Lo(e,t,n){let o=Le(e,t);if(!o)throw new Error(`revealRound: round ${t} not found`);let r=Hn(o);if(r!==null)throw new Error(`revealRound: round ${t} already terminal (${r})`);e.transact(()=>{o.set("revealedAt",n),$o(e,o,t,n);});}function Ho(e,t,n){let o=Le(e,t);if(!o)throw new Error(`skipRound: round ${t} not found`);let r=Hn(o);if(r!==null)throw new Error(`skipRound: round ${t} already terminal (${r})`);e.transact(()=>{o.set("skippedAt",n),$o(e,o,t,n);});}function Bo(e,t,n,o){let r=Le(e,t);if(!r)throw new Error(`discardRound: round ${t} not found`);let i=Hn(r);if(i!==null)throw new Error(`discardRound: round ${t} already terminal (${i})`);e.transact(()=>{r.set("discardedAt",n),r.set("discardedBy",o);});}function jo(e,t){e.transact(()=>{Vt(e).set("sessionEndedAt",t);});}function Fo(e,t,n){let r=Te(e).get(t);r&&e.transact(()=>{r.set("leftAt",n),r.set("removedBy",t);});}function Vo(e,t){let o=Te(e).get(t);!o||!o.has("leftAt")||e.transact(()=>{o.delete("leftAt"),o.delete("removedBy");});}function Wo(e,t,n,o){if(n===t)return;let i=Te(e).get(n);i&&e.transact(()=>{i.set("leftAt",o),i.set("removedBy",t);});}function me(e){let{rounds:t}=e;if(t.length===0)return null;for(let n=t.length-1;n>=0;n-=1){let o=t[n];if(o.status==="pending"||o.status==="voting")return o}for(let n=t.length-1;n>=0;n-=1){let o=t[n];if(o.status!=="discarded")return o}return null}function tt(e){let{rounds:t}=e;for(let n=t.length-1;n>=0;n-=1){let o=t[n];if(et(o.status))return o}return null}function jn(e){let t=Object.values(e.votes);return t.length<2?false:t.every(n=>n===t[0])}function Kt(e,t){let n=gt(e);for(let o=0;o<n.length;o++){let r=n.get(o);if(r.get("id")===t)return r}}function St(e,t){return !!e?.trim()||!!t?.trim()}function Yo(e,t){if(!St(t.title,t.ticketId))throw new Error("appendAgendaItem: at least one of {title, ticketId} is required");let n=crypto.randomUUID(),o=gt(e),r=null;o.forEach(a=>{if(a.get("state")==="pending"){let s=a.get("sortKey");s!==void 0&&(r===null||s>r)&&(r=s);}});let i=On(r,null);return e.transact(()=>{let a=new _e.Map;a.set("id",n),a.set("state","pending"),a.set("source",t.source??"manual"),a.set("sortKey",i),a.set("createdAt",t.createdAt),t.title!==void 0&&a.set("title",t.title),t.description!==void 0&&a.set("description",t.description),t.ticketId!==void 0&&a.set("ticketId",t.ticketId),t.externalId!==void 0&&a.set("externalId",t.externalId),gt(e).push([a]);}),n}function Jo(e,t,n){let o=Kt(e,t);if(!o)throw new Error(`updateAgendaItemFields: item ${t} not found`);let r=o.get("state");if(r==="skipped"||r==="cancelled")throw new Error(`updateAgendaItemFields: item ${t} is ${r} and cannot be edited`);let i=n.title!==void 0?n.title:o.get("title"),a=n.ticketId!==void 0?n.ticketId:o.get("ticketId");if(!St(i,a))throw new Error("updateAgendaItemFields: at least one of {title, ticketId} must remain non-empty");e.transact(()=>{n.title!==void 0&&o.set("title",n.title),n.ticketId!==void 0&&o.set("ticketId",n.ticketId),n.description!==void 0&&o.set("description",n.description);});}function Fn(e,t,n,o={}){let r=Kt(e,t);if(!r)throw new Error(`setAgendaItemState: item ${t} not found`);let i=r.get("state");if(!(i===n&&n==="consumed")){if(i!=="pending")throw new Error(`setAgendaItemState: invalid transition '${i}' \u2192 '${n}' for item ${t}`);if(n==="consumed"&&o.timestamp===void 0)throw new Error(`setAgendaItemState: timestamp is required when consuming item ${t}`);e.transact(()=>{r.set("state",n),n==="consumed"&&(r.set("consumedAt",o.timestamp),o.consumedByRoundId!==void 0&&r.set("consumedByRoundId",o.consumedByRoundId));});}}function Ko(e,t,n,o){let r=Kt(e,t);if(!r)throw new Error(`reorderAgendaItem: item ${t} not found`);let i=r.get("state");if(i!=="pending")throw new Error(`reorderAgendaItem: item ${t} is ${i}; only pending items may be reordered`);let a=On(n??null,o??null);e.transact(()=>{r.set("sortKey",a);});}function He(e){for(let t of e.agenda)if(t.state==="pending")return t;return null}function Go(e,t){let n=F(e).agenda.find(o=>o.id===t);return n||{applied:false,reason:"not-found"}}function Vn(e,t){let n=Go(e,t);return xt(n)?n:n.state!=="pending"?{applied:false,reason:"not-pending"}:n}function Ms(e){return e.state==="skipped"||e.state==="cancelled"}function xt(e){return "applied"in e}function nt(e,t,n=Date.now){if(!St(t.title,t.ticketId))return {applied:false,reason:"invalid-fields"};let o=n();return {applied:true,id:Yo(e,{...t,createdAt:o}),at:o}}function zo(e,t,n){let o=Go(e,t);if(xt(o))return o;if(Ms(o))return {applied:false,reason:"not-pending"};let r=n.title!==void 0?n.title:o.title,i=n.ticketId!==void 0?n.ticketId:o.ticketId;return St(r,i)?(Jo(e,t,n),{applied:true,id:t}):{applied:false,reason:"invalid-fields"}}function Gt(e,t){let n=Vn(e,t);return xt(n)?n:(Fn(e,t,"skipped"),{applied:true,id:t})}function zt(e,t){let n=Vn(e,t);return xt(n)?n:(Fn(e,t,"cancelled"),{applied:true,id:t})}function qt(e,t,n,o){let r=Vn(e,t);return xt(r)?r:(Ko(e,t,n,o),{applied:true,id:t})}var Wn={"unknown-room":4001,"wrong-password":4002,"invalid-invite":4003,"expired-invite":4004,"invite-already-redeemed":4005,"room-full":4006,"malformed-credentials":4010},qo=new Map(Object.entries(Wn).map(([e,t])=>[t,e])),Xo=20;function ge(e){return e.role??"voter"}function Be(e){return e.leftAt===void 0}var Xt={id:"fibonacci",cards:["0","1","2","3","5","8","13","21"]},Qo={id:"t-shirt",cards:["XS","S","M","L","XL"]},Zo={id:"powers-of-2",cards:["1","2","4","8","16","32","64"]},er={id:"linear",cards:["1","2","3","4","5","6","7","8","9","10"]},tr={id:"risk",cards:["Low","Medium","High","Critical"]},de={[Xt.id]:Xt,[Qo.id]:Qo,[Zo.id]:Zo,[er.id]:er,[tr.id]:tr},nr={fibonacci:"Fibonacci","t-shirt":"T-shirt","powers-of-2":"Powers of 2",linear:"Linear (1\u201310)",risk:"Risk"},Us="Custom scale",_s=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;function or(e){if(e in nr)return nr[e];if(e.length===0)return e;let t=e.startsWith("custom-")?e.slice(7):e;return t!==e&&_s.test(t)?Us:t.split("-").map(n=>n.length===0?n:n.charAt(0).toUpperCase()+n.slice(1)).join(" ")}function $s(e,t,n){if(!e||e.status!=="voting"&&e.status!=="pending")return false;let o=new Set(t.filter(c=>Be(c)&&n.has(c.id)&&ge(c)!=="viewer").map(c=>c.id));if(o.size===0)return false;let r=Object.entries(e.votes).filter(([c])=>o.has(c)),i=r.filter(([,c])=>Z(c)).length,a=r.length-i,s=o.size-i;return s<=0?false:a>=s}function Ls(e,t){return e.participants.some(n=>Be(n)&&n.id!==t)}function rr(e){function t(){let o=e.projection();if(!o||!e.presenceTrusted()&&Ls(o,e.selfId()))return;let r=me(o);$s(r,o.participants,e.onlineIds())&&e.reveal();}let n=e.subscribe(t);return t(),{stop(){n();}}}var ot={"racing-green":{base:"#0B3D2E",soft:"rgba(11,61,46,0.14)",ink:"#fff",label:"Racing Green"},dijon:{base:"#C9A227",soft:"rgba(201,162,39,0.18)",ink:"#000",label:"Dijon"},blue:{base:"#0A84FF",soft:"rgba(10,132,255,0.14)",ink:"#fff",label:"Blue"},indigo:{base:"#5E5CE6",soft:"rgba(94,92,230,0.14)",ink:"#fff",label:"Indigo"},violet:{base:"#BF5AF2",soft:"rgba(191,90,242,0.14)",ink:"#fff",label:"Violet"},pink:{base:"#FF375F",soft:"rgba(255,55,95,0.14)",ink:"#fff",label:"Pink"},red:{base:"#FF453A",soft:"rgba(255,69,58,0.14)",ink:"#fff",label:"Red"},orange:{base:"#FF9F0A",soft:"rgba(255,159,10,0.16)",ink:"#000",label:"Orange"},amber:{base:"#FFD60A",soft:"rgba(255,214,10,0.18)",ink:"#000",label:"Amber"},green:{base:"#30D158",soft:"rgba(48,209,88,0.14)",ink:"#000",label:"Green"},teal:{base:"#40C8E0",soft:"rgba(64,200,224,0.14)",ink:"#000",label:"Teal"},graphite:{base:"#1C1C1E",soft:"rgba(28,28,30,0.10)",ink:"#fff",label:"Graphite"}};var wt=["racing-green","dijon","blue","indigo","violet","pink","red","orange","amber","green","teal","graphite"],Hs=/^#[0-9a-fA-F]{6}$/;function Bs(e){return Object.hasOwn(ot,e)}function je(e){return e?Bs(e)?ot[e].base:Hs.test(e)?e.toLowerCase():null:null}function ir(e){let t=5381;for(let o=0;o<e.length;o++)t=(t<<5)+t+e.charCodeAt(o)|0;let n=Math.abs(t)%wt.length;return wt[n]}var js=5e3,Ee="participantId";function sr(e){let t=new Set;for(let n of e.values()){if(typeof n!="object"||n===null)continue;let o=n[Ee];typeof o=="string"&&t.add(o);}return t}function ar(e,t){let n=new Set;for(let o of e.participants)t.has(o.id)&&Be(o)&&n.add(o.id);return n}function Fs(e,t,n){let o=e.settings.hostParticipantId;return o?ar(e,t).has(o)?{kind:"cancel"}:n.missingHostId!==o?{kind:"start-debounce",hostId:o}:{kind:"none"}:{kind:"none"}}function Vs(e,t,n,o){let r=e.settings.hostParticipantId;if(!o||r!==o)return {promote:false};let i=ar(e,t);if(i.has(r))return {promote:false};let a=[...i].toSorted();if(a.length===0)return {promote:false};let s=a[0];return s!==n?{promote:false}:{promote:true,winner:s}}function dr(e){let t=null,n=null;function o(){n!==null&&(clearTimeout(n),n=null),t=null;}function r(){n=null;let s=t;t=null;let c=e.projection(),l=e.myId();if(!c||l===null)return;let u=Vs(c,e.onlineIds(),l,s);u.promote&&e.promote(u.winner);}function i(){let s=e.projection();if(!s||e.myId()===null){o();return}let c=Fs(s,e.onlineIds(),{missingHostId:t});switch(c.kind){case "cancel":o();break;case "start-debounce":o(),t=c.hostId,n=setTimeout(r,js);break;}}let a=e.subscribe(i);return i(),{stop(){o(),a();}}}function Qt(e){let t=Math.max(0,Math.floor(e/1e3)),n=Math.floor(t/60),o=t%60;return `${n}:${o.toString().padStart(2,"0")}`}function cr(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return false}}function Yn(e){if(e===null||typeof e!="object"||Array.isArray(e))return {version:2,entries:{}};let t=e;if(t.version===2&&ur(t.entries)){let n=t.entries,o={};for(let[r,i]of Object.entries(n)){let a=Ws(i);a!==null&&(o[r]=a);}return {version:2,entries:o}}if(typeof t.roomCode=="string"&&typeof t.roomUuid=="string"&&typeof t.lastSeenAt=="number"){let n={roomCode:t.roomCode,roomUuid:t.roomUuid,lastSeenAt:t.lastSeenAt,...typeof t.passwordHash=="string"?{passwordHash:t.passwordHash}:{}};return {version:2,entries:{[n.roomUuid]:n}}}return {version:2,entries:{}}}function lr(e,t,n=864e5){let o={};for(let[r,i]of Object.entries(e.entries))t-i.lastSeenAt>n||(i.lastSeenAt>t?o[r]={...i,lastSeenAt:t}:o[r]=i);return {version:2,entries:o}}function ur(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Ws(e){if(!ur(e))return null;let t=e;return typeof t.roomCode!="string"||typeof t.roomUuid!="string"||typeof t.lastSeenAt!="number"?null:{roomCode:t.roomCode,roomUuid:t.roomUuid,lastSeenAt:t.lastSeenAt,...typeof t.passwordHash=="string"?{passwordHash:t.passwordHash}:{}}}function fr(e,t){let n=t.filter(f=>f.status!=="discarded"),o=new Map;for(let f of n)o.set(f.id,f);let r=o.get(e);if(r===void 0||r.parentRoundId===void 0)return null;let i=new Set([r.id]),a=r,s=1;for(;a.parentRoundId!==void 0;){let f=o.get(a.parentRoundId);if(f===void 0||i.has(f.id))return null;i.add(f.id),a=f,s+=1;}let c=a,l=new Map;for(let f of n){if(f.parentRoundId===void 0)continue;let T=l.get(f.parentRoundId);T===void 0?l.set(f.parentRoundId,[f]):T.push(f);}let u=0,d=[c];for(;d.length>0;){let f=d.shift();u+=1;let T=l.get(f.id);T!==void 0&&d.push(...T);}return {chainRoot:c,depth:s,total:u}}var pr="PBKDF2",Ys="SHA-256",mr=new TextEncoder;function Js(e){return Array.from(new Uint8Array(e)).map(t=>t.toString(16).padStart(2,"0")).join("")}var Ks=/^[\s\u200B-\u200D\u2060]+|[\s\u200B-\u200D\u2060]+$/gu,Jn=120;function ke(e){return e.normalize("NFC").replace(Ks,"")}async function Zt(e,t){let n=await crypto.subtle.importKey("raw",mr.encode(ke(e)),pr,false,["deriveBits"]),o=await crypto.subtle.deriveBits({name:pr,salt:mr.encode(t),iterations:1e5,hash:Ys},n,256);return Js(o)}var Ct=class extends Error{reason;constructor(t){super(`relay rejected resolve: ${t}`),this.reason=t,this.name="RelayRejectionError";}},Kn=1e4;async function hr(e,t){let n=await fetch(`${e}/rooms`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({}),signal:AbortSignal.timeout(Kn)});if(!n.ok)throw new Error(`POST /rooms failed: ${n.status}`);return await n.json()}function Sr(e){if(typeof e!="object"||e===null)return null;let{reason:t}=e;return typeof t=="string"&&Object.hasOwn(Wn,t)?t:null}async function ce(e,t){let n=await fetch(`${e}/rooms/${encodeURIComponent(t)}`,{signal:AbortSignal.timeout(Kn)});if(n.status===404){let o=await n.json().catch(()=>null),r=Sr(o);if(r!==null)throw new Ct(r)}if(!n.ok)throw new Error(`GET /rooms/:code failed: ${n.status}`);return await n.json()}async function Gn(e,t,n){let o=await fetch(`${e}/rooms/${t}/access`,{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({passwordHash:n}),signal:AbortSignal.timeout(Kn)});if(!o.ok)throw new Error(`PATCH /rooms/:uuid/access failed: ${o.status}`);return await o.json()}var zs=6e4,qs=3,Xs=5e3,Qs=8e3;async function Zs(e,t,n){let o,r;try{let s=await fetch(`${e}/rooms/${encodeURIComponent(n.roomCode)}`,{signal:AbortSignal.timeout(Qs)});o=s.status,r=await s.json().catch(()=>null);}catch{return null}if(o===404)return Sr(r)==="unknown-room"?"unknown-room":null;if(o!==200||typeof r!="object"||r===null)return null;let{uuid:i,accessMode:a}=r;return typeof i!="string"?null:i!==t?"unknown-room":a==="password"&&n.passwordHash===void 0?"wrong-password":null}function ea(e){return e.replace(/^https?:\/\//,t=>t==="https://"?"wss://":"ws://")}function gr(e){let t={did:e.deviceId};return e.passwordHash!==void 0&&(t.pw=e.passwordHash),t}function ta(){return globalThis.window}function xr(e){let t="connecting",n=null,o=false,r=false,i=false,a=false,s=false,c=[],l=()=>{let I=o&&t!=="connected"&&n===null&&!r&&!a;I!==i&&(i=I,e.onReconnectingChange?.(I));},u=`${ea(e.httpBaseUrl)}/ws`,d=e.credentials,f=new WebsocketProvider(u,e.roomUuid,e.doc,{params:gr(d),connect:true,...e.awareness!==void 0&&{awareness:e.awareness},...e.WebSocketPolyfill!==void 0&&{WebSocketPolyfill:e.WebSocketPolyfill}}),T=()=>{let{awareness:I}=f;for(let H of I.meta.keys())H!==I.clientID&&!I.states.has(H)&&I.meta.delete(H);},D=()=>{let I=f.awareness.getLocalState();I!==null&&f.awareness.setLocalState(I);},b=I=>{I!==s&&(s=I,e.onSyncedChange?.(I));};T();let R=I=>{t=I.status,I.status==="disconnected"&&T(),I.status==="connected"&&D(),e.onStatusChange?.(I.status),I.status==="connected"&&(o=true,a=false,n=null,e.onRejectionChange?.(null),c.length=0),l();},U=false,P=()=>{U=true;try{f.disconnect();}finally{U=false;}},A=I=>{n=I,e.onRejectionChange?.(I),f.shouldConnect=false,P(),l();},p=false,w=Number.NEGATIVE_INFINITY,_=()=>r||n!==null,y=async()=>{let I=Date.now();if(I<w&&(w=Number.NEGATIVE_INFINITY),p||I-w<Xs)return;p=true,w=I;let H=d;try{let K=await Zs(e.httpBaseUrl,e.roomUuid,H);if(K===null||_()||t==="connected"||H!==d||a)return;A(K);}finally{p=false;}},O=I=>{if(U)return;a=false;let H=I===null?void 0:qo.get(I.code);if(H===void 0){let K=Date.now();c.push(K);let m=K-zs;for(;c.length>0&&c[0]<m;)c.shift();c.length>=qs&&(c.length=0,e.onRepeatRejection?.()),l(),y();return}A(H);};f.on("status",R),f.on("connection-close",O);let v=f,k=null;if(e.onSynced!==void 0){let I=H=>{H&&(v.off("synced",I),k=null,e.onSynced?.());};k=I,v.on("synced",I);}let te=I=>{b(I);};v.on("synced",te);let X=()=>{r||(t="disconnected",b(false),e.onStatusChange?.("disconnected"),l());},Q=()=>{r||n!==null||t!=="connected"&&(f.ws!==null?(f.wsUnsuccessfulReconnects=0,f.ws.close()):f.connect());},V=ta();V?.addEventListener("offline",X),V?.addEventListener("online",Q);let J=false;return {awareness:f.awareness,updateCredentials(I){let H=I.passwordHash??void 0;H!==d.passwordHash&&(d=H===void 0?{roomCode:d.roomCode,deviceId:d.deviceId}:{...d,passwordHash:H},a=t==="connected",n!==null&&(n=null,e.onRejectionChange?.(null)),f.shouldConnect=false,P(),f.params=gr(d),f.connect());},disconnect(){J||(J=true,r=true,l(),f.off("status",R),f.off("connection-close",O),k!==null&&(v.off("synced",k),k=null),v.off("synced",te),b(false),V?.removeEventListener("offline",X),V?.removeEventListener("online",Q),f.shouldConnect=false,P(),f.destroy());}}}var wr="ABCDEFGHJKMNPQRSTUVWXYZ23456789";if(wr.length!==31)throw new Error(`Room code alphabet must be 31 characters, got ${wr.length}`);function zn(e){return e.trim().replaceAll(/-/g,"").toUpperCase()}function Cr(e,t=true){let n=zn(e);return !t||n.length!==6?n:`${n.slice(0,3)}-${n.slice(3)}`}function yt(e,t){return F(e).participants.find(n=>n.id===t)}function yr(e,t,n){let o=F(e);return {isHost:o.settings.hostParticipantId===t,target:o.participants.find(r=>r.id===n)}}function na(e,t){return F(e).settings.hostParticipantId===t}function vr(e,t){let n=t.role??e.role;return {displayName:t.displayName??e.displayName,joinedAt:e.joinedAt,...n!==void 0&&{role:n},...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}}function Ir(e,t,n){let o=yt(e,t);return o?($n(e,t,vr(o,{displayName:n})),{applied:true}):{applied:false,reason:"not-found"}}function br(e,t,n){return yt(e,t)?(Mo(e,t,n),{applied:true}):{applied:false,reason:"not-found"}}function Ar(e,t){let n=yt(e,t);if(!n)return {applied:false,reason:"not-found"};let o=ge(n)==="voter"?"viewer":"voter";return $n(e,t,vr(n,{role:o})),{applied:true}}function Rr(e,t,n=Date.now){if(!yt(e,t))return {applied:false,reason:"not-found"};let o=n();return Fo(e,t,o),{applied:true,at:o}}function Tr(e,t){return yt(e,t)?(Vo(e,t),{applied:true}):{applied:false,reason:"not-found"}}function Er(e,t,n,o=Date.now){let r=yr(e,t,n);if(!r.isHost)return {applied:false,reason:"not-host"};if(n===t)return {applied:false,reason:"self-target"};if(!r.target)return {applied:false,reason:"not-found"};let i=o();return Wo(e,t,n,i),{applied:true,at:i}}function kr(e,t,n,o){let r=yr(e,t,n);return r.isHost?r.target?o.has(n)?(Yt(e,{hostParticipantId:n}),{applied:true}):{applied:false,reason:"not-online"}:{applied:false,reason:"not-found"}:{applied:false,reason:"not-host"}}function Pr(e,t){return Yt(e,{hostParticipantId:t}),{applied:true}}function Nr(e,t,n=Date.now){if(!na(e,t))return {applied:false,reason:"not-host"};let o=n();return jo(e,o),{applied:true,at:o}}function Dr(e,t={},n=Date.now){let o=F(e).settings.hostParticipantId;if(!o)return {applied:false,reason:"no-host"};let r=crypto.randomUUID(),i=n();return Uo(e,{id:r,createdAt:i,createdBy:o,...t.title!==void 0&&{title:t.title},...t.description!==void 0&&{description:t.description},...t.ticketId!==void 0&&{ticketId:t.ticketId},...t.parentRoundId!==void 0&&{parentRoundId:t.parentRoundId},...t.agendaItemId!==void 0&&{agendaItemId:t.agendaItemId}}),{applied:true,id:r,at:i}}function qn(e){let t=me(F(e));return t?et(t.status)?{round:t}:{applied:false,reason:"already-terminal"}:{applied:false,reason:"no-current-round"}}function Or(e,t=Date.now){let n=qn(e);if("applied"in n)return n;let o=t();return Lo(e,n.round.id,o),{applied:true,at:o}}function Mr(e,t=Date.now){let n=qn(e);if("applied"in n)return n;let o=t();return Ho(e,n.round.id,o),{applied:true,at:o}}function Ur(e,t,n=Date.now){let o=qn(e);if("applied"in o)return o;let r=n();return Bo(e,o.round.id,r,t),{applied:true,at:r}}function vt(e,t){let n=0;for(let o of t){if(o.status==="discarded"){if(o.id===e.id)return 0;continue}if(n+=1,o.id===e.id)return n}return 0}function Qn(e,t){let n=fr(e.id,t);return n!==null?`Round ${n.depth}/${n.total} [re-vote]`:`Round ${vt(e,t)}`}function _r(e){let t=new Set(e).size;return t===1?"unanimous":t===2?"close":"spread"}function oa(e,t){let n=new Map;t.forEach((i,a)=>n.set(i,a));let o=[...new Set(e.filter(i=>!n.has(i)))].toSorted(),r=new Map;return o.forEach((i,a)=>r.set(i,t.length+a)),i=>n.get(i)??r.get(i)??Number.MAX_SAFE_INTEGER}function Xn(e,t){let n=new Map;for(let s of e)n.set(s,(n.get(s)??0)+1);let o=null,r=0,i=[...n.keys()].toSorted((s,c)=>t(s)-t(c));for(let s of i){let c=n.get(s);c>r&&(r=c,o=s);}let a=i.filter(s=>n.get(s)===r).length>1;return {mode:o,modeTied:a}}function ra(e,t){let n=Object.values(e);if(n.length===0)return null;let o=oa(n,t.cards);if(t.cards.every(i=>Number.isFinite(parseFloat(i)))){let i=n.map(parseFloat).filter(Number.isFinite);if(i.length===0)return {kind:"categorical",...Xn(n,o),spread:_r(n)};let a=i.reduce((d,f)=>d+f,0)/i.length,s=[...i].toSorted((d,f)=>d-f),c=Math.floor(s.length/2),l=s.length%2===1?s[c]:(s[c-1]+s[c])/2,u;if(new Set(n).size===1)u="unanimous";else {let d=n.map(D=>o(D)),f=Math.min(...d);u=Math.max(...d)-f<=1?"close":"spread";}return {kind:"numeric",mean:a,median:l,...Xn(n,o),spread:u}}return {kind:"categorical",...Xn(n,o),spread:_r(n)}}function en(e){let t=Object.fromEntries(Object.entries(e.votes).filter(([,n])=>!Z(n)));return ra(t,e.scale)}function ia(e){return e==="unanimous"?"Unanimous":e==="close"?"Close":"Spread"}function tn(e){if(e===null)return null;let t=ia(e.spread),n=e.modeTied?null:e.mode;return e.kind==="numeric"?{kind:"numeric",mean:e.mean.toFixed(1),median:e.median.toFixed(1),mode:n,spread:t}:{kind:"categorical",mode:n,spread:t}}function rt(e){return e.status!=="revealed"||e.terminalAt===void 0||e.timerStartedAt===void 0?null:Qt(e.terminalAt-e.timerStartedAt)}function Zn(e){return e.replaceAll(/\|/g,"\\|")}function sa(e){return e.replaceAll(/\\/g,"\\\\").replaceAll(/]/g,"\\]")}function aa(e){let n=(e.match(/`+/g)??[]).reduce((o,r)=>Math.max(o,r.length),0);return "`".repeat(n+1)}function eo(e){if(!e)return "";if(cr(e))return ` ([${sa(e)}](<${e}>))`;let t=aa(e);return ` (${t}${e}${t})`}function da(e){return e instanceof Map?e:new Map(Object.entries(e))}function ca(e){let t=new Map;for(let r of e)t.set(r.id,r);function n(r){if(!r.parentRoundId)return r;let i=t.get(r.parentRoundId);return i?n(i):r}let o=new Map;for(let r of e){let i=n(r),a=o.get(i.id);a?a.push(r):o.set(i.id,[r]);}return o}function $r(e,t){let n=new Map;e.scale.cards.forEach((s,c)=>n.set(s,c));let o=new Map,r=[];for(let[s,c]of Object.entries(e.votes)){let l=t.get(s)??s;if(Z(c)){r.push(l);continue}let u=o.get(c);u?u.push(l):o.set(c,[l]);}let i=[...o.entries()].map(([s,c])=>({card:s,scaleIndex:n.get(s)??Number.MAX_SAFE_INTEGER,voters:[...c].toSorted().map(Zn)}));i.sort((s,c)=>{let l=c.voters.length-s.voters.length;return l!==0?l:s.scaleIndex-c.scaleIndex});let a=i.map(s=>`| ${Zn(s.card)} | ${s.voters.join(", ")} |`);return r.length>0&&a.push(`| Abstained | ${[...r].toSorted().map(Zn).join(", ")} |`),["| Vote | Voters |","|------|--------|",...a].join(`
|
|
3
|
-
`)}function Lr(e){let t=
|
|
2
|
+
import Md from'yargs';import {hideBin}from'yargs/helpers';import yn,{useState,useEffect,useCallback,useMemo,useRef}from'react';import {render,useApp,useInput,Box,Text}from'ink';import*as $e from'yjs';import {Awareness}from'y-protocols/awareness';import {existsSync,readFileSync,writeFileSync,unlinkSync,mkdirSync,chmodSync}from'fs';import {homedir}from'os';import {join}from'path';import {randomUUID}from'crypto';import {createInterface}from'readline';import {WebsocketProvider}from'y-websocket';import Ca from'ws';import Es from'clipboardy';import {jsxs,jsx,Fragment}from'react/jsx-runtime';var Ht="hnch_abstain";function Z(e){return e===Ht}var Te="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Bt=Te.length,Dn=Math.floor(Bt/2);function pt(e){let t=Te.indexOf(e);if(t===-1)throw new Error(`fractional-index: invalid character '${e}'`);return t}function Eo(e,t){return e.length>=t?e:e+"0".repeat(t-e.length)}function gi(e){let t=e.length-1;for(;t>0&&e[t]==="0";)t--;return e.slice(0,t+1)}function hi(e,t){let n=e.length,o=Array.from({length:n+1}).fill(0),r=0;for(let i=n-1;i>=0;i--){let c=e[i]+t[i]+r;o[i+1]=c%Bt,r=Math.floor(c/Bt);}o[0]=r;let s=Array.from({length:n+1}).fill(0),a=0;for(let i=0;i<=n;i++){let c=o[i]+a*Bt;s[i]=Math.floor(c/2),a=c%2;}return s.slice(1)}function On(e,t){let n=Te[Dn];if(e===null&&t===null)return n+n;if(t===null)return e+n+n+n+n;if(e===null)return Si(t);if(e>=t)throw new Error(`keyBetween: a must be < b (a='${e}', b='${t}')`);return xi(e,t)}function Si(e){for(let t=e.length-1;t>=0;t--){let n=pt(e[t]);if(n>0)return e.slice(0,t)+Te[n-1]+Te[Dn]}if(e.length>1)return e.slice(0,-1);throw new Error(`keyBetween: cannot generate key before '${e}' \u2014 use keyBetween(null, null) for the initial key`)}function xi(e,t){let n=Math.max(e.length,t.length),o=Eo(e,n).split("").map(c=>pt(c)),r=Eo(t,n).split("").map(c=>pt(c)),a=hi(o,r).map(c=>Te[c]).join(""),i=gi(a);return i>e&&i<t?i:a>e&&a<t?a:wi(e,t)}function wi(e,t){for(let n=0;n<t.length;n++){let o=n<e.length?pt(e[n]):0;if(pt(t[n])===o+1)return (n<e.length?e.slice(0,n+1):e+Te[0])+Te[Dn]}throw new Error(`keyBetween: space exhausted between '${e}' and '${t}'`)}function Mn(e){let{revealedAt:t,skippedAt:n,discardedAt:o}=e;if(t===void 0&&n===void 0&&o===void 0)return null;let r=[];t!==void 0&&r.push({kind:"revealed",at:t}),n!==void 0&&r.push({kind:"skipped",at:n}),o!==void 0&&r.push({kind:"discarded",at:o});let s={revealed:0,skipped:1,discarded:2};return r.sort((a,i)=>a.at-i.at||s[a.kind]-s[i.kind]),r[0].kind}function mt(e){return e==="revealed"||e==="skipped"||e==="discarded"}function jt(e){return e==="revealed"||e==="skipped"}function et(e){return !mt(e)}var ko="meta",Po="settings",No="participants",Do="rounds",Oo="agenda",Ci=["roomUuid","createdAt","createdBy","sessionEndedAt"],yi=["name","defaultScale","hostParticipantId"],vi=["displayName","joinedAt","role","leftAt","removedBy","avatarColor"],Ii=["id","title","description","ticketId","state","source","externalId","sortKey","createdAt","consumedAt","consumedByRoundId"],bi=["id","title","description","ticketId","parentRoundId","scale","timerStartedAt","revealedAt","skippedAt","discardedAt","discardedBy","createdBy","createdAt","agendaItemId"];function Ft(e){return e.getMap(ko)}function Vt(e){return e.getMap(Po)}function Ee(e){return e.getMap(No)}function _n(e){return e.getArray(Do)}function gt(e){return e.getArray(Oo)}function ht(e,t){let n={};for(let o of t){let r=e.get(o);r!==void 0&&(n[o]=r);}return n}function Ai(e){return ht(Ft(e),Ci)}function Ri(e){return ht(Vt(e),yi)}function Ti(e){let t=Ee(e),n=[];return t.forEach((o,r)=>{let s=ht(o,vi);n.push({id:r,...s});}),n.sort((o,r)=>o.joinedAt-r.joinedAt||o.id.localeCompare(r.id)),n}function Ei(e){let t={};return e.forEach((n,o)=>{t[o]=n;}),t}function ki(e){let t=ht(e,bi),n=e.get("votes"),o=n?Ei(n):{},r=Mn(t),{revealedAt:s,skippedAt:a,discardedAt:i,...c}=t,l=r??(t.timerStartedAt!==void 0?"voting":"pending"),u=r==="revealed"?s:r==="skipped"?a:r==="discarded"?i:void 0;return u===void 0?{...c,votes:o,status:l}:{...c,votes:o,status:l,terminalAt:u}}function Pi(e){let t=_n(e),n=[];return t.forEach(o=>{n.push(ki(o));}),n}function Ni(e){return ht(e,Ii)}function Di(e){let t=gt(e),n=[];return t.forEach(o=>{n.push(Ni(o));}),n.sort((o,r)=>o.sortKey.localeCompare(r.sortKey)),n}function F(e){return {meta:Ai(e),settings:Ri(e),participants:Ti(e),rounds:Pi(e),agenda:Di(e)}}function Un(e,t){if(Ft(e).has("roomUuid"))throw new Error("initDoc: doc already seeded");e.transact(()=>{let n=Ft(e);n.set("roomUuid",t.roomUuid),n.set("createdAt",t.createdAt),n.set("createdBy",t.participantId);let o=Vt(e);t.sessionName!==void 0&&o.set("name",t.sessionName),o.set("defaultScale",t.defaultScale),o.set("hostParticipantId",t.participantId);let r=new $e.Map;r.set("displayName",t.displayName),r.set("joinedAt",t.createdAt),t.avatarColor!==void 0&&r.set("avatarColor",t.avatarColor),Ee(e).set(t.participantId,r);});}function Le(e,t){e.transact(()=>{let n=Ee(e),o=n.get(t.participantId),r=o??new $e.Map;r.set("displayName",t.displayName),o===void 0&&r.set("joinedAt",t.joinedAt),t.avatarColor!==void 0&&r.set("avatarColor",t.avatarColor),r.delete("leftAt"),r.delete("removedBy"),o===void 0&&n.set(t.participantId,r);});}function Yt(e,t){e.transact(()=>{let n=Vt(e);for(let[o,r]of Object.entries(t))r===void 0?n.delete(o):n.set(o,r);});}function Wt(e,t){Yt(e,t);}function $n(e,t,n){e.transact(()=>{let o=Ee(e),r=o.get(t),s=r??new $e.Map;s.set("displayName",n.displayName),s.set("joinedAt",n.joinedAt),n.role!==void 0&&s.set("role",n.role),n.avatarColor!==void 0&&s.set("avatarColor",n.avatarColor),r===void 0&&o.set(t,s);});}function Mo(e,t,n){e.transact(()=>{let r=Ee(e).get(t);r&&r.set("avatarColor",n);});}function _o(e,t){let n=t.scale??Vt(e).get("defaultScale");if(!n)throw new Error("appendRound: no scale (settings.defaultScale missing)");if(t.parentRoundId!==void 0){let o=He(e,t.parentRoundId);if(o!==void 0&&o.get("discardedAt")!==void 0)throw new Error(`appendRound: parentRoundId ${t.parentRoundId} points at a discarded round`)}return e.transact(()=>{let o=new $e.Map;o.set("id",t.id),o.set("createdAt",t.createdAt),o.set("createdBy",t.createdBy),o.set("scale",n),t.title!==void 0&&o.set("title",t.title),t.description!==void 0&&o.set("description",t.description),t.ticketId!==void 0&&o.set("ticketId",t.ticketId),t.parentRoundId!==void 0&&o.set("parentRoundId",t.parentRoundId),t.agendaItemId!==void 0&&o.set("agendaItemId",t.agendaItemId),o.set("timerStartedAt",t.createdAt),o.set("votes",new $e.Map),_n(e).push([o]);}),t.id}function Ln(e,t,n){let o=He(e,t);if(!o)throw new Error(`patchRoundDescriptor: round ${t} not found`);e.transact(()=>{n.title!==void 0&&o.set("title",n.title),n.description!==void 0&&o.set("description",n.description);});}function He(e,t){let n=_n(e);for(let o=0;o<n.length;o+=1){let r=n.get(o);if(r.get("id")===t)return r}}function Hn(e){return Mn({revealedAt:e.get("revealedAt"),skippedAt:e.get("skippedAt"),discardedAt:e.get("discardedAt")})}function Uo(e,t,n,o){let r=He(e,t);if(!r)throw new Error(`castVote: round ${t} not found`);r.get("revealedAt")===void 0&&e.transact(()=>{r.get("votes").set(n,o);});}function Bn(e,t,n){let o=He(e,t);if(!o)throw new Error(`clearVote: round ${t} not found`);o.get("revealedAt")===void 0&&e.transact(()=>{o.get("votes").delete(n);});}function $o(e,t,n,o){let r=t.get("agendaItemId");if(r===void 0)return;let s=Jt(e,r);s!==void 0&&s.get("state")==="pending"&&(s.set("state","consumed"),s.set("consumedAt",o),s.set("consumedByRoundId",n));}function Lo(e,t,n){let o=He(e,t);if(!o)throw new Error(`revealRound: round ${t} not found`);let r=Hn(o);if(r!==null)throw new Error(`revealRound: round ${t} already terminal (${r})`);e.transact(()=>{o.set("revealedAt",n),$o(e,o,t,n);});}function Ho(e,t,n){let o=He(e,t);if(!o)throw new Error(`skipRound: round ${t} not found`);let r=Hn(o);if(r!==null)throw new Error(`skipRound: round ${t} already terminal (${r})`);e.transact(()=>{o.set("skippedAt",n),$o(e,o,t,n);});}function Bo(e,t,n,o){let r=He(e,t);if(!r)throw new Error(`discardRound: round ${t} not found`);let s=Hn(r);if(s!==null)throw new Error(`discardRound: round ${t} already terminal (${s})`);e.transact(()=>{r.set("discardedAt",n),r.set("discardedBy",o);});}function jo(e,t){e.transact(()=>{Ft(e).set("sessionEndedAt",t);});}function Fo(e,t,n){let r=Ee(e).get(t);r&&e.transact(()=>{r.set("leftAt",n),r.set("removedBy",t);});}function Vo(e,t){let o=Ee(e).get(t);!o||!o.has("leftAt")||e.transact(()=>{o.delete("leftAt"),o.delete("removedBy");});}function Yo(e,t,n,o){if(n===t)return;let s=Ee(e).get(n);s&&e.transact(()=>{s.set("leftAt",o),s.set("removedBy",t);});}function me(e){let{rounds:t}=e;if(t.length===0)return null;for(let n=t.length-1;n>=0;n-=1){let o=t[n];if(o.status==="pending"||o.status==="voting")return o}for(let n=t.length-1;n>=0;n-=1){let o=t[n];if(o.status!=="discarded")return o}return null}function tt(e){let{rounds:t}=e;for(let n=t.length-1;n>=0;n-=1){let o=t[n];if(et(o.status))return o}return null}function jn(e){let t=Object.values(e.votes);return t.length<2?false:t.every(n=>n===t[0])}function Jt(e,t){let n=gt(e);for(let o=0;o<n.length;o++){let r=n.get(o);if(r.get("id")===t)return r}}function St(e,t){return !!e?.trim()||!!t?.trim()}function Wo(e,t){if(!St(t.title,t.ticketId))throw new Error("appendAgendaItem: at least one of {title, ticketId} is required");let n=crypto.randomUUID(),o=gt(e),r=null;o.forEach(a=>{if(a.get("state")==="pending"){let i=a.get("sortKey");i!==void 0&&(r===null||i>r)&&(r=i);}});let s=On(r,null);return e.transact(()=>{let a=new $e.Map;a.set("id",n),a.set("state","pending"),a.set("source",t.source??"manual"),a.set("sortKey",s),a.set("createdAt",t.createdAt),t.title!==void 0&&a.set("title",t.title),t.description!==void 0&&a.set("description",t.description),t.ticketId!==void 0&&a.set("ticketId",t.ticketId),t.externalId!==void 0&&a.set("externalId",t.externalId),gt(e).push([a]);}),n}function Jo(e,t,n){let o=Jt(e,t);if(!o)throw new Error(`updateAgendaItemFields: item ${t} not found`);let r=o.get("state");if(r==="skipped"||r==="cancelled")throw new Error(`updateAgendaItemFields: item ${t} is ${r} and cannot be edited`);let s=n.title!==void 0?n.title:o.get("title"),a=n.ticketId!==void 0?n.ticketId:o.get("ticketId");if(!St(s,a))throw new Error("updateAgendaItemFields: at least one of {title, ticketId} must remain non-empty");e.transact(()=>{n.title!==void 0&&o.set("title",n.title),n.ticketId!==void 0&&o.set("ticketId",n.ticketId),n.description!==void 0&&o.set("description",n.description);});}function Fn(e,t,n,o={}){let r=Jt(e,t);if(!r)throw new Error(`setAgendaItemState: item ${t} not found`);let s=r.get("state");if(!(s===n&&n==="consumed")){if(s!=="pending")throw new Error(`setAgendaItemState: invalid transition '${s}' \u2192 '${n}' for item ${t}`);if(n==="consumed"&&o.timestamp===void 0)throw new Error(`setAgendaItemState: timestamp is required when consuming item ${t}`);e.transact(()=>{r.set("state",n),n==="consumed"&&(r.set("consumedAt",o.timestamp),o.consumedByRoundId!==void 0&&r.set("consumedByRoundId",o.consumedByRoundId));});}}function Ko(e,t,n,o){let r=Jt(e,t);if(!r)throw new Error(`reorderAgendaItem: item ${t} not found`);let s=r.get("state");if(s!=="pending")throw new Error(`reorderAgendaItem: item ${t} is ${s}; only pending items may be reordered`);let a=On(n??null,o??null);e.transact(()=>{r.set("sortKey",a);});}function Be(e){for(let t of e.agenda)if(t.state==="pending")return t;return null}function Go(e,t){let n=F(e).agenda.find(o=>o.id===t);return n||{applied:false,reason:"not-found"}}function Vn(e,t){let n=Go(e,t);return xt(n)?n:n.state!=="pending"?{applied:false,reason:"not-pending"}:n}function Oi(e){return e.state==="skipped"||e.state==="cancelled"}function xt(e){return "applied"in e}function nt(e,t,n=Date.now){if(!St(t.title,t.ticketId))return {applied:false,reason:"invalid-fields"};let o=n();return {applied:true,id:Wo(e,{...t,createdAt:o}),at:o}}function qo(e,t,n){let o=Go(e,t);if(xt(o))return o;if(Oi(o))return {applied:false,reason:"not-pending"};let r=n.title!==void 0?n.title:o.title,s=n.ticketId!==void 0?n.ticketId:o.ticketId;return St(r,s)?(Jo(e,t,n),{applied:true,id:t}):{applied:false,reason:"invalid-fields"}}function Kt(e,t){let n=Vn(e,t);return xt(n)?n:(Fn(e,t,"skipped"),{applied:true,id:t})}function Gt(e,t){let n=Vn(e,t);return xt(n)?n:(Fn(e,t,"cancelled"),{applied:true,id:t})}function qt(e,t,n,o){let r=Vn(e,t);return xt(r)?r:(Ko(e,t,n,o),{applied:true,id:t})}var Yn={"unknown-room":4001,"wrong-password":4002,"invalid-invite":4003,"expired-invite":4004,"invite-already-redeemed":4005,"room-full":4006,"malformed-credentials":4010},zo=new Map(Object.entries(Yn).map(([e,t])=>[t,e])),Xo=20;function ge(e){return e.role??"voter"}function we(e){return e.leftAt===void 0}var zt={id:"fibonacci",cards:["0","1","2","3","5","8","13","21"]},Qo={id:"t-shirt",cards:["XS","S","M","L","XL"]},Zo={id:"powers-of-2",cards:["1","2","4","8","16","32","64"]},er={id:"linear",cards:["1","2","3","4","5","6","7","8","9","10"]},tr={id:"risk",cards:["Low","Medium","High","Critical"]},de={[zt.id]:zt,[Qo.id]:Qo,[Zo.id]:Zo,[er.id]:er,[tr.id]:tr},nr={fibonacci:"Fibonacci","t-shirt":"T-shirt","powers-of-2":"Powers of 2",linear:"Linear (1\u201310)",risk:"Risk"},Mi="Custom scale",_i=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;function or(e){if(e in nr)return nr[e];if(e.length===0)return e;let t=e.startsWith("custom-")?e.slice(7):e;return t!==e&&_i.test(t)?Mi:t.split("-").map(n=>n.length===0?n:n.charAt(0).toUpperCase()+n.slice(1)).join(" ")}function Ui(e,t,n){if(!e||e.status!=="voting"&&e.status!=="pending")return false;let o=new Set(t.filter(c=>we(c)&&n.has(c.id)&&ge(c)!=="viewer").map(c=>c.id));if(o.size===0)return false;let r=Object.entries(e.votes).filter(([c])=>o.has(c)),s=r.filter(([,c])=>Z(c)).length,a=r.length-s,i=o.size-s;return i<=0?false:a>=i}function $i(e,t){return e.participants.some(n=>we(n)&&n.id!==t)}function rr(e){function t(){let o=e.projection();if(!o||!e.presenceTrusted()&&$i(o,e.selfId()))return;let r=me(o);Ui(r,o.participants,e.onlineIds())&&e.reveal();}let n=e.subscribe(t);return t(),{stop(){n();}}}var ot={"racing-green":{base:"#0B3D2E",soft:"rgba(11,61,46,0.14)",ink:"#fff",label:"Racing Green"},dijon:{base:"#C9A227",soft:"rgba(201,162,39,0.18)",ink:"#000",label:"Dijon"},blue:{base:"#0A84FF",soft:"rgba(10,132,255,0.14)",ink:"#fff",label:"Blue"},indigo:{base:"#5E5CE6",soft:"rgba(94,92,230,0.14)",ink:"#fff",label:"Indigo"},violet:{base:"#BF5AF2",soft:"rgba(191,90,242,0.14)",ink:"#fff",label:"Violet"},pink:{base:"#FF375F",soft:"rgba(255,55,95,0.14)",ink:"#fff",label:"Pink"},red:{base:"#FF453A",soft:"rgba(255,69,58,0.14)",ink:"#fff",label:"Red"},orange:{base:"#FF9F0A",soft:"rgba(255,159,10,0.16)",ink:"#000",label:"Orange"},amber:{base:"#FFD60A",soft:"rgba(255,214,10,0.18)",ink:"#000",label:"Amber"},green:{base:"#30D158",soft:"rgba(48,209,88,0.14)",ink:"#000",label:"Green"},teal:{base:"#40C8E0",soft:"rgba(64,200,224,0.14)",ink:"#000",label:"Teal"},graphite:{base:"#1C1C1E",soft:"rgba(28,28,30,0.10)",ink:"#fff",label:"Graphite"}};var wt=["racing-green","dijon","blue","indigo","violet","pink","red","orange","amber","green","teal","graphite"],Li=/^#[0-9a-fA-F]{6}$/;function Hi(e){return Object.hasOwn(ot,e)}function je(e){return e?Hi(e)?ot[e].base:Li.test(e)?e.toLowerCase():null:null}function sr(e){let t=5381;for(let o=0;o<e.length;o++)t=(t<<5)+t+e.charCodeAt(o)|0;let n=Math.abs(t)%wt.length;return wt[n]}var Bi=5e3,ke="participantId";function ir(e){let t=new Set;for(let n of e.values()){if(typeof n!="object"||n===null)continue;let o=n[ke];typeof o=="string"&&t.add(o);}return t}function ar(e,t){let n=new Set;for(let o of e.participants)t.has(o.id)&&we(o)&&n.add(o.id);return n}function ji(e,t,n){let o=e.settings.hostParticipantId;return o?ar(e,t).has(o)?{kind:"cancel"}:n.missingHostId!==o?{kind:"start-debounce",hostId:o}:{kind:"none"}:{kind:"none"}}function Fi(e,t,n,o){let r=e.settings.hostParticipantId;if(!o||r!==o)return {promote:false};let s=ar(e,t);if(s.has(r))return {promote:false};let a=[...s].toSorted();if(a.length===0)return {promote:false};let i=a[0];return i!==n?{promote:false}:{promote:true,winner:i}}function dr(e){let t=null,n=null;function o(){n!==null&&(clearTimeout(n),n=null),t=null;}function r(){n=null;let i=t;t=null;let c=e.projection(),l=e.myId();if(!c||l===null)return;let u=Fi(c,e.onlineIds(),l,i);u.promote&&e.promote(u.winner);}function s(){let i=e.projection();if(!i||e.myId()===null){o();return}let c=ji(i,e.onlineIds(),{missingHostId:t});switch(c.kind){case "cancel":o();break;case "start-debounce":o(),t=c.hostId,n=setTimeout(r,Bi);break;}}let a=e.subscribe(s);return s(),{stop(){o(),a();}}}function Xt(e){let t=Math.max(0,Math.floor(e/1e3)),n=Math.floor(t/60),o=t%60;return `${n}:${o.toString().padStart(2,"0")}`}function cr(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return false}}function Wn(e){if(e===null||typeof e!="object"||Array.isArray(e))return {version:2,entries:{}};let t=e;if(t.version===2&&ur(t.entries)){let n=t.entries,o={};for(let[r,s]of Object.entries(n)){let a=Vi(s);a!==null&&(o[r]=a);}return {version:2,entries:o}}if(typeof t.roomCode=="string"&&typeof t.roomUuid=="string"&&typeof t.lastSeenAt=="number"){let n={roomCode:t.roomCode,roomUuid:t.roomUuid,lastSeenAt:t.lastSeenAt,...typeof t.passwordHash=="string"?{passwordHash:t.passwordHash}:{}};return {version:2,entries:{[n.roomUuid]:n}}}return {version:2,entries:{}}}function lr(e,t,n=864e5){let o={};for(let[r,s]of Object.entries(e.entries))t-s.lastSeenAt>n||(s.lastSeenAt>t?o[r]={...s,lastSeenAt:t}:o[r]=s);return {version:2,entries:o}}function ur(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Vi(e){if(!ur(e))return null;let t=e;return typeof t.roomCode!="string"||typeof t.roomUuid!="string"||typeof t.lastSeenAt!="number"?null:{roomCode:t.roomCode,roomUuid:t.roomUuid,lastSeenAt:t.lastSeenAt,...typeof t.passwordHash=="string"?{passwordHash:t.passwordHash}:{}}}function fr(e,t){let n=t.filter(f=>f.status!=="discarded"),o=new Map;for(let f of n)o.set(f.id,f);let r=o.get(e);if(r===void 0||r.parentRoundId===void 0)return null;let s=new Set([r.id]),a=r,i=1;for(;a.parentRoundId!==void 0;){let f=o.get(a.parentRoundId);if(f===void 0||s.has(f.id))return null;s.add(f.id),a=f,i+=1;}let c=a,l=new Map;for(let f of n){if(f.parentRoundId===void 0)continue;let P=l.get(f.parentRoundId);P===void 0?l.set(f.parentRoundId,[f]):P.push(f);}let u=0,d=[c];for(;d.length>0;){let f=d.shift();u+=1;let P=l.get(f.id);P!==void 0&&d.push(...P);}return {chainRoot:c,depth:i,total:u}}var pr="PBKDF2",Yi="SHA-256",mr=new TextEncoder;function Wi(e){return Array.from(new Uint8Array(e)).map(t=>t.toString(16).padStart(2,"0")).join("")}var Ji=/^[\s\u200B-\u200D\u2060]+|[\s\u200B-\u200D\u2060]+$/gu,Jn=120;function Pe(e){return e.normalize("NFC").replace(Ji,"")}async function Qt(e,t){let n=await crypto.subtle.importKey("raw",mr.encode(Pe(e)),pr,false,["deriveBits"]),o=await crypto.subtle.deriveBits({name:pr,salt:mr.encode(t),iterations:1e5,hash:Yi},n,256);return Wi(o)}var Ct=class extends Error{reason;constructor(t){super(`relay rejected resolve: ${t}`),this.reason=t,this.name="RelayRejectionError";}},Kn=1e4;async function hr(e,t){let n=await fetch(`${e}/rooms`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({}),signal:AbortSignal.timeout(Kn)});if(!n.ok)throw new Error(`POST /rooms failed: ${n.status}`);return await n.json()}function Sr(e){if(typeof e!="object"||e===null)return null;let{reason:t}=e;return typeof t=="string"&&Object.hasOwn(Yn,t)?t:null}async function ce(e,t){let n=await fetch(`${e}/rooms/${encodeURIComponent(t)}`,{signal:AbortSignal.timeout(Kn)});if(n.status===404){let o=await n.json().catch(()=>null),r=Sr(o);if(r!==null)throw new Ct(r)}if(!n.ok)throw new Error(`GET /rooms/:code failed: ${n.status}`);return await n.json()}async function Gn(e,t,n){let o=await fetch(`${e}/rooms/${t}/access`,{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({passwordHash:n}),signal:AbortSignal.timeout(Kn)});if(!o.ok)throw new Error(`PATCH /rooms/:uuid/access failed: ${o.status}`);return await o.json()}var Gi=6e4,qi=3,zi=5e3,Xi=8e3;async function Qi(e,t,n){let o,r;try{let i=await fetch(`${e}/rooms/${encodeURIComponent(n.roomCode)}`,{signal:AbortSignal.timeout(Xi)});o=i.status,r=await i.json().catch(()=>null);}catch{return null}if(o===404)return Sr(r)==="unknown-room"?"unknown-room":null;if(o!==200||typeof r!="object"||r===null)return null;let{uuid:s,accessMode:a}=r;return typeof s!="string"?null:s!==t?"unknown-room":a==="password"&&n.passwordHash===void 0?"wrong-password":null}function Zi(e){return e.replace(/^https?:\/\//,t=>t==="https://"?"wss://":"ws://")}function gr(e){let t={did:e.deviceId};return e.passwordHash!==void 0&&(t.pw=e.passwordHash),t}function ea(){return globalThis.window}function xr(e){let t="connecting",n=null,o=false,r=false,s=false,a=false,i=false,c=[],l=()=>{let R=o&&t!=="connected"&&n===null&&!r&&!a;R!==s&&(s=R,e.onReconnectingChange?.(R));},u=`${Zi(e.httpBaseUrl)}/ws`,d=e.credentials,f=new WebsocketProvider(u,e.roomUuid,e.doc,{params:gr(d),connect:true,...e.awareness!==void 0&&{awareness:e.awareness},...e.WebSocketPolyfill!==void 0&&{WebSocketPolyfill:e.WebSocketPolyfill}}),P=()=>{let{awareness:R}=f;for(let H of R.meta.keys())H!==R.clientID&&!R.states.has(H)&&R.meta.delete(H);},_=()=>{let R=f.awareness.getLocalState();R!==null&&f.awareness.setLocalState(R);},S=R=>{R!==i&&(i=R,e.onSyncedChange?.(R));};P();let C=R=>{t=R.status,R.status==="disconnected"&&P(),R.status==="connected"&&_(),e.onStatusChange?.(R.status),R.status==="connected"&&(o=true,a=false,n=null,e.onRejectionChange?.(null),c.length=0),l();},E=false,T=()=>{E=true;try{f.disconnect();}finally{E=false;}},A=R=>{n=R,e.onRejectionChange?.(R),f.shouldConnect=false,T(),l();},k=false,v=Number.NEGATIVE_INFINITY,h=()=>r||n!==null,w=async()=>{let R=Date.now();if(R<v&&(v=Number.NEGATIVE_INFINITY),k||R-v<zi)return;k=true,v=R;let H=d;try{let K=await Qi(e.httpBaseUrl,e.roomUuid,H);if(K===null||h()||t==="connected"||H!==d||a)return;A(K);}finally{k=false;}},N=R=>{if(E)return;a=false;let H=R===null?void 0:zo.get(R.code);if(H===void 0){let K=Date.now();c.push(K);let p=K-Gi;for(;c.length>0&&c[0]<p;)c.shift();c.length>=qi&&(c.length=0,e.onRepeatRejection?.()),l(),w();return}A(H);};f.on("status",C),f.on("connection-close",N);let b=f,O=null;if(e.onSynced!==void 0){let R=H=>{H&&(b.off("synced",R),O=null,e.onSynced?.());};O=R,b.on("synced",R);}let te=R=>{S(R);};b.on("synced",te);let X=()=>{r||(t="disconnected",S(false),e.onStatusChange?.("disconnected"),l());},Q=()=>{r||n!==null||t!=="connected"&&(f.ws!==null?(f.wsUnsuccessfulReconnects=0,f.ws.close()):f.connect());},V=ea();V?.addEventListener("offline",X),V?.addEventListener("online",Q);let J=false;return {awareness:f.awareness,updateCredentials(R){let H=R.passwordHash??void 0;H!==d.passwordHash&&(d=H===void 0?{roomCode:d.roomCode,deviceId:d.deviceId}:{...d,passwordHash:H},a=t==="connected",n!==null&&(n=null,e.onRejectionChange?.(null)),f.shouldConnect=false,T(),f.params=gr(d),f.connect());},disconnect(){J||(J=true,r=true,l(),f.off("status",C),f.off("connection-close",N),O!==null&&(b.off("synced",O),O=null),b.off("synced",te),S(false),V?.removeEventListener("offline",X),V?.removeEventListener("online",Q),f.shouldConnect=false,T(),f.destroy());}}}var wr="ABCDEFGHJKMNPQRSTUVWXYZ23456789";if(wr.length!==31)throw new Error(`Room code alphabet must be 31 characters, got ${wr.length}`);function qn(e){return e.trim().replaceAll(/-/g,"").toUpperCase()}function Cr(e,t=true){let n=qn(e);return !t||n.length!==6?n:`${n.slice(0,3)}-${n.slice(3)}`}function yt(e,t){return F(e).participants.find(n=>n.id===t)}function yr(e,t,n){let o=F(e);return {isHost:o.settings.hostParticipantId===t,target:o.participants.find(r=>r.id===n)}}function ta(e,t){return F(e).settings.hostParticipantId===t}function vr(e,t){let n=t.role??e.role;return {displayName:t.displayName??e.displayName,joinedAt:e.joinedAt,...n!==void 0&&{role:n},...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}}function Ir(e,t,n){let o=yt(e,t);return o?($n(e,t,vr(o,{displayName:n})),{applied:true}):{applied:false,reason:"not-found"}}function br(e,t,n){return yt(e,t)?(Mo(e,t,n),{applied:true}):{applied:false,reason:"not-found"}}function Ar(e,t){let n=yt(e,t);if(!n)return {applied:false,reason:"not-found"};let o=ge(n)==="voter"?"viewer":"voter";return $n(e,t,vr(n,{role:o})),{applied:true}}function Rr(e,t,n=Date.now){if(!yt(e,t))return {applied:false,reason:"not-found"};let o=n();return Fo(e,t,o),{applied:true,at:o}}function Tr(e,t){return yt(e,t)?(Vo(e,t),{applied:true}):{applied:false,reason:"not-found"}}function Er(e,t,n,o=Date.now){let r=yr(e,t,n);if(!r.isHost)return {applied:false,reason:"not-host"};if(n===t)return {applied:false,reason:"self-target"};if(!r.target)return {applied:false,reason:"not-found"};let s=o();return Yo(e,t,n,s),{applied:true,at:s}}function kr(e,t,n,o){let r=yr(e,t,n);return r.isHost?r.target?o.has(n)?(Yt(e,{hostParticipantId:n}),{applied:true}):{applied:false,reason:"not-online"}:{applied:false,reason:"not-found"}:{applied:false,reason:"not-host"}}function Pr(e,t){return Yt(e,{hostParticipantId:t}),{applied:true}}function Nr(e,t,n=Date.now){if(!ta(e,t))return {applied:false,reason:"not-host"};let o=n();return jo(e,o),{applied:true,at:o}}function Dr(e,t={},n=Date.now){let o=F(e).settings.hostParticipantId;if(!o)return {applied:false,reason:"no-host"};let r=crypto.randomUUID(),s=n();return _o(e,{id:r,createdAt:s,createdBy:o,...t.title!==void 0&&{title:t.title},...t.description!==void 0&&{description:t.description},...t.ticketId!==void 0&&{ticketId:t.ticketId},...t.parentRoundId!==void 0&&{parentRoundId:t.parentRoundId},...t.agendaItemId!==void 0&&{agendaItemId:t.agendaItemId}}),{applied:true,id:r,at:s}}function zn(e){let t=me(F(e));return t?et(t.status)?{round:t}:{applied:false,reason:"already-terminal"}:{applied:false,reason:"no-current-round"}}function Or(e,t=Date.now){let n=zn(e);if("applied"in n)return n;let o=t();return Lo(e,n.round.id,o),{applied:true,at:o}}function Mr(e,t=Date.now){let n=zn(e);if("applied"in n)return n;let o=t();return Ho(e,n.round.id,o),{applied:true,at:o}}function _r(e,t,n=Date.now){let o=zn(e);if("applied"in o)return o;let r=n();return Bo(e,o.round.id,r,t),{applied:true,at:r}}function vt(e,t){let n=0;for(let o of t){if(o.status==="discarded"){if(o.id===e.id)return 0;continue}if(n+=1,o.id===e.id)return n}return 0}function Qn(e,t){let n=fr(e.id,t);return n!==null?`Round ${n.depth}/${n.total} [re-vote]`:`Round ${vt(e,t)}`}function Ur(e){let t=new Set(e).size;return t===1?"unanimous":t===2?"close":"spread"}function na(e,t){let n=new Map;t.forEach((s,a)=>n.set(s,a));let o=[...new Set(e.filter(s=>!n.has(s)))].toSorted(),r=new Map;return o.forEach((s,a)=>r.set(s,t.length+a)),s=>n.get(s)??r.get(s)??Number.MAX_SAFE_INTEGER}function Xn(e,t){let n=new Map;for(let i of e)n.set(i,(n.get(i)??0)+1);let o=null,r=0,s=[...n.keys()].toSorted((i,c)=>t(i)-t(c));for(let i of s){let c=n.get(i);c>r&&(r=c,o=i);}let a=s.filter(i=>n.get(i)===r).length>1;return {mode:o,modeTied:a}}function oa(e,t){let n=Object.values(e);if(n.length===0)return null;let o=na(n,t.cards);if(t.cards.every(s=>Number.isFinite(parseFloat(s)))){let s=n.map(parseFloat).filter(Number.isFinite);if(s.length===0)return {kind:"categorical",...Xn(n,o),spread:Ur(n)};let a=s.reduce((d,f)=>d+f,0)/s.length,i=[...s].toSorted((d,f)=>d-f),c=Math.floor(i.length/2),l=i.length%2===1?i[c]:(i[c-1]+i[c])/2,u;if(new Set(n).size===1)u="unanimous";else {let d=n.map(_=>o(_)),f=Math.min(...d);u=Math.max(...d)-f<=1?"close":"spread";}return {kind:"numeric",mean:a,median:l,...Xn(n,o),spread:u}}return {kind:"categorical",...Xn(n,o),spread:Ur(n)}}function Zt(e){let t=Object.fromEntries(Object.entries(e.votes).filter(([,n])=>!Z(n)));return oa(t,e.scale)}function ra(e){return e==="unanimous"?"Unanimous":e==="close"?"Close":"Spread"}function en(e){if(e===null)return null;let t=ra(e.spread),n=e.modeTied?null:e.mode;return e.kind==="numeric"?{kind:"numeric",mean:e.mean.toFixed(1),median:e.median.toFixed(1),mode:n,spread:t}:{kind:"categorical",mode:n,spread:t}}function rt(e){return e.status!=="revealed"||e.terminalAt===void 0||e.timerStartedAt===void 0?null:Xt(e.terminalAt-e.timerStartedAt)}function Zn(e){return e.replaceAll(/\|/g,"\\|")}function sa(e){return e.replaceAll(/\\/g,"\\\\").replaceAll(/]/g,"\\]")}function ia(e){let n=(e.match(/`+/g)??[]).reduce((o,r)=>Math.max(o,r.length),0);return "`".repeat(n+1)}function eo(e){if(!e)return "";if(cr(e))return ` ([${sa(e)}](<${e}>))`;let t=ia(e);return ` (${t}${e}${t})`}function aa(e){return e instanceof Map?e:new Map(Object.entries(e))}function da(e){let t=new Map;for(let r of e)t.set(r.id,r);function n(r){if(!r.parentRoundId)return r;let s=t.get(r.parentRoundId);return s?n(s):r}let o=new Map;for(let r of e){let s=n(r),a=o.get(s.id);a?a.push(r):o.set(s.id,[r]);}return o}function $r(e,t){let n=new Map;e.scale.cards.forEach((i,c)=>n.set(i,c));let o=new Map,r=[];for(let[i,c]of Object.entries(e.votes)){let l=t.get(i)??i;if(Z(c)){r.push(l);continue}let u=o.get(c);u?u.push(l):o.set(c,[l]);}let s=[...o.entries()].map(([i,c])=>({card:i,scaleIndex:n.get(i)??Number.MAX_SAFE_INTEGER,voters:[...c].toSorted().map(Zn)}));s.sort((i,c)=>{let l=c.voters.length-i.voters.length;return l!==0?l:i.scaleIndex-c.scaleIndex});let a=s.map(i=>`| ${Zn(i.card)} | ${i.voters.join(", ")} |`);return r.length>0&&a.push(`| Abstained | ${[...r].toSorted().map(Zn).join(", ")} |`),["| Vote | Voters |","|------|--------|",...a].join(`
|
|
3
|
+
`)}function Lr(e){let t=en(Zt(e)),n=rt(e),o=[];return t?.kind==="numeric"?o.push(`Avg ${t.mean} \xB7 Med ${t.median}`):t?.kind==="categorical"&&t.mode!==null&&o.push(`Most common: ${t.mode}`),n!==null&&o.push(`Elapsed ${n}`),o.join(" \xB7 ")}function Hr(e){let{rounds:t}=e,n=aa(e.participants),o=new Map;for(let[u,d]of n)o.set(u,d.displayName);let r=t.filter(u=>u.status==="revealed");if(r.length===0)return "";let s=new Map;for(let u of t)s.set(u.id,vt(u,t));let a=da(r),i=new Set,c=[];for(let u of r)for(let[d,f]of a)if(f.includes(u)&&!i.has(d)){i.add(d),c.push(d);break}let l=[];for(let u of c){let d=a.get(u),f=d.find(A=>A.id===u),P=d.filter(A=>A.id!==u),_=s.get(f.id)??0,S=f.title?`## Round ${_} \u2014 ${f.title}${eo(f.ticketId)}`:`## Round ${_}${eo(f.ticketId)}`,C=$r(f,o),E=Lr(f),T=E?`${S}
|
|
4
4
|
|
|
5
|
-
${
|
|
5
|
+
${C}
|
|
6
6
|
|
|
7
|
-
${
|
|
7
|
+
${E}`:`${S}
|
|
8
8
|
|
|
9
|
-
${
|
|
9
|
+
${C}`;l.push(T);for(let A of P){let v=`### Re-vote ${s.get(A.id)??0}${eo(A.ticketId)}`,h=$r(A,o),w=Lr(A),N=w?`${v}
|
|
10
10
|
|
|
11
|
-
${
|
|
11
|
+
${h}
|
|
12
12
|
|
|
13
|
-
${
|
|
13
|
+
${w}`:`${v}
|
|
14
14
|
|
|
15
|
-
${
|
|
15
|
+
${h}`;l.push(N);}}return l.join(`
|
|
16
16
|
|
|
17
17
|
`)+`
|
|
18
|
-
`}function
|
|
19
|
-
`,"utf-8");}async function
|
|
20
|
-
`,"utf-8");}function rn(e){let t=
|
|
21
|
-
`);}function an(e){let t=Date.now();if(!existsSync(
|
|
22
|
-
`,
|
|
23
|
-
`),n(130)),d===
|
|
24
|
-
`),o(r);return}if(d===
|
|
25
|
-
`),o(r);return}continue}if(d===_a){u+=La(l,u)-1;continue}if(d===ka||d===Pa){r=Array.from(r).slice(0,-1).join("");continue}if(d===Ma){r="";continue}if(d===Ua){r=r.replace(/\S*\s*$/u,"");continue}$a(d)||(r+=d);}};e.on("data",s);})}function ln(){let e=null,t;return {refused:()=>e,note(n){e=n,t?.();},attach(n){t=n,e!==null&&n();}}}function ni(e,t){switch(e){case "wrong-password":return !t.wasIn&&t.typedPassword?{message:"That password is incorrect.",exitCode:1,remembered:"forget-session"}:{message:`Password changed \u2014 rejoin with: hnch join ${t.roomCode} --password`,exitCode:0,remembered:"forget-password"};case "room-full":return {message:`This room is full (max ${Xo} participants).`,exitCode:1,remembered:t.wasIn?"keep":"forget-session"};default:return {message:`The relay refused the connection (${e}).`,exitCode:1,remembered:t.wasIn?"keep":"forget-session"}}}var ja="@xauyxau/hnch";function un(e){return Cr(e)}function fn(e){return `${process.env.HNCH_SHARE_ORIGIN??"https://hnch.dev"}/join?code=${e}`}function pn(e){return `npx ${ja} join ${e}`}function co(e){let t=e.trim();return t===""?void 0:t}function mn(e){return e?{title:e.title??"",ticketId:e.ticketId??"",agendaItemId:e.id}:{title:"",ticketId:"",agendaItemId:void 0}}function oi(e,t,n){return [e,co(t),n]}var Fa={connecting:"yellow",connected:"green",disconnected:"red"};function si({roomCode:e,sessionName:t,status:n,isHost:o}){let r=t?`${e} \xB7 ${t}`:e;return jsxs(Box,{borderStyle:"single",borderColor:"gray",paddingX:1,justifyContent:"space-between",children:[jsxs(Text,{bold:true,children:["hnch \xB7 ",r]}),jsxs(Box,{gap:2,children:[o&&jsx(Text,{color:"yellow",children:"[host]"}),jsx(Text,{color:Fa[n],children:n})]})]})}function he({items:e,onSelect:t,onClose:n,title:o}){if(e.length===0)return jsxs(Box,{flexDirection:"column",gap:1,children:[o&&jsx(Text,{bold:true,children:o}),jsx(Text,{dimColor:true,children:"(no items)"})]});let r=e.findIndex(s=>!s.disabled),[i,a]=useState(Math.max(r,0));return useInput((s,c)=>{if(c.upArrow)a(l=>{let u=(l-1+e.length)%e.length,d=0;for(;e[u]?.disabled&&d<e.length;)u=(u-1+e.length)%e.length,d++;return u});else if(c.downArrow)a(l=>{let u=(l+1)%e.length,d=0;for(;e[u]?.disabled&&d<e.length;)u=(u+1)%e.length,d++;return u});else if(c.return){let l=e[i];l&&!l.disabled&&t(l.value);}else c.escape&&n?.();}),jsxs(Box,{flexDirection:"column",gap:1,children:[o&&jsx(Text,{bold:true,children:o}),jsx(Box,{flexDirection:"column",children:e.map((s,c)=>{let l=c===i,u=s.disabled??false;return jsxs(Box,{gap:1,children:[jsx(Text,{...l&&{color:"cyan"},dimColor:u,children:l?">":" "}),jsx(Text,{bold:l,dimColor:u,children:s.label}),s.detail&&jsx(Text,{dimColor:true,children:s.detail})]},s.value)})}),jsx(Text,{dimColor:true,children:"\u2191\u2193 select \u23CE confirm esc close"})]})}function W({value:e,onChange:t,onSubmit:n,onCancel:o,placeholder:r,isActive:i=true,mask:a=false}){useInput((u,d)=>{d.escape?o?.():d.return?n(e):d.backspace||d.delete?t(e.slice(0,-1)):u&&!d.ctrl&&!d.meta&&t(e+u);},{isActive:i});let s=a&&e.length>0?"*".repeat(e.length):e,c=s.length>0?s:r??"",l=e.length===0&&r!==void 0;return jsxs(Text,{children:[jsx(Text,{dimColor:l,children:c}),jsx(Text,{inverse:true,children:" "})]})}function li({mode:e,password:t,onModeChange:n,onPasswordChange:o,onClose:r}){let[i,a]=useState(e==="open"?0:1),[s,c]=useState(false);return useEffect(()=>{a(e==="open"?0:1);},[e]),useInput((l,u)=>{if(u.leftArrow)a(d=>Math.max(0,d-1));else if(u.rightArrow)a(d=>Math.min(1,d+1));else if(u.return){let d=i===0?"open":"password";d!==e&&n(d),d==="password"&&c(true);}else u.escape&&r?.();},{isActive:!s}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Box,{gap:1,children:["open","password"].map((l,u)=>{let d=u===i,f=l===e,T=l==="open"?"Open":"Password";return jsx(Text,{inverse:d,bold:f,...f&&{color:"cyan"},children:f?`[${T}]`:` ${T} `},l)})}),e==="password"&&jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{children:"Password: "}),jsx(W,{value:t,onChange:o,onSubmit:()=>c(false),onCancel:()=>c(false),placeholder:"(required to join)",isActive:s,mask:true}),!s&&jsx(Text,{dimColor:true,children:"\u23CE edit \u2190 \u2192 switch mode esc close"}),s&&jsx(Text,{dimColor:true,children:"\u23CE done esc cancel"})]}),e==="open"&&jsx(Text,{dimColor:true,children:"\u2190\u2192 toggle \u23CE confirm esc close"})]})}function pi({scaleId:e,cards:t,disabledIndices:n,onOverrideChange:o,onClose:r}){let i=useMemo(()=>new Set(n),[n]),[a,s]=useState(0),c=l=>{let u=new Set(i);if(u.has(l))u.delete(l);else {if(u.size>=t.length-1)return;u.add(l);}let d=Array.from(u).toSorted((f,T)=>f-T);o(e,d);};return useInput((l,u)=>{u.leftArrow?s(d=>Math.max(0,d-1)):u.rightArrow?s(d=>Math.min(t.length-1,d+1)):l===" "?c(a):(u.return||u.escape)&&r();}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Box,{gap:1,children:t.map((l,u)=>{let d=u===a,f=i.has(u);return jsx(Text,{inverse:d,bold:!f,...!f&&{color:"cyan"},strikethrough:f,dimColor:f,children:l},l)})}),jsx(Text,{dimColor:true,children:" \u2190\u2192 navigate space toggle \u23CE/esc done"})]})}function So({initialName:e="",initialCards:t=[],onSave:n,onCancel:o}){let r=e.length>0,[i,a]=useState(e),[s,c]=useState(t.length>0?t:[""]),[l,u]=useState(0),[d,f]=useState("editing-name"),[T,D]=useState(""),b=()=>{let P=i.trim();if(P.length===0||P.length>40){D("Name must be 1-40 characters");return}a(P),D(""),f("editing-cards");},R=()=>{let P=i.trim();if(P.length===0||P.length>40){D("Name must be 1-40 characters");return}let A=s.map(w=>w.trim()).filter(w=>w.length>0),p=Array.from(new Set(A));if(p.length<2){D("Need at least 2 unique non-empty cards");return}D(""),n(P,p);};return useInput((P,A)=>{if(d==="editing-cards"){if(A.leftArrow)u(p=>Math.max(0,p-1));else if(A.rightArrow)u(p=>{let w=p+1;return w>=s.length&&s.length<25?(c(_=>[..._,""]),w):Math.min(w,s.length-1)});else if(A.return)R();else if(A.escape)o();else if(A.tab)f("editing-name");else if(A.backspace){let p=s[l]||"";if(p.length===0){if(s.length>2){let w=s.filter((_,y)=>y!==l);c(w),u(Math.max(0,l-1));}}else {let w=[...s];w[l]=p.slice(0,-1),c(w);}}else if(P&&!A.ctrl&&!A.meta){let p=s[l]||"";if(p.length<10){let w=[...s];w[l]=p+P,c(w);}}}},{isActive:d==="editing-cards"}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:r?"\u2500\u2500 Edit Custom Scale \u2500\u2500":"\u2500\u2500 Create Custom Scale \u2500\u2500"}),jsxs(Box,{flexDirection:"column",gap:0,children:[jsx(Text,{children:"Name:"}),jsx(W,{value:i,onChange:a,onSubmit:b,onCancel:o,placeholder:"Scale name",isActive:d==="editing-name"})]}),d==="editing-cards"&&jsxs(Box,{flexDirection:"column",gap:0,children:[jsx(Text,{children:"Cards:"}),jsx(Box,{gap:1,flexWrap:"wrap",children:s.map((P,A)=>{let p=A===l;return jsx(Text,{inverse:p,...!p&&{color:"cyan"},children:P.length>0?P:"\xB7"},A)})})]}),T&&jsx(Text,{color:"red",children:T}),jsx(Text,{dimColor:true,children:d==="editing-name"?"\u23CE next esc cancel":"\u2190\u2192 navigate typing adds card bsp delete \u23CE save tab name esc cancel"})]})}function Sn({scales:e,selectedScaleId:t,presetOverrides:n,customScales:o=[],onSelect:r,onOverrideChange:i,onCustomScaleCreate:a,onCustomScaleEdit:s,onCustomScaleDelete:c,onClose:l,showNoneOption:u=false}){let[d,f]=useState(0),[T,D]=useState(null),[b,R]=useState("browsing"),[U,P]=useState(null),[A,p]=useState(null),w=a?[...e,{id:"__create-custom__",cards:[]}]:e,_=w.length;if(useInput((y,O)=>{if(b==="browsing"){if(O.escape){l();return}if(_===0)return;if(O.upArrow)f(v=>(v-1+_)%_);else if(O.downArrow)f(v=>(v+1)%_);else if(O.return){let v=w[d];if(!v)return;if(v.id==="__create-custom__"){R("creating");return}v.id in de?D(T===v.id?null:v.id):r(v.id);}else if(y===" "){let v=w[d];v&&v.id!=="__create-custom__"&&r(v.id);}else if(y==="e"||y==="E"){let v=w[d];s&&v?.id.startsWith("custom-")&&(P(v.id),R("editing"));}else if(y==="d"||y==="D"){let v=w[d];c&&v?.id.startsWith("custom-")&&(p(v.id),R("confirming-delete"));}}else b==="confirming-delete"&&(y==="y"||y==="Y"?(A&&c&&c(A),p(null),R("browsing")):(y==="n"||y==="N"||O.escape)&&(p(null),R("browsing")));},{isActive:b==="browsing"&&T===null||b==="confirming-delete"}),b==="creating")return jsx(So,{onSave:(y,O)=>{a&&a(y,O),R("browsing");},onCancel:()=>R("browsing")});if(b==="editing"&&U){let y=o?.find(v=>v.id===U);if(e.find(v=>v.id===U)&&y)return jsx(So,{initialName:y.label,initialCards:y.cards,onSave:(v,k)=>{s&&s(U,v,k),P(null),R("browsing");},onCancel:()=>{P(null),R("browsing");}})}if(b==="confirming-delete"&&A){let y=w.find(v=>v.id===A),O=y?Fe(y.id,o):"Unknown";return jsxs(Box,{flexDirection:"column",gap:1,children:[jsxs(Text,{children:["Delete ",O,"? "]}),jsx(Text,{children:"[y] yes [n] no esc cancel"})]})}return w.length===0?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{dimColor:true,children:"(no scales available)"}),jsx(Text,{dimColor:true,children:"esc back"})]}):jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Box,{flexDirection:"column",children:w.map((y,O)=>{let v=O===d,k=y.id===t,te=T===y.id,X=y.id in de,Q=y.id==="__create-custom__",V=y.cards.join(", "),J=u&&y.id==="",I=J?"(none)":Q?"[+ Create custom scale]":Fe(y.id,o);return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{...v&&{color:"cyan"},children:v?">":" "}),jsx(Text,{bold:v,children:I}),!J&&!Q&&jsx(Text,{dimColor:true,children:V}),k&&jsx(Text,{color:"cyan",children:"[current]"})]}),te&&!J&&!Q&&jsx(Box,{paddingLeft:2,children:X?jsx(pi,{scaleId:y.id,cards:de[y.id]?.cards??[],disabledIndices:n?.[y.id]??[],onOverrideChange:i,onClose:()=>D(null)}):null})]},y.id||"none")})}),jsx(Text,{dimColor:true,children:(()=>{let y=d<w.length?w[d]:null;return y?.id.startsWith("custom-")?`\u2191\u2193 navigate space select${s?" [e] edit":""}${c?" [d] delete":""} esc back`:y&&y.id in de?"\u2191\u2193 navigate \u23CE customize space select esc back":"\u2191\u2193 navigate \u23CE/space select esc back"})()})]})}function nd(e,t){return t?[...e]:e.filter(n=>n.value==="display-name")}function mi({sessionName:e,displayName:t,currentScale:n,accessMode:o,presetOverrides:r,customScales:i,isHost:a=true,onChangeName:s,onChangeScale:c,onChangeDisplayName:l,onChangeAccess:u,onClose:d}){let[f,T]=useState(r??{}),D=useMemo(()=>on(f,i),[f,i]),[b,R]=useState("main-menu"),[U,P]=useState(e??""),[A,p]=useState(t),[w,_]=useState(o==="password"?"password":"open"),[y,O]=useState(""),[v,k]=useState(false),te=[{label:"Room name",value:"room-name",detail:`[${e??"(none)"}]`},{label:"Scale",value:"scale",detail:`[${Fe(n.id,i)}]`},{label:"Access",value:"access",detail:`[${o==="open"?"Open":"Password"}]`},{label:"Display name",value:"display-name",detail:`[${t}]`}],X=nd(te,a);function Q(m){!a&&m!=="display-name"||(m==="room-name"?(P(e??""),R("editing-room-name")):m==="scale"?R("picking-scale"):m==="access"?R("picking-access"):m==="display-name"&&(p(t),R("editing-display-name")));}function V(m){let x=m.trim()===""?void 0:m.trim();s(x),R("main-menu");}function J(m){let x=m.trim();x.length>0&&(l(x),process.nextTick(()=>Y({displayName:x}))),R("main-menu");}function I(m){let x=D.find(E=>E.id===m);x&&c(x),R("main-menu");}function H(m,x){let E={...f};x.length===0?delete E[m]:E[m]=x,T(E),Y({presetOverrides:Object.keys(E).length>0?E:void 0});}async function K(m,x){k(true);try{await u(m,x),_(m),O(m==="password"?x??"":"");}catch(E){console.error(`Failed to update access: ${E}`);}finally{k(false),R("main-menu");}}return b==="main-menu"?jsx(he,{title:"\u2500\u2500 Settings \u2500\u2500",items:X,onSelect:Q,onClose:d}):b==="editing-room-name"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),jsx(Text,{children:"Room name: "}),jsx(W,{value:U,onChange:P,onSubmit:V,onCancel:()=>R("main-menu"),placeholder:"(leave empty to remove)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]}):b==="editing-display-name"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),jsx(Text,{children:"Display name: "}),jsx(W,{value:A,onChange:p,onSubmit:J,onCancel:()=>R("main-menu"),placeholder:"(required)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]}):b==="picking-scale"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),jsx(Sn,{scales:D,selectedScaleId:n.id,presetOverrides:f,onSelect:I,onOverrideChange:H,onClose:()=>R("main-menu")})]}):b==="picking-access"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),v&&jsx(Text,{dimColor:true,children:"Updating access..."}),!v&&jsx(li,{mode:w,password:y,onModeChange:m=>{m==="open"&&K("open");},onPasswordChange:O,onClose:()=>R("main-menu")})]}):jsx(Box,{})}function Cn({participants:e,onlineIds:t,hostId:n,votes:o,revealed:r,participantId:i}){return jsxs(Box,{flexDirection:"column",children:[jsxs(Text,{bold:true,children:["Participants (",e.length,")"]}),e.map(a=>{let s=t.has(a.id),c=s?"\u25CF":"\u25CB",l=s?"green":"gray",u=a.id===n,d=ge(a)==="viewer",f=a.id===i,T=a.id in o,D=d?" (viewer)":r?o[a.id]?` \u2192 ${o[a.id]}`:"":T?" \u2713":" \xB7",b=f&&!d&&!(r&&o[a.id]);return jsxs(Box,{gap:1,children:[jsx(Text,{color:l,children:c}),jsxs(Text,{children:[a.displayName,u?" (host)":""]}),b?jsx(Text,{color:"cyan",children:"(voter)"}):jsx(Text,{color:d?"gray":T?"green":"gray",children:D})]},a.id)})]})}var od=[{label:"End session for everyone",value:"end-session",detail:"Disconnects all participants. Cannot be undone."}];function hi({onPick:e,onClose:t}){return jsx(he,{title:"Host Actions",items:od,onSelect:e,onClose:t})}function yn({roomCode:e,onPick:t,onClose:n}){let o=[{label:"Copy code",value:"code",detail:un(e)},{label:"Copy share link",value:"url",detail:fn(e)},{label:"Copy npx command",value:"npx",detail:pn(e)}];return jsx(he,{title:"Share",items:o,onSelect:r=>t(r),onClose:n})}function sd(e){let t=Object.fromEntries(e.participants.map(n=>[n.id,n]));return Hr({rounds:e.rounds,participants:t})}async function Si(e,t,n){let o=sd(e);try{await t(o),n("Results copied to clipboard");}catch{n("Clipboard write failed");}}function xi(e,t){let n=Qn(e,t),o=e.title?` \u2014 ${e.title}`:"",r=e.ticketId?` [${e.ticketId}]`:"",i=e.status==="skipped"?" \u2014 Skipped":" \u2014 Results";return `${n}${o}${r}${i}`}function wi(e,t){let n=Qn(e,t);if(e.status==="skipped"){let d=e.title?` ${e.title}`:"",f=e.ticketId?` [${e.ticketId}]`:"";return `${n}:${d}${f} \u2014 Skipped`}let o=new Map;for(let d of Object.values(e.votes))Z(d)||o.set(d,(o.get(d)??0)+1);let r=[...o.entries()].toSorted((d,f)=>f[1]-d[1]||d[0].localeCompare(f[0])).map(([d,f])=>`${d}\xD7${f}`).join(", "),i=Object.values(e.votes).filter(Z).length,a=i>0?` (${i} abstained)`:"",s=e.title?` ${e.title}`:"",c=e.ticketId?` [${e.ticketId}]`:"",l=rt(e),u=l!==null?` \u2014 ${l}`:"";return `${n}:${s}${c} \u2014 ${r||"(no votes)"}${a}${u}`}function Ci({projection:e,onlineIds:t,isHost:n,participantId:o,rounds:r,currentRound:i,settingsOpen:a,onStartRound:s,onNewRound:c,onRevote:l,onOpenSettings:u,onHandoffHost:d,onEndSession:f,onShare:T,shareOpen:D,onSetShareOpen:b,roomCode:R,confirmingQuit:U,myRole:P,onToggleRole:A,roundTitlePromptActive:p,roundTitleInput:w,onRoundTitleChange:_,onRoundTitleSubmit:y,onRoundTitleCancel:O,roundTicketIdPromptActive:v,roundTicketIdInput:k,onRoundTicketIdChange:te,onRoundTicketIdSubmit:X,onRoundTicketIdCancel:Q,descriptorPromptActive:V,descriptorInput:J,onDescriptorChange:I,onDescriptorSubmit:H,onDescriptorCancel:K,onEditDescriptor:m,canExport:x,onExportResults:E,onAgendaAdd:G,agendaAddPromptActive:ue,agendaAddTitleInput:ut,onAgendaAddTitleChange:kn,onAgendaAddTitleSubmit:qe,onAgendaAddTitleCancel:Ut,agendaAddTicketIdPromptActive:ve,agendaAddTicketIdInput:Pn,onAgendaAddTicketIdChange:Xe,onAgendaAddTicketIdSubmit:Qe,onAgendaAddTicketIdCancel:Me}){let[oe,re]=vn.useState("idle"),[Se,Ie]=vn.useState(null),[ft,ae]=vn.useState(false),[fe,xe]=vn.useState(false);useEffect(()=>{n||(re("idle"),Ie(null),ae(false),xe(false));},[n]),useInput(C=>{if(C==="c"||C==="C"){b(true);return}if(C==="w"||C==="W"){A();return}if((C==="x"||C==="X")&&x){E();return}if(n){if(C==="a"||C==="A"){G();return}(C==="e"||C==="E")&&u(),(C==="s"||C==="S")&&s(),(C==="h"||C==="H")&&re("picking"),(C==="m"||C==="M")&&ae(true),i!==null&&mt(i.status)&&((C==="n"||C==="N")&&c(),(C==="v"||C==="V")&&i.status!=="skipped"&&l(),(C==="t"||C==="T")&&m());}},{isActive:!a&&!U&&oe==="idle"&&!p&&!v&&!ft&&!fe&&!D&&!V&&!ue&&!ve}),useInput((C,pe)=>{C==="y"||C==="Y"?(f(),xe(false)):(C==="n"||C==="N"||pe.escape)&&xe(false);},{isActive:fe});let be=e.participants.filter(C=>C.id!==o&&t.has(C.id));useInput(C=>{if(oe==="picking"){let pe=parseInt(C,10);!isNaN(pe)&&pe>=1&&pe<=be.length?(Ie(be[pe-1].id),re("confirming")):(C==="Escape"||C==="q"||C==="Q")&&re("idle");}},{isActive:oe==="picking"}),useInput(C=>{oe==="confirming"&&Se&&(C==="y"||C==="Y"?(d(Se),re("idle"),Ie(null)):(C==="n"||C==="N"||C==="Escape")&&(re("idle"),Ie(null)));},{isActive:oe==="confirming"});let Ze=r.filter(C=>Ft(C.status)),Ue=Ze.length>0,_t=i!==null?Ze.slice(0,-1):Ze;return ft?jsx(hi,{onPick:C=>{ae(false),C==="end-session"&&xe(true);},onClose:()=>ae(false)}):D?jsx(yn,{roomCode:R,onPick:C=>{b(false),T(C);},onClose:()=>b(false)}):jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:Ue?"Session":"Waiting for participants..."}),!Ue&&jsx(Text,{dimColor:true,children:"No rounds started yet."}),jsx(Cn,{participants:e.participants,onlineIds:t,hostId:e.settings.hostParticipantId,votes:{},revealed:false,participantId:o}),e.agenda.length>0&&jsx(ud,{items:e.agenda,nextPending:He(e)}),i!==null&&mt(i.status)&&jsx(dd,{projection:e,round:i,rounds:r}),_t.length>0&&jsxs(Box,{flexDirection:"column",children:[jsx(Text,{dimColor:true,children:"\u2500\u2500 History \u2500\u2500"}),_t.map(C=>jsx(Text,{dimColor:true,children:wi(C,r)},C.id))]}),oe==="picking"&&be.length>0&&jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{children:"Hand off to:"}),be.map((C,pe)=>jsxs(Text,{children:["[",pe+1,"] ",C.displayName]},C.id)),jsx(Text,{dimColor:true,children:"[q] Cancel"})]}),oe==="picking"&&be.length===0&&jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{dimColor:true,children:"No other online participants"}),jsx(Text,{dimColor:true,children:"[q] Cancel"})]}),oe==="confirming"&&Se&&jsx(Box,{flexDirection:"column",children:jsxs(Text,{children:["Hand off to ",e.participants.find(C=>C.id===Se)?.displayName,"? [y/n]"]})}),p&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Round title (optional, Enter to skip):"}),jsx(W,{value:w,onChange:_,onSubmit:y,onCancel:O,placeholder:"Enter to skip",isActive:p})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),v&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Ticket ID (optional, Enter to skip):"}),jsx(W,{value:k,onChange:te,onSubmit:X,onCancel:Q,placeholder:"e.g. PROJ-1234",isActive:v})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),V&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Edit round title:"}),jsx(W,{value:J,onChange:I,onSubmit:H,onCancel:K,placeholder:"Enter to save",isActive:V})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel \xB7 empty submit cancels"})]}),fe&&jsxs(Box,{children:[jsx(Text,{color:"red",children:"End session for everyone? This cannot be undone. "}),jsx(Text,{dimColor:true,children:"y/n [Esc] Cancel"})]}),ue&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Agenda title (optional, Enter to skip):"}),jsx(W,{value:ut,onChange:kn,onSubmit:qe,onCancel:Ut,placeholder:"Enter to skip",isActive:ue})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),ve&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Agenda ticket ID (optional, Enter to skip):"}),jsx(W,{value:Pn,onChange:Xe,onSubmit:Qe,onCancel:Me,placeholder:"e.g. PROJ-1234",isActive:ve})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),oe==="idle"&&!p&&!v&&!V&&!fe&&!ue&&!ve&&jsxs(Box,{gap:2,children:[n?jsx(Fragment,{children:i!==null&&mt(i.status)?jsxs(Fragment,{children:[i.status!=="skipped"&&jsx(Text,{color:"yellow",children:"[v] Revote"}),jsx(Text,{color:"yellow",children:"[n] Next"}),jsx(Text,{color:"yellow",children:"[t] Edit title"}),jsx(Text,{color:"yellow",children:"[h] Handoff"}),jsx(Text,{color:"yellow",children:"[e] Settings"}),jsx(Text,{color:"yellow",children:"[c] Share"}),x&&jsx(Text,{color:"yellow",children:"[x] Export"}),jsxs(Text,{color:"yellow",children:["[w] ",P==="viewer"?"Vote":"Observe"]}),jsx(Text,{color:"yellow",children:"[m] Menu"})]}):jsxs(Fragment,{children:[jsx(Text,{color:"yellow",children:"[s] Start round"}),jsx(Text,{color:"yellow",children:"[a] Agenda"}),jsx(Text,{color:"yellow",children:"[h] Handoff"}),jsx(Text,{color:"yellow",children:"[e] Settings"}),jsx(Text,{color:"yellow",children:"[c] Share"}),x&&jsx(Text,{color:"yellow",children:"[x] Export"}),jsxs(Text,{color:"yellow",children:["[w] ",P==="viewer"?"Vote":"Observe"]}),jsx(Text,{color:"yellow",children:"[m] Menu"})]})}):jsxs(Fragment,{children:[jsx(Text,{dimColor:true,children:"Waiting for host to start a round..."}),jsx(Text,{children:"[c] Share"}),x&&jsx(Text,{color:"yellow",children:"[x] Export"}),jsxs(Text,{color:"yellow",children:["[w] ",P==="viewer"?"Vote":"Observe"]})]}),jsx(Text,{children:"[q] Quit"})]})]})}function dd({projection:e,round:t,rounds:n}){let o=xi(t,n);if(t.status==="skipped")return jsx(Box,{flexDirection:"column",gap:1,children:jsx(Text,{bold:true,children:o})});let r=tn(en(t)),i=new Map(e.participants.map(d=>[d.id,d.displayName])),a=rt(t),s=Object.entries(t.votes),c=s.filter(([,d])=>!Z(d)),l=s.filter(([,d])=>Z(d)).map(([d])=>d),u=c[0]?.[1];return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:o}),jn(t)&&u!==void 0&&jsxs(Text,{bold:true,color:"green",children:["Consensus! Everyone voted ",u]}),jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:2,children:[jsx(Text,{bold:true,underline:true,children:"Name".padEnd(20)}),jsx(Text,{bold:true,underline:true,children:"Estimate".padEnd(10)})]}),c.map(([d,f])=>jsxs(Box,{gap:2,children:[jsx(Text,{children:(i.get(d)??d).padEnd(20)}),jsx(Text,{color:"cyan",bold:true,children:f.padEnd(10)})]},d)),l.map(d=>jsxs(Box,{gap:2,children:[jsx(Text,{dimColor:true,children:(i.get(d)??d).padEnd(20)}),jsx(Text,{dimColor:true,children:"(abstained)".padEnd(10)})]},d)),e.participants.filter(d=>!(d.id in t.votes)).map(d=>jsxs(Box,{gap:2,children:[jsx(Text,{dimColor:true,children:d.displayName.padEnd(20)}),jsx(Text,{dimColor:true,children:"(no vote)".padEnd(10)})]},d.id))]}),(r!==null||a!==null)&&jsxs(Box,{gap:2,children:[r?.kind==="numeric"&&jsxs(Text,{children:["Avg: ",jsx(Text,{bold:true,children:r.mean})]}),r?.kind==="numeric"&&jsxs(Text,{children:["Med: ",jsx(Text,{bold:true,children:r.median})]}),r?.kind==="categorical"&&r.mode!==null&&jsxs(Text,{children:["Most common: ",jsx(Text,{bold:true,children:r.mode})]}),r!==null&&jsxs(Text,{children:["Spread: ",jsx(Text,{bold:true,children:r.spread})]}),a!==null&&jsxs(Text,{dimColor:true,children:["\u23F1 ",a]})]})]})}var cd={pending:"\u2022",consumed:"\u2713",skipped:"~",cancelled:"\u2717"},ld={consumed:"green",skipped:"yellow",cancelled:"red"};function ud({items:e,nextPending:t}){let n=e.filter(o=>o.state!=="cancelled");return jsxs(Box,{flexDirection:"column",children:[jsx(Text,{dimColor:true,children:"\u2500\u2500 Agenda \u2500\u2500"}),n.map(o=>{let r=cd[o.state]??"?",i=ld[o.state],a=t!==null&&o.id===t.id,s=[o.ticketId?`[${o.ticketId}]`:"",o.title??""].filter(Boolean).join(" ").trim()||o.id;return jsxs(Box,{gap:1,children:[i!==void 0?jsx(Text,{color:i,children:r}):jsx(Text,{children:r}),i!==void 0?jsx(Text,{color:i,children:s}):jsx(Text,{children:s}),a&&jsx(Text,{color:"cyan",children:"(next)"})]},o.id)}),n.length===0&&jsx(Text,{dimColor:true,children:"No pending items."})]})}function Ii({scale:e,selected:t,onToggleCurrentVote:n,onClearCurrentVote:o,disabled:r}){let[i,a]=useState(0);return useInput((s,c)=>{r||(c.leftArrow?a(l=>Math.max(0,l-1)):c.rightArrow?a(l=>Math.min(e.cards.length-1,l+1)):c.return?n(e.cards[i]):(c.backspace||c.delete)&&o());}),jsxs(Box,{flexDirection:"column",gap:0,children:[jsx(Box,{gap:1,children:e.cards.map((s,c)=>{let l=c===i,u=s===t;return jsx(Text,{inverse:l,bold:u,...u&&{color:"cyan"},children:u?`[${s}]`:` ${s} `},s)})}),jsx(Text,{dimColor:true,children:" \u2190\u2192 navigate \u23CE select \u232B clear"})]})}function bi({projection:e,round:t,onlineIds:n,isHost:o,myId:r,myRole:i,elapsedMs:a,roomCode:s,shareOpen:c,settingsOpen:l,onToggleCurrentVote:u,onClearCurrentVote:d,onReveal:f,onSkip:T,onDiscard:D,onToggleRole:b,onShare:R,onSetShareOpen:U,onOpenSettings:P,confirmingQuit:A}){let p=t.votes[r],w=p!==void 0&&Z(p);if(useInput(k=>{if(k==="e"||k==="E"){P();return}if(k==="c"||k==="C"){U(true);return}if(i==="voter"&&(k==="a"||k==="A")){u(Bt);return}o&&(k==="r"||k==="R")&&f(),o&&(k==="s"||k==="S")&&T(),o&&(k==="d"||k==="D")&&D(),(k==="w"||k==="W")&&b();},{isActive:!A&&!l&&!c}),c)return jsx(yn,{roomCode:s,onPick:k=>{U(false),R(k);},onClose:()=>U(false)});let _=p,y=vt(t,e.rounds),O=t.title?` \u2014 ${t.title}`:"",v=t.ticketId?` [${t.ticketId}]`:"";return jsxs(Box,{flexDirection:"column",gap:1,children:[jsxs(Box,{gap:2,children:[jsxs(Text,{bold:true,children:["Round ",y,O,v]}),a!==void 0&&jsxs(Text,{dimColor:true,children:["\u23F1 ",Qt(a)]})]}),jsxs(Box,{gap:4,children:[jsx(Cn,{participants:e.participants,onlineIds:n,hostId:e.settings.hostParticipantId,votes:t.votes,revealed:false}),i==="viewer"?jsx(Box,{flexDirection:"column",children:jsx(Text,{dimColor:true,children:"You're observing"})}):jsxs(Box,{flexDirection:"column",gap:1,children:[w&&jsx(Text,{dimColor:true,children:"(abstaining this round \u2014 press [a] to vote)"}),jsx(Ii,{scale:t.scale,selected:w?void 0:_,onToggleCurrentVote:u,onClearCurrentVote:d,disabled:A||w})]})]}),jsxs(Box,{gap:2,children:[o&&jsx(Text,{color:"yellow",children:"[r] Reveal"}),o&&jsx(Text,{color:"yellow",children:"[s] Skip"}),o&&jsx(Text,{color:"yellow",children:"[d] Discard"}),i==="voter"&&jsxs(Text,{color:"yellow",children:["[a] ",w?"Vote":"Abstain"]}),jsxs(Text,{color:"yellow",children:["[w] ",i==="viewer"?"Vote":"Observe"]}),jsx(Text,{children:"[e] Settings"}),jsx(Text,{children:"[c] Share"}),jsx(Text,{children:"[q] Quit"})]})]})}var wd=3e3;function Nt(e=wd){let[t,n]=useState(null),o=useRef(null),r=useCallback(()=>{o.current!==null&&(clearTimeout(o.current),o.current=null);},[]),i=useCallback(s=>{r(),n(s),o.current=setTimeout(()=>{n(null),o.current=null;},e);},[r,e]),a=useCallback(()=>{r(),n(null);},[r]);return useEffect(()=>()=>{r();},[r]),{notice:t,show:i,dismiss:a}}var vd={"not-host":"only the current host can hand off","not-found":"that participant is not in the session","not-online":"that participant is offline","self-target":"you cannot hand off to yourself"};function An({session:e,participantId:t,displayName:n,accessMode:o,presetOverrides:r,customScales:i}){let{exit:a}=useApp(),[s,c]=useState(e.projection()),[l,u]=useState("connecting"),[d,f]=useState(e.onlineIds()),[T,D]=useState(),[b,R]=useState(false),[U,P]=useState(o==="password"?"password":"open"),[A,p]=useState(n),[w,_]=useState(false),[y,O]=useState(false),[v,k]=useState(""),[te,X]=useState(false),[Q,V]=useState(""),[J,I]=useState(),[H,K]=useState(false),[m,x]=useState(""),[E,G]=useState(null),[ue,ut]=useState(false),[kn,qe]=useState(""),[Ut,ve]=useState(false),[Pn,Xe]=useState(""),[Qe,Me]=useState(),[oe,re]=useState(),Se=Nt(3e3),[Ie,ft]=useState(false),ae=Nt(3e3),fe=Nt(3e3),xe=Nt(3e3);useEffect(()=>{let S=e.onChange(()=>{c(e.projection()),f(e.onlineIds());}),L=e.onStatusChange(u),Ae=e.onHostChange(Lt=>{let ps=e.projection().participants.find(gs=>gs.id===Lt),ms=Lt===t?"You are now the host":`${ps?.displayName||"Unknown"} is now the host`;Se.show(ms);}),$t=setInterval(()=>{f(e.onlineIds());let Lt=e.projection(),Ht=me(Lt);Ht?.timerStartedAt!==void 0&&et(Ht.status)?D(Date.now()-Ht.timerStartedAt):D(void 0);},1e3);return ()=>{S(),L(),Ae(),clearInterval($t);}},[e,t,Se.show]),useInput(S=>{(S==="q"||S==="Q")&&_(true);},{isActive:!b&&!w&&!y&&!te&&!H&&!Ie&&!ue&&!Ut}),useInput((S,L)=>{S==="y"||S==="Y"?(e.disconnect(),a()):(S==="n"||S==="N"||L.escape)&&_(false);},{isActive:w});let be=Vr(s),Ze=me(s),Ue=s.settings.hostParticipantId===t,_t=s.participants.find(S=>S.id===t),C=ge(_t??{}),pe=useCallback(()=>{let S=mn(He(s));k(S.title),re(S.agendaItemId),O(true);},[s]),Li=useCallback(S=>{O(false),k(""),I(co(S));let L=mn(He(s));V(L.ticketId),X(true);},[s]),Hi=useCallback(()=>{O(false),k(""),I(void 0),re(void 0);},[]),Bi=useCallback(S=>{X(false),V("");let[L,Ae,$t]=oi(J,S,oe);e.commands.startRound({...L!==void 0&&{title:L},...Ae!==void 0&&{ticketId:Ae},...$t!==void 0&&{agendaItemId:$t}}),I(void 0),re(void 0);},[e,J,oe]),ji=useCallback(()=>{X(false),V(""),I(void 0),re(void 0);},[]),Fi=useCallback(()=>{let S=e.current();!S||S.status!=="revealed"||(G(S.id),x(S.title??""),K(true));},[e]),Vi=useCallback(S=>{let L=E;if(K(false),G(null),!L)return;let Ae=S.trim();Ae!==""&&e.updateRoundDescriptor(L,{title:Ae});},[e,E]),Wi=useCallback(()=>{K(false),G(null);},[]),Yi=useCallback(S=>{e.commands.toggleCurrentVote(S);},[e]),Ji=useCallback(()=>{e.commands.clearCurrentVote();},[e]),Ki=useCallback(()=>{e.commands.revealCurrentRound();},[e]),Gi=useCallback(()=>{e.commands.skipCurrentRound();},[e]),zi=useCallback(()=>{e.commands.discardCurrentRound();},[e]),qi=useCallback(()=>{let S=mn(He(s));k(S.title),re(S.agendaItemId),O(true);},[s]),Xi=useCallback(()=>{let S=e.current();S&&e.commands.startRound({parentRoundId:S.id,...S.title!==void 0&&{title:S.title},...S.description!==void 0&&{description:S.description},...S.ticketId!==void 0&&{ticketId:S.ticketId},...S.agendaItemId!==void 0&&{agendaItemId:S.agendaItemId}});},[e]),Ao=useCallback(()=>{e.commands.toggleRole();},[e]),Qi=useCallback(S=>{e.updateName(S);},[e]),Zi=useCallback(S=>{e.updateScale(S);},[e]),es=useCallback(S=>{e.commands.rename(S),p(S);},[e]),ts=useCallback(async(S,L)=>{await e.updateAccess(S,L),P(S);},[e]),ns=useCallback(S=>{let L=e.commands.handoffHost(S);L.applied||console.error(`Handoff failed: ${vd[L.reason]}`);},[e]),Ro=useCallback(()=>{R(true);},[]),os=useCallback(()=>{R(false);},[]),rs=useCallback(()=>{e.commands.endSession();},[e]),To=useCallback(async S=>{let L=S==="code"?un(e.roomCode):S==="url"?fn(e.roomCode):pn(e.roomCode);try{await Ri.write(L),ae.show("Copied!");}catch{ae.show(`Copy failed \u2014 ${L}`);}},[e.roomCode,ae]),Nn=s.rounds.filter(S=>Ft(S.status)),is=Nn.length>0?Nn.at(-1):null,ss=Nn.length>0,as=useCallback(()=>Si(s,S=>Ri.write(S),fe.show),[s,fe.show]),ds=useCallback(()=>{qe(""),ut(true);},[]),cs=useCallback(S=>{ut(false),qe("");let L=S.trim()===""?void 0:S.trim();Me(L),Xe(""),ve(true);},[]),ls=useCallback(()=>{ut(false),qe(""),Me(void 0);},[]),us=useCallback(S=>{ve(false),Xe("");let L=S.trim()===""?void 0:S.trim();if(!Qe&&!L){Me(void 0);return}if(!nt(e.doc,{...Qe!==void 0&&{title:Qe},...L!==void 0&&{ticketId:L}}).applied){xe.show("Add failed \u2014 an agenda item needs a title or a ticket id");return}Me(void 0);},[e.doc,Qe,xe]),fs=useCallback(()=>{ve(false),Xe(""),Me(void 0);},[]);return jsxs(Box,{flexDirection:"column",children:[jsx(si,{roomCode:e.roomCode,sessionName:s.settings.name,status:l,isHost:Ue}),Se.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:"yellow",children:Se.notice})}),ae.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:ae.notice.startsWith("Copy failed")?"red":"green",children:ae.notice})}),fe.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:fe.notice.startsWith("Clipboard write failed")?"red":"green",children:fe.notice})}),xe.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:"red",children:xe.notice})}),b?jsx(mi,{sessionName:s.settings.name,displayName:A,currentScale:s.settings.defaultScale,accessMode:U,presetOverrides:r,customScales:i,isHost:Ue,onChangeName:Qi,onChangeScale:Zi,onChangeDisplayName:es,onChangeAccess:ts,onClose:os}):be==="lobby"?jsx(Ci,{projection:s,onlineIds:d,isHost:Ue,participantId:t,rounds:s.rounds,currentRound:is,settingsOpen:b,onStartRound:pe,onNewRound:qi,roundTitlePromptActive:y,roundTitleInput:v,onRoundTitleChange:k,onRoundTitleSubmit:Li,onRoundTitleCancel:Hi,roundTicketIdPromptActive:te,roundTicketIdInput:Q,onRoundTicketIdChange:V,onRoundTicketIdSubmit:Bi,onRoundTicketIdCancel:ji,onRevote:Xi,onOpenSettings:Ro,onHandoffHost:ns,onEndSession:rs,onShare:To,shareOpen:Ie,onSetShareOpen:ft,roomCode:e.roomCode,confirmingQuit:w,myRole:C,onToggleRole:Ao,descriptorPromptActive:H,descriptorInput:m,onDescriptorChange:x,onDescriptorSubmit:Vi,onDescriptorCancel:Wi,onEditDescriptor:Fi,canExport:ss,onExportResults:as,onAgendaAdd:ds,agendaAddPromptActive:ue,agendaAddTitleInput:kn,onAgendaAddTitleChange:qe,onAgendaAddTitleSubmit:cs,onAgendaAddTitleCancel:ls,agendaAddTicketIdPromptActive:Ut,agendaAddTicketIdInput:Pn,onAgendaAddTicketIdChange:Xe,onAgendaAddTicketIdSubmit:us,onAgendaAddTicketIdCancel:fs}):be==="estimating"&&Ze?jsx(bi,{projection:s,round:Ze,onlineIds:d,isHost:Ue,myId:t,myRole:C,elapsedMs:T,onToggleCurrentVote:Yi,onClearCurrentVote:Ji,onReveal:Ki,onSkip:Gi,onDiscard:zi,onToggleRole:Ao,onShare:To,onSetShareOpen:ft,shareOpen:Ie,settingsOpen:b,onOpenSettings:Ro,roomCode:e.roomCode,confirmingQuit:w}):null,w&&jsx(Box,{children:jsx(Text,{dimColor:true,children:"Leave session? y/n"})})]})}function Ti({presetOverrides:e,customScales:t}){let{exit:n}=useApp(),[o,r]=useState("main-menu"),[i,a]=useState(Ve()),[s,c]=useState(i.displayName??""),[l,u]=useState(i.relayUrl??""),[d,f]=useState(i.defaultSessionName??""),[T,D]=useState(i.avatarColor?.startsWith("#")?i.avatarColor:""),[b,R]=useState(t??[]),[U,P]=useState(e??{});useInput(m=>{(m==="q"||m==="Q")&&n();},{isActive:o==="main-menu"});let A=useMemo(()=>on(U,b),[U,b]),p=i.defaultScale,w=p?A.find(m=>m.id===p):void 0,_=[{label:"Display name",value:"display-name",detail:`[${i.displayName??"(none)"}]`},{label:"Relay URL",value:"relay-url",detail:`[${i.relayUrl??"(none)"}]`},{label:"Default scale",value:"default-scale",detail:`[${w?Fe(w.id,b):"(none)"}]`},{label:"Default session name",value:"default-session-name",detail:`[${i.defaultSessionName??"(none)"}]`},{label:"Default password",value:"default-password",detail:`[${i.defaultPassword?"on":"off"}]`},{label:"Avatar color",value:"avatar-color",detail:`[${Ed(i.avatarColor)}]`}];function y(m){m==="display-name"?(c(i.displayName??""),r("editing-display-name")):m==="relay-url"?(u(i.relayUrl??""),r("editing-relay-url")):m==="default-scale"?r("picking-scale"):m==="default-session-name"?(f(i.defaultSessionName??""),r("editing-session-name")):m==="default-password"?r("picking-default-password"):m==="avatar-color"&&r("picking-avatar-color");}function O(m){if(m==="custom-hex"){D(i.avatarColor?.startsWith("#")?i.avatarColor:""),r("editing-avatar-hex");return}if(je(m)===null){r("main-menu");return}a({...i,avatarColor:m}),Y({avatarColor:m}),r("main-menu");}function v(m){let x=m.trim();if(x.length===0){r("picking-avatar-color");return}let E=x.startsWith("#")?x.toLowerCase():`#${x.toLowerCase()}`;je(E)!==null&&(a({...i,avatarColor:E}),Y({avatarColor:E}),r("main-menu"));}function k(m){let x=m.trim();if(x.length>0){let E={...i,displayName:x};a(E),Y({displayName:x});}r("main-menu");}function te(m){let x=m.trim();if(x.length>0){let E={...i,relayUrl:x};a(E),Y({relayUrl:x});}r("main-menu");}function X(m){let x=m.trim(),E=x.length>0?{...i,defaultSessionName:x}:{...i};x.length===0?(delete E.defaultSessionName,a(E),bt({defaultSessionName:""})):(a(E),Y({defaultSessionName:x})),r("main-menu");}function Q(m){let x=m.length>0?{...i,defaultScale:m}:{...i};m.length===0?(delete x.defaultScale,a(x),bt({defaultScale:""})):(a(x),Y({defaultScale:m})),r("main-menu");}function V(m,x){let E={...U};x.length===0?delete E[m]:E[m]=x,P(E),Y({presetOverrides:Object.keys(E).length>0?E:void 0});}function J(m){let x=m==="on",E={...i,defaultPassword:x};a(E),Y({defaultPassword:x}),r("main-menu");}function I(m,x){let E=`custom-${randomUUID()}`,G=[...b,{id:E,label:m,cards:x}];R(G),a({...i,customScales:G}),Y({customScales:G});}function H(m,x,E){let G=b.map(ue=>ue.id===m?{id:m,label:x,cards:E}:ue);R(G),a({...i,customScales:G}),Y({customScales:G});}function K(m){let x=b.filter(G=>G.id!==m);R(x);let E={...i,customScales:x};i.defaultScale===m?(E.defaultScale="fibonacci",Y({customScales:x,defaultScale:"fibonacci"})):Y({customScales:x}),a(E);}if(o==="main-menu")return jsx(he,{title:"\u2500\u2500 Config Settings \u2500\u2500",items:_,onSelect:y,onClose:()=>n()});if(o==="editing-display-name")return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(Text,{children:"Display name: "}),jsx(W,{value:s,onChange:c,onSubmit:k,onCancel:()=>r("main-menu"),placeholder:"(required)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]});if(o==="editing-relay-url")return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(Text,{children:"Relay URL: "}),jsx(W,{value:l,onChange:u,onSubmit:te,onCancel:()=>r("main-menu"),placeholder:"(required)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]});if(o==="editing-session-name")return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(Text,{children:"Default session name: "}),jsx(W,{value:d,onChange:f,onSubmit:X,onCancel:()=>r("main-menu"),placeholder:"(leave empty to clear)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]});if(o==="picking-scale"){let m=[{id:"",cards:[]},...A];return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(Sn,{scales:m,selectedScaleId:p??"",presetOverrides:U,customScales:b,onSelect:Q,onOverrideChange:V,onCustomScaleCreate:I,onCustomScaleEdit:H,onCustomScaleDelete:K,onClose:()=>r("main-menu"),showNoneOption:true})]})}if(o==="picking-avatar-color"){let m=wt.map(x=>({label:ot[x].label,value:x,detail:i.avatarColor===x?"[current]":ot[x].base}));return m.push({label:"Custom hex\u2026",value:"custom-hex",detail:i.avatarColor?.startsWith("#")?`[${i.avatarColor}]`:void 0}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(he,{title:"Avatar color:",items:m,onSelect:O,onClose:()=>r("main-menu")})]})}if(o==="editing-avatar-hex")return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(Text,{children:"Custom hex color: "}),jsx(W,{value:T,onChange:D,onSubmit:v,onCancel:()=>r("picking-avatar-color"),placeholder:"#rrggbb",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]});if(o==="picking-default-password"){let m=[{label:"On",value:"on",detail:i.defaultPassword?"[current]":void 0},{label:"Off",value:"off",detail:i.defaultPassword?void 0:"[current]"}];return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(he,{title:"Default password:",items:m,onSelect:J,onClose:()=>r("main-menu")})]})}return jsx(Box,{})}function Ed(e){return e?e.startsWith("#")?e:wt.includes(e)?ot[e].label:e:"(auto)"}var Pd={pending:"\u2022",consumed:"\u2713",skipped:"~",cancelled:"\u2717"};function Nd(e){let t=Pd[e.state]??"?",n=[];e.ticketId&&n.push(`[${e.ticketId}]`),e.title&&n.push(e.title);let o=n.join(" ")||e.id;return `${t} ${o}`}function Rn(e){switch(e){case "not-found":return "no agenda item with that id";case "not-pending":return "the item is no longer pending \u2014 a peer may have skipped, cancelled or estimated it";case "invalid-fields":return "an agenda item needs at least one of --title or --ticket"}}async function Ot(e){let t=new _e.Doc,n=new Awareness(t);$e(t,{participantId:e.participantId,displayName:e.displayName,joinedAt:Date.now()}),n.setLocalStateField(Ee,e.participantId);let o=it({doc:t,awareness:n,roomCode:e.roomCode,roomUuid:e.roomUuid,participantId:e.participantId,relayUrl:e.relayUrl,...e.passwordHash!==void 0&&{passwordHash:e.passwordHash}});return await new Promise(r=>{let i=setTimeout(r,2e3),a=o.onStatusChange(s=>{s==="connected"&&setTimeout(()=>{clearTimeout(i),a(),r();},200);});}),{doc:t,disconnect:()=>o.disconnect()}}async function Mt(){let e=an();e.length===0&&(console.error("No active session. Join a room first with: hnch join <code>"),process.exit(1));let t=e[0];return {roomCode:t.roomCode,roomUuid:t.roomUuid,...t.passwordHash!==void 0&&{passwordHash:t.passwordHash}}}async function ki(e){!e.title?.trim()&&!e.ticket?.trim()&&(console.error("At least one of --title or --ticket is required"),process.exit(1));let t=await le(),n=await Mt();try{await ce(t.relayUrl,n.roomCode);}catch{console.error(`Room ${n.roomCode} not found on relay \u2014 session may have expired.`),process.exit(1);}let{doc:o,disconnect:r}=await Ot({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{let i=nt(o,{...e.title?.trim()?{title:e.title.trim()}:{},...e.ticket?.trim()?{ticketId:e.ticket.trim()}:{},...e.description?.trim()?{description:e.description.trim()}:{}});i.applied||(console.error(`Add failed: ${Rn(i.reason)}`),process.exit(1)),await new Promise(a=>{setTimeout(a,300);}),console.log(`Added agenda item: ${i.id}`);}finally{r();}}async function Pi(){let e=await le(),t=await Mt();try{await ce(e.relayUrl,t.roomCode);}catch{console.error(`Room ${t.roomCode} not found on relay \u2014 session may have expired.`),process.exit(1);}let{doc:n,disconnect:o}=await Ot({relayUrl:e.relayUrl,participantId:e.participantId,displayName:e.displayName,roomCode:t.roomCode,roomUuid:t.roomUuid,...t.passwordHash!==void 0&&{passwordHash:t.passwordHash}});try{let i=F(n).agenda;if(i.length===0){console.log("No agenda items.");return}i.forEach((a,s)=>{console.log(`${String(s+1).padStart(2)}. ${Nd(a)}`);});}finally{o();}}async function Ni(e){let t=await le(),n=await Mt();try{await ce(t.relayUrl,n.roomCode);}catch{console.error(`Room ${n.roomCode} not found on relay \u2014 session may have expired.`),process.exit(1);}let{doc:o,disconnect:r}=await Ot({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{let i=Gt(o,e.id);i.applied||(console.error(`Skip failed: ${Rn(i.reason)}`),process.exit(1)),await new Promise(a=>{setTimeout(a,300);}),console.log(`Skipped agenda item: ${e.id}`);}finally{r();}}async function Di(e){let t=await le(),n=await Mt();try{await ce(t.relayUrl,n.roomCode);}catch{console.error(`Room ${n.roomCode} not found on relay \u2014 session may have expired.`),process.exit(1);}let{doc:o,disconnect:r}=await Ot({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{let i=zt(o,e.id);i.applied||(console.error(`Cancel failed: ${Rn(i.reason)}`),process.exit(1)),await new Promise(a=>{setTimeout(a,300);}),console.log(`Cancelled agenda item: ${e.id}`);}finally{r();}}async function Oi(e){let t=await le(),n=await Mt();try{await ce(t.relayUrl,n.roomCode);}catch{console.error(`Room ${n.roomCode} not found on relay \u2014 session may have expired.`),process.exit(1);}let{doc:o,disconnect:r}=await Ot({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{let i=qt(o,e.id,e.before,e.after);i.applied||(console.error(`Move failed: ${Rn(i.reason)}`),process.exit(1)),await new Promise(a=>{setTimeout(a,300);}),console.log(`Reordered agenda item: ${e.id}`);}finally{r();}}async function vo(){let e=await ti(),t=rn(e);return t.ok||(console.error(t.message),process.exit(1)),t.password}function Io(e,t,n){let o=ni(e,{roomCode:t.roomCode,...n});o.remembered==="forget-password"&&so(t.roomUuid),o.remembered==="forget-session"&&At(t.roomUuid),console.error(o.message),t.disconnect(),process.exit(o.exitCode);}function lt(e){try{At(e);}catch(t){console.error(`Failed to clear cached session: ${t instanceof Error?t.message:String(t)}`);}}function bo(e){ao({clearLastSession:()=>{e!==void 0&&At(e);},logger:console,exit:process.exit});}async function Ud(e){let t=await le(),n=e.scale??t.defaultScale??"fibonacci",o=e.name??t.defaultSessionName,r=e.password??t.defaultPassword??false,i;r&&(i=await vo());let a=nn(n,t.presetOverrides,t.customScales);if(!a){let f=Object.keys(de).join(", ");console.error(`Unknown or fully-disabled scale: "${n}". Builtin IDs: ${f}`),process.exit(1);}let s=ln(),c,l=await Gr({participantId:t.participantId,displayName:t.displayName,relayUrl:t.relayUrl,sessionName:o,password:i,defaultScale:a,...t.avatarColor!==void 0&&{avatarColor:t.avatarColor},onRejection(f){f==="unknown-room"?bo(c):s.note(f);}});c=l.roomUuid,dn({roomCode:l.roomCode,roomUuid:l.roomUuid,lastSeenAt:Date.now(),...l.passwordHash!==void 0&&{passwordHash:l.passwordHash}}),console.error(`Room created: ${l.roomCode}`),console.error(`Share: hnch join ${l.roomCode}`),console.error("");let u=render(vn.createElement(An,{session:l,participantId:t.participantId,displayName:t.displayName,accessMode:i?"password":"open",presetOverrides:t.presetOverrides,customScales:t.customScales}));s.attach(u.unmount),cn({doc:l.doc,localParticipantId:t.participantId,onEnded:f=>{console.error(f.isLocal?"Session ended.":`Session ended by ${f.hostName}.`),u.unmount(),lt(l.roomUuid),l.disconnect(),process.exit(0);}}),await u.waitUntilExit();let d=s.refused();d!==null&&Io(d,l,{wasIn:true,typedPassword:i!==void 0}),l.disconnect(),lt(l.roomUuid),process.exit(0);}async function _d(e){let t=await le(),n=qr(e.code);n===null&&(console.error("invalid room code"),process.exit(1));let o;e.password&&(o=await vo());let r=await ce(t.relayUrl,n),i;r.accessMode==="password"&&!e.password?i=await vo():e.password&&(i=o);let a=ln(),s=await zr({participantId:t.participantId,displayName:t.displayName,relayUrl:t.relayUrl,roomCode:n,password:i,...t.avatarColor!==void 0&&{avatarColor:t.avatarColor},onRejection(u){u==="unknown-room"?bo(r.uuid):a.note(u);}});dn({roomCode:s.roomCode,roomUuid:s.roomUuid,lastSeenAt:Date.now(),...s.passwordHash!==void 0&&{passwordHash:s.passwordHash}}),console.error(`Joined room: ${s.roomCode}`),console.error("");let c=render(vn.createElement(An,{session:s,participantId:t.participantId,displayName:t.displayName,accessMode:r.accessMode,presetOverrides:t.presetOverrides,customScales:t.customScales}));a.attach(c.unmount),cn({doc:s.doc,localParticipantId:t.participantId,onEnded:u=>{console.error(u.isLocal?"Session ended.":`Session ended by ${u.hostName}.`),c.unmount(),lt(s.roomUuid),s.disconnect(),process.exit(0);}}),await c.waitUntilExit();let l=a.refused();l!==null&&Io(l,s,{wasIn:s.hasJoined(),typedPassword:i!==void 0}),s.disconnect(),lt(s.roomUuid),process.exit(0);}function $d(e,t=Date.now()){let n=t-e,o=Math.floor(n/6e4);return o<60?`${o}m ago`:`${Math.floor(o/60)}h ago`}async function Ld(e){return new Promise((t,n)=>{let o=createInterface({input:process.stdin,output:process.stderr}),r=()=>{process.stderr.write(`Select [1-${e}]: `),o.question("",i=>{let a=parseInt(i.trim(),10);Number.isInteger(a)&&a>=1&&a<=e?(o.close(),t(a)):(process.stderr.write(`Invalid choice \u2014 enter a number between 1 and ${e}.
|
|
26
|
-
`),r());});};o.on("close",()=>n(new Error("stdin closed"))),r();})}async function
|
|
27
|
-
`);for(let[r,
|
|
18
|
+
`}function tn(e,t,n){if(e.startsWith("custom-")){let r=(n??[]).find(s=>s.id===e);return r?{id:r.id,cards:r.cards}:void 0}let o=de[e];if(o){let r=(t??{})[e]??[];if(r.length===0)return o;let s=o.cards.filter((a,i)=>!r.includes(i));return s.length===0?void 0:{id:e,cards:s}}}function nn(e,t){let n=Object.keys(de).map(r=>tn(r,e,t)).filter(r=>r!==void 0),o=(t??[]).map(r=>({id:r.id,cards:r.cards}));return [...n,...o]}function Fe(e,t){if(e.startsWith("custom-")){let n=(t??[]).find(o=>o.id===e);if(n&&n.label.trim().length>0)return n.label}return or(e)}function Br(e,t,n){let o=F(e),r=tt(o);if(!r)return {applied:false,reason:"no-active-round"};let s=o.participants.find(a=>a.id===t);return !s||!we(s)||ge(s)!=="voter"?{applied:false,reason:"not-a-voter"}:r.votes[t]===n?(Bn(e,r.id,t),{applied:true,effect:"cleared"}):(Uo(e,r.id,t,n),{applied:true,effect:"cast"})}function jr(e,t){let n=F(e),o=tt(n);return o?(Bn(e,o.id,t),{applied:true,effect:"cleared"}):{applied:false,reason:"no-active-round"}}function Fr(e){let{doc:t,participantId:n,onlineIds:o}=e,r=e.now??Date.now;return {startRound:s=>Dr(t,s,r),revealCurrentRound:()=>Or(t,r),skipCurrentRound:()=>Mr(t,r),discardCurrentRound:()=>_r(t,n,r),toggleCurrentVote:s=>Br(t,n,s),clearCurrentVote:()=>jr(t,n),addItem:s=>nt(t,s,r),editItem:(s,a)=>qo(t,s,a),skipItem:s=>Kt(t,s),cancelItem:s=>Gt(t,s),moveItem:(s,a,i)=>qt(t,s,a,i),rename:s=>Ir(t,n,s),recolor:s=>br(t,n,s),toggleRole:()=>Ar(t,n),leave:()=>Rr(t,n,r),kick:s=>Er(t,n,s,r),handoffHost:s=>kr(t,n,s,o()),endSession:()=>Nr(t,n,r)}}function Vr(e){let{prevName:t,newName:n,isSelf:o,wasSelf:r=false,cause:s=null}=e,a=o?"You are now the host":`${n} is now the host`;if(!t||r||s===null)return a;switch(s){case "left":return `${t} left. ${a}.`;case "disconnected":return `${t} disconnected. ${a}.`}}var ca="Session ended.",la=e=>`Session ended by ${e}`,ua="Removed by host";function on(e,t){if(t!==null)return e.find(n=>n.id===t)?.displayName||void 0}function Yr(e){let t=false,n=null,o=null,r=null,s="unset",a=false,i=[],c=false;function l(S){let C=S.meta.sessionEndedAt;if(C==null){n=null;return}if(C===n)return;n=C;let E=S.settings.hostParticipantId||null,T=on(S.participants,E)??on(S.participants,S.meta.createdBy)??"Host";i.push(()=>{let A=e.endedLocally();return {kind:"ended",endedAt:C,endedLocally:A,hostId:E,hostName:T,message:A?ca:la(T)}});}function u(S){let C=S.participants.find(v=>v.id===e.selfId);if(!C)return;let{leftAt:E,removedBy:T}=C;if(E===void 0){s=void 0,r=null;return}if(T===e.selfId){s=E;return}if(!a){s=E;return}if(s==="unset"){s=E;return}if(s!==void 0){s=E;return}if(s=E,E===r)return;r=E;let A=T??null,k={kind:"removed",leftAt:E,removedBy:A,removedByName:A===null?null:on(S.participants,A)??A,message:ua};i.push(()=>k);}function d(S){let C=S.settings.hostParticipantId||null;if(C===null){o=null;return}if(o===null){o=C;return}if(C===o)return;let E=o;o=C;let T=S.participants.find(N=>N.id===E),A=T===void 0?null:T.displayName||E,k=T!==void 0&&!we(T),v=on(S.participants,C)??C,h=E===e.selfId,w=C===e.selfId;i.push(()=>{let N=null;return k?N="left":T!==void 0&&e.presenceTrusted()&&!e.onlineIds().has(E)&&(N="disconnected"),{kind:"host-changed",previousHostId:E,previousHostName:A,hostId:C,hostName:v,cause:N,wasSelf:h,isSelf:w,message:Vr({prevName:A,newName:v,isSelf:w,wasSelf:h,cause:N})}});}function f(){c=false;let S=i;i=[];for(let C of S){if(t)return;e.emit(C());}}function P(){if(t)return;let S=e.projection();S&&(!a&&e.firstSyncCompleted()&&(a=true),l(S),u(S),d(S),i.length>0&&!c&&(c=true,queueMicrotask(f)));}let _=e.subscribe(P);return P(),{stop(){t||(t=true,i=[],_());}}}function Wr(e){return tt(e)===null?"lobby":"estimating"}var Sa="https://hnch.dev";function It(){let t=process.env.XDG_CONFIG_HOME||join(homedir(),".config");return join(t,"hnch")}function no(){return join(It(),"config.json")}function Gr(){let e=It();existsSync(e)||mkdirSync(e,{recursive:true});}function Ve(){let e=no();if(!existsSync(e))return {};try{return JSON.parse(readFileSync(e,"utf-8"))}catch{return {}}}function W(e){Gr();let n={...Ve(),...e};writeFileSync(no(),JSON.stringify(n,null,2)+`
|
|
19
|
+
`,"utf-8");}async function xa(e){let t=createInterface({input:process.stdin,output:process.stderr});return new Promise(n=>{t.question(e,o=>{t.close(),n(o.trim());});})}function wa(e){return e.startsWith("wss://")?"https://"+e.slice(6):e.startsWith("ws://")?"http://"+e.slice(5):e}async function le(){let e=Ve(),t=false;if(e.participantId||(e.participantId=randomUUID(),t=true),!e.displayName){let o=await xa("Enter your display name: ");e.displayName=o||`user-${e.participantId.slice(0,6)}`,t=true;}e.relayUrl||(e.relayUrl=Sa,t=true),(!e.avatarColor||je(e.avatarColor)===null)&&(e.avatarColor=sr(e.participantId),t=true),t&&W(e);let n=process.env.HNCH_RELAY_URL||e.relayUrl;return n=wa(n),{participantId:e.participantId,displayName:e.displayName,relayUrl:n,defaultScale:e.defaultScale,defaultSessionName:e.defaultSessionName,defaultPassword:e.defaultPassword,presetOverrides:e.presetOverrides,customScales:e.customScales,avatarColor:e.avatarColor}}function bt(e){Gr();let n={...Ve()};for(let[o,r]of Object.entries(e))r===""?delete n[o]:r!==void 0&&(n[o]=r);writeFileSync(no(),JSON.stringify(n,null,2)+`
|
|
20
|
+
`,"utf-8");}function rn(e){let t=Pe(e);return t===""?{ok:false,message:"Password cannot be empty."}:e.trim().length>Jn?{ok:false,message:`Password is too long (at most ${Jn} characters).`}:{ok:true,password:t}}async function zr(e){let t,n=await hr(e.relayUrl);e.password!==void 0&&Pe(e.password)!==""&&(t=await Qt(e.password,n.uuid),await Gn(e.relayUrl,n.uuid,t));let o=new $e.Doc,r=new Awareness(o),s=Date.now();return Un(o,{roomUuid:n.uuid,createdAt:s,participantId:e.participantId,displayName:e.displayName,defaultScale:e.defaultScale??zt,...e.sessionName!==void 0&&{sessionName:e.sessionName},...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}),r.setLocalStateField(ke,e.participantId),st({doc:o,awareness:r,roomCode:n.code,roomUuid:n.uuid,participantId:e.participantId,relayUrl:e.relayUrl,passwordHash:t,onRejection:e.onRejection})}async function Xr(e){let t=await ce(e.relayUrl,e.roomCode),n;if(t.accessMode==="password"){if(e.password===void 0||Pe(e.password)==="")throw new Error("Room requires a password");n=await Qt(e.password,t.uuid);}let o=new $e.Doc,r=new Awareness(o);return Le(o,{participantId:e.participantId,displayName:e.displayName,joinedAt:Date.now(),...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}),r.setLocalStateField(ke,e.participantId),st({doc:o,awareness:r,roomCode:e.roomCode,roomUuid:t.uuid,participantId:e.participantId,relayUrl:e.relayUrl,passwordHash:n,onRejection:e.onRejection,clearLeftStatusOnSync:true})}function st(e){let{doc:t,awareness:n,participantId:o,relayUrl:r,roomUuid:s}=e,a=new Set,i=new Set,c=new Set,l=false,u=false,d=xr({httpBaseUrl:e.relayUrl,roomUuid:e.roomUuid,doc:t,credentials:{roomCode:e.roomCode,deviceId:o,...e.passwordHash!==void 0&&{passwordHash:e.passwordHash}},awareness:n,WebSocketPolyfill:Ca,onStatusChange(h){a.forEach(w=>w(h));},onRejectionChange(h){h!==null&&(console.error(`Connection rejected: ${h}`),e.onRejection?.(h));},onRepeatRejection(){console.error("Trouble reaching the room \u2014 retrying.");},onSyncedChange(h){l=h,h&&(u=true),i.forEach(w=>w());},...e.clearLeftStatusOnSync===true&&{onSynced:()=>{Tr(t,o);}}}),f=()=>{i.forEach(h=>h());};t.getMap("meta").observeDeep(f),t.getMap("settings").observeDeep(f),t.getMap("participants").observeDeep(f),t.getArray("rounds").observeDeep(f);function P(){return ir(n.getStates())}function _(h){return i.add(h),n.on("change",h),()=>{i.delete(h),n.off("change",h);}}let S=Fr({doc:t,participantId:o,onlineIds:P}),C=false,E={...S,endSession(){let h=S.endSession();return h.applied&&(C=true),h}},T=dr({projection:()=>F(t),onlineIds:P,myId:()=>o,subscribe:_,promote(h){Pr(t,h);}}),A=rr({projection:()=>F(t),onlineIds:P,presenceTrusted:()=>l,selfId:()=>o,subscribe:_,reveal(){E.revealCurrentRound();}}),k=Yr({projection:()=>F(t),onlineIds:P,presenceTrusted:()=>l,firstSyncCompleted:()=>u,endedLocally:()=>C,selfId:o,subscribe:_,emit:h=>{for(let w of c)w(h);}}),v=false;return {doc:t,awareness:n,roomCode:e.roomCode,roomUuid:e.roomUuid,passwordHash:e.passwordHash,commands:E,projection(){return F(t)},current(){return me(F(t))},hasJoined(){return u},isHost(){return F(t).settings.hostParticipantId===o},onlineIds:P,updateRoundDescriptor(h,w){Ln(t,h,w);},updateName(h){Wt(t,{name:h});},updateScale(h){Wt(t,{defaultScale:h});},async updateAccess(h,w){let N=null;if(h==="password"){let b=rn(w??"");if(!b.ok)throw new Error(b.message);N=await Qt(b.password,s);}await Gn(r,s,N),d.updateCredentials({passwordHash:N});},onChange(h){return i.add(h),()=>i.delete(h)},onStatusChange(h){return a.add(h),()=>a.delete(h)},onSessionEvent(h){return c.add(h),()=>{c.delete(h);}},disconnect(){v||(v=true,k.stop(),A.stop(),T.stop(),t.getMap("meta").unobserveDeep(f),t.getMap("settings").unobserveDeep(f),t.getMap("participants").unobserveDeep(f),t.getArray("rounds").unobserveDeep(f),d.disconnect());}}}function Qr(e){let t=qn(e);return t===""?null:t}function Ye(){return join(It(),"last-session.json")}function Aa(e,t){let n=It();mkdirSync(n,{recursive:true,mode:448}),chmodSync(n,448),writeFileSync(e,t,{encoding:"utf-8",mode:384}),chmodSync(e,384);}function ns(){let e=Ye();try{unlinkSync(e);}catch(t){if(t.code!=="ENOENT")throw t}}function ro(){let e=Ye();if(!existsSync(e))return {};try{let t=JSON.parse(readFileSync(e,"utf-8"));return {...Wn(t).entries}}catch{return {}}}function so(e){let t={version:2,entries:e};Aa(Ye(),JSON.stringify(t,null,2)+`
|
|
21
|
+
`);}function an(e){let t=Date.now();if(!existsSync(Ye()))return [];let n;try{n=JSON.parse(readFileSync(Ye(),"utf-8"));}catch{return []}let o=Wn(n),r=lr(o,t),s=Object.values(r.entries);return s.length===0?(ns(),[]):s.toSorted((a,i)=>i.lastSeenAt-a.lastSeenAt)}function Ra(e,t){return e!==void 0?{passwordHash:e}:t!==void 0?{passwordHash:t}:{}}function dn(e){let t=Date.now(),n=ro(),o=n[e.roomUuid];n[e.roomUuid]={roomCode:e.roomCode,roomUuid:e.roomUuid,lastSeenAt:e.lastSeenAt??t,...Ra(e.passwordHash,o?.passwordHash)};let r=Object.keys(n);if(r.length>5){let s=r.toSorted((a,i)=>(n[a]?.lastSeenAt??0)-(n[i]?.lastSeenAt??0)).slice(0,r.length-5);for(let a of s)delete n[a];}so(n);}function At(e){if(!existsSync(Ye()))return;let t=ro();if(delete t[e],Object.keys(t).length===0){ns();return}so(t);}function io(e){if(!existsSync(Ye()))return;let t=ro(),n=t[e];if(!n)return;let{passwordHash:o,...r}=n;t[e]=r,so(t);}async function ao(e){let t=true;try{await e.clearLastSession();}catch(n){t=false,e.logger.error(`Failed to clear cached session: ${n instanceof Error?n.message:String(n)}`);}return t?e.logger.error("Session expired (room no longer exists). Cached session cleared."):e.logger.error("Session expired. Could not delete ~/.config/hnch/last-session.json \u2014 please remove it manually."),e.exit(1)}function Ea(e){return e.isTTY===true&&typeof e.setRawMode=="function"}var ka="\r",Pa=`
|
|
22
|
+
`,Na="\x7F",Da="\b",Oa=" ",Ma="",_a="",Ua="",$a="",La="\x1B";function Ha(e){return e<" "&&e!==Oa}function Ba(e,t){let n=e[t+1];if(n===void 0)return 1;if(n==="O")return Math.min(3,e.length-t);if(n!=="[")return 2;for(let o=t+2;o<e.length;o++){let r=e[o];if(r>="@"&&r<="~")return o-t+1}return e.length-t}async function os(e={}){let t=e.stdin??process.stdin,n=e.stderr??process.stderr,o=e.exit??process.exit;n.write("Password: ");let r=Ea(t)?await Fa(t,n,o):await ja(t);return Pe(r)}function ja(e){return new Promise(t=>{let n=createInterface({input:e}),o=false,r=s=>{o||(o=true,n.close(),t(s));};n.once("line",r),n.once("close",()=>r(""));})}function Fa(e,t,n){return new Promise(o=>{let r="",s=false;e.setRawMode(true),e.resume(),e.setEncoding("utf8");let a=()=>{s=true,e.setRawMode(false),e.pause(),e.removeListener("data",i);},i=c=>{let l=Array.from(c);for(let u=0;u<l.length&&!s;u++){let d=l[u];if(d===Ma&&(a(),t.write(`
|
|
23
|
+
`),n(130)),d===ka||d===Pa){a(),t.write(`
|
|
24
|
+
`),o(r);return}if(d===_a){if(r.length===0){a(),t.write(`
|
|
25
|
+
`),o(r);return}continue}if(d===La){u+=Ba(l,u)-1;continue}if(d===Na||d===Da){r=Array.from(r).slice(0,-1).join("");continue}if(d===Ua){r="";continue}if(d===$a){r=r.replace(/\S*\s*$/u,"");continue}Ha(d)||(r+=d);}};e.on("data",i);})}function cn(){let e=null,t;return {refused:()=>e,note(n){e=n,t?.();},attach(n){t=n,e!==null&&n();}}}function rs(e,t){switch(e){case "wrong-password":return !t.wasIn&&t.typedPassword?{message:"That password is incorrect.",exitCode:1,remembered:"forget-session"}:{message:`Password changed \u2014 rejoin with: hnch join ${t.roomCode} --password`,exitCode:0,remembered:"forget-password"};case "room-full":return {message:`This room is full (max ${Xo} participants).`,exitCode:1,remembered:t.wasIn?"keep":"forget-session"};default:return {message:`The relay refused the connection (${e}).`,exitCode:1,remembered:t.wasIn?"keep":"forget-session"}}}var Va="@xauyxau/hnch";function ln(e){return Cr(e)}function un(e){return `${process.env.HNCH_SHARE_ORIGIN??"https://hnch.dev"}/join?code=${e}`}function fn(e){return `npx ${Va} join ${e}`}function co(e){let t=e.trim();return t===""?void 0:t}function pn(e){return e?{title:e.title??"",ticketId:e.ticketId??"",agendaItemId:e.id}:{title:"",ticketId:"",agendaItemId:void 0}}function ss(e,t,n){return [e,co(t),n]}var Ya={connecting:"yellow",connected:"green",disconnected:"red"};function ds({roomCode:e,sessionName:t,status:n,isHost:o}){let r=t?`${e} \xB7 ${t}`:e;return jsxs(Box,{borderStyle:"single",borderColor:"gray",paddingX:1,justifyContent:"space-between",children:[jsxs(Text,{bold:true,children:["hnch \xB7 ",r]}),jsxs(Box,{gap:2,children:[o&&jsx(Text,{color:"yellow",children:"[host]"}),jsx(Text,{color:Ya[n],children:n})]})]})}function he({items:e,onSelect:t,onClose:n,title:o}){if(e.length===0)return jsxs(Box,{flexDirection:"column",gap:1,children:[o&&jsx(Text,{bold:true,children:o}),jsx(Text,{dimColor:true,children:"(no items)"})]});let r=e.findIndex(i=>!i.disabled),[s,a]=useState(Math.max(r,0));return useInput((i,c)=>{if(c.upArrow)a(l=>{let u=(l-1+e.length)%e.length,d=0;for(;e[u]?.disabled&&d<e.length;)u=(u-1+e.length)%e.length,d++;return u});else if(c.downArrow)a(l=>{let u=(l+1)%e.length,d=0;for(;e[u]?.disabled&&d<e.length;)u=(u+1)%e.length,d++;return u});else if(c.return){let l=e[s];l&&!l.disabled&&t(l.value);}else c.escape&&n?.();}),jsxs(Box,{flexDirection:"column",gap:1,children:[o&&jsx(Text,{bold:true,children:o}),jsx(Box,{flexDirection:"column",children:e.map((i,c)=>{let l=c===s,u=i.disabled??false;return jsxs(Box,{gap:1,children:[jsx(Text,{...l&&{color:"cyan"},dimColor:u,children:l?">":" "}),jsx(Text,{bold:l,dimColor:u,children:i.label}),i.detail&&jsx(Text,{dimColor:true,children:i.detail})]},i.value)})}),jsx(Text,{dimColor:true,children:"\u2191\u2193 select \u23CE confirm esc close"})]})}function Y({value:e,onChange:t,onSubmit:n,onCancel:o,placeholder:r,isActive:s=true,mask:a=false}){useInput((u,d)=>{d.escape?o?.():d.return?n(e):d.backspace||d.delete?t(e.slice(0,-1)):u&&!d.ctrl&&!d.meta&&t(e+u);},{isActive:s});let i=a&&e.length>0?"*".repeat(e.length):e,c=i.length>0?i:r??"",l=e.length===0&&r!==void 0;return jsxs(Text,{children:[jsx(Text,{dimColor:l,children:c}),jsx(Text,{inverse:true,children:" "})]})}function fs({mode:e,password:t,onModeChange:n,onPasswordChange:o,onClose:r}){let[s,a]=useState(e==="open"?0:1),[i,c]=useState(false);return useEffect(()=>{a(e==="open"?0:1);},[e]),useInput((l,u)=>{if(u.leftArrow)a(d=>Math.max(0,d-1));else if(u.rightArrow)a(d=>Math.min(1,d+1));else if(u.return){let d=s===0?"open":"password";d!==e&&n(d),d==="password"&&c(true);}else u.escape&&r?.();},{isActive:!i}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Box,{gap:1,children:["open","password"].map((l,u)=>{let d=u===s,f=l===e,P=l==="open"?"Open":"Password";return jsx(Text,{inverse:d,bold:f,...f&&{color:"cyan"},children:f?`[${P}]`:` ${P} `},l)})}),e==="password"&&jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{children:"Password: "}),jsx(Y,{value:t,onChange:o,onSubmit:()=>c(false),onCancel:()=>c(false),placeholder:"(required to join)",isActive:i,mask:true}),!i&&jsx(Text,{dimColor:true,children:"\u23CE edit \u2190 \u2192 switch mode esc close"}),i&&jsx(Text,{dimColor:true,children:"\u23CE done esc cancel"})]}),e==="open"&&jsx(Text,{dimColor:true,children:"\u2190\u2192 toggle \u23CE confirm esc close"})]})}function gs({scaleId:e,cards:t,disabledIndices:n,onOverrideChange:o,onClose:r}){let s=useMemo(()=>new Set(n),[n]),[a,i]=useState(0),c=l=>{let u=new Set(s);if(u.has(l))u.delete(l);else {if(u.size>=t.length-1)return;u.add(l);}let d=Array.from(u).toSorted((f,P)=>f-P);o(e,d);};return useInput((l,u)=>{u.leftArrow?i(d=>Math.max(0,d-1)):u.rightArrow?i(d=>Math.min(t.length-1,d+1)):l===" "?c(a):(u.return||u.escape)&&r();}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Box,{gap:1,children:t.map((l,u)=>{let d=u===a,f=s.has(u);return jsx(Text,{inverse:d,bold:!f,...!f&&{color:"cyan"},strikethrough:f,dimColor:f,children:l},l)})}),jsx(Text,{dimColor:true,children:" \u2190\u2192 navigate space toggle \u23CE/esc done"})]})}function So({initialName:e="",initialCards:t=[],onSave:n,onCancel:o}){let r=e.length>0,[s,a]=useState(e),[i,c]=useState(t.length>0?t:[""]),[l,u]=useState(0),[d,f]=useState("editing-name"),[P,_]=useState(""),S=()=>{let T=s.trim();if(T.length===0||T.length>40){_("Name must be 1-40 characters");return}a(T),_(""),f("editing-cards");},C=()=>{let T=s.trim();if(T.length===0||T.length>40){_("Name must be 1-40 characters");return}let A=i.map(v=>v.trim()).filter(v=>v.length>0),k=Array.from(new Set(A));if(k.length<2){_("Need at least 2 unique non-empty cards");return}_(""),n(T,k);};return useInput((T,A)=>{if(d==="editing-cards"){if(A.leftArrow)u(k=>Math.max(0,k-1));else if(A.rightArrow)u(k=>{let v=k+1;return v>=i.length&&i.length<25?(c(h=>[...h,""]),v):Math.min(v,i.length-1)});else if(A.return)C();else if(A.escape)o();else if(A.tab)f("editing-name");else if(A.backspace){let k=i[l]||"";if(k.length===0){if(i.length>2){let v=i.filter((h,w)=>w!==l);c(v),u(Math.max(0,l-1));}}else {let v=[...i];v[l]=k.slice(0,-1),c(v);}}else if(T&&!A.ctrl&&!A.meta){let k=i[l]||"";if(k.length<10){let v=[...i];v[l]=k+T,c(v);}}}},{isActive:d==="editing-cards"}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:r?"\u2500\u2500 Edit Custom Scale \u2500\u2500":"\u2500\u2500 Create Custom Scale \u2500\u2500"}),jsxs(Box,{flexDirection:"column",gap:0,children:[jsx(Text,{children:"Name:"}),jsx(Y,{value:s,onChange:a,onSubmit:S,onCancel:o,placeholder:"Scale name",isActive:d==="editing-name"})]}),d==="editing-cards"&&jsxs(Box,{flexDirection:"column",gap:0,children:[jsx(Text,{children:"Cards:"}),jsx(Box,{gap:1,flexWrap:"wrap",children:i.map((T,A)=>{let k=A===l;return jsx(Text,{inverse:k,...!k&&{color:"cyan"},children:T.length>0?T:"\xB7"},A)})})]}),P&&jsx(Text,{color:"red",children:P}),jsx(Text,{dimColor:true,children:d==="editing-name"?"\u23CE next esc cancel":"\u2190\u2192 navigate typing adds card bsp delete \u23CE save tab name esc cancel"})]})}function hn({scales:e,selectedScaleId:t,presetOverrides:n,customScales:o=[],onSelect:r,onOverrideChange:s,onCustomScaleCreate:a,onCustomScaleEdit:i,onCustomScaleDelete:c,onClose:l,showNoneOption:u=false}){let[d,f]=useState(0),[P,_]=useState(null),[S,C]=useState("browsing"),[E,T]=useState(null),[A,k]=useState(null),v=a?[...e,{id:"__create-custom__",cards:[]}]:e,h=v.length;if(useInput((w,N)=>{if(S==="browsing"){if(N.escape){l();return}if(h===0)return;if(N.upArrow)f(b=>(b-1+h)%h);else if(N.downArrow)f(b=>(b+1)%h);else if(N.return){let b=v[d];if(!b)return;if(b.id==="__create-custom__"){C("creating");return}b.id in de?_(P===b.id?null:b.id):r(b.id);}else if(w===" "){let b=v[d];b&&b.id!=="__create-custom__"&&r(b.id);}else if(w==="e"||w==="E"){let b=v[d];i&&b?.id.startsWith("custom-")&&(T(b.id),C("editing"));}else if(w==="d"||w==="D"){let b=v[d];c&&b?.id.startsWith("custom-")&&(k(b.id),C("confirming-delete"));}}else S==="confirming-delete"&&(w==="y"||w==="Y"?(A&&c&&c(A),k(null),C("browsing")):(w==="n"||w==="N"||N.escape)&&(k(null),C("browsing")));},{isActive:S==="browsing"&&P===null||S==="confirming-delete"}),S==="creating")return jsx(So,{onSave:(w,N)=>{a&&a(w,N),C("browsing");},onCancel:()=>C("browsing")});if(S==="editing"&&E){let w=o?.find(b=>b.id===E);if(e.find(b=>b.id===E)&&w)return jsx(So,{initialName:w.label,initialCards:w.cards,onSave:(b,O)=>{i&&i(E,b,O),T(null),C("browsing");},onCancel:()=>{T(null),C("browsing");}})}if(S==="confirming-delete"&&A){let w=v.find(b=>b.id===A),N=w?Fe(w.id,o):"Unknown";return jsxs(Box,{flexDirection:"column",gap:1,children:[jsxs(Text,{children:["Delete ",N,"? "]}),jsx(Text,{children:"[y] yes [n] no esc cancel"})]})}return v.length===0?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{dimColor:true,children:"(no scales available)"}),jsx(Text,{dimColor:true,children:"esc back"})]}):jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Box,{flexDirection:"column",children:v.map((w,N)=>{let b=N===d,O=w.id===t,te=P===w.id,X=w.id in de,Q=w.id==="__create-custom__",V=w.cards.join(", "),J=u&&w.id==="",R=J?"(none)":Q?"[+ Create custom scale]":Fe(w.id,o);return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{...b&&{color:"cyan"},children:b?">":" "}),jsx(Text,{bold:b,children:R}),!J&&!Q&&jsx(Text,{dimColor:true,children:V}),O&&jsx(Text,{color:"cyan",children:"[current]"})]}),te&&!J&&!Q&&jsx(Box,{paddingLeft:2,children:X?jsx(gs,{scaleId:w.id,cards:de[w.id]?.cards??[],disabledIndices:n?.[w.id]??[],onOverrideChange:s,onClose:()=>_(null)}):null})]},w.id||"none")})}),jsx(Text,{dimColor:true,children:(()=>{let w=d<v.length?v[d]:null;return w?.id.startsWith("custom-")?`\u2191\u2193 navigate space select${i?" [e] edit":""}${c?" [d] delete":""} esc back`:w&&w.id in de?"\u2191\u2193 navigate \u23CE customize space select esc back":"\u2191\u2193 navigate \u23CE/space select esc back"})()})]})}function rd(e,t){return t?[...e]:e.filter(n=>n.value==="display-name")}function hs({sessionName:e,displayName:t,currentScale:n,accessMode:o,presetOverrides:r,customScales:s,isHost:a=true,onChangeName:i,onChangeScale:c,onChangeDisplayName:l,onChangeAccess:u,onClose:d}){let[f,P]=useState(r??{}),_=useMemo(()=>nn(f,s),[f,s]),[S,C]=useState("main-menu"),[E,T]=useState(e??""),[A,k]=useState(t),[v,h]=useState(o==="password"?"password":"open"),[w,N]=useState(""),[b,O]=useState(false),te=[{label:"Room name",value:"room-name",detail:`[${e??"(none)"}]`},{label:"Scale",value:"scale",detail:`[${Fe(n.id,s)}]`},{label:"Access",value:"access",detail:`[${o==="open"?"Open":"Password"}]`},{label:"Display name",value:"display-name",detail:`[${t}]`}],X=rd(te,a);function Q(p){!a&&p!=="display-name"||(p==="room-name"?(T(e??""),C("editing-room-name")):p==="scale"?C("picking-scale"):p==="access"?C("picking-access"):p==="display-name"&&(k(t),C("editing-display-name")));}function V(p){let y=p.trim()===""?void 0:p.trim();i(y),C("main-menu");}function J(p){let y=p.trim();y.length>0&&(l(y),process.nextTick(()=>W({displayName:y}))),C("main-menu");}function R(p){let y=_.find(D=>D.id===p);y&&c(y),C("main-menu");}function H(p,y){let D={...f};y.length===0?delete D[p]:D[p]=y,P(D),W({presetOverrides:Object.keys(D).length>0?D:void 0});}async function K(p,y){O(true);try{await u(p,y),h(p),N(p==="password"?y??"":"");}catch(D){console.error(`Failed to update access: ${D}`);}finally{O(false),C("main-menu");}}return S==="main-menu"?jsx(he,{title:"\u2500\u2500 Settings \u2500\u2500",items:X,onSelect:Q,onClose:d}):S==="editing-room-name"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),jsx(Text,{children:"Room name: "}),jsx(Y,{value:E,onChange:T,onSubmit:V,onCancel:()=>C("main-menu"),placeholder:"(leave empty to remove)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]}):S==="editing-display-name"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),jsx(Text,{children:"Display name: "}),jsx(Y,{value:A,onChange:k,onSubmit:J,onCancel:()=>C("main-menu"),placeholder:"(required)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]}):S==="picking-scale"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),jsx(hn,{scales:_,selectedScaleId:n.id,presetOverrides:f,onSelect:R,onOverrideChange:H,onClose:()=>C("main-menu")})]}):S==="picking-access"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),b&&jsx(Text,{dimColor:true,children:"Updating access..."}),!b&&jsx(fs,{mode:v,password:w,onModeChange:p=>{p==="open"&&K("open");},onPasswordChange:N,onClose:()=>C("main-menu")})]}):jsx(Box,{})}function wn({participants:e,onlineIds:t,hostId:n,votes:o,revealed:r,participantId:s}){return jsxs(Box,{flexDirection:"column",children:[jsxs(Text,{bold:true,children:["Participants (",e.length,")"]}),e.map(a=>{let i=t.has(a.id),c=i?"\u25CF":"\u25CB",l=i?"green":"gray",u=a.id===n,d=ge(a)==="viewer",f=a.id===s,P=a.id in o,_=d?" (viewer)":r?o[a.id]?` \u2192 ${o[a.id]}`:"":P?" \u2713":" \xB7",S=f&&!d&&!(r&&o[a.id]);return jsxs(Box,{gap:1,children:[jsx(Text,{color:l,children:c}),jsxs(Text,{children:[a.displayName,u?" (host)":""]}),S?jsx(Text,{color:"cyan",children:"(voter)"}):jsx(Text,{color:d?"gray":P?"green":"gray",children:_})]},a.id)})]})}var sd=[{label:"End session for everyone",value:"end-session",detail:"Disconnects all participants. Cannot be undone."}];function xs({onPick:e,onClose:t}){return jsx(he,{title:"Host Actions",items:sd,onSelect:e,onClose:t})}function Cn({roomCode:e,onPick:t,onClose:n}){let o=[{label:"Copy code",value:"code",detail:ln(e)},{label:"Copy share link",value:"url",detail:un(e)},{label:"Copy npx command",value:"npx",detail:fn(e)}];return jsx(he,{title:"Share",items:o,onSelect:r=>t(r),onClose:n})}function dd(e){let t=Object.fromEntries(e.participants.map(n=>[n.id,n]));return Hr({rounds:e.rounds,participants:t})}async function ws(e,t,n){let o=dd(e);try{await t(o),n("Results copied to clipboard");}catch{n("Clipboard write failed");}}function Cs(e,t){let n=Qn(e,t),o=e.title?` \u2014 ${e.title}`:"",r=e.ticketId?` [${e.ticketId}]`:"",s=e.status==="skipped"?" \u2014 Skipped":" \u2014 Results";return `${n}${o}${r}${s}`}function ys(e,t){let n=Qn(e,t);if(e.status==="skipped"){let d=e.title?` ${e.title}`:"",f=e.ticketId?` [${e.ticketId}]`:"";return `${n}:${d}${f} \u2014 Skipped`}let o=new Map;for(let d of Object.values(e.votes))Z(d)||o.set(d,(o.get(d)??0)+1);let r=[...o.entries()].toSorted((d,f)=>f[1]-d[1]||d[0].localeCompare(f[0])).map(([d,f])=>`${d}\xD7${f}`).join(", "),s=Object.values(e.votes).filter(Z).length,a=s>0?` (${s} abstained)`:"",i=e.title?` ${e.title}`:"",c=e.ticketId?` [${e.ticketId}]`:"",l=rt(e),u=l!==null?` \u2014 ${l}`:"";return `${n}:${i}${c} \u2014 ${r||"(no votes)"}${a}${u}`}function vs({projection:e,onlineIds:t,isHost:n,participantId:o,rounds:r,currentRound:s,settingsOpen:a,onStartRound:i,onNewRound:c,onRevote:l,onOpenSettings:u,onHandoffHost:d,onEndSession:f,onShare:P,shareOpen:_,onSetShareOpen:S,roomCode:C,confirmingQuit:E,myRole:T,onToggleRole:A,roundTitlePromptActive:k,roundTitleInput:v,onRoundTitleChange:h,onRoundTitleSubmit:w,onRoundTitleCancel:N,roundTicketIdPromptActive:b,roundTicketIdInput:O,onRoundTicketIdChange:te,onRoundTicketIdSubmit:X,onRoundTicketIdCancel:Q,descriptorPromptActive:V,descriptorInput:J,onDescriptorChange:R,onDescriptorSubmit:H,onDescriptorCancel:K,onEditDescriptor:p,canExport:y,onExportResults:D,onAgendaAdd:G,agendaAddPromptActive:ue,agendaAddTitleInput:ut,onAgendaAddTitleChange:En,onAgendaAddTitleSubmit:ze,onAgendaAddTitleCancel:_t,agendaAddTicketIdPromptActive:Ie,agendaAddTicketIdInput:kn,onAgendaAddTicketIdChange:Xe,onAgendaAddTicketIdSubmit:Qe,onAgendaAddTicketIdCancel:_e}){let[oe,re]=yn.useState("idle"),[Se,be]=yn.useState(null),[ft,ae]=yn.useState(false),[fe,xe]=yn.useState(false);useEffect(()=>{n||(re("idle"),be(null),ae(false),xe(false));},[n]),useInput(I=>{if(I==="c"||I==="C"){S(true);return}if(I==="w"||I==="W"){A();return}if((I==="x"||I==="X")&&y){D();return}if(n){if(I==="a"||I==="A"){G();return}(I==="e"||I==="E")&&u(),(I==="s"||I==="S")&&i(),(I==="h"||I==="H")&&re("picking"),(I==="m"||I==="M")&&ae(true),s!==null&&mt(s.status)&&((I==="n"||I==="N")&&c(),(I==="v"||I==="V")&&s.status!=="skipped"&&l(),(I==="t"||I==="T")&&p());}},{isActive:!a&&!E&&oe==="idle"&&!k&&!b&&!ft&&!fe&&!_&&!V&&!ue&&!Ie}),useInput((I,pe)=>{I==="y"||I==="Y"?(f(),xe(false)):(I==="n"||I==="N"||pe.escape)&&xe(false);},{isActive:fe});let Ae=e.participants.filter(I=>I.id!==o&&t.has(I.id));useInput(I=>{if(oe==="picking"){let pe=parseInt(I,10);!isNaN(pe)&&pe>=1&&pe<=Ae.length?(be(Ae[pe-1].id),re("confirming")):(I==="Escape"||I==="q"||I==="Q")&&re("idle");}},{isActive:oe==="picking"}),useInput(I=>{oe==="confirming"&&Se&&(I==="y"||I==="Y"?(d(Se),re("idle"),be(null)):(I==="n"||I==="N"||I==="Escape")&&(re("idle"),be(null)));},{isActive:oe==="confirming"});let Ze=r.filter(I=>jt(I.status)),Ue=Ze.length>0,Ut=s!==null?Ze.slice(0,-1):Ze;return ft?jsx(xs,{onPick:I=>{ae(false),I==="end-session"&&xe(true);},onClose:()=>ae(false)}):_?jsx(Cn,{roomCode:C,onPick:I=>{S(false),P(I);},onClose:()=>S(false)}):jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:Ue?"Session":"Waiting for participants..."}),!Ue&&jsx(Text,{dimColor:true,children:"No rounds started yet."}),jsx(wn,{participants:e.participants,onlineIds:t,hostId:e.settings.hostParticipantId,votes:{},revealed:false,participantId:o}),e.agenda.length>0&&jsx(pd,{items:e.agenda,nextPending:Be(e)}),s!==null&&mt(s.status)&&jsx(ld,{projection:e,round:s,rounds:r}),Ut.length>0&&jsxs(Box,{flexDirection:"column",children:[jsx(Text,{dimColor:true,children:"\u2500\u2500 History \u2500\u2500"}),Ut.map(I=>jsx(Text,{dimColor:true,children:ys(I,r)},I.id))]}),oe==="picking"&&Ae.length>0&&jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{children:"Hand off to:"}),Ae.map((I,pe)=>jsxs(Text,{children:["[",pe+1,"] ",I.displayName]},I.id)),jsx(Text,{dimColor:true,children:"[q] Cancel"})]}),oe==="picking"&&Ae.length===0&&jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{dimColor:true,children:"No other online participants"}),jsx(Text,{dimColor:true,children:"[q] Cancel"})]}),oe==="confirming"&&Se&&jsx(Box,{flexDirection:"column",children:jsxs(Text,{children:["Hand off to ",e.participants.find(I=>I.id===Se)?.displayName,"? [y/n]"]})}),k&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Round title (optional, Enter to skip):"}),jsx(Y,{value:v,onChange:h,onSubmit:w,onCancel:N,placeholder:"Enter to skip",isActive:k})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),b&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Ticket ID (optional, Enter to skip):"}),jsx(Y,{value:O,onChange:te,onSubmit:X,onCancel:Q,placeholder:"e.g. PROJ-1234",isActive:b})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),V&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Edit round title:"}),jsx(Y,{value:J,onChange:R,onSubmit:H,onCancel:K,placeholder:"Enter to save",isActive:V})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel \xB7 empty submit cancels"})]}),fe&&jsxs(Box,{children:[jsx(Text,{color:"red",children:"End session for everyone? This cannot be undone. "}),jsx(Text,{dimColor:true,children:"y/n [Esc] Cancel"})]}),ue&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Agenda title (optional, Enter to skip):"}),jsx(Y,{value:ut,onChange:En,onSubmit:ze,onCancel:_t,placeholder:"Enter to skip",isActive:ue})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),Ie&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Agenda ticket ID (optional, Enter to skip):"}),jsx(Y,{value:kn,onChange:Xe,onSubmit:Qe,onCancel:_e,placeholder:"e.g. PROJ-1234",isActive:Ie})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),oe==="idle"&&!k&&!b&&!V&&!fe&&!ue&&!Ie&&jsxs(Box,{gap:2,children:[n?jsx(Fragment,{children:s!==null&&mt(s.status)?jsxs(Fragment,{children:[s.status!=="skipped"&&jsx(Text,{color:"yellow",children:"[v] Revote"}),jsx(Text,{color:"yellow",children:"[n] Next"}),jsx(Text,{color:"yellow",children:"[t] Edit title"}),jsx(Text,{color:"yellow",children:"[h] Handoff"}),jsx(Text,{color:"yellow",children:"[e] Settings"}),jsx(Text,{color:"yellow",children:"[c] Share"}),y&&jsx(Text,{color:"yellow",children:"[x] Export"}),jsxs(Text,{color:"yellow",children:["[w] ",T==="viewer"?"Vote":"Observe"]}),jsx(Text,{color:"yellow",children:"[m] Menu"})]}):jsxs(Fragment,{children:[jsx(Text,{color:"yellow",children:"[s] Start round"}),jsx(Text,{color:"yellow",children:"[a] Agenda"}),jsx(Text,{color:"yellow",children:"[h] Handoff"}),jsx(Text,{color:"yellow",children:"[e] Settings"}),jsx(Text,{color:"yellow",children:"[c] Share"}),y&&jsx(Text,{color:"yellow",children:"[x] Export"}),jsxs(Text,{color:"yellow",children:["[w] ",T==="viewer"?"Vote":"Observe"]}),jsx(Text,{color:"yellow",children:"[m] Menu"})]})}):jsxs(Fragment,{children:[jsx(Text,{dimColor:true,children:"Waiting for host to start a round..."}),jsx(Text,{children:"[c] Share"}),y&&jsx(Text,{color:"yellow",children:"[x] Export"}),jsxs(Text,{color:"yellow",children:["[w] ",T==="viewer"?"Vote":"Observe"]})]}),jsx(Text,{children:"[q] Quit"})]})]})}function ld({projection:e,round:t,rounds:n}){let o=Cs(t,n);if(t.status==="skipped")return jsx(Box,{flexDirection:"column",gap:1,children:jsx(Text,{bold:true,children:o})});let r=en(Zt(t)),s=new Map(e.participants.map(d=>[d.id,d.displayName])),a=rt(t),i=Object.entries(t.votes),c=i.filter(([,d])=>!Z(d)),l=i.filter(([,d])=>Z(d)).map(([d])=>d),u=c[0]?.[1];return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:o}),jn(t)&&u!==void 0&&jsxs(Text,{bold:true,color:"green",children:["Consensus! Everyone voted ",u]}),jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:2,children:[jsx(Text,{bold:true,underline:true,children:"Name".padEnd(20)}),jsx(Text,{bold:true,underline:true,children:"Estimate".padEnd(10)})]}),c.map(([d,f])=>jsxs(Box,{gap:2,children:[jsx(Text,{children:(s.get(d)??d).padEnd(20)}),jsx(Text,{color:"cyan",bold:true,children:f.padEnd(10)})]},d)),l.map(d=>jsxs(Box,{gap:2,children:[jsx(Text,{dimColor:true,children:(s.get(d)??d).padEnd(20)}),jsx(Text,{dimColor:true,children:"(abstained)".padEnd(10)})]},d)),e.participants.filter(d=>!(d.id in t.votes)).map(d=>jsxs(Box,{gap:2,children:[jsx(Text,{dimColor:true,children:d.displayName.padEnd(20)}),jsx(Text,{dimColor:true,children:"(no vote)".padEnd(10)})]},d.id))]}),(r!==null||a!==null)&&jsxs(Box,{gap:2,children:[r?.kind==="numeric"&&jsxs(Text,{children:["Avg: ",jsx(Text,{bold:true,children:r.mean})]}),r?.kind==="numeric"&&jsxs(Text,{children:["Med: ",jsx(Text,{bold:true,children:r.median})]}),r?.kind==="categorical"&&r.mode!==null&&jsxs(Text,{children:["Most common: ",jsx(Text,{bold:true,children:r.mode})]}),r!==null&&jsxs(Text,{children:["Spread: ",jsx(Text,{bold:true,children:r.spread})]}),a!==null&&jsxs(Text,{dimColor:true,children:["\u23F1 ",a]})]})]})}var ud={pending:"\u2022",consumed:"\u2713",skipped:"~",cancelled:"\u2717"},fd={consumed:"green",skipped:"yellow",cancelled:"red"};function pd({items:e,nextPending:t}){let n=e.filter(o=>o.state!=="cancelled");return jsxs(Box,{flexDirection:"column",children:[jsx(Text,{dimColor:true,children:"\u2500\u2500 Agenda \u2500\u2500"}),n.map(o=>{let r=ud[o.state]??"?",s=fd[o.state],a=t!==null&&o.id===t.id,i=[o.ticketId?`[${o.ticketId}]`:"",o.title??""].filter(Boolean).join(" ").trim()||o.id;return jsxs(Box,{gap:1,children:[s!==void 0?jsx(Text,{color:s,children:r}):jsx(Text,{children:r}),s!==void 0?jsx(Text,{color:s,children:i}):jsx(Text,{children:i}),a&&jsx(Text,{color:"cyan",children:"(next)"})]},o.id)}),n.length===0&&jsx(Text,{dimColor:true,children:"No pending items."})]})}function As({scale:e,selected:t,onToggleCurrentVote:n,onClearCurrentVote:o,disabled:r}){let[s,a]=useState(0);return useInput((i,c)=>{r||(c.leftArrow?a(l=>Math.max(0,l-1)):c.rightArrow?a(l=>Math.min(e.cards.length-1,l+1)):c.return?n(e.cards[s]):(c.backspace||c.delete)&&o());}),jsxs(Box,{flexDirection:"column",gap:0,children:[jsx(Box,{gap:1,children:e.cards.map((i,c)=>{let l=c===s,u=i===t;return jsx(Text,{inverse:l,bold:u,...u&&{color:"cyan"},children:u?`[${i}]`:` ${i} `},i)})}),jsx(Text,{dimColor:true,children:" \u2190\u2192 navigate \u23CE select \u232B clear"})]})}function Rs({projection:e,round:t,onlineIds:n,isHost:o,myId:r,myRole:s,elapsedMs:a,roomCode:i,shareOpen:c,settingsOpen:l,onToggleCurrentVote:u,onClearCurrentVote:d,onReveal:f,onSkip:P,onDiscard:_,onToggleRole:S,onShare:C,onSetShareOpen:E,onOpenSettings:T,confirmingQuit:A}){let k=t.votes[r],v=k!==void 0&&Z(k);if(useInput(O=>{if(O==="e"||O==="E"){T();return}if(O==="c"||O==="C"){E(true);return}if(s==="voter"&&(O==="a"||O==="A")){u(Ht);return}o&&(O==="r"||O==="R")&&f(),o&&(O==="s"||O==="S")&&P(),o&&(O==="d"||O==="D")&&_(),(O==="w"||O==="W")&&S();},{isActive:!A&&!l&&!c}),c)return jsx(Cn,{roomCode:i,onPick:O=>{E(false),C(O);},onClose:()=>E(false)});let h=k,w=vt(t,e.rounds),N=t.title?` \u2014 ${t.title}`:"",b=t.ticketId?` [${t.ticketId}]`:"";return jsxs(Box,{flexDirection:"column",gap:1,children:[jsxs(Box,{gap:2,children:[jsxs(Text,{bold:true,children:["Round ",w,N,b]}),a!==void 0&&jsxs(Text,{dimColor:true,children:["\u23F1 ",Xt(a)]})]}),jsxs(Box,{gap:4,children:[jsx(wn,{participants:e.participants,onlineIds:n,hostId:e.settings.hostParticipantId,votes:t.votes,revealed:false}),s==="viewer"?jsx(Box,{flexDirection:"column",children:jsx(Text,{dimColor:true,children:"You're observing"})}):jsxs(Box,{flexDirection:"column",gap:1,children:[v&&jsx(Text,{dimColor:true,children:"(abstaining this round \u2014 press [a] to vote)"}),jsx(As,{scale:t.scale,selected:v?void 0:h,onToggleCurrentVote:u,onClearCurrentVote:d,disabled:A||v})]})]}),jsxs(Box,{gap:2,children:[o&&jsx(Text,{color:"yellow",children:"[r] Reveal"}),o&&jsx(Text,{color:"yellow",children:"[s] Skip"}),o&&jsx(Text,{color:"yellow",children:"[d] Discard"}),s==="voter"&&jsxs(Text,{color:"yellow",children:["[a] ",v?"Vote":"Abstain"]}),jsxs(Text,{color:"yellow",children:["[w] ",s==="viewer"?"Vote":"Observe"]}),jsx(Text,{children:"[e] Settings"}),jsx(Text,{children:"[c] Share"}),jsx(Text,{children:"[q] Quit"})]})]})}var yd=3e3;function Nt(e=yd){let[t,n]=useState(null),o=useRef(null),r=useCallback(()=>{o.current!==null&&(clearTimeout(o.current),o.current=null);},[]),s=useCallback(i=>{r(),n(i),o.current=setTimeout(()=>{n(null),o.current=null;},e);},[r,e]),a=useCallback(()=>{r(),n(null);},[r]);return useEffect(()=>()=>{r();},[r]),{notice:t,show:s,dismiss:a}}var bd={"not-host":"only the current host can hand off","not-found":"that participant is not in the session","not-online":"that participant is offline","self-target":"you cannot hand off to yourself"};function bn({session:e,participantId:t,displayName:n,accessMode:o,presetOverrides:r,customScales:s}){let{exit:a}=useApp(),[i,c]=useState(e.projection()),[l,u]=useState("connecting"),[d,f]=useState(e.onlineIds()),[P,_]=useState(),[S,C]=useState(false),[E,T]=useState(o==="password"?"password":"open"),[A,k]=useState(n),[v,h]=useState(false),[w,N]=useState(false),[b,O]=useState(""),[te,X]=useState(false),[Q,V]=useState(""),[J,R]=useState(),[H,K]=useState(false),[p,y]=useState(""),[D,G]=useState(null),[ue,ut]=useState(false),[En,ze]=useState(""),[_t,Ie]=useState(false),[kn,Xe]=useState(""),[Qe,_e]=useState(),[oe,re]=useState(),Se=Nt(3e3),[be,ft]=useState(false),ae=Nt(3e3),fe=Nt(3e3),xe=Nt(3e3);useEffect(()=>{let x=e.onChange(()=>{c(e.projection()),f(e.onlineIds());}),L=e.onStatusChange(u),Re=e.onSessionEvent(Lt=>{Lt.kind==="host-changed"&&Se.show(Lt.message);}),$t=setInterval(()=>{f(e.onlineIds());let Lt=e.projection(),Nn=me(Lt);Nn?.timerStartedAt!==void 0&&et(Nn.status)?_(Date.now()-Nn.timerStartedAt):_(void 0);},1e3);return ()=>{x(),L(),Re(),clearInterval($t);}},[e,Se.show]),useInput(x=>{(x==="q"||x==="Q")&&h(true);},{isActive:!S&&!v&&!w&&!te&&!H&&!be&&!ue&&!_t}),useInput((x,L)=>{x==="y"||x==="Y"?(e.disconnect(),a()):(x==="n"||x==="N"||L.escape)&&h(false);},{isActive:v});let Ae=Wr(i),Ze=me(i),Ue=i.settings.hostParticipantId===t,Ut=i.participants.find(x=>x.id===t),I=ge(Ut??{}),pe=useCallback(()=>{let x=pn(Be(i));O(x.title),re(x.agendaItemId),N(true);},[i]),Bs=useCallback(x=>{N(false),O(""),R(co(x));let L=pn(Be(i));V(L.ticketId),X(true);},[i]),js=useCallback(()=>{N(false),O(""),R(void 0),re(void 0);},[]),Fs=useCallback(x=>{X(false),V("");let[L,Re,$t]=ss(J,x,oe);e.commands.startRound({...L!==void 0&&{title:L},...Re!==void 0&&{ticketId:Re},...$t!==void 0&&{agendaItemId:$t}}),R(void 0),re(void 0);},[e,J,oe]),Vs=useCallback(()=>{X(false),V(""),R(void 0),re(void 0);},[]),Ys=useCallback(()=>{let x=e.current();!x||x.status!=="revealed"||(G(x.id),y(x.title??""),K(true));},[e]),Ws=useCallback(x=>{let L=D;if(K(false),G(null),!L)return;let Re=x.trim();Re!==""&&e.updateRoundDescriptor(L,{title:Re});},[e,D]),Js=useCallback(()=>{K(false),G(null);},[]),Ks=useCallback(x=>{e.commands.toggleCurrentVote(x);},[e]),Gs=useCallback(()=>{e.commands.clearCurrentVote();},[e]),qs=useCallback(()=>{e.commands.revealCurrentRound();},[e]),zs=useCallback(()=>{e.commands.skipCurrentRound();},[e]),Xs=useCallback(()=>{e.commands.discardCurrentRound();},[e]),Qs=useCallback(()=>{let x=pn(Be(i));O(x.title),re(x.agendaItemId),N(true);},[i]),Zs=useCallback(()=>{let x=e.current();x&&e.commands.startRound({parentRoundId:x.id,...x.title!==void 0&&{title:x.title},...x.description!==void 0&&{description:x.description},...x.ticketId!==void 0&&{ticketId:x.ticketId},...x.agendaItemId!==void 0&&{agendaItemId:x.agendaItemId}});},[e]),Ao=useCallback(()=>{e.commands.toggleRole();},[e]),ei=useCallback(x=>{e.updateName(x);},[e]),ti=useCallback(x=>{e.updateScale(x);},[e]),ni=useCallback(x=>{e.commands.rename(x),k(x);},[e]),oi=useCallback(async(x,L)=>{await e.updateAccess(x,L),T(x);},[e]),ri=useCallback(x=>{let L=e.commands.handoffHost(x);L.applied||console.error(`Handoff failed: ${bd[L.reason]}`);},[e]),Ro=useCallback(()=>{C(true);},[]),si=useCallback(()=>{C(false);},[]),ii=useCallback(()=>{e.commands.endSession();},[e]),To=useCallback(async x=>{let L=x==="code"?ln(e.roomCode):x==="url"?un(e.roomCode):fn(e.roomCode);try{await Es.write(L),ae.show("Copied!");}catch{ae.show(`Copy failed \u2014 ${L}`);}},[e.roomCode,ae]),Pn=i.rounds.filter(x=>jt(x.status)),ai=Pn.length>0?Pn.at(-1):null,di=Pn.length>0,ci=useCallback(()=>ws(i,x=>Es.write(x),fe.show),[i,fe.show]),li=useCallback(()=>{ze(""),ut(true);},[]),ui=useCallback(x=>{ut(false),ze("");let L=x.trim()===""?void 0:x.trim();_e(L),Xe(""),Ie(true);},[]),fi=useCallback(()=>{ut(false),ze(""),_e(void 0);},[]),pi=useCallback(x=>{Ie(false),Xe("");let L=x.trim()===""?void 0:x.trim();if(!Qe&&!L){_e(void 0);return}if(!nt(e.doc,{...Qe!==void 0&&{title:Qe},...L!==void 0&&{ticketId:L}}).applied){xe.show("Add failed \u2014 an agenda item needs a title or a ticket id");return}_e(void 0);},[e.doc,Qe,xe]),mi=useCallback(()=>{Ie(false),Xe(""),_e(void 0);},[]);return jsxs(Box,{flexDirection:"column",children:[jsx(ds,{roomCode:e.roomCode,sessionName:i.settings.name,status:l,isHost:Ue}),Se.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:"yellow",children:Se.notice})}),ae.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:ae.notice.startsWith("Copy failed")?"red":"green",children:ae.notice})}),fe.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:fe.notice.startsWith("Clipboard write failed")?"red":"green",children:fe.notice})}),xe.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:"red",children:xe.notice})}),S?jsx(hs,{sessionName:i.settings.name,displayName:A,currentScale:i.settings.defaultScale,accessMode:E,presetOverrides:r,customScales:s,isHost:Ue,onChangeName:ei,onChangeScale:ti,onChangeDisplayName:ni,onChangeAccess:oi,onClose:si}):Ae==="lobby"?jsx(vs,{projection:i,onlineIds:d,isHost:Ue,participantId:t,rounds:i.rounds,currentRound:ai,settingsOpen:S,onStartRound:pe,onNewRound:Qs,roundTitlePromptActive:w,roundTitleInput:b,onRoundTitleChange:O,onRoundTitleSubmit:Bs,onRoundTitleCancel:js,roundTicketIdPromptActive:te,roundTicketIdInput:Q,onRoundTicketIdChange:V,onRoundTicketIdSubmit:Fs,onRoundTicketIdCancel:Vs,onRevote:Zs,onOpenSettings:Ro,onHandoffHost:ri,onEndSession:ii,onShare:To,shareOpen:be,onSetShareOpen:ft,roomCode:e.roomCode,confirmingQuit:v,myRole:I,onToggleRole:Ao,descriptorPromptActive:H,descriptorInput:p,onDescriptorChange:y,onDescriptorSubmit:Ws,onDescriptorCancel:Js,onEditDescriptor:Ys,canExport:di,onExportResults:ci,onAgendaAdd:li,agendaAddPromptActive:ue,agendaAddTitleInput:En,onAgendaAddTitleChange:ze,onAgendaAddTitleSubmit:ui,onAgendaAddTitleCancel:fi,agendaAddTicketIdPromptActive:_t,agendaAddTicketIdInput:kn,onAgendaAddTicketIdChange:Xe,onAgendaAddTicketIdSubmit:pi,onAgendaAddTicketIdCancel:mi}):Ae==="estimating"&&Ze?jsx(Rs,{projection:i,round:Ze,onlineIds:d,isHost:Ue,myId:t,myRole:I,elapsedMs:P,onToggleCurrentVote:Ks,onClearCurrentVote:Gs,onReveal:qs,onSkip:zs,onDiscard:Xs,onToggleRole:Ao,onShare:To,onSetShareOpen:ft,shareOpen:be,settingsOpen:S,onOpenSettings:Ro,roomCode:e.roomCode,confirmingQuit:v}):null,v&&jsx(Box,{children:jsx(Text,{dimColor:true,children:"Leave session? y/n"})})]})}function ks({presetOverrides:e,customScales:t}){let{exit:n}=useApp(),[o,r]=useState("main-menu"),[s,a]=useState(Ve()),[i,c]=useState(s.displayName??""),[l,u]=useState(s.relayUrl??""),[d,f]=useState(s.defaultSessionName??""),[P,_]=useState(s.avatarColor?.startsWith("#")?s.avatarColor:""),[S,C]=useState(t??[]),[E,T]=useState(e??{});useInput(p=>{(p==="q"||p==="Q")&&n();},{isActive:o==="main-menu"});let A=useMemo(()=>nn(E,S),[E,S]),k=s.defaultScale,v=k?A.find(p=>p.id===k):void 0,h=[{label:"Display name",value:"display-name",detail:`[${s.displayName??"(none)"}]`},{label:"Relay URL",value:"relay-url",detail:`[${s.relayUrl??"(none)"}]`},{label:"Default scale",value:"default-scale",detail:`[${v?Fe(v.id,S):"(none)"}]`},{label:"Default session name",value:"default-session-name",detail:`[${s.defaultSessionName??"(none)"}]`},{label:"Default password",value:"default-password",detail:`[${s.defaultPassword?"on":"off"}]`},{label:"Avatar color",value:"avatar-color",detail:`[${Pd(s.avatarColor)}]`}];function w(p){p==="display-name"?(c(s.displayName??""),r("editing-display-name")):p==="relay-url"?(u(s.relayUrl??""),r("editing-relay-url")):p==="default-scale"?r("picking-scale"):p==="default-session-name"?(f(s.defaultSessionName??""),r("editing-session-name")):p==="default-password"?r("picking-default-password"):p==="avatar-color"&&r("picking-avatar-color");}function N(p){if(p==="custom-hex"){_(s.avatarColor?.startsWith("#")?s.avatarColor:""),r("editing-avatar-hex");return}if(je(p)===null){r("main-menu");return}a({...s,avatarColor:p}),W({avatarColor:p}),r("main-menu");}function b(p){let y=p.trim();if(y.length===0){r("picking-avatar-color");return}let D=y.startsWith("#")?y.toLowerCase():`#${y.toLowerCase()}`;je(D)!==null&&(a({...s,avatarColor:D}),W({avatarColor:D}),r("main-menu"));}function O(p){let y=p.trim();if(y.length>0){let D={...s,displayName:y};a(D),W({displayName:y});}r("main-menu");}function te(p){let y=p.trim();if(y.length>0){let D={...s,relayUrl:y};a(D),W({relayUrl:y});}r("main-menu");}function X(p){let y=p.trim(),D=y.length>0?{...s,defaultSessionName:y}:{...s};y.length===0?(delete D.defaultSessionName,a(D),bt({defaultSessionName:""})):(a(D),W({defaultSessionName:y})),r("main-menu");}function Q(p){let y=p.length>0?{...s,defaultScale:p}:{...s};p.length===0?(delete y.defaultScale,a(y),bt({defaultScale:""})):(a(y),W({defaultScale:p})),r("main-menu");}function V(p,y){let D={...E};y.length===0?delete D[p]:D[p]=y,T(D),W({presetOverrides:Object.keys(D).length>0?D:void 0});}function J(p){let y=p==="on",D={...s,defaultPassword:y};a(D),W({defaultPassword:y}),r("main-menu");}function R(p,y){let D=`custom-${randomUUID()}`,G=[...S,{id:D,label:p,cards:y}];C(G),a({...s,customScales:G}),W({customScales:G});}function H(p,y,D){let G=S.map(ue=>ue.id===p?{id:p,label:y,cards:D}:ue);C(G),a({...s,customScales:G}),W({customScales:G});}function K(p){let y=S.filter(G=>G.id!==p);C(y);let D={...s,customScales:y};s.defaultScale===p?(D.defaultScale="fibonacci",W({customScales:y,defaultScale:"fibonacci"})):W({customScales:y}),a(D);}if(o==="main-menu")return jsx(he,{title:"\u2500\u2500 Config Settings \u2500\u2500",items:h,onSelect:w,onClose:()=>n()});if(o==="editing-display-name")return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(Text,{children:"Display name: "}),jsx(Y,{value:i,onChange:c,onSubmit:O,onCancel:()=>r("main-menu"),placeholder:"(required)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]});if(o==="editing-relay-url")return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(Text,{children:"Relay URL: "}),jsx(Y,{value:l,onChange:u,onSubmit:te,onCancel:()=>r("main-menu"),placeholder:"(required)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]});if(o==="editing-session-name")return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(Text,{children:"Default session name: "}),jsx(Y,{value:d,onChange:f,onSubmit:X,onCancel:()=>r("main-menu"),placeholder:"(leave empty to clear)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]});if(o==="picking-scale"){let p=[{id:"",cards:[]},...A];return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(hn,{scales:p,selectedScaleId:k??"",presetOverrides:E,customScales:S,onSelect:Q,onOverrideChange:V,onCustomScaleCreate:R,onCustomScaleEdit:H,onCustomScaleDelete:K,onClose:()=>r("main-menu"),showNoneOption:true})]})}if(o==="picking-avatar-color"){let p=wt.map(y=>({label:ot[y].label,value:y,detail:s.avatarColor===y?"[current]":ot[y].base}));return p.push({label:"Custom hex\u2026",value:"custom-hex",detail:s.avatarColor?.startsWith("#")?`[${s.avatarColor}]`:void 0}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(he,{title:"Avatar color:",items:p,onSelect:N,onClose:()=>r("main-menu")})]})}if(o==="editing-avatar-hex")return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(Text,{children:"Custom hex color: "}),jsx(Y,{value:P,onChange:_,onSubmit:b,onCancel:()=>r("picking-avatar-color"),placeholder:"#rrggbb",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]});if(o==="picking-default-password"){let p=[{label:"On",value:"on",detail:s.defaultPassword?"[current]":void 0},{label:"Off",value:"off",detail:s.defaultPassword?void 0:"[current]"}];return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(he,{title:"Default password:",items:p,onSelect:J,onClose:()=>r("main-menu")})]})}return jsx(Box,{})}function Pd(e){return e?e.startsWith("#")?e:wt.includes(e)?ot[e].label:e:"(auto)"}var Dd={pending:"\u2022",consumed:"\u2713",skipped:"~",cancelled:"\u2717"};function Od(e){let t=Dd[e.state]??"?",n=[];e.ticketId&&n.push(`[${e.ticketId}]`),e.title&&n.push(e.title);let o=n.join(" ")||e.id;return `${t} ${o}`}function An(e){switch(e){case "not-found":return "no agenda item with that id";case "not-pending":return "the item is no longer pending \u2014 a peer may have skipped, cancelled or estimated it";case "invalid-fields":return "an agenda item needs at least one of --title or --ticket"}}async function Ot(e){let t=new $e.Doc,n=new Awareness(t);Le(t,{participantId:e.participantId,displayName:e.displayName,joinedAt:Date.now()}),n.setLocalStateField(ke,e.participantId);let o=st({doc:t,awareness:n,roomCode:e.roomCode,roomUuid:e.roomUuid,participantId:e.participantId,relayUrl:e.relayUrl,...e.passwordHash!==void 0&&{passwordHash:e.passwordHash}});return await new Promise(r=>{let s=setTimeout(r,2e3),a=o.onStatusChange(i=>{i==="connected"&&setTimeout(()=>{clearTimeout(s),a(),r();},200);});}),{doc:t,disconnect:()=>o.disconnect()}}async function Mt(){let e=an();e.length===0&&(console.error("No active session. Join a room first with: hnch join <code>"),process.exit(1));let t=e[0];return {roomCode:t.roomCode,roomUuid:t.roomUuid,...t.passwordHash!==void 0&&{passwordHash:t.passwordHash}}}async function Ns(e){!e.title?.trim()&&!e.ticket?.trim()&&(console.error("At least one of --title or --ticket is required"),process.exit(1));let t=await le(),n=await Mt();try{await ce(t.relayUrl,n.roomCode);}catch{console.error(`Room ${n.roomCode} not found on relay \u2014 session may have expired.`),process.exit(1);}let{doc:o,disconnect:r}=await Ot({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{let s=nt(o,{...e.title?.trim()?{title:e.title.trim()}:{},...e.ticket?.trim()?{ticketId:e.ticket.trim()}:{},...e.description?.trim()?{description:e.description.trim()}:{}});s.applied||(console.error(`Add failed: ${An(s.reason)}`),process.exit(1)),await new Promise(a=>{setTimeout(a,300);}),console.log(`Added agenda item: ${s.id}`);}finally{r();}}async function Ds(){let e=await le(),t=await Mt();try{await ce(e.relayUrl,t.roomCode);}catch{console.error(`Room ${t.roomCode} not found on relay \u2014 session may have expired.`),process.exit(1);}let{doc:n,disconnect:o}=await Ot({relayUrl:e.relayUrl,participantId:e.participantId,displayName:e.displayName,roomCode:t.roomCode,roomUuid:t.roomUuid,...t.passwordHash!==void 0&&{passwordHash:t.passwordHash}});try{let s=F(n).agenda;if(s.length===0){console.log("No agenda items.");return}s.forEach((a,i)=>{console.log(`${String(i+1).padStart(2)}. ${Od(a)}`);});}finally{o();}}async function Os(e){let t=await le(),n=await Mt();try{await ce(t.relayUrl,n.roomCode);}catch{console.error(`Room ${n.roomCode} not found on relay \u2014 session may have expired.`),process.exit(1);}let{doc:o,disconnect:r}=await Ot({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{let s=Kt(o,e.id);s.applied||(console.error(`Skip failed: ${An(s.reason)}`),process.exit(1)),await new Promise(a=>{setTimeout(a,300);}),console.log(`Skipped agenda item: ${e.id}`);}finally{r();}}async function Ms(e){let t=await le(),n=await Mt();try{await ce(t.relayUrl,n.roomCode);}catch{console.error(`Room ${n.roomCode} not found on relay \u2014 session may have expired.`),process.exit(1);}let{doc:o,disconnect:r}=await Ot({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{let s=Gt(o,e.id);s.applied||(console.error(`Cancel failed: ${An(s.reason)}`),process.exit(1)),await new Promise(a=>{setTimeout(a,300);}),console.log(`Cancelled agenda item: ${e.id}`);}finally{r();}}async function _s(e){let t=await le(),n=await Mt();try{await ce(t.relayUrl,n.roomCode);}catch{console.error(`Room ${n.roomCode} not found on relay \u2014 session may have expired.`),process.exit(1);}let{doc:o,disconnect:r}=await Ot({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{let s=qt(o,e.id,e.before,e.after);s.applied||(console.error(`Move failed: ${An(s.reason)}`),process.exit(1)),await new Promise(a=>{setTimeout(a,300);}),console.log(`Reordered agenda item: ${e.id}`);}finally{r();}}async function vo(){let e=await os(),t=rn(e);return t.ok||(console.error(t.message),process.exit(1)),t.password}function Io(e,t,n){let o=rs(e,{roomCode:t.roomCode,...n});o.remembered==="forget-password"&&io(t.roomUuid),o.remembered==="forget-session"&&At(t.roomUuid),console.error(o.message),t.disconnect(),process.exit(o.exitCode);}function lt(e){try{At(e);}catch(t){console.error(`Failed to clear cached session: ${t instanceof Error?t.message:String(t)}`);}}function bo(e){ao({clearLastSession:()=>{e!==void 0&&At(e);},logger:console,exit:process.exit});}async function $d(e){let t=await le(),n=e.scale??t.defaultScale??"fibonacci",o=e.name??t.defaultSessionName,r=e.password??t.defaultPassword??false,s;r&&(s=await vo());let a=tn(n,t.presetOverrides,t.customScales);if(!a){let f=Object.keys(de).join(", ");console.error(`Unknown or fully-disabled scale: "${n}". Builtin IDs: ${f}`),process.exit(1);}let i=cn(),c,l=await zr({participantId:t.participantId,displayName:t.displayName,relayUrl:t.relayUrl,sessionName:o,password:s,defaultScale:a,...t.avatarColor!==void 0&&{avatarColor:t.avatarColor},onRejection(f){f==="unknown-room"?bo(c):i.note(f);}});c=l.roomUuid,dn({roomCode:l.roomCode,roomUuid:l.roomUuid,lastSeenAt:Date.now(),...l.passwordHash!==void 0&&{passwordHash:l.passwordHash}}),console.error(`Room created: ${l.roomCode}`),console.error(`Share: hnch join ${l.roomCode}`),console.error("");let u=render(yn.createElement(bn,{session:l,participantId:t.participantId,displayName:t.displayName,accessMode:s?"password":"open",presetOverrides:t.presetOverrides,customScales:t.customScales}));i.attach(u.unmount),l.onSessionEvent(f=>{f.kind!=="host-changed"&&(console.error(f.message),u.unmount(),lt(l.roomUuid),l.disconnect(),process.exit(0));}),await u.waitUntilExit();let d=i.refused();d!==null&&Io(d,l,{wasIn:true,typedPassword:s!==void 0}),l.disconnect(),lt(l.roomUuid),process.exit(0);}async function Ld(e){let t=await le(),n=Qr(e.code);n===null&&(console.error("invalid room code"),process.exit(1));let o;e.password&&(o=await vo());let r=await ce(t.relayUrl,n),s;r.accessMode==="password"&&!e.password?s=await vo():e.password&&(s=o);let a=cn(),i=await Xr({participantId:t.participantId,displayName:t.displayName,relayUrl:t.relayUrl,roomCode:n,password:s,...t.avatarColor!==void 0&&{avatarColor:t.avatarColor},onRejection(u){u==="unknown-room"?bo(r.uuid):a.note(u);}});dn({roomCode:i.roomCode,roomUuid:i.roomUuid,lastSeenAt:Date.now(),...i.passwordHash!==void 0&&{passwordHash:i.passwordHash}}),console.error(`Joined room: ${i.roomCode}`),console.error("");let c=render(yn.createElement(bn,{session:i,participantId:t.participantId,displayName:t.displayName,accessMode:r.accessMode,presetOverrides:t.presetOverrides,customScales:t.customScales}));a.attach(c.unmount),i.onSessionEvent(u=>{u.kind!=="host-changed"&&(console.error(u.message),c.unmount(),lt(i.roomUuid),i.disconnect(),process.exit(0));}),await c.waitUntilExit();let l=a.refused();l!==null&&Io(l,i,{wasIn:i.hasJoined(),typedPassword:s!==void 0}),i.disconnect(),lt(i.roomUuid),process.exit(0);}function Hd(e,t=Date.now()){let n=t-e,o=Math.floor(n/6e4);return o<60?`${o}m ago`:`${Math.floor(o/60)}h ago`}async function Bd(e){return new Promise((t,n)=>{let o=createInterface({input:process.stdin,output:process.stderr}),r=()=>{process.stderr.write(`Select [1-${e}]: `),o.question("",s=>{let a=parseInt(s.trim(),10);Number.isInteger(a)&&a>=1&&a<=e?(o.close(),t(a)):(process.stderr.write(`Invalid choice \u2014 enter a number between 1 and ${e}.
|
|
26
|
+
`),r());});};o.on("close",()=>n(new Error("stdin closed"))),r();})}async function Us(e,t){let n;try{n=await ce(e.relayUrl,t.roomCode);}catch(l){if(l instanceof Ct&&l.reason==="unknown-room")return await ao({clearLastSession:()=>At(t.roomUuid),logger:console,exit:process.exit});console.error("Could not reach relay \u2014 try again later."),process.exit(0);}n.accessMode==="password"&&!t.passwordHash&&(console.error(`Password changed \u2014 rejoin with: hnch join ${t.roomCode} --password`),io(t.roomUuid),process.exit(0)),console.error(`Rejoining room ${t.roomCode}\u2026`),console.error("");let o=new $e.Doc,r=new Awareness(o);Le(o,{participantId:e.participantId,displayName:e.displayName,joinedAt:Date.now(),...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}),r.setLocalStateField(ke,e.participantId);let s=cn(),a=st({doc:o,awareness:r,roomCode:t.roomCode,roomUuid:t.roomUuid,participantId:e.participantId,relayUrl:e.relayUrl,passwordHash:t.passwordHash,clearLeftStatusOnSync:true,onRejection(l){l==="unknown-room"?bo(t.roomUuid):s.note(l);}});dn({roomCode:a.roomCode,roomUuid:a.roomUuid,lastSeenAt:Date.now(),...t.passwordHash!==void 0&&{passwordHash:t.passwordHash}});let i=render(yn.createElement(bn,{session:a,participantId:e.participantId,displayName:e.displayName,accessMode:n.accessMode,presetOverrides:e.presetOverrides,customScales:e.customScales}));s.attach(i.unmount),a.onSessionEvent(l=>{l.kind!=="host-changed"&&(console.error(l.message),i.unmount(),lt(t.roomUuid),a.disconnect(),process.exit(0));}),await i.waitUntilExit();let c=s.refused();c!==null&&Io(c,a,{wasIn:true,typedPassword:false}),a.disconnect(),lt(t.roomUuid),process.exit(0);}async function jd(){let e=await le(),t=an();if(t.length===0&&(console.error("No recent session to resume."),process.exit(0)),t.length===1)return Us(e,t[0]);let n=Date.now();process.stderr.write(`Recent rooms:
|
|
27
|
+
`);for(let[r,s]of t.entries()){let a=Hd(s.lastSeenAt,n);process.stderr.write(` ${r+1}. ${s.roomCode} (${a})
|
|
28
28
|
`);}process.stderr.write(`
|
|
29
|
-
`);let o;try{o=await
|
|
29
|
+
`);let o;try{o=await Bd(t.length);}catch{console.error("No selection made."),process.exit(1);}return Us(e,t[o-1])}async function Fd(e){if(!(e.name!==void 0||e.relayUrl!==void 0||e.scale!==void 0||e.sessionName!==void 0||e.password!==void 0||e.color!==void 0)){let o=await le(),{waitUntilExit:r}=render(yn.createElement(ks,{presetOverrides:o.presetOverrides,customScales:o.customScales}));await r(),process.exit(0);}let n={};if(e.name!==void 0&&(n.displayName=e.name),e.relayUrl!==void 0&&(n.relayUrl=e.relayUrl),e.scale!==void 0){if(e.scale!==""){let o=Ve();if(!tn(e.scale,o.presetOverrides,o.customScales)){console.error(`Unknown scale: "${e.scale}". Builtin IDs: ${Object.keys(de).join(", ")}`);return}}n.defaultScale=e.scale;}if(e.sessionName!==void 0&&(n.defaultSessionName=e.sessionName),e.password!==void 0&&(n.defaultPassword=e.password),e.color!==void 0){let o=e.color.startsWith("#")||e.color===""?e.color:e.color.toLowerCase();o!==""&&je(o)===null&&(console.error(`Invalid color: "${e.color}". Pass a palette key or #rrggbb hex literal.`),process.exit(1)),n.avatarColor=o;}bt(n),console.log("Config updated.");}var Hs=Md(hideBin(process.argv)).scriptName("hnch").usage("$0 <command> \u2014 terminal pointing poker").command("create","Create a new room",e=>e.option("name",{type:"string",describe:"Session name"}).option("password",{type:"boolean",describe:"Protect room with a password"}).option("scale",{type:"string",describe:"Estimation scale ID (fibonacci, t-shirt, powers-of-2, linear, risk, or custom-<id>)"}),e=>{$d(e).catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1);});}).command("join <code>","Join an existing room",e=>e.positional("code",{type:"string",demandOption:true,describe:"6-character room code"}).option("password",{type:"boolean",describe:"Room requires a password",default:false}),e=>{Ld(e).catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1);});}).command("resume","Rejoin your last session",e=>e,()=>{jd().catch(e=>{console.error(e instanceof Error?e.message:e),process.exit(1);});}).command("config","View or update CLI config",e=>e.option("name",{type:"string",describe:"Set display name"}).option("relay-url",{type:"string",describe:"Set relay URL"}).option("scale",{type:"string",describe:"Set default estimation scale ID (empty string clears)"}).option("session-name",{type:"string",describe:"Set default session name (empty string clears)"}).option("password",{type:"boolean",describe:"Set default password prompt on (--password) or off (--no-password)"}).option("color",{type:"string",describe:'Set avatar color: a palette key (e.g. "blue", "racing-green") or a #rrggbb hex literal'}),e=>{Fd(e).catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1);});}).command("agenda","Manage the pre-session story agenda",e=>e.command("add","Add an agenda item",t=>t.option("title",{type:"string",describe:"Story title"}).option("ticket",{type:"string",describe:"Issue tracker reference (e.g. PROJ-123)"}).option("description",{type:"string",describe:"Story description"}).check(n=>{if(!n.title?.trim()&&!n.ticket?.trim())throw new Error("At least one of --title or --ticket is required");return true}),t=>{Ns(t).catch(n=>{console.error(n instanceof Error?n.message:n),process.exit(1);});}).command("list","List agenda items in order",t=>t,()=>{Ds().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1);});}).command("skip <id>","Mark an agenda item as skipped",t=>t.positional("id",{type:"string",demandOption:true,describe:"Agenda item ID"}),t=>{Os(t).catch(n=>{console.error(n instanceof Error?n.message:n),process.exit(1);});}).command("cancel <id>","Soft-delete (cancel) an agenda item",t=>t.positional("id",{type:"string",demandOption:true,describe:"Agenda item ID"}),t=>{Ms(t).catch(n=>{console.error(n instanceof Error?n.message:n),process.exit(1);});}).command("mv <id>","Reorder an agenda item (--before <id> | --after <id>)",t=>t.positional("id",{type:"string",demandOption:true,describe:"Agenda item ID to move"}).option("before",{type:"string",describe:"sortKey of item that should come before the moved item"}).option("after",{type:"string",describe:"sortKey of item that should come after the moved item"}).check(n=>{if(n.before!==void 0&&n.after!==void 0)throw new Error("--before and --after are mutually exclusive");if(n.before===void 0&&n.after===void 0)throw new Error("Specify either --before <id> or --after <id>");return true}),t=>{_s(t).catch(n=>{console.error(n instanceof Error?n.message:n),process.exit(1);});}).demandCommand(1,"Specify an agenda subcommand: add, list, skip, cancel, mv").strict().help(),()=>{}).demandCommand(1,"Specify a command: create, join, resume, config, or agenda").strict().help(),yo=hideBin(process.argv);(yo.length===0||yo.length===1&&yo[0]==="--")&&(Hs.showHelp(),process.exit(0));Hs.parse();
|