@xauyxau/hnch 1.16.0 → 1.16.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.
Files changed (2) hide show
  1. package/dist/index.js +14 -14
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,25 +1,25 @@
1
1
  #!/usr/bin/env node
2
- import pa from'yargs';import {hideBin}from'yargs/helpers';import on,{useState,useEffect,useCallback,useMemo,useRef}from'react';import {render,useApp,useInput,Box,Text}from'ink';import*as Ue 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 ps from'ws';import $r from'clipboardy';import {jsxs,jsx,Fragment}from'react/jsx-runtime';var Pt="hnch_abstain";function W(e){return e===Pt}var Ai={"unknown-room":4001,"wrong-password":4002,"invalid-invite":4003,"expired-invite":4004,"invite-already-redeemed":4005,"room-full":4006,"malformed-credentials":4010},lo=new Map(Object.entries(Ai).map(([e,t])=>[t,e]));function me(e){return e.role??"voter"}function Ze(e){return e.leftAt===void 0}var Nt={id:"fibonacci",cards:["0","1","2","3","5","8","13","21"]},uo={id:"t-shirt",cards:["XS","S","M","L","XL"]},po={id:"powers-of-2",cards:["1","2","4","8","16","32","64"]},fo={id:"linear",cards:["1","2","3","4","5","6","7","8","9","10"]},mo={id:"risk",cards:["Low","Medium","High","Critical"]},se={[Nt.id]:Nt,[uo.id]:uo,[po.id]:po,[fo.id]:fo,[mo.id]:mo},go={fibonacci:"Fibonacci","t-shirt":"T-shirt","powers-of-2":"Powers of 2",linear:"Linear (1\u201310)",risk:"Risk"};function ho(e){return e in go?go[e]:e.length===0?e:(e.startsWith("custom-")?e.slice(7):e).split("-").map(n=>n.length===0?n:n.charAt(0).toUpperCase()+n.slice(1)).join(" ")}function So(e,t,n){if(!e||e.status!=="voting"&&e.status!=="pending")return false;let o=new Set(t.filter(d=>Ze(d)&&n.has(d.id)&&me(d)!=="viewer").map(d=>d.id));if(o.size===0)return false;let r=Object.entries(e.votes).filter(([d])=>o.has(d)),i=r.filter(([,d])=>W(d)).length,a=r.length-i,s=o.size-i;return s<=0?false:a>=s}var et={"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 lt=["racing-green","dijon","blue","indigo","violet","pink","red","orange","amber","green","teal","graphite"],Ri=/^#[0-9a-fA-F]{6}$/;function Ti(e){return Object.hasOwn(et,e)}function $e(e){return e?Ti(e)?et[e].base:Ri.test(e)?e.toLowerCase():null:null}function xo(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)%lt.length;return lt[n]}var Re="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Dt=Re.length,hn=Math.floor(Dt/2);function ut(e){let t=Re.indexOf(e);if(t===-1)throw new Error(`fractional-index: invalid character '${e}'`);return t}function wo(e,t){return e.length>=t?e:e+"0".repeat(t-e.length)}function Ei(e){let t=e.length-1;for(;t>0&&e[t]==="0";)t--;return e.slice(0,t+1)}function ki(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 d=e[s]+t[s]+r;o[s+1]=d%Dt,r=Math.floor(d/Dt);}o[0]=r;let i=Array.from({length:n+1}).fill(0),a=0;for(let s=0;s<=n;s++){let d=o[s]+a*Dt;i[s]=Math.floor(d/2),a=d%2;}return i.slice(1)}function Sn(e,t){let n=Re[hn];if(e===null&&t===null)return n+n;if(t===null)return e+n+n+n+n;if(e===null)return Pi(t);if(e>=t)throw new Error(`keyBetween: a must be < b (a='${e}', b='${t}')`);return Ni(e,t)}function Pi(e){for(let t=e.length-1;t>=0;t--){let n=ut(e[t]);if(n>0)return e.slice(0,t)+Re[n-1]+Re[hn]}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 Ni(e,t){let n=Math.max(e.length,t.length),o=wo(e,n).split("").map(d=>ut(d)),r=wo(t,n).split("").map(d=>ut(d)),a=ki(o,r).map(d=>Re[d]).join(""),s=Ei(a);return s>e&&s<t?s:a>e&&a<t?a:Di(e,t)}function Di(e,t){for(let n=0;n<t.length;n++){let o=n<e.length?ut(e[n]):0;if(ut(t[n])===o+1)return (n<e.length?e.slice(0,n+1):e+Re[0])+Re[hn]}throw new Error(`keyBetween: space exhausted between '${e}' and '${t}'`)}function xn(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 ae(e){return e==="revealed"||e==="skipped"||e==="discarded"}function tt(e){return !ae(e)}var Co="meta",yo="settings",vo="participants",bo="rounds",Io="agenda",Oi=["roomUuid","createdAt","createdBy","sessionEndedAt"],Mi=["name","defaultScale","hostParticipantId"],$i=["displayName","joinedAt","role","leftAt","removedBy","avatarColor"],Ui=["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 Ot(e){return e.getMap(Co)}function Mt(e){return e.getMap(yo)}function $t(e){return e.getMap(vo)}function wn(e){return e.getArray(bo)}function pt(e){return e.getArray(Io)}function ft(e,t){let n={};for(let o of t){let r=e.get(o);r!==void 0&&(n[o]=r);}return n}function Hi(e){return ft(Ot(e),Oi)}function _i(e){return ft(Mt(e),Mi)}function Li(e){let t=$t(e),n=[];return t.forEach((o,r)=>{let i=ft(o,$i);n.push({id:r,...i});}),n.sort((o,r)=>o.joinedAt-r.joinedAt||o.id.localeCompare(r.id)),n}function ji(e){let t={};return e.forEach((n,o)=>{t[o]=n;}),t}function Fi(e){let t=ft(e,Bi),n=e.get("votes"),o=n?ji(n):{},r=xn(t),{revealedAt:i,skippedAt:a,discardedAt:s,...d}=t,u=r??(t.timerStartedAt!==void 0?"voting":"pending"),c=r==="revealed"?i:r==="skipped"?a:r==="discarded"?s:void 0;return c===void 0?{...d,votes:o,status:u}:{...d,votes:o,status:u,terminalAt:c}}function Vi(e){let t=wn(e),n=[];return t.forEach(o=>{n.push(Fi(o));}),n}function Yi(e){return ft(e,Ui)}function Wi(e){let t=pt(e),n=[];return t.forEach(o=>{n.push(Yi(o));}),n.sort((o,r)=>o.sortKey.localeCompare(r.sortKey)),n}function L(e){return {meta:Hi(e),settings:_i(e),participants:Li(e),rounds:Vi(e),agenda:Wi(e)}}function Cn(e,t){if(Ot(e).has("roomUuid"))throw new Error("initDoc: doc already seeded");e.transact(()=>{let n=Ot(e);n.set("roomUuid",t.roomUuid),n.set("createdAt",t.createdAt),n.set("createdBy",t.participantId);let o=Mt(e);t.sessionName!==void 0&&o.set("name",t.sessionName),o.set("defaultScale",t.defaultScale),o.set("hostParticipantId",t.participantId);let r=new Ue.Map;r.set("displayName",t.displayName),r.set("joinedAt",t.createdAt),t.avatarColor!==void 0&&r.set("avatarColor",t.avatarColor),$t(e).set(t.participantId,r);});}function Be(e,t){e.transact(()=>{let n=$t(e),o=n.get(t.participantId),r=o??new Ue.Map;r.set("displayName",t.displayName),o===void 0&&r.set("joinedAt",Date.now()),t.avatarColor!==void 0&&r.set("avatarColor",t.avatarColor),r.delete("leftAt"),r.delete("removedBy"),o===void 0&&n.set(t.participantId,r);});}function nt(e,t){e.transact(()=>{let n=Mt(e);for(let[o,r]of Object.entries(t))r===void 0?n.delete(o):n.set(o,r);});}function Ut(e,t,n){e.transact(()=>{let o=$t(e),r=o.get(t),i=r??new Ue.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 Bt(e,t){let n=t.scale??Mt(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 Ue.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 Ue.Map),wn(e).push([o]);}),t.id}function yn(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=wn(e);for(let o=0;o<n.length;o+=1){let r=n.get(o);if(r.get("id")===t)return r}}function vn(e){return xn({revealedAt:e.get("revealedAt"),skippedAt:e.get("skippedAt"),discardedAt:e.get("discardedAt")})}function Ao(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 Ro(e,t,n,o){let r=t.get("agendaItemId");if(r===void 0)return;let i=Rn(e,r);i!==void 0&&i.get("state")==="pending"&&(i.set("state","consumed"),i.set("consumedAt",o),i.set("consumedByRoundId",n));}function To(e,t,n){let o=He(e,t);if(!o)throw new Error(`revealRound: round ${t} not found`);let r=vn(o);if(r!==null)throw new Error(`revealRound: round ${t} already terminal (${r})`);e.transact(()=>{o.set("revealedAt",n),Ro(e,o,t,n);});}function Eo(e,t,n){let o=He(e,t);if(!o)throw new Error(`skipRound: round ${t} not found`);let r=vn(o);if(r!==null)throw new Error(`skipRound: round ${t} already terminal (${r})`);e.transact(()=>{o.set("skippedAt",n),Ro(e,o,t,n);});}function ko(e,t,n,o){let r=He(e,t);if(!r)throw new Error(`discardRound: round ${t} not found`);let i=vn(r);if(i!==null)throw new Error(`discardRound: round ${t} already terminal (${i})`);e.transact(()=>{r.set("discardedAt",n),r.set("discardedBy",o);});}function In(e){e.transact(()=>{Ot(e).set("sessionEndedAt",Date.now());});}function de(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 Ht(e){let{rounds:t}=e;for(let n=t.length-1;n>=0;n-=1){let o=t[n];if(tt(o.status))return o}return null}function An(e){let t=Object.values(e.votes);return t.length<2?false:t.every(n=>n===t[0])}function Rn(e,t){let n=pt(e);for(let o=0;o<n.length;o++){let r=n.get(o);if(r.get("id")===t)return r}}function mt(e,t){if(!t.title?.trim()&&!t.ticketId?.trim())throw new Error("appendAgendaItem: at least one of {title, ticketId} is required");let n=crypto.randomUUID(),o=pt(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=Sn(r,null);return e.transact(()=>{let a=new Ue.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),pt(e).push([a]);}),n}function _t(e,t,n,o={}){let r=Rn(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}`);e.transact(()=>{r.set("state",n),n==="consumed"&&(r.set("consumedAt",o.timestamp??Date.now()),o.consumedByRoundId!==void 0&&r.set("consumedByRoundId",o.consumedByRoundId));});}}function Tn(e,t,n,o){let r=Rn(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=Sn(n??null,o??null);e.transact(()=>{r.set("sortKey",a);});}function _e(e){for(let t of e.agenda)if(t.state==="pending")return t;return null}var Ki=5e3,Te="participantId";function Po(e){let t=new Set;for(let n of e.values()){if(typeof n!="object"||n===null)continue;let o=n[Te];typeof o=="string"&&t.add(o);}return t}function No(e,t){let n=new Set;for(let o of e.participants)t.has(o.id)&&Ze(o)&&n.add(o.id);return n}function Ji(e,t,n){let o=e.settings.hostParticipantId;return o?No(e,t).has(o)?{kind:"cancel"}:n.missingHostId!==o?{kind:"start-debounce",hostId:o}:{kind:"none"}:{kind:"none"}}function Gi(e,t,n,o){let r=e.settings.hostParticipantId;if(!o||r!==o)return {promote:false};let i=No(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 Do(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 d=e.projection(),u=e.myId();if(!d||u===null)return;let c=Gi(d,e.onlineIds(),u,s);c.promote&&e.promote(c.winner);}function i(){let s=e.projection();if(!s||e.myId()===null){o();return}let d=Ji(s,e.onlineIds(),{missingHostId:t});switch(d.kind){case "cancel":o();break;case "start-debounce":o(),t=d.hostId,n=setTimeout(r,Ki);break;}}let a=e.subscribe(i);return i(),{stop(){o(),a();}}}function Oo(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 Mo(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return false}}function En(e){if(e===null||typeof e!="object"||Array.isArray(e))return {version:2,entries:{}};let t=e;if(t.version===2&&Uo(t.entries)){let n=t.entries,o={};for(let[r,i]of Object.entries(n)){let a=qi(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 $o(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 Uo(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function qi(e){if(!Uo(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 Bo(e,t){let n=t.filter(p=>p.status!=="discarded"),o=new Map;for(let p of n)o.set(p.id,p);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 p=o.get(a.parentRoundId);if(p===void 0||i.has(p.id))return null;i.add(p.id),a=p,s+=1;}let d=a,u=new Map;for(let p of n){if(p.parentRoundId===void 0)continue;let A=u.get(p.parentRoundId);A===void 0?u.set(p.parentRoundId,[p]):A.push(p);}let c=0,l=[d];for(;l.length>0;){let p=l.shift();c+=1;let A=u.get(p.id);A!==void 0&&l.push(...A);}return {chainRoot:d,depth:s,total:c}}var Ho="PBKDF2",zi="SHA-256",_o=new TextEncoder;function Xi(e){return Array.from(new Uint8Array(e)).map(t=>t.toString(16).padStart(2,"0")).join("")}async function Le(e,t){let n=await crypto.subtle.importKey("raw",_o.encode(e),Ho,false,["deriveBits"]),o=await crypto.subtle.deriveBits({name:Ho,salt:_o.encode(t),iterations:1e5,hash:zi},n,256);return Xi(o)}var Lo="ABCDEFGHJKMNPQRSTUVWXYZ23456789";if(Lo.length!==31)throw new Error(`Room code alphabet must be 31 characters, got ${Lo.length}`);function kn(e){return e.trim().replaceAll(/-/g,"").toUpperCase()}function jo(e,t=true){let n=kn(e);return !t||n.length!==6?n:`${n.slice(0,3)}-${n.slice(3)}`}function Pn(e){let t=de(L(e));return t?tt(t.status)?{round:t}:{applied:false,reason:"already-terminal"}:{applied:false,reason:"no-current-round"}}function Nn(e,t=Date.now){let n=Pn(e);if("applied"in n)return n;let o=t();return To(e,n.round.id,o),{applied:true,at:o}}function Fo(e,t=Date.now){let n=Pn(e);if("applied"in n)return n;let o=t();return Eo(e,n.round.id,o),{applied:true,at:o}}function Vo(e,t,n=Date.now){let o=Pn(e);if("applied"in o)return o;let r=n();return ko(e,o.round.id,r,t),{applied:true,at:r}}function Yo(e){let t=new Set(e).size;return t===1?"unanimous":t===2?"close":"spread"}function Qi(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 Dn(e,t){let n=new Map;for(let a of e)n.set(a,(n.get(a)??0)+1);let o=null,r=0,i=[...n.keys()].toSorted((a,s)=>t(a)-t(s));for(let a of i){let s=n.get(a);s>r&&(r=s,o=a);}return o}function Wo(e,t){let n=Object.values(e);if(n.length===0)return null;let o=Qi(n,t.cards);if(t.cards.every(a=>Number.isFinite(parseFloat(a)))){let a=n.map(parseFloat).filter(Number.isFinite);if(a.length===0)return {kind:"categorical",mode:Dn(n,o),spread:Yo(n)};let s=a.reduce((A,P)=>A+P,0)/a.length,d=[...a].toSorted((A,P)=>A-P),u=Math.floor(d.length/2),c=d.length%2===1?d[u]:(d[u-1]+d[u])/2,l=Dn(n,o),p;if(new Set(n).size===1)p="unanimous";else {let A=n.map(T=>o(T)),P=Math.min(...A);p=Math.max(...A)-P<=1?"close":"spread";}return {kind:"numeric",mean:s,median:c,mode:l,spread:p}}return {kind:"categorical",mode:Dn(n,o),spread:Yo(n)}}function On(e){return e.replaceAll(/\|/g,"\\|")}function Zi(e){return e.replaceAll(/\\/g,"\\\\").replaceAll(/]/g,"\\]")}function es(e){let n=(e.match(/`+/g)??[]).reduce((o,r)=>Math.max(o,r.length),0);return "`".repeat(n+1)}function Mn(e){if(!e)return "";if(Mo(e))return ` ([${Zi(e)}](<${e}>))`;let t=es(e);return ` (${t}${e}${t})`}function ts(e){return e instanceof Map?e:new Map(Object.entries(e))}function ns(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 Ko(e,t){let n=new Map;e.scale.cards.forEach((s,d)=>n.set(s,d));let o=new Map,r=[];for(let[s,d]of Object.entries(e.votes)){let u=t.get(s)??s;if(W(d)){r.push(u);continue}let c=o.get(d);c?c.push(u):o.set(d,[u]);}let i=[...o.entries()].map(([s,d])=>({card:s,scaleIndex:n.get(s)??Number.MAX_SAFE_INTEGER,voters:[...d].toSorted().map(On)}));i.sort((s,d)=>{let u=d.voters.length-s.voters.length;return u!==0?u:s.scaleIndex-d.scaleIndex});let a=i.map(s=>`| ${On(s.card)} | ${s.voters.join(", ")} |`);return r.length>0&&a.push(`| Abstained | ${[...r].toSorted().map(On).join(", ")} |`),["| Vote | Voters |","|------|--------|",...a].join(`
3
- `)}function Jo(e){let t=Object.fromEntries(Object.entries(e.votes).filter(([,i])=>!W(i))),n=Wo(t,e.scale),o=e.timerStartedAt!=null&&e.status==="revealed"&&e.terminalAt!=null?Oo(e.terminalAt-e.timerStartedAt):null,r=[];return n?.kind==="numeric"?r.push(`Avg ${n.mean.toFixed(1)} \xB7 Med ${n.median}`):n?.kind==="categorical"&&r.push(`Most common: ${n.mode}`),o!=null&&r.push(`Elapsed ${o}`),r.join(" \xB7 ")}function Go(e){let{rounds:t}=e,n=ts(e.participants),o=new Map;for(let[c,l]of n)o.set(c,l.displayName);let r=t.filter(c=>c.status==="revealed");if(r.length===0)return "";let i=new Map;t.forEach((c,l)=>i.set(c.id,l+1));let a=ns(r),s=new Set,d=[];for(let c of r)for(let[l,p]of a)if(p.includes(c)&&!s.has(l)){s.add(l),d.push(l);break}let u=[];for(let c of d){let l=a.get(c),p=l.find(S=>S.id===c),A=l.filter(S=>S.id!==c),P=i.get(p.id)??0,R=p.title?`## Round ${P} \u2014 ${p.title}${Mn(p.ticketId)}`:`## Round ${P}${Mn(p.ticketId)}`,T=Ko(p,o),U=Jo(p),f=U?`${R}
2
+ import Va from'yargs';import {hideBin}from'yargs/helpers';import un,{useState,useEffect,useCallback,useMemo,useRef}from'react';import {render,useApp,useInput,Box,Text}from'ink';import*as Ue 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 Ys from'ws';import ni from'clipboardy';import {jsxs,jsx,Fragment}from'react/jsx-runtime';var Mt="hnch_abstain";function G(e){return e===Mt}var Te="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",$t=Te.length,vn=Math.floor($t/2);function pt(e){let t=Te.indexOf(e);if(t===-1)throw new Error(`fractional-index: invalid character '${e}'`);return t}function Co(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 Ji(e,t){let n=e.length,o=Array.from({length:n+1}).fill(0),r=0;for(let a=n-1;a>=0;a--){let c=e[a]+t[a]+r;o[a+1]=c%$t,r=Math.floor(c/$t);}o[0]=r;let i=Array.from({length:n+1}).fill(0),s=0;for(let a=0;a<=n;a++){let c=o[a]+s*$t;i[a]=Math.floor(c/2),s=c%2;}return i.slice(1)}function In(e,t){let n=Te[vn];if(e===null&&t===null)return n+n;if(t===null)return e+n+n+n+n;if(e===null)return qi(t);if(e>=t)throw new Error(`keyBetween: a must be < b (a='${e}', b='${t}')`);return zi(e,t)}function qi(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[vn]}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 zi(e,t){let n=Math.max(e.length,t.length),o=Co(e,n).split("").map(c=>pt(c)),r=Co(t,n).split("").map(c=>pt(c)),s=Ji(o,r).map(c=>Te[c]).join(""),a=Gi(s);return a>e&&a<t?a:s>e&&s<t?s:Xi(e,t)}function Xi(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[vn]}throw new Error(`keyBetween: space exhausted between '${e}' and '${t}'`)}function bn(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((s,a)=>s.at-a.at||i[s.kind]-i[a.kind]),r[0].kind}function fe(e){return e==="revealed"||e==="skipped"||e==="discarded"}function Ze(e){return !fe(e)}var wo="meta",yo="settings",vo="participants",Io="rounds",bo="agenda",Qi=["roomUuid","createdAt","createdBy","sessionEndedAt"],Zi=["name","defaultScale","hostParticipantId"],es=["displayName","joinedAt","role","leftAt","removedBy","avatarColor"],ts=["id","title","description","ticketId","state","source","externalId","sortKey","createdAt","consumedAt","consumedByRoundId"],ns=["id","title","description","ticketId","parentRoundId","scale","timerStartedAt","revealedAt","skippedAt","discardedAt","discardedBy","createdBy","createdAt","agendaItemId"];function Ut(e){return e.getMap(wo)}function Ht(e){return e.getMap(yo)}function mt(e){return e.getMap(vo)}function An(e){return e.getArray(Io)}function ft(e){return e.getArray(bo)}function gt(e,t){let n={};for(let o of t){let r=e.get(o);r!==void 0&&(n[o]=r);}return n}function os(e){return gt(Ut(e),Qi)}function rs(e){return gt(Ht(e),Zi)}function is(e){let t=mt(e),n=[];return t.forEach((o,r)=>{let i=gt(o,es);n.push({id:r,...i});}),n.sort((o,r)=>o.joinedAt-r.joinedAt||o.id.localeCompare(r.id)),n}function ss(e){let t={};return e.forEach((n,o)=>{t[o]=n;}),t}function as(e){let t=gt(e,ns),n=e.get("votes"),o=n?ss(n):{},r=bn(t),{revealedAt:i,skippedAt:s,discardedAt:a,...c}=t,u=r??(t.timerStartedAt!==void 0?"voting":"pending"),d=r==="revealed"?i:r==="skipped"?s:r==="discarded"?a:void 0;return d===void 0?{...c,votes:o,status:u}:{...c,votes:o,status:u,terminalAt:d}}function ds(e){let t=An(e),n=[];return t.forEach(o=>{n.push(as(o));}),n}function cs(e){return gt(e,ts)}function ls(e){let t=ft(e),n=[];return t.forEach(o=>{n.push(cs(o));}),n.sort((o,r)=>o.sortKey.localeCompare(r.sortKey)),n}function _(e){return {meta:os(e),settings:rs(e),participants:is(e),rounds:ds(e),agenda:ls(e)}}function Rn(e,t){if(Ut(e).has("roomUuid"))throw new Error("initDoc: doc already seeded");e.transact(()=>{let n=Ut(e);n.set("roomUuid",t.roomUuid),n.set("createdAt",t.createdAt),n.set("createdBy",t.participantId);let o=Ht(e);t.sessionName!==void 0&&o.set("name",t.sessionName),o.set("defaultScale",t.defaultScale),o.set("hostParticipantId",t.participantId);let r=new Ue.Map;r.set("displayName",t.displayName),r.set("joinedAt",t.createdAt),t.avatarColor!==void 0&&r.set("avatarColor",t.avatarColor),mt(e).set(t.participantId,r);});}function He(e,t){e.transact(()=>{let n=mt(e),o=n.get(t.participantId),r=o??new Ue.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 Lt(e,t){e.transact(()=>{let n=Ht(e);for(let[o,r]of Object.entries(t))r===void 0?n.delete(o):n.set(o,r);});}function Bt(e,t){Lt(e,t);}function Tn(e,t,n){e.transact(()=>{let o=mt(e),r=o.get(t),i=r??new Ue.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 _t(e,t){let n=t.scale??Ht(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 Ue.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 Ue.Map),An(e).push([o]);}),t.id}function En(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=An(e);for(let o=0;o<n.length;o+=1){let r=n.get(o);if(r.get("id")===t)return r}}function kn(e){return bn({revealedAt:e.get("revealedAt"),skippedAt:e.get("skippedAt"),discardedAt:e.get("discardedAt")})}function Ao(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 Pn(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 Ro(e,t,n,o){let r=t.get("agendaItemId");if(r===void 0)return;let i=Dn(e,r);i!==void 0&&i.get("state")==="pending"&&(i.set("state","consumed"),i.set("consumedAt",o),i.set("consumedByRoundId",n));}function To(e,t,n){let o=Le(e,t);if(!o)throw new Error(`revealRound: round ${t} not found`);let r=kn(o);if(r!==null)throw new Error(`revealRound: round ${t} already terminal (${r})`);e.transact(()=>{o.set("revealedAt",n),Ro(e,o,t,n);});}function Eo(e,t,n){let o=Le(e,t);if(!o)throw new Error(`skipRound: round ${t} not found`);let r=kn(o);if(r!==null)throw new Error(`skipRound: round ${t} already terminal (${r})`);e.transact(()=>{o.set("skippedAt",n),Ro(e,o,t,n);});}function ko(e,t,n,o){let r=Le(e,t);if(!r)throw new Error(`discardRound: round ${t} not found`);let i=kn(r);if(i!==null)throw new Error(`discardRound: round ${t} already terminal (${i})`);e.transact(()=>{r.set("discardedAt",n),r.set("discardedBy",o);});}function Po(e,t){e.transact(()=>{Ut(e).set("sessionEndedAt",t);});}function No(e,t){let o=mt(e).get(t);!o||!o.has("leftAt")||e.transact(()=>{o.delete("leftAt"),o.delete("removedBy");});}function ie(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 et(e){let{rounds:t}=e;for(let n=t.length-1;n>=0;n-=1){let o=t[n];if(Ze(o.status))return o}return null}function Nn(e){let t=Object.values(e.votes);return t.length<2?false:t.every(n=>n===t[0])}function Dn(e,t){let n=ft(e);for(let o=0;o<n.length;o++){let r=n.get(o);if(r.get("id")===t)return r}}function On(e,t){return !!e?.trim()||!!t?.trim()}function Do(e,t){if(!On(t.title,t.ticketId))throw new Error("appendAgendaItem: at least one of {title, ticketId} is required");let n=crypto.randomUUID(),o=ft(e),r=null;o.forEach(s=>{if(s.get("state")==="pending"){let a=s.get("sortKey");a!==void 0&&(r===null||a>r)&&(r=a);}});let i=In(r,null);return e.transact(()=>{let s=new Ue.Map;s.set("id",n),s.set("state","pending"),s.set("source",t.source??"manual"),s.set("sortKey",i),s.set("createdAt",t.createdAt),t.title!==void 0&&s.set("title",t.title),t.description!==void 0&&s.set("description",t.description),t.ticketId!==void 0&&s.set("ticketId",t.ticketId),t.externalId!==void 0&&s.set("externalId",t.externalId),ft(e).push([s]);}),n}function Mn(e,t,n,o={}){let r=Dn(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 Oo(e,t,n,o){let r=Dn(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 s=In(n??null,o??null);e.transact(()=>{r.set("sortKey",s);});}function Be(e){for(let t of e.agenda)if(t.state==="pending")return t;return null}function us(e,t){let n=_(e).agenda.find(o=>o.id===t);return n||{applied:false,reason:"not-found"}}function $n(e,t){let n=us(e,t);return jt(n)?n:n.state!=="pending"?{applied:false,reason:"not-pending"}:n}function jt(e){return "applied"in e}function Ft(e,t,n=Date.now){if(!On(t.title,t.ticketId))return {applied:false,reason:"invalid-fields"};let o=n();return {applied:true,id:Do(e,{...t,createdAt:o}),at:o}}function Mo(e,t){let n=$n(e,t);return jt(n)?n:(Mn(e,t,"skipped"),{applied:true,id:t})}function $o(e,t){let n=$n(e,t);return jt(n)?n:(Mn(e,t,"cancelled"),{applied:true,id:t})}function Uo(e,t,n,o){let r=$n(e,t);return jt(r)?r:(Oo(e,t,n,o),{applied:true,id:t})}var ps={"unknown-room":4001,"wrong-password":4002,"invalid-invite":4003,"expired-invite":4004,"invite-already-redeemed":4005,"room-full":4006,"malformed-credentials":4010},Ho=new Map(Object.entries(ps).map(([e,t])=>[t,e]));function me(e){return e.role??"voter"}function tt(e){return e.leftAt===void 0}var Vt={id:"fibonacci",cards:["0","1","2","3","5","8","13","21"]},Lo={id:"t-shirt",cards:["XS","S","M","L","XL"]},Bo={id:"powers-of-2",cards:["1","2","4","8","16","32","64"]},_o={id:"linear",cards:["1","2","3","4","5","6","7","8","9","10"]},jo={id:"risk",cards:["Low","Medium","High","Critical"]},se={[Vt.id]:Vt,[Lo.id]:Lo,[Bo.id]:Bo,[_o.id]:_o,[jo.id]:jo},Fo={fibonacci:"Fibonacci","t-shirt":"T-shirt","powers-of-2":"Powers of 2",linear:"Linear (1\u201310)",risk:"Risk"};function Vo(e){return e in Fo?Fo[e]:e.length===0?e:(e.startsWith("custom-")?e.slice(7):e).split("-").map(n=>n.length===0?n:n.charAt(0).toUpperCase()+n.slice(1)).join(" ")}function fs(e,t,n){if(!e||e.status!=="voting"&&e.status!=="pending")return false;let o=new Set(t.filter(c=>tt(c)&&n.has(c.id)&&me(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])=>G(c)).length,s=r.length-i,a=o.size-i;return a<=0?false:s>=a}function Yo(e){function t(){let o=e.projection();if(!o)return;let r=ie(o);fs(r,o.participants,e.onlineIds())&&e.reveal();}let n=e.subscribe(t);return t(),{stop(){n();}}}var nt={"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 ht=["racing-green","dijon","blue","indigo","violet","pink","red","orange","amber","green","teal","graphite"],ms=/^#[0-9a-fA-F]{6}$/;function gs(e){return Object.hasOwn(nt,e)}function _e(e){return e?gs(e)?nt[e].base:ms.test(e)?e.toLowerCase():null:null}function Wo(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)%ht.length;return ht[n]}var hs=5e3,Ee="participantId";function Ko(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 Go(e,t){let n=new Set;for(let o of e.participants)t.has(o.id)&&tt(o)&&n.add(o.id);return n}function xs(e,t,n){let o=e.settings.hostParticipantId;return o?Go(e,t).has(o)?{kind:"cancel"}:n.missingHostId!==o?{kind:"start-debounce",hostId:o}:{kind:"none"}:{kind:"none"}}function Ss(e,t,n,o){let r=e.settings.hostParticipantId;if(!o||r!==o)return {promote:false};let i=Go(e,t);if(i.has(r))return {promote:false};let s=[...i].toSorted();if(s.length===0)return {promote:false};let a=s[0];return a!==n?{promote:false}:{promote:true,winner:a}}function Jo(e){let t=null,n=null;function o(){n!==null&&(clearTimeout(n),n=null),t=null;}function r(){n=null;let a=t;t=null;let c=e.projection(),u=e.myId();if(!c||u===null)return;let d=Ss(c,e.onlineIds(),u,a);d.promote&&e.promote(d.winner);}function i(){let a=e.projection();if(!a||e.myId()===null){o();return}let c=xs(a,e.onlineIds(),{missingHostId:t});switch(c.kind){case "cancel":o();break;case "start-debounce":o(),t=c.hostId,n=setTimeout(r,hs);break;}}let s=e.subscribe(i);return i(),{stop(){o(),s();}}}function Yt(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 qo(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return false}}function Un(e){if(e===null||typeof e!="object"||Array.isArray(e))return {version:2,entries:{}};let t=e;if(t.version===2&&Xo(t.entries)){let n=t.entries,o={};for(let[r,i]of Object.entries(n)){let s=Cs(i);s!==null&&(o[r]=s);}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 zo(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 Xo(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Cs(e){if(!Xo(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 Qo(e,t){let n=t.filter(p=>p.status!=="discarded"),o=new Map;for(let p of n)o.set(p.id,p);let r=o.get(e);if(r===void 0||r.parentRoundId===void 0)return null;let i=new Set([r.id]),s=r,a=1;for(;s.parentRoundId!==void 0;){let p=o.get(s.parentRoundId);if(p===void 0||i.has(p.id))return null;i.add(p.id),s=p,a+=1;}let c=s,u=new Map;for(let p of n){if(p.parentRoundId===void 0)continue;let A=u.get(p.parentRoundId);A===void 0?u.set(p.parentRoundId,[p]):A.push(p);}let d=0,l=[c];for(;l.length>0;){let p=l.shift();d+=1;let A=u.get(p.id);A!==void 0&&l.push(...A);}return {chainRoot:c,depth:a,total:d}}var Zo="PBKDF2",ws="SHA-256",er=new TextEncoder;function ys(e){return Array.from(new Uint8Array(e)).map(t=>t.toString(16).padStart(2,"0")).join("")}async function je(e,t){let n=await crypto.subtle.importKey("raw",er.encode(e),Zo,false,["deriveBits"]),o=await crypto.subtle.deriveBits({name:Zo,salt:er.encode(t),iterations:1e5,hash:ws},n,256);return ys(o)}var xt=class extends Error{reason;constructor(t){super(`relay rejected resolve: ${t}`),this.reason=t,this.name="RelayRejectionError";}};async function nr(e,t){let n=await fetch(`${e}/rooms`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({})});if(!n.ok)throw new Error(`POST /rooms failed: ${n.status}`);return await n.json()}async function ae(e,t){let n=await fetch(`${e}/rooms/${encodeURIComponent(t)}`);if(n.status===404){let o=await n.json().catch(()=>null);throw new xt(o?.reason??"unknown-room")}if(!n.ok)throw new Error(`GET /rooms/:code failed: ${n.status}`);return await n.json()}async function Hn(e,t,n){let o=await fetch(`${e}/rooms/${t}/access`,{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({passwordHash:n})});if(!o.ok)throw new Error(`PATCH /rooms/:uuid/access failed: ${o.status}`);return await o.json()}var Is=6e4,bs=3;function As(e){return e.replace(/^https?:\/\//,t=>t==="https://"?"wss://":"ws://")}function tr(e){let t={did:e.deviceId};return e.passwordHash!==void 0&&(t.pw=e.passwordHash),t}function Rs(){return globalThis.window}function or(e){let t="connecting",n=null,o=false,r=false,i=false,s=[],a=()=>{let S=o&&t!=="connected"&&n===null&&!r;S!==i&&(i=S,e.onReconnectingChange?.(S));},c=`${As(e.httpBaseUrl)}/ws`,u=e.credentials,d=new WebsocketProvider(c,e.roomUuid,e.doc,{params:tr(u),connect:true,...e.awareness!==void 0&&{awareness:e.awareness},...e.WebSocketPolyfill!==void 0&&{WebSocketPolyfill:e.WebSocketPolyfill}}),l=S=>{t=S.status,e.onStatusChange?.(S.status),S.status==="connected"&&(o=true,n=null,e.onRejectionChange?.(null),s.length=0),a();},p=S=>{if(S===null)return;let v=Ho.get(S.code);if(v===void 0){let y=Date.now();s.push(y);let L=y-Is;for(;s.length>0&&s[0]<L;)s.shift();s.length>=bs&&(s.length=0,e.onRepeatRejection?.()),a();return}n=v,e.onRejectionChange?.(v),d.shouldConnect=false,d.disconnect(),a();};d.on("status",l),d.on("connection-close",p);let A=d,k=null;if(e.onSynced!==void 0){let S=v=>{v&&(A.off("synced",S),k=null,e.onSynced?.());};k=S,A.on("synced",S);}let R=()=>{r||(t="disconnected",e.onStatusChange?.("disconnected"),a());},T=()=>{r||n!==null||t!=="connected"&&(d.ws!==null?(d.wsUnsuccessfulReconnects=0,d.ws.close()):d.connect());},f=Rs();f?.addEventListener("offline",R),f?.addEventListener("online",T);let I=false;return {awareness:d.awareness,updateCredentials(S){let v=S.passwordHash??void 0;v!==u.passwordHash&&(u=v===void 0?{roomCode:u.roomCode,deviceId:u.deviceId}:{...u,passwordHash:v},d.shouldConnect=false,d.disconnect(),d.params=tr(u),d.connect());},disconnect(){I||(I=true,r=true,a(),d.off("status",l),d.off("connection-close",p),k!==null&&(A.off("synced",k),k=null),f?.removeEventListener("offline",R),f?.removeEventListener("online",T),d.shouldConnect=false,d.disconnect(),d.destroy());}}}var rr="ABCDEFGHJKMNPQRSTUVWXYZ23456789";if(rr.length!==31)throw new Error(`Room code alphabet must be 31 characters, got ${rr.length}`);function Ln(e){return e.trim().replaceAll(/-/g,"").toUpperCase()}function ir(e,t=true){let n=Ln(e);return !t||n.length!==6?n:`${n.slice(0,3)}-${n.slice(3)}`}function Bn(e,t){return _(e).participants.find(n=>n.id===t)}function Ts(e,t,n){let o=_(e);return {isHost:o.settings.hostParticipantId===t,target:o.participants.find(r=>r.id===n)}}function Es(e,t){return _(e).settings.hostParticipantId===t}function sr(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 ar(e,t,n){let o=Bn(e,t);return o?(Tn(e,t,sr(o,{displayName:n})),{applied:true}):{applied:false,reason:"not-found"}}function dr(e,t){let n=Bn(e,t);if(!n)return {applied:false,reason:"not-found"};let o=me(n)==="voter"?"viewer":"voter";return Tn(e,t,sr(n,{role:o})),{applied:true}}function cr(e,t){return Bn(e,t)?(No(e,t),{applied:true}):{applied:false,reason:"not-found"}}function lr(e,t,n,o){let r=Ts(e,t,n);return r.isHost?r.target?o.has(n)?(Lt(e,{hostParticipantId:n}),{applied:true}):{applied:false,reason:"not-online"}:{applied:false,reason:"not-found"}:{applied:false,reason:"not-host"}}function ur(e,t){return Lt(e,{hostParticipantId:t}),{applied:true}}function pr(e,t,n=Date.now){if(!Es(e,t))return {applied:false,reason:"not-host"};let o=n();return Po(e,o),{applied:true,at:o}}function _n(e){let t=ie(_(e));return t?Ze(t.status)?{round:t}:{applied:false,reason:"already-terminal"}:{applied:false,reason:"no-current-round"}}function jn(e,t=Date.now){let n=_n(e);if("applied"in n)return n;let o=t();return To(e,n.round.id,o),{applied:true,at:o}}function fr(e,t=Date.now){let n=_n(e);if("applied"in n)return n;let o=t();return Eo(e,n.round.id,o),{applied:true,at:o}}function mr(e,t,n=Date.now){let o=_n(e);if("applied"in o)return o;let r=n();return ko(e,o.round.id,r,t),{applied:true,at:r}}function Vn(e,t){let n=Qo(e.id,t);return n!==null?`Round ${n.depth}/${n.total} [re-vote]`:`Round ${t.findIndex(o=>o.id===e.id)+1}`}function gr(e){let t=new Set(e).size;return t===1?"unanimous":t===2?"close":"spread"}function ks(e,t){let n=new Map;t.forEach((i,s)=>n.set(i,s));let o=[...new Set(e.filter(i=>!n.has(i)))].toSorted(),r=new Map;return o.forEach((i,s)=>r.set(i,t.length+s)),i=>n.get(i)??r.get(i)??Number.MAX_SAFE_INTEGER}function Fn(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,a)=>t(s)-t(a));for(let s of i){let a=n.get(s);a>r&&(r=a,o=s);}return o}function Ps(e,t){let n=Object.values(e);if(n.length===0)return null;let o=ks(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",mode:Fn(n,o),spread:gr(n)};let a=s.reduce((A,k)=>A+k,0)/s.length,c=[...s].toSorted((A,k)=>A-k),u=Math.floor(c.length/2),d=c.length%2===1?c[u]:(c[u-1]+c[u])/2,l=Fn(n,o),p;if(new Set(n).size===1)p="unanimous";else {let A=n.map(T=>o(T)),k=Math.min(...A);p=Math.max(...A)-k<=1?"close":"spread";}return {kind:"numeric",mean:a,median:d,mode:l,spread:p}}return {kind:"categorical",mode:Fn(n,o),spread:gr(n)}}function Wt(e){let t=Object.fromEntries(Object.entries(e.votes).filter(([,n])=>!G(n)));return Ps(t,e.scale)}function Ns(e){return e==="unanimous"?"Unanimous":e==="close"?"Close":"Spread"}function Kt(e){if(e===null)return null;let t=Ns(e.spread);return e.kind==="numeric"?{kind:"numeric",mean:e.mean.toFixed(1),median:e.median.toFixed(1),mode:e.mode,spread:t}:{kind:"categorical",mode:e.mode,spread:t}}function ot(e){return e.status!=="revealed"||e.terminalAt===void 0||e.timerStartedAt===void 0?null:Yt(e.terminalAt-e.timerStartedAt)}function Yn(e){return e.replaceAll(/\|/g,"\\|")}function Ds(e){return e.replaceAll(/\\/g,"\\\\").replaceAll(/]/g,"\\]")}function Os(e){let n=(e.match(/`+/g)??[]).reduce((o,r)=>Math.max(o,r.length),0);return "`".repeat(n+1)}function Wn(e){if(!e)return "";if(qo(e))return ` ([${Ds(e)}](<${e}>))`;let t=Os(e);return ` (${t}${e}${t})`}function Ms(e){return e instanceof Map?e:new Map(Object.entries(e))}function $s(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),s=o.get(i.id);s?s.push(r):o.set(i.id,[r]);}return o}function hr(e,t){let n=new Map;e.scale.cards.forEach((a,c)=>n.set(a,c));let o=new Map,r=[];for(let[a,c]of Object.entries(e.votes)){let u=t.get(a)??a;if(G(c)){r.push(u);continue}let d=o.get(c);d?d.push(u):o.set(c,[u]);}let i=[...o.entries()].map(([a,c])=>({card:a,scaleIndex:n.get(a)??Number.MAX_SAFE_INTEGER,voters:[...c].toSorted().map(Yn)}));i.sort((a,c)=>{let u=c.voters.length-a.voters.length;return u!==0?u:a.scaleIndex-c.scaleIndex});let s=i.map(a=>`| ${Yn(a.card)} | ${a.voters.join(", ")} |`);return r.length>0&&s.push(`| Abstained | ${[...r].toSorted().map(Yn).join(", ")} |`),["| Vote | Voters |","|------|--------|",...s].join(`
3
+ `)}function xr(e){let t=Kt(Wt(e)),n=ot(e),o=[];return t?.kind==="numeric"?o.push(`Avg ${t.mean} \xB7 Med ${t.median}`):t?.kind==="categorical"&&o.push(`Most common: ${t.mode}`),n!==null&&o.push(`Elapsed ${n}`),o.join(" \xB7 ")}function Sr(e){let{rounds:t}=e,n=Ms(e.participants),o=new Map;for(let[d,l]of n)o.set(d,l.displayName);let r=t.filter(d=>d.status==="revealed");if(r.length===0)return "";let i=new Map;t.forEach((d,l)=>i.set(d.id,l+1));let s=$s(r),a=new Set,c=[];for(let d of r)for(let[l,p]of s)if(p.includes(d)&&!a.has(l)){a.add(l),c.push(l);break}let u=[];for(let d of c){let l=s.get(d),p=l.find(S=>S.id===d),A=l.filter(S=>S.id!==d),k=i.get(p.id)??0,R=p.title?`## Round ${k} \u2014 ${p.title}${Wn(p.ticketId)}`:`## Round ${k}${Wn(p.ticketId)}`,T=hr(p,o),f=xr(p),I=f?`${R}
4
4
 
5
5
  ${T}
6
6
 
7
- ${U}`:`${R}
7
+ ${f}`:`${R}
8
8
 
9
- ${T}`;u.push(f);for(let S of A){let C=`### Re-vote ${i.get(S.id)??0}${Mn(S.ticketId)}`,O=Ko(S,o),v=Jo(S),M=v?`${C}
9
+ ${T}`;u.push(I);for(let S of A){let y=`### Re-vote ${i.get(S.id)??0}${Wn(S.ticketId)}`,L=hr(S,o),b=xr(S),M=b?`${y}
10
10
 
11
- ${O}
11
+ ${L}
12
12
 
13
- ${v}`:`${C}
13
+ ${b}`:`${y}
14
14
 
15
- ${O}`;u.push(M);}}return u.join(`
15
+ ${L}`;u.push(M);}}return u.join(`
16
16
 
17
17
  `)+`
18
- `}function Lt(e,t,n){if(e.startsWith("custom-")){let r=(n??[]).find(i=>i.id===e);return r?{id:r.id,cards:r.cards}:void 0}let o=se[e];if(o){let r=(t??{})[e]??[];if(r.length===0)return o;let i=o.cards.filter((a,s)=>!r.includes(s));return i.length===0?void 0:{id:e,cards:i}}}function jt(e,t){let n=Object.keys(se).map(r=>Lt(r,e,t)).filter(r=>r!==void 0),o=(t??[]).map(r=>({id:r.id,cards:r.cards}));return [...n,...o]}function je(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 ho(e)}function qo(e,t,n){let o=L(e),r=Ht(o);if(!r)return {applied:false,reason:"no-active-round"};let i=o.participants.find(a=>a.id===t);return !i||!Ze(i)||me(i)!=="voter"?{applied:false,reason:"not-a-voter"}:r.votes[t]===n?(bn(e,r.id,t),{applied:true,effect:"cleared"}):(Ao(e,r.id,t,n),{applied:true,effect:"cast"})}function zo(e,t){let n=L(e),o=Ht(n);return o?(bn(e,o.id,t),{applied:true,effect:"cleared"}):{applied:false,reason:"no-active-round"}}var ds="https://hnch.dev";function gt(){let t=process.env.XDG_CONFIG_HOME||join(homedir(),".config");return join(t,"hnch")}function Un(){return join(gt(),"config.json")}function Zo(){let e=gt();existsSync(e)||mkdirSync(e,{recursive:true});}function Fe(){let e=Un();if(!existsSync(e))return {};try{return JSON.parse(readFileSync(e,"utf-8"))}catch{return {}}}function F(e){Zo();let n={...Fe(),...e};writeFileSync(Un(),JSON.stringify(n,null,2)+`
19
- `,"utf-8");}async function cs(e){let t=createInterface({input:process.stdin,output:process.stderr});return new Promise(n=>{t.question(e,o=>{t.close(),n(o.trim());});})}function ls(e){return e.startsWith("wss://")?"https://"+e.slice(6):e.startsWith("ws://")?"http://"+e.slice(5):e}async function ce(){let e=Fe(),t=false;if(e.participantId||(e.participantId=randomUUID(),t=true),!e.displayName){let o=await cs("Enter your display name: ");e.displayName=o||`user-${e.participantId.slice(0,6)}`,t=true;}e.relayUrl||(e.relayUrl=ds,t=true),(!e.avatarColor||$e(e.avatarColor)===null)&&(e.avatarColor=xo(e.participantId),t=true),t&&F(e);let n=process.env.HNCH_RELAY_URL||e.relayUrl;return n=ls(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 ht(e){Zo();let n={...Fe()};for(let[o,r]of Object.entries(e))r===""?delete n[o]:r!==void 0&&(n[o]=r);writeFileSync(Un(),JSON.stringify(n,null,2)+`
20
- `,"utf-8");}async function er(e,t){let n=await fetch(`${e}/rooms`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({})});if(!n.ok)throw new Error(`POST /rooms failed: ${n.status}`);return await n.json()}async function le(e,t){let n=await fetch(`${e}/rooms/${encodeURIComponent(t)}`);if(n.status===404){let o=await n.json().catch(()=>null);throw new Error(`Room not found: ${o?.reason??"unknown-room"}`)}if(!n.ok)throw new Error(`GET /rooms/:code failed: ${n.status}`);return await n.json()}async function Bn(e,t,n){let o=await fetch(`${e}/rooms/${t}/access`,{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({passwordHash:n})});if(!o.ok)throw new Error(`PATCH /rooms/:uuid/access failed: ${o.status}`)}function tr(e){let n=`${e.wsBaseUrl.replace(/^http/,"ws")}/ws`,o={did:e.deviceId};e.passwordHash!==void 0&&(o.pw=e.passwordHash);let r=new WebsocketProvider(n,e.roomUuid,e.doc,{params:o,connect:true,...e.awareness!==void 0&&{awareness:e.awareness},WebSocketPolyfill:ps}),i=u=>{e.onStatusChange?.(u.status);},a=u=>{if(u===null)return;let c=lo.get(u.code);c!==void 0&&(e.onRejection?.(c),r.shouldConnect=false,r.disconnect());};r.on("status",i),r.on("connection-close",a);let s=false,d=e.passwordHash;return {doc:e.doc,awareness:r.awareness,updateCredentials(u){if(u.passwordHash===d)return;d=u.passwordHash??void 0,r.shouldConnect=false,r.disconnect();let l={did:r.params.did??""};d!==void 0&&(l.pw=d),r.params=l,r.connect();},disconnect(){s||(s=true,r.off("status",i),r.off("connection-close",a),r.shouldConnect=false,r.disconnect(),r.destroy());}}}async function rr(e){let t,n=await er(e.relayUrl);e.password&&(t=await Le(e.password,n.uuid),await Bn(e.relayUrl,n.uuid,t));let o=new Ue.Doc,r=new Awareness(o),i=Date.now();return Cn(o,{roomUuid:n.uuid,createdAt:i,participantId:e.participantId,displayName:e.displayName,defaultScale:e.defaultScale??Nt,...e.sessionName!==void 0&&{sessionName:e.sessionName},...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}),r.setLocalStateField(Te,e.participantId),ot({doc:o,awareness:r,roomCode:n.code,roomUuid:n.uuid,participantId:e.participantId,relayUrl:e.relayUrl,passwordHash:t})}async function ir(e){let t=await le(e.relayUrl,e.roomCode),n;if(t.accessMode==="password"){if(!e.password)throw new Error("Room requires a password");n=await Le(e.password,t.uuid);}let o=new Ue.Doc,r=new Awareness(o);return Be(o,{participantId:e.participantId,displayName:e.displayName,...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}),r.setLocalStateField(Te,e.participantId),ot({doc:o,awareness:r,roomCode:e.roomCode,roomUuid:t.uuid,participantId:e.participantId,relayUrl:e.relayUrl,passwordHash:n,onRejection:e.onRejection})}function ot(e){let{doc:t,awareness:n,participantId:o,relayUrl:r,roomUuid:i}=e,a=new Set,s=new Set,d=new Set,u=tr({wsBaseUrl:e.relayUrl,roomUuid:e.roomUuid,doc:t,deviceId:o,passwordHash:e.passwordHash,awareness:n,onStatusChange(f){a.forEach(S=>S(f));},onRejection(f){console.error(`Connection rejected: ${f}`),e.onRejection?.(f);}}),c=()=>{s.forEach(f=>f());};t.getMap("meta").observeDeep(c),t.getMap("settings").observeDeep(c),t.getMap("participants").observeDeep(c),t.getArray("rounds").observeDeep(c);function l(){return Po(n.getStates())}let p=Do({projection:()=>L(t),onlineIds:l,myId:()=>o,subscribe(f){return s.add(f),n.on("change",f),()=>{s.delete(f),n.off("change",f);}},promote(f){nt(t,{hostParticipantId:f});}}),A=new Set,P=setInterval(()=>{let f=L(t),S=de(f);!S||A.has(S.id)||So(S,f.participants,l())&&(A.add(S.id),Nn(t));},250),R=t.getMap("settings").get("hostParticipantId"),T=()=>{let f=t.getMap("settings").get("hostParticipantId");f!==R&&f!==void 0&&d.forEach(S=>S(f)),R=f;};t.getMap("settings").observe(T);let U=false;return {doc:t,awareness:n,roomCode:e.roomCode,roomUuid:e.roomUuid,projection(){return L(t)},current(){return de(L(t))},isHost(){return L(t).settings.hostParticipantId===o},onlineIds:l,toggleCurrentVote(f){return qo(t,o,f)},clearCurrentVote(){return zo(t,o)},reveal(){Nn(t);},skip(){Fo(t);},newRound(f,S,b){let C=randomUUID(),O=Date.now();return Bt(t,{id:C,createdAt:O,createdBy:o,...f!==void 0&&{title:f},...S!==void 0&&{ticketId:S},...b!==void 0&&{agendaItemId:b}}),C},discardCurrentRound(){Vo(t,o);},revote(){let f=de(L(t)),S=randomUUID();return Bt(t,{id:S,createdAt:Date.now(),createdBy:o,...f?.id!==void 0&&{parentRoundId:f.id},...f?.title!==void 0&&{title:f.title},...f?.description!==void 0&&{description:f.description},...f?.ticketId!==void 0&&{ticketId:f.ticketId},...f?.agendaItemId!==void 0&&{agendaItemId:f.agendaItemId}}),S},updateRoundDescriptor(f,S){yn(t,f,S);},updateName(f){nt(t,{name:f});},updateScale(f){nt(t,{defaultScale:f});},updateDisplayName(f){let C=L(t).participants.find(O=>O.id===o)?.joinedAt??Date.now();Ut(t,o,{displayName:f,joinedAt:C});},async updateAccess(f,S){let b=null;if(f==="password"){if(!S)throw new Error("Password required for password mode");b=await Le(S,i);}await Bn(r,i,b),u.updateCredentials({passwordHash:b});},handoffHost(f){if(!this.isHost())throw new Error("Only the current host can hand off");if(!l().has(f))throw new Error("Target participant is not online");if(!L(t).participants.some(O=>O.id===f))throw new Error("Target participant does not exist");nt(t,{hostParticipantId:f});},toggleRole(){let S=L(t).participants.find(v=>v.id===o),C=me(S??{})==="viewer"?"voter":"viewer",O=S?.joinedAt??Date.now();Ut(t,o,{displayName:S?.displayName??"",joinedAt:O,role:C});},endSessionForEveryone(){if(!this.isHost())throw new Error("Only the current host can end the session");In(t);},onChange(f){return s.add(f),()=>s.delete(f)},onStatusChange(f){return a.add(f),()=>a.delete(f)},onHostChange(f){return d.add(f),()=>d.delete(f)},disconnect(){U||(U=true,clearInterval(P),p.stop(),t.getMap("meta").unobserveDeep(c),t.getMap("settings").unobserveDeep(c),t.getMap("settings").unobserve(T),t.getMap("participants").unobserveDeep(c),t.getArray("rounds").unobserveDeep(c),u.disconnect());}}}function sr(e){let t=kn(e);return t===""?null:t}function Ve(){return join(gt(),"last-session.json")}function Ss(e,t){let n=gt();mkdirSync(n,{recursive:true,mode:448}),chmodSync(n,448),writeFileSync(e,t,{encoding:"utf-8",mode:384}),chmodSync(e,384);}function _n(){let e=Ve();try{unlinkSync(e);}catch(t){if(t.code!=="ENOENT")throw t}}function Ln(){let e=Ve();if(!existsSync(e))return {};try{let t=JSON.parse(readFileSync(e,"utf-8"));return {...En(t).entries}}catch{return {}}}function jn(e){let t={version:2,entries:e};Ss(Ve(),JSON.stringify(t,null,2)+`
21
- `);}function Vt(e){let t=Date.now();if(!existsSync(Ve()))return [];let n;try{n=JSON.parse(readFileSync(Ve(),"utf-8"));}catch{return []}let o=En(n),r=$o(o,t),i=Object.values(r.entries);return i.length===0?(_n(),[]):i.toSorted((a,s)=>s.lastSeenAt-a.lastSeenAt)}function xs(e,t){return e!==void 0?{passwordHash:e}:t!==void 0?{passwordHash:t}:{}}function Fn(e){let t=Date.now(),n=Ln(),o=n[e.roomUuid];n[e.roomUuid]={roomCode:e.roomCode,roomUuid:e.roomUuid,lastSeenAt:e.lastSeenAt??t,...xs(e.passwordHash,o?.passwordHash)};let r=Object.keys(n);if(r.length>5){let i=r.toSorted((a,s)=>(n[a]?.lastSeenAt??0)-(n[s]?.lastSeenAt??0)).slice(0,r.length-5);for(let a of i)delete n[a];}jn(n);}function St(e){if(!existsSync(Ve()))return;let t=Ln();if(delete t[e],Object.keys(t).length===0){_n();return}jn(t);}function ws(){_n();}function Vn(e){if(!existsSync(Ve()))return;let t=Ln(),n=t[e];if(!n)return;let{passwordHash:o,...r}=n;t[e]=r,jn(t);}function Yn(e){Fn(e);}function xe(){ws();}async function Yt(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 Wt(e){let t=e.doc.getMap("meta"),n=null,o=false;function r(){if(o)return;let i=t.get("sessionEndedAt");if(i==null||i===n)return;n=i;let a=t.get("createdBy"),s=a===e.localParticipantId,d=e.doc.getMap("participants"),u=e.doc.getMap("settings").get("hostParticipantId")??a,c="host";if(u){let p=d.get(u)?.get("displayName");typeof p=="string"&&p.length>0&&(c=p);}setImmediate(()=>{o||e.onEnded({isLocal:s,hostName:c,timestamp:i});});}return t.observe(r),r(),()=>{o=true,t.unobserve(r);}}var Cs="@xauyxau/hnch";function Kt(e){return jo(e)}function Jt(e){return `${process.env.HNCH_SHARE_ORIGIN??"https://hnch.dev"}/join?code=${e}`}function Gt(e){return `npx ${Cs} join ${e}`}function Wn(e){let t=e.trim();return t===""?void 0:t}function qt(e){return e?{title:e.title??"",ticketId:e.ticketId??"",agendaItemId:e.id}:{title:"",ticketId:"",agendaItemId:void 0}}function lr(e,t,n){return [e,Wn(t),n]}var ys={connecting:"yellow",connected:"green",disconnected:"red"};function fr({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:ys[n],children:n})]})]})}function ge({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,d)=>{if(d.upArrow)a(u=>{let c=(u-1+e.length)%e.length,l=0;for(;e[c]?.disabled&&l<e.length;)c=(c-1+e.length)%e.length,l++;return c});else if(d.downArrow)a(u=>{let c=(u+1)%e.length,l=0;for(;e[c]?.disabled&&l<e.length;)c=(c+1)%e.length,l++;return c});else if(d.return){let u=e[i];u&&!u.disabled&&t(u.value);}else d.escape&&n?.();}),jsxs(Box,{flexDirection:"column",gap:1,children:[o&&jsx(Text,{bold:true,children:o}),jsx(Box,{flexDirection:"column",children:e.map((s,d)=>{let u=d===i,c=s.disabled??false;return jsxs(Box,{gap:1,children:[jsx(Text,{...u&&{color:"cyan"},dimColor:c,children:u?">":" "}),jsx(Text,{bold:u,dimColor:c,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 j({value:e,onChange:t,onSubmit:n,onCancel:o,placeholder:r,isActive:i=true,mask:a=false}){useInput((c,l)=>{l.escape?o?.():l.return?n(e):l.backspace||l.delete?t(e.slice(0,-1)):c&&!l.ctrl&&!l.meta&&t(e+c);},{isActive:i});let s=a&&e.length>0?"*".repeat(e.length):e,d=s.length>0?s:r??"",u=e.length===0&&r!==void 0;return jsxs(Text,{children:[jsx(Text,{dimColor:u,children:d}),jsx(Text,{inverse:true,children:" "})]})}function Sr({mode:e,password:t,onModeChange:n,onPasswordChange:o,onClose:r}){let[i,a]=useState(e==="open"?0:1),[s,d]=useState(false);return useEffect(()=>{a(e==="open"?0:1);},[e]),useInput((u,c)=>{if(c.leftArrow)a(l=>Math.max(0,l-1));else if(c.rightArrow)a(l=>Math.min(1,l+1));else if(c.return){let l=i===0?"open":"password";l!==e&&n(l),l==="password"&&d(true);}else c.escape&&r?.();},{isActive:!s}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Box,{gap:1,children:["open","password"].map((u,c)=>{let l=c===i,p=u===e,A=u==="open"?"Open":"Password";return jsx(Text,{inverse:l,bold:p,...p&&{color:"cyan"},children:p?`[${A}]`:` ${A} `},u)})}),e==="password"&&jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{children:"Password: "}),jsx(j,{value:t,onChange:o,onSubmit:()=>d(false),onCancel:()=>d(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 Cr({scaleId:e,cards:t,disabledIndices:n,onOverrideChange:o,onClose:r}){let i=useMemo(()=>new Set(n),[n]),[a,s]=useState(0),d=u=>{let c=new Set(i);if(c.has(u))c.delete(u);else {if(c.size>=t.length-1)return;c.add(u);}let l=Array.from(c).toSorted((p,A)=>p-A);o(e,l);};return useInput((u,c)=>{c.leftArrow?s(l=>Math.max(0,l-1)):c.rightArrow?s(l=>Math.min(t.length-1,l+1)):u===" "?d(a):(c.return||c.escape)&&r();}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Box,{gap:1,children:t.map((u,c)=>{let l=c===a,p=i.has(c);return jsx(Text,{inverse:l,bold:!p,...!p&&{color:"cyan"},strikethrough:p,dimColor:p,children:u},u)})}),jsx(Text,{dimColor:true,children:" \u2190\u2192 navigate space toggle \u23CE/esc done"})]})}function Zn({initialName:e="",initialCards:t=[],onSave:n,onCancel:o}){let r=e.length>0,[i,a]=useState(e),[s,d]=useState(t.length>0?t:[""]),[u,c]=useState(0),[l,p]=useState("editing-name"),[A,P]=useState(""),R=()=>{let f=i.trim();if(f.length===0||f.length>40){P("Name must be 1-40 characters");return}a(f),P(""),p("editing-cards");},T=()=>{let f=i.trim();if(f.length===0||f.length>40){P("Name must be 1-40 characters");return}let S=s.map(C=>C.trim()).filter(C=>C.length>0),b=Array.from(new Set(S));if(b.length<2){P("Need at least 2 unique non-empty cards");return}P(""),n(f,b);};return useInput((f,S)=>{if(l==="editing-cards"){if(S.leftArrow)c(b=>Math.max(0,b-1));else if(S.rightArrow)c(b=>{let C=b+1;return C>=s.length&&s.length<25?(d(O=>[...O,""]),C):Math.min(C,s.length-1)});else if(S.return)T();else if(S.escape)o();else if(S.tab)p("editing-name");else if(S.backspace){let b=s[u]||"";if(b.length===0){if(s.length>2){let C=s.filter((O,v)=>v!==u);d(C),c(Math.max(0,u-1));}}else {let C=[...s];C[u]=b.slice(0,-1),d(C);}}else if(f&&!S.ctrl&&!S.meta){let b=s[u]||"";if(b.length<10){let C=[...s];C[u]=b+f,d(C);}}}},{isActive:l==="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(j,{value:i,onChange:a,onSubmit:R,onCancel:o,placeholder:"Scale name",isActive:l==="editing-name"})]}),l==="editing-cards"&&jsxs(Box,{flexDirection:"column",gap:0,children:[jsx(Text,{children:"Cards:"}),jsx(Box,{gap:1,flexWrap:"wrap",children:s.map((f,S)=>{let b=S===u;return jsx(Text,{inverse:b,...!b&&{color:"cyan"},children:f.length>0?f:"\xB7"},S)})})]}),A&&jsx(Text,{color:"red",children:A}),jsx(Text,{dimColor:true,children:l==="editing-name"?"\u23CE next esc cancel":"\u2190\u2192 navigate typing adds card bsp delete \u23CE save tab name esc cancel"})]})}function Qt({scales:e,selectedScaleId:t,presetOverrides:n,customScales:o=[],onSelect:r,onOverrideChange:i,onCustomScaleCreate:a,onCustomScaleEdit:s,onCustomScaleDelete:d,onClose:u,showNoneOption:c=false}){let[l,p]=useState(0),[A,P]=useState(null),[R,T]=useState("browsing"),[U,f]=useState(null),[S,b]=useState(null),C=a?[...e,{id:"__create-custom__",cards:[]}]:e,O=C.length;if(useInput((v,M)=>{if(R==="browsing"){if(M.escape){u();return}if(O===0)return;if(M.upArrow)p(I=>(I-1+O)%O);else if(M.downArrow)p(I=>(I+1)%O);else if(M.return){let I=C[l];if(!I)return;if(I.id==="__create-custom__"){T("creating");return}I.id in se?P(A===I.id?null:I.id):r(I.id);}else if(v===" "){let I=C[l];I&&I.id!=="__create-custom__"&&r(I.id);}else if(v==="e"||v==="E"){let I=C[l];s&&I?.id.startsWith("custom-")&&(f(I.id),T("editing"));}else if(v==="d"||v==="D"){let I=C[l];d&&I?.id.startsWith("custom-")&&(b(I.id),T("confirming-delete"));}}else R==="confirming-delete"&&(v==="y"||v==="Y"?(S&&d&&d(S),b(null),T("browsing")):(v==="n"||v==="N"||M.escape)&&(b(null),T("browsing")));},{isActive:R==="browsing"&&A===null||R==="confirming-delete"}),R==="creating")return jsx(Zn,{onSave:(v,M)=>{a&&a(v,M),T("browsing");},onCancel:()=>T("browsing")});if(R==="editing"&&U){let v=o?.find(I=>I.id===U);if(e.find(I=>I.id===U)&&v)return jsx(Zn,{initialName:v.label,initialCards:v.cards,onSave:(I,N)=>{s&&s(U,I,N),f(null),T("browsing");},onCancel:()=>{f(null),T("browsing");}})}if(R==="confirming-delete"&&S){let v=C.find(I=>I.id===S),M=v?je(v.id,o):"Unknown";return jsxs(Box,{flexDirection:"column",gap:1,children:[jsxs(Text,{children:["Delete ",M,"? "]}),jsx(Text,{children:"[y] yes [n] no esc cancel"})]})}return C.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:C.map((v,M)=>{let I=M===l,N=v.id===t,ue=A===v.id,oe=v.id in se,re=v.id==="__create-custom__",V=v.cards.join(", "),q=c&&v.id==="",z=q?"(none)":re?"[+ Create custom scale]":je(v.id,o);return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{...I&&{color:"cyan"},children:I?">":" "}),jsx(Text,{bold:I,children:z}),!q&&!re&&jsx(Text,{dimColor:true,children:V}),N&&jsx(Text,{color:"cyan",children:"[current]"})]}),ue&&!q&&!re&&jsx(Box,{paddingLeft:2,children:oe?jsx(Cr,{scaleId:v.id,cards:se[v.id]?.cards??[],disabledIndices:n?.[v.id]??[],onOverrideChange:i,onClose:()=>P(null)}):null})]},v.id||"none")})}),jsx(Text,{dimColor:true,children:(()=>{let v=l<C.length?C[l]:null;return v?.id.startsWith("custom-")?`\u2191\u2193 navigate space select${s?" [e] edit":""}${d?" [d] delete":""} esc back`:v&&v.id in se?"\u2191\u2193 navigate \u23CE customize space select esc back":"\u2191\u2193 navigate \u23CE/space select esc back"})()})]})}function $s(e,t){return t?[...e]:e.filter(n=>n.value==="display-name")}function yr({sessionName:e,displayName:t,currentScale:n,accessMode:o,presetOverrides:r,customScales:i,isHost:a=true,onChangeName:s,onChangeScale:d,onChangeDisplayName:u,onChangeAccess:c,onClose:l}){let[p,A]=useState(r??{}),P=useMemo(()=>jt(p,i),[p,i]),[R,T]=useState("main-menu"),[U,f]=useState(e??""),[S,b]=useState(t),[C,O]=useState(o==="password"?"password":"open"),[v,M]=useState(""),[I,N]=useState(false),ue=[{label:"Room name",value:"room-name",detail:`[${e??"(none)"}]`},{label:"Scale",value:"scale",detail:`[${je(n.id,i)}]`},{label:"Access",value:"access",detail:`[${o==="open"?"Open":"Password"}]`},{label:"Display name",value:"display-name",detail:`[${t}]`}],oe=$s(ue,a);function re(m){!a&&m!=="display-name"||(m==="room-name"?(f(e??""),T("editing-room-name")):m==="scale"?T("picking-scale"):m==="access"?T("picking-access"):m==="display-name"&&(b(t),T("editing-display-name")));}function V(m){let x=m.trim()===""?void 0:m.trim();s(x),T("main-menu");}function q(m){let x=m.trim();x.length>0&&(u(x),process.nextTick(()=>F({displayName:x}))),T("main-menu");}function z(m){let x=P.find(E=>E.id===m);x&&d(x),T("main-menu");}function ve(m,x){let E={...p};x.length===0?delete E[m]:E[m]=x,A(E),F({presetOverrides:Object.keys(E).length>0?E:void 0});}async function he(m,x){N(true);try{await c(m,x),O(m),M(m==="password"?x??"":"");}catch(E){console.error(`Failed to update access: ${E}`);}finally{N(false),T("main-menu");}}return R==="main-menu"?jsx(ge,{title:"\u2500\u2500 Settings \u2500\u2500",items:oe,onSelect:re,onClose:l}):R==="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(j,{value:U,onChange:f,onSubmit:V,onCancel:()=>T("main-menu"),placeholder:"(leave empty to remove)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]}):R==="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(j,{value:S,onChange:b,onSubmit:q,onCancel:()=>T("main-menu"),placeholder:"(required)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]}):R==="picking-scale"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),jsx(Qt,{scales:P,selectedScaleId:n.id,presetOverrides:p,onSelect:z,onOverrideChange:ve,onClose:()=>T("main-menu")})]}):R==="picking-access"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),I&&jsx(Text,{dimColor:true,children:"Updating access..."}),!I&&jsx(Sr,{mode:C,password:v,onModeChange:m=>{m==="open"&&he("open");},onPasswordChange:M,onClose:()=>T("main-menu")})]}):jsx(Box,{})}function tn({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),d=s?"\u25CF":"\u25CB",u=s?"green":"gray",c=a.id===n,l=me(a)==="viewer",p=a.id===i,A=a.id in o,P=l?" (viewer)":r?o[a.id]?` \u2192 ${o[a.id]}`:"":A?" \u2713":" \xB7",R=p&&!l&&!(r&&o[a.id]);return jsxs(Box,{gap:1,children:[jsx(Text,{color:u,children:d}),jsxs(Text,{children:[a.displayName,c?" (host)":""]}),R?jsx(Text,{color:"cyan",children:"(voter)"}):jsx(Text,{color:l?"gray":A?"green":"gray",children:P})]},a.id)})]})}var Us=[{label:"End session for everyone",value:"end-session",detail:"Disconnects all participants. Cannot be undone."}];function br({onPick:e,onClose:t}){return jsx(ge,{title:"Host Actions",items:Us,onSelect:e,onClose:t})}function nn({roomCode:e,onPick:t,onClose:n}){let o=[{label:"Copy code",value:"code",detail:Kt(e)},{label:"Copy share link",value:"url",detail:Jt(e)},{label:"Copy npx command",value:"npx",detail:Gt(e)}];return jsx(ge,{title:"Share",items:o,onSelect:r=>t(r),onClose:n})}function _s(e){let t=e.rounds.filter(o=>ae(o.status)),n=Object.fromEntries(e.participants.map(o=>[o.id,o]));return Go({rounds:t,participants:n})}async function Ir(e,t,n){let o=_s(e);try{await t(o),n("Results copied to clipboard");}catch{n("Clipboard write failed");}}function Ar(e,t,n){let o=Bo(e.id,n);return o===null?`Round ${t}`:`Round ${o.depth}/${o.total} [re-vote]`}function Rr(e,t,n){let o=Ar(e,t,n),r=e.title?` \u2014 ${e.title}`:"",i=e.ticketId?` [${e.ticketId}]`:"",a=e.status==="skipped"?" \u2014 Skipped":" \u2014 Results";return `${o}${r}${i}${a}`}function Tr(e){let t=Object.values(e).filter(c=>!W(c)).map(c=>parseFloat(c)).filter(c=>!isNaN(c)).toSorted((c,l)=>c-l);if(t.length===0)return {average:"-",median:"-",agreement:"-"};let o=t.reduce((c,l)=>c+l,0)/t.length,r=Math.floor(t.length/2),i=t.length%2===0?(t[r-1]+t[r])/2:t[r],a=Object.values(e).filter(c=>!W(c)),s=new Map;for(let c of a)s.set(c,(s.get(c)??0)+1);let d=Math.max(...s.values()),u=a.length>0?Math.round(d/a.length*100):0;return {average:o.toFixed(1),median:i.toFixed(1),agreement:`${u}%`}}function to(e,t){let n=Math.floor((t-e)/1e3),o=Math.floor(n/60),r=n%60;return `${o}:${r.toString().padStart(2,"0")}`}function Er(e,t,n=[]){let o=Ar(e,t,n);if(e.status==="skipped"){let l=e.title?` ${e.title}`:"",p=e.ticketId?` [${e.ticketId}]`:"";return `${o}:${l}${p} \u2014 Skipped`}let r=new Map;for(let l of Object.values(e.votes))W(l)||r.set(l,(r.get(l)??0)+1);let i=[...r.entries()].toSorted((l,p)=>p[1]-l[1]||l[0].localeCompare(p[0])).map(([l,p])=>`${l}\xD7${p}`).join(", "),a=Object.values(e.votes).filter(W).length,s=a>0?` (${a} abstained)`:"",d=e.title?` ${e.title}`:"",u=e.ticketId?` [${e.ticketId}]`:"",c=e.timerStartedAt!==void 0&&e.status==="revealed"&&e.terminalAt!==void 0?` \u2014 ${to(e.timerStartedAt,e.terminalAt)}`:"";return `${o}:${d}${u} \u2014 ${i||"(no votes)"}${s}${c}`}function kr({projection:e,onlineIds:t,isHost:n,participantId:o,rounds:r,currentRound:i,settingsOpen:a,onStartRound:s,onNewRound:d,onRevote:u,onOpenSettings:c,onHandoffHost:l,onEndSession:p,onShare:A,shareOpen:P,onSetShareOpen:R,roomCode:T,confirmingQuit:U,myRole:f,onToggleRole:S,roundTitlePromptActive:b,roundTitleInput:C,onRoundTitleChange:O,onRoundTitleSubmit:v,onRoundTitleCancel:M,roundTicketIdPromptActive:I,roundTicketIdInput:N,onRoundTicketIdChange:ue,onRoundTicketIdSubmit:oe,onRoundTicketIdCancel:re,descriptorPromptActive:V,descriptorInput:q,onDescriptorChange:z,onDescriptorSubmit:ve,onDescriptorCancel:he,onEditDescriptor:m,canExport:x,onExportResults:E,onAgendaAdd:Y,agendaAddPromptActive:pe,agendaAddTitleInput:at,onAgendaAddTitleChange:pn,onAgendaAddTitleSubmit:qe,onAgendaAddTitleCancel:Rt,agendaAddTicketIdPromptActive:be,agendaAddTicketIdInput:fn,onAgendaAddTicketIdChange:ze,onAgendaAddTicketIdSubmit:Xe,onAgendaAddTicketIdCancel:De}){let[X,Q]=on.useState("idle"),[Se,Ie]=on.useState(null),[dt,ie]=on.useState(false),[fe,Oe]=on.useState(false);useEffect(()=>{n||(Q("idle"),Ie(null),ie(false),Oe(false));},[n]),useInput(w=>{if(w==="c"||w==="C"){R(true);return}if(w==="w"||w==="W"){S();return}if((w==="x"||w==="X")&&x){E();return}if(n){if(w==="a"||w==="A"){Y();return}(w==="e"||w==="E")&&c(),(w==="s"||w==="S")&&s(),(w==="h"||w==="H")&&Q("picking"),(w==="m"||w==="M")&&ie(true),i!==null&&ae(i.status)&&((w==="n"||w==="N")&&d(),(w==="v"||w==="V")&&i.status!=="skipped"&&u(),(w==="t"||w==="T")&&m());}},{isActive:!a&&!U&&X==="idle"&&!b&&!I&&!dt&&!fe&&!P&&!V&&!pe&&!be}),useInput((w,Z)=>{w==="y"||w==="Y"?(p(),Oe(false)):(w==="n"||w==="N"||Z.escape)&&Oe(false);},{isActive:fe});let Ae=e.participants.filter(w=>w.id!==o&&t.has(w.id));useInput(w=>{if(X==="picking"){let Z=parseInt(w,10);!isNaN(Z)&&Z>=1&&Z<=Ae.length?(Ie(Ae[Z-1].id),Q("confirming")):(w==="Escape"||w==="q"||w==="Q")&&Q("idle");}},{isActive:X==="picking"}),useInput(w=>{X==="confirming"&&Se&&(w==="y"||w==="Y"?(l(Se),Q("idle"),Ie(null)):(w==="n"||w==="N"||w==="Escape")&&(Q("idle"),Ie(null)));},{isActive:X==="confirming"});let Me=r.length>0,Tt=r.filter(w=>ae(w.status)),ct=i!==null?Tt.slice(0,-1):Tt;return dt?jsx(br,{onPick:w=>{ie(false),w==="end-session"&&Oe(true);},onClose:()=>ie(false)}):P?jsx(nn,{roomCode:T,onPick:w=>{R(false),A(w);},onClose:()=>R(false)}):jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:Me?"Session":"Waiting for participants..."}),!Me&&jsx(Text,{dimColor:true,children:"No rounds started yet."}),jsx(tn,{participants:e.participants,onlineIds:t,hostId:e.settings.hostParticipantId,votes:{},revealed:false,participantId:o}),e.agenda.length>0&&jsx(Ys,{items:e.agenda,nextPending:_e(e)}),i!==null&&ae(i.status)&&jsx(js,{projection:e,round:i,rounds:r}),ct.length>0&&jsxs(Box,{flexDirection:"column",children:[jsx(Text,{dimColor:true,children:"\u2500\u2500 History \u2500\u2500"}),ct.map(w=>{let Z=r.indexOf(w)+1;return jsx(Text,{dimColor:true,children:Er(w,Z,r)},w.id)})]}),X==="picking"&&Ae.length>0&&jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{children:"Hand off to:"}),Ae.map((w,Z)=>jsxs(Text,{children:["[",Z+1,"] ",w.displayName]},w.id)),jsx(Text,{dimColor:true,children:"[q] Cancel"})]}),X==="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"})]}),X==="confirming"&&Se&&jsx(Box,{flexDirection:"column",children:jsxs(Text,{children:["Hand off to ",e.participants.find(w=>w.id===Se)?.displayName,"? [y/n]"]})}),b&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Round title (optional, Enter to skip):"}),jsx(j,{value:C,onChange:O,onSubmit:v,onCancel:M,placeholder:"Enter to skip",isActive:b})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),I&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Ticket ID (optional, Enter to skip):"}),jsx(j,{value:N,onChange:ue,onSubmit:oe,onCancel:re,placeholder:"e.g. PROJ-1234",isActive:I})]}),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(j,{value:q,onChange:z,onSubmit:ve,onCancel:he,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"})]}),pe&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Agenda title (optional, Enter to skip):"}),jsx(j,{value:at,onChange:pn,onSubmit:qe,onCancel:Rt,placeholder:"Enter to skip",isActive:pe})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),be&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Agenda ticket ID (optional, Enter to skip):"}),jsx(j,{value:fn,onChange:ze,onSubmit:Xe,onCancel:De,placeholder:"e.g. PROJ-1234",isActive:be})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),X==="idle"&&!b&&!I&&!V&&!fe&&!pe&&!be&&jsxs(Box,{gap:2,children:[n?jsx(Fragment,{children:i!==null&&ae(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] ",f==="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] ",f==="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] ",f==="viewer"?"Vote":"Observe"]})]}),jsx(Text,{children:"[q] Quit"})]})]})}function js({projection:e,round:t,rounds:n}){let o=n.indexOf(t)+1,r=Rr(t,o,n);if(t.status==="skipped")return jsx(Box,{flexDirection:"column",gap:1,children:jsx(Text,{bold:true,children:r})});let i=Tr(t.votes),a=new Map(e.participants.map(p=>[p.id,p.displayName])),s=t.timerStartedAt!==void 0&&t.status==="revealed"&&t.terminalAt!==void 0?to(t.timerStartedAt,t.terminalAt):null,d=Object.entries(t.votes),u=d.filter(([,p])=>!W(p)),c=d.filter(([,p])=>W(p)).map(([p])=>p),l=u[0]?.[1];return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:r}),An(t)&&l!==void 0&&jsxs(Text,{bold:true,color:"green",children:["Consensus! Everyone voted ",l]}),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)})]}),u.map(([p,A])=>jsxs(Box,{gap:2,children:[jsx(Text,{children:(a.get(p)??p).padEnd(20)}),jsx(Text,{color:"cyan",bold:true,children:A.padEnd(10)})]},p)),c.map(p=>jsxs(Box,{gap:2,children:[jsx(Text,{dimColor:true,children:(a.get(p)??p).padEnd(20)}),jsx(Text,{dimColor:true,children:"(abstained)".padEnd(10)})]},p)),e.participants.filter(p=>!(p.id in t.votes)).map(p=>jsxs(Box,{gap:2,children:[jsx(Text,{dimColor:true,children:p.displayName.padEnd(20)}),jsx(Text,{dimColor:true,children:"(no vote)".padEnd(10)})]},p.id))]}),jsxs(Box,{gap:2,children:[jsxs(Text,{children:["Avg: ",jsx(Text,{bold:true,children:i.average})]}),jsxs(Text,{children:["Med: ",jsx(Text,{bold:true,children:i.median})]}),jsxs(Text,{children:["Agreement: ",jsx(Text,{bold:true,children:i.agreement})]}),s!==null&&jsxs(Text,{dimColor:true,children:["\u23F1 ",s]})]})]})}var Fs={pending:"\u2022",consumed:"\u2713",skipped:"~",cancelled:"\u2717"},Vs={consumed:"green",skipped:"yellow",cancelled:"red"};function Ys({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=Fs[o.state]??"?",i=Vs[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 Dr({scale:e,selected:t,onToggleCurrentVote:n,onClearCurrentVote:o,disabled:r}){let[i,a]=useState(0);return useInput((s,d)=>{r||(d.leftArrow?a(u=>Math.max(0,u-1)):d.rightArrow?a(u=>Math.min(e.cards.length-1,u+1)):d.return?n(e.cards[i]):(d.backspace||d.delete)&&o());}),jsxs(Box,{flexDirection:"column",gap:0,children:[jsx(Box,{gap:1,children:e.cards.map((s,d)=>{let u=d===i,c=s===t;return jsx(Text,{inverse:u,bold:c,...c&&{color:"cyan"},children:c?`[${s}]`:` ${s} `},s)})}),jsx(Text,{dimColor:true,children:" \u2190\u2192 navigate \u23CE select \u232B clear"})]})}function qs(e){let t=Math.floor(e/1e3),n=Math.floor(t/60),o=t%60;return `${n}:${o.toString().padStart(2,"0")}`}function Or({projection:e,round:t,onlineIds:n,isHost:o,myId:r,myRole:i,elapsedMs:a,roomCode:s,shareOpen:d,settingsOpen:u,onToggleCurrentVote:c,onClearCurrentVote:l,onReveal:p,onSkip:A,onDiscard:P,onToggleRole:R,onShare:T,onSetShareOpen:U,onOpenSettings:f,confirmingQuit:S}){let b=t.votes[r],C=b!==void 0&&W(b);if(useInput(N=>{if(N==="e"||N==="E"){f();return}if(N==="c"||N==="C"){U(true);return}if(i==="voter"&&(N==="a"||N==="A")){c(Pt);return}o&&(N==="r"||N==="R")&&p(),o&&(N==="s"||N==="S")&&A(),o&&(N==="d"||N==="D")&&P(),(N==="w"||N==="W")&&R();},{isActive:!S&&!u&&!d}),d)return jsx(nn,{roomCode:s,onPick:N=>{U(false),T(N);},onClose:()=>U(false)});let O=b,v=e.rounds.indexOf(t)+1,M=t.title?` \u2014 ${t.title}`:"",I=t.ticketId?` [${t.ticketId}]`:"";return jsxs(Box,{flexDirection:"column",gap:1,children:[jsxs(Box,{gap:2,children:[jsxs(Text,{bold:true,children:["Round ",v,M,I]}),a!==void 0&&jsxs(Text,{dimColor:true,children:["\u23F1 ",qs(a)]})]}),jsxs(Box,{gap:4,children:[jsx(tn,{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:[C&&jsx(Text,{dimColor:true,children:"(abstaining this round \u2014 press [a] to vote)"}),jsx(Dr,{scale:t.scale,selected:C?void 0:O,onToggleCurrentVote:c,onClearCurrentVote:l,disabled:S||C})]})]}),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] ",C?"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 Zs=3e3;function an(e=Zs){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}}function na(e){let t=de(e);return !t||ae(t.status)?"lobby":"voting"}function cn({session:e,participantId:t,displayName:n,accessMode:o,presetOverrides:r,customScales:i}){let{exit:a}=useApp(),[s,d]=useState(e.projection()),[u,c]=useState("connecting"),[l,p]=useState(e.onlineIds()),[A,P]=useState(),[R,T]=useState(false),[U,f]=useState(o==="password"?"password":"open"),[S,b]=useState(n),[C,O]=useState(false),[v,M]=useState(false),[I,N]=useState(""),[ue,oe]=useState(false),[re,V]=useState(""),[q,z]=useState(),[ve,he]=useState(false),[m,x]=useState(""),[E,Y]=useState(null),[pe,at]=useState(false),[pn,qe]=useState(""),[Rt,be]=useState(false),[fn,ze]=useState(""),[Xe,De]=useState(),[X,Q]=useState(),Se=an(3e3),[Ie,dt]=useState(false),ie=an(3e3),fe=an(3e3);useEffect(()=>{let y=e.onChange(()=>{d(e.projection()),p(e.onlineIds());}),B=e.onStatusChange(c),Qe=e.onHostChange(Et=>{let vi=e.projection().participants.find(Ii=>Ii.id===Et),bi=Et===t?"You are now the host":`${vi?.displayName||"Unknown"} is now the host`;Se.show(bi);}),gn=setInterval(()=>{p(e.onlineIds());let Et=e.projection(),kt=de(Et);kt?.timerStartedAt!==void 0&&tt(kt.status)?P(Date.now()-kt.timerStartedAt):P(void 0);},1e3);return ()=>{y(),B(),Qe(),clearInterval(gn);}},[e,t,Se.show]),useInput(y=>{(y==="q"||y==="Q")&&O(true);},{isActive:!R&&!C&&!v&&!ue&&!ve&&!Ie&&!pe&&!Rt}),useInput((y,B)=>{y==="y"||y==="Y"?(e.disconnect(),a()):(y==="n"||y==="N"||B.escape)&&O(false);},{isActive:C});let Oe=na(s),Ae=de(s),Me=s.settings.hostParticipantId===t,Tt=s.participants.find(y=>y.id===t),ct=me(Tt??{}),w=useCallback(()=>{let y=qt(_e(s));N(y.title),Q(y.agendaItemId),M(true);},[s]),Z=useCallback(y=>{M(false),N(""),z(Wn(y));let B=qt(_e(s));V(B.ticketId),oe(true);},[s]),Gr=useCallback(()=>{M(false),N(""),z(void 0),Q(void 0);},[]),qr=useCallback(y=>{oe(false),V("");let[B,Qe,gn]=lr(q,y,X);e.newRound(B,Qe,gn),z(void 0),Q(void 0);},[e,q,X]),zr=useCallback(()=>{oe(false),V(""),z(void 0),Q(void 0);},[]),Xr=useCallback(()=>{let y=e.current();!y||y.status!=="revealed"||(Y(y.id),x(y.title??""),he(true));},[e]),Qr=useCallback(y=>{let B=E;if(he(false),Y(null),!B)return;let Qe=y.trim();Qe!==""&&e.updateRoundDescriptor(B,{title:Qe});},[e,E]),Zr=useCallback(()=>{he(false),Y(null);},[]),ei=useCallback(y=>{e.toggleCurrentVote(y);},[e]),ti=useCallback(()=>{e.clearCurrentVote();},[e]),ni=useCallback(()=>{e.reveal();},[e]),oi=useCallback(()=>{e.skip();},[e]),ri=useCallback(()=>{e.discardCurrentRound();},[e]),ii=useCallback(()=>{let y=qt(_e(s));N(y.title),Q(y.agendaItemId),M(true);},[s]),si=useCallback(()=>{e.revote();},[e]),so=useCallback(()=>{e.toggleRole();},[e]),ai=useCallback(y=>{e.updateName(y);},[e]),di=useCallback(y=>{e.updateScale(y);},[e]),ci=useCallback(y=>{e.updateDisplayName(y),b(y);},[e]),li=useCallback(async(y,B)=>{await e.updateAccess(y,B),f(y);},[e]),ui=useCallback(y=>{try{e.handoffHost(y);}catch(B){console.error(`Handoff failed: ${B instanceof Error?B.message:String(B)}`);}},[e]),ao=useCallback(()=>{T(true);},[]),pi=useCallback(()=>{T(false);},[]),fi=useCallback(()=>{e.endSessionForEveryone();},[e]),co=useCallback(async y=>{let B=y==="code"?Kt(e.roomCode):y==="url"?Jt(e.roomCode):Gt(e.roomCode);try{await $r.write(B),ie.show("Copied!");}catch{ie.show(`Copy failed \u2014 ${B}`);}},[e.roomCode,ie]),mn=s.rounds.filter(y=>ae(y.status)),mi=mn.length>0?mn.at(-1):null,gi=mn.length>0,hi=useCallback(()=>Ir(s,y=>$r.write(y),fe.show),[s,fe.show]),Si=useCallback(()=>{qe(""),at(true);},[]),xi=useCallback(y=>{at(false),qe("");let B=y.trim()===""?void 0:y.trim();De(B),ze(""),be(true);},[]),wi=useCallback(()=>{at(false),qe(""),De(void 0);},[]),Ci=useCallback(y=>{be(false),ze("");let B=y.trim()===""?void 0:y.trim();if(!Xe&&!B){De(void 0);return}mt(e.doc,{...Xe!==void 0&&{title:Xe},...B!==void 0&&{ticketId:B},createdAt:Date.now()}),De(void 0);},[e.doc,Xe]),yi=useCallback(()=>{be(false),ze(""),De(void 0);},[]);return jsxs(Box,{flexDirection:"column",children:[jsx(fr,{roomCode:e.roomCode,sessionName:s.settings.name,status:u,isHost:Me}),Se.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:"yellow",children:Se.notice})}),ie.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:ie.notice.startsWith("Copy failed")?"red":"green",children:ie.notice})}),fe.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:fe.notice.startsWith("Clipboard write failed")?"red":"green",children:fe.notice})}),R?jsx(yr,{sessionName:s.settings.name,displayName:S,currentScale:s.settings.defaultScale,accessMode:U,presetOverrides:r,customScales:i,isHost:Me,onChangeName:ai,onChangeScale:di,onChangeDisplayName:ci,onChangeAccess:li,onClose:pi}):Oe==="lobby"?jsx(kr,{projection:s,onlineIds:l,isHost:Me,participantId:t,rounds:s.rounds,currentRound:mi,settingsOpen:R,onStartRound:w,onNewRound:ii,roundTitlePromptActive:v,roundTitleInput:I,onRoundTitleChange:N,onRoundTitleSubmit:Z,onRoundTitleCancel:Gr,roundTicketIdPromptActive:ue,roundTicketIdInput:re,onRoundTicketIdChange:V,onRoundTicketIdSubmit:qr,onRoundTicketIdCancel:zr,onRevote:si,onOpenSettings:ao,onHandoffHost:ui,onEndSession:fi,onShare:co,shareOpen:Ie,onSetShareOpen:dt,roomCode:e.roomCode,confirmingQuit:C,myRole:ct,onToggleRole:so,descriptorPromptActive:ve,descriptorInput:m,onDescriptorChange:x,onDescriptorSubmit:Qr,onDescriptorCancel:Zr,onEditDescriptor:Xr,canExport:gi,onExportResults:hi,onAgendaAdd:Si,agendaAddPromptActive:pe,agendaAddTitleInput:pn,onAgendaAddTitleChange:qe,onAgendaAddTitleSubmit:xi,onAgendaAddTitleCancel:wi,agendaAddTicketIdPromptActive:Rt,agendaAddTicketIdInput:fn,onAgendaAddTicketIdChange:ze,onAgendaAddTicketIdSubmit:Ci,onAgendaAddTicketIdCancel:yi}):Oe==="voting"&&Ae?jsx(Or,{projection:s,round:Ae,onlineIds:l,isHost:Me,myId:t,myRole:ct,elapsedMs:A,onToggleCurrentVote:ei,onClearCurrentVote:ti,onReveal:ni,onSkip:oi,onDiscard:ri,onToggleRole:so,onShare:co,onSetShareOpen:dt,shareOpen:Ie,settingsOpen:R,onOpenSettings:ao,roomCode:e.roomCode,confirmingQuit:C}):null,C&&jsx(Box,{children:jsx(Text,{dimColor:true,children:"Leave session? y/n"})})]})}function Ur({presetOverrides:e,customScales:t}){let{exit:n}=useApp(),[o,r]=useState("main-menu"),[i,a]=useState(Fe()),[s,d]=useState(i.displayName??""),[u,c]=useState(i.relayUrl??""),[l,p]=useState(i.defaultSessionName??""),[A,P]=useState(i.avatarColor?.startsWith("#")?i.avatarColor:""),[R,T]=useState(t??[]),[U,f]=useState(e??{});useInput(m=>{(m==="q"||m==="Q")&&n();},{isActive:o==="main-menu"});let S=useMemo(()=>jt(U,R),[U,R]),b=i.defaultScale,C=b?S.find(m=>m.id===b):void 0,O=[{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:`[${C?je(C.id,R):"(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:`[${da(i.avatarColor)}]`}];function v(m){m==="display-name"?(d(i.displayName??""),r("editing-display-name")):m==="relay-url"?(c(i.relayUrl??""),r("editing-relay-url")):m==="default-scale"?r("picking-scale"):m==="default-session-name"?(p(i.defaultSessionName??""),r("editing-session-name")):m==="default-password"?r("picking-default-password"):m==="avatar-color"&&r("picking-avatar-color");}function M(m){if(m==="custom-hex"){P(i.avatarColor?.startsWith("#")?i.avatarColor:""),r("editing-avatar-hex");return}if($e(m)===null){r("main-menu");return}a({...i,avatarColor:m}),F({avatarColor:m}),r("main-menu");}function I(m){let x=m.trim();if(x.length===0){r("picking-avatar-color");return}let E=x.startsWith("#")?x.toLowerCase():`#${x.toLowerCase()}`;$e(E)!==null&&(a({...i,avatarColor:E}),F({avatarColor:E}),r("main-menu"));}function N(m){let x=m.trim();if(x.length>0){let E={...i,displayName:x};a(E),F({displayName:x});}r("main-menu");}function ue(m){let x=m.trim();if(x.length>0){let E={...i,relayUrl:x};a(E),F({relayUrl:x});}r("main-menu");}function oe(m){let x=m.trim(),E=x.length>0?{...i,defaultSessionName:x}:{...i};x.length===0?(delete E.defaultSessionName,a(E),ht({defaultSessionName:""})):(a(E),F({defaultSessionName:x})),r("main-menu");}function re(m){let x=m.length>0?{...i,defaultScale:m}:{...i};m.length===0?(delete x.defaultScale,a(x),ht({defaultScale:""})):(a(x),F({defaultScale:m})),r("main-menu");}function V(m,x){let E={...U};x.length===0?delete E[m]:E[m]=x,f(E),F({presetOverrides:Object.keys(E).length>0?E:void 0});}function q(m){let x=m==="on",E={...i,defaultPassword:x};a(E),F({defaultPassword:x}),r("main-menu");}function z(m,x){let E=`custom-${randomUUID()}`,Y=[...R,{id:E,label:m,cards:x}];T(Y),a({...i,customScales:Y}),F({customScales:Y});}function ve(m,x,E){let Y=R.map(pe=>pe.id===m?{id:m,label:x,cards:E}:pe);T(Y),a({...i,customScales:Y}),F({customScales:Y});}function he(m){let x=R.filter(Y=>Y.id!==m);T(x);let E={...i,customScales:x};i.defaultScale===m?(E.defaultScale="fibonacci",F({customScales:x,defaultScale:"fibonacci"})):F({customScales:x}),a(E);}if(o==="main-menu")return jsx(ge,{title:"\u2500\u2500 Config Settings \u2500\u2500",items:O,onSelect:v,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(j,{value:s,onChange:d,onSubmit:N,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(j,{value:u,onChange:c,onSubmit:ue,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(j,{value:l,onChange:p,onSubmit:oe,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:[]},...S];return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(Qt,{scales:m,selectedScaleId:b??"",presetOverrides:U,customScales:R,onSelect:re,onOverrideChange:V,onCustomScaleCreate:z,onCustomScaleEdit:ve,onCustomScaleDelete:he,onClose:()=>r("main-menu"),showNoneOption:true})]})}if(o==="picking-avatar-color"){let m=lt.map(x=>({label:et[x].label,value:x,detail:i.avatarColor===x?"[current]":et[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(ge,{title:"Avatar color:",items:m,onSelect:M,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(j,{value:A,onChange:P,onSubmit:I,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(ge,{title:"Default password:",items:m,onSelect:q,onClose:()=>r("main-menu")})]})}return jsx(Box,{})}function da(e){return e?e.startsWith("#")?e:lt.includes(e)?et[e].label:e:"(auto)"}var la={pending:"\u2022",consumed:"\u2713",skipped:"~",cancelled:"\u2717"};function ua(e){let t=la[e.state]??"?",n=[];e.ticketId&&n.push(`[${e.ticketId}]`),e.title&&n.push(e.title);let o=n.join(" ")||e.id;return `${t} ${o}`}async function It(e){let t=new Ue.Doc,n=new Awareness(t);Be(t,{participantId:e.participantId,displayName:e.displayName}),n.setLocalStateField(Te,e.participantId);let o=ot({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 At(){let e=Vt();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 Hr(e){!e.title?.trim()&&!e.ticket?.trim()&&(console.error("At least one of --title or --ticket is required"),process.exit(1));let t=await ce(),n=await At();try{await le(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 It({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=mt(o,{...e.title?.trim()?{title:e.title.trim()}:{},...e.ticket?.trim()?{ticketId:e.ticket.trim()}:{},...e.description?.trim()?{description:e.description.trim()}:{},createdAt:Date.now()});await new Promise(a=>{setTimeout(a,300);}),console.log(`Added agenda item: ${i}`);}finally{r();}}async function _r(){let e=await ce(),t=await At();try{await le(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 It({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=L(n).agenda;if(i.length===0){console.log("No agenda items.");return}i.forEach((a,s)=>{console.log(`${String(s+1).padStart(2)}. ${ua(a)}`);});}finally{o();}}async function Lr(e){let t=await ce(),n=await At();try{await le(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 It({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{_t(o,e.id,"skipped",{timestamp:Date.now()}),await new Promise(i=>{setTimeout(i,300);}),console.log(`Skipped agenda item: ${e.id}`);}catch(i){console.error(`Skip failed: ${i instanceof Error?i.message:String(i)}`),process.exit(1);}finally{r();}}async function jr(e){let t=await ce(),n=await At();try{await le(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 It({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{_t(o,e.id,"cancelled",{timestamp:Date.now()}),await new Promise(i=>{setTimeout(i,300);}),console.log(`Cancelled agenda item: ${e.id}`);}catch(i){console.error(`Cancel failed: ${i instanceof Error?i.message:String(i)}`),process.exit(1);}finally{r();}}async function Fr(e){let t=await ce(),n=await At();try{await le(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 It({relayUrl:t.relayUrl,participantId:t.participantId,displayName:t.displayName,roomCode:n.roomCode,roomUuid:n.roomUuid,...n.passwordHash!==void 0&&{passwordHash:n.passwordHash}});try{Tn(o,e.id,e.before,e.after),await new Promise(i=>{setTimeout(i,300);}),console.log(`Reordered agenda item: ${e.id}`);}catch(i){console.error(`Move failed: ${i instanceof Error?i.message:String(i)}`),process.exit(1);}finally{r();}}async function io(){return new Promise(e=>{let t=createInterface({input:process.stdin,output:process.stderr});process.stderr.write("Password: "),t.question("",n=>{t.close(),e(n);});})}async function ma(e){let t=await ce(),n=e.scale??t.defaultScale??"fibonacci",o=e.name??t.defaultSessionName,r=e.password??t.defaultPassword??false,i;r&&(i=await io());let a=Lt(n,t.presetOverrides,t.customScales);if(!a){let l=Object.keys(se).join(", ");console.error(`Unknown or fully-disabled scale: "${n}". Builtin IDs: ${l}`),process.exit(1);}let s=await rr({participantId:t.participantId,displayName:t.displayName,relayUrl:t.relayUrl,sessionName:o,password:i,defaultScale:a,...t.avatarColor!==void 0&&{avatarColor:t.avatarColor}}),d;i&&(d=await Le(i,s.roomUuid)),Yn({roomCode:s.roomCode,roomUuid:s.roomUuid,lastSeenAt:Date.now(),...d!==void 0&&{passwordHash:d}}),console.error(`Room created: ${s.roomCode}`),console.error(`Share: hnch join ${s.roomCode}`),console.error("");let{waitUntilExit:u,unmount:c}=render(on.createElement(cn,{session:s,participantId:t.participantId,displayName:t.displayName,accessMode:i?"password":"open",presetOverrides:t.presetOverrides,customScales:t.customScales}));Wt({doc:s.doc,localParticipantId:t.participantId,onEnded:async l=>{console.error(l.isLocal?"Session ended.":`Session ended by ${l.hostName}.`),c();try{await xe();}catch(p){console.error(`Failed to clear cached session: ${p instanceof Error?p.message:String(p)}`);}s.disconnect(),process.exit(0);}}),await u(),s.disconnect(),xe(),process.exit(0);}async function ga(e){let t=await ce(),n=sr(e.code);n===null&&(console.error("invalid room code"),process.exit(1));let o;e.password&&(o=await io());let r=await le(t.relayUrl,n),i;r.accessMode==="password"&&!e.password?i=await io():e.password&&(i=o);let a,s=false,d=await ir({participantId:t.participantId,displayName:t.displayName,relayUrl:t.relayUrl,roomCode:n,password:i,...t.avatarColor!==void 0&&{avatarColor:t.avatarColor},onRejection(l){if(l==="unknown-room"){Yt({clearLastSession:xe,logger:console,exit:process.exit});return}l==="room-full"&&(s=true,a?.());}}),u;i&&(u=await Le(i,d.roomUuid)),Yn({roomCode:d.roomCode,roomUuid:d.roomUuid,lastSeenAt:Date.now(),...u!==void 0&&{passwordHash:u}}),console.error(`Joined room: ${d.roomCode}`),console.error("");let c=render(on.createElement(cn,{session:d,participantId:t.participantId,displayName:t.displayName,accessMode:r.accessMode,presetOverrides:t.presetOverrides,customScales:t.customScales}));a=c.unmount,Wt({doc:d.doc,localParticipantId:t.participantId,onEnded:async l=>{console.error(l.isLocal?"Session ended.":`Session ended by ${l.hostName}.`),a?.();try{await xe();}catch(p){console.error(`Failed to clear cached session: ${p instanceof Error?p.message:String(p)}`);}d.disconnect(),process.exit(0);}}),await c.waitUntilExit(),s&&(console.error("This room is full (max 20 participants)."),d.disconnect(),xe(),process.exit(1)),d.disconnect(),xe(),process.exit(0);}function ha(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 Sa(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}.
22
- `),r());});};o.on("close",()=>n(new Error("stdin closed"))),r();})}async function Vr(e,t){let n;try{n=await le(e.relayUrl,t.roomCode);}catch(c){if((c instanceof Error?c.message:String(c)).includes("Room not found"))return St(t.roomUuid),await Yt({clearLastSession:xe,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`),Vn(t.roomUuid),process.exit(0)),console.error(`Rejoining room ${t.roomCode}\u2026`),console.error("");let o=new Ue.Doc,r=new Awareness(o);Be(o,{participantId:e.participantId,displayName:e.displayName,...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}),r.setLocalStateField(Te,e.participantId);let i=false,a=false,s,d=ot({doc:o,awareness:r,roomCode:t.roomCode,roomUuid:t.roomUuid,participantId:e.participantId,relayUrl:e.relayUrl,passwordHash:t.passwordHash,onRejection(c){if(c==="unknown-room"){St(t.roomUuid),Yt({clearLastSession:xe,logger:console,exit:process.exit});return}c==="wrong-password"&&(i=true,s?.()),c==="room-full"&&(a=true,s?.());}});Fn({roomCode:d.roomCode,roomUuid:d.roomUuid,lastSeenAt:Date.now(),...t.passwordHash!==void 0&&{passwordHash:t.passwordHash}});let u=render(on.createElement(cn,{session:d,participantId:e.participantId,displayName:e.displayName,accessMode:n.accessMode,presetOverrides:e.presetOverrides,customScales:e.customScales}));s=u.unmount,Wt({doc:d.doc,localParticipantId:e.participantId,onEnded:async c=>{console.error(c.isLocal?"Session ended.":`Session ended by ${c.hostName}.`),s?.();try{St(t.roomUuid);}catch(l){console.error(`Failed to clear cached session: ${l instanceof Error?l.message:String(l)}`);}d.disconnect(),process.exit(0);}}),await u.waitUntilExit(),a&&(console.error("This room is full (max 20 participants)."),d.disconnect(),process.exit(1)),i&&(Vn(t.roomUuid),console.error(`Password changed \u2014 rejoin with: hnch join ${t.roomCode} --password`),d.disconnect(),process.exit(0)),d.disconnect(),St(t.roomUuid),process.exit(0);}async function xa(){let e=await ce(),t=Vt();if(t.length===0&&(console.error("No recent session to resume."),process.exit(0)),t.length===1)return Vr(e,t[0]);let n=Date.now();process.stderr.write(`Recent rooms:
23
- `);for(let[r,i]of t.entries()){let a=ha(i.lastSeenAt,n);process.stderr.write(` ${r+1}. ${i.roomCode} (${a})
18
+ `}function Gt(e,t,n){if(e.startsWith("custom-")){let r=(n??[]).find(i=>i.id===e);return r?{id:r.id,cards:r.cards}:void 0}let o=se[e];if(o){let r=(t??{})[e]??[];if(r.length===0)return o;let i=o.cards.filter((s,a)=>!r.includes(a));return i.length===0?void 0:{id:e,cards:i}}}function Jt(e,t){let n=Object.keys(se).map(r=>Gt(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 Vo(e)}function Cr(e){return et(e)===null?"lobby":"estimating"}function wr(e,t,n){let o=_(e),r=et(o);if(!r)return {applied:false,reason:"no-active-round"};let i=o.participants.find(s=>s.id===t);return !i||!tt(i)||me(i)!=="voter"?{applied:false,reason:"not-a-voter"}:r.votes[t]===n?(Pn(e,r.id,t),{applied:true,effect:"cleared"}):(Ao(e,r.id,t,n),{applied:true,effect:"cast"})}function yr(e,t){let n=_(e),o=et(n);return o?(Pn(e,o.id,t),{applied:true,effect:"cleared"}):{applied:false,reason:"no-active-round"}}var js="https://hnch.dev";function St(){let t=process.env.XDG_CONFIG_HOME||join(homedir(),".config");return join(t,"hnch")}function Gn(){return join(St(),"config.json")}function br(){let e=St();existsSync(e)||mkdirSync(e,{recursive:true});}function Ve(){let e=Gn();if(!existsSync(e))return {};try{return JSON.parse(readFileSync(e,"utf-8"))}catch{return {}}}function F(e){br();let n={...Ve(),...e};writeFileSync(Gn(),JSON.stringify(n,null,2)+`
19
+ `,"utf-8");}async function Fs(e){let t=createInterface({input:process.stdin,output:process.stderr});return new Promise(n=>{t.question(e,o=>{t.close(),n(o.trim());});})}function Vs(e){return e.startsWith("wss://")?"https://"+e.slice(6):e.startsWith("ws://")?"http://"+e.slice(5):e}async function de(){let e=Ve(),t=false;if(e.participantId||(e.participantId=randomUUID(),t=true),!e.displayName){let o=await Fs("Enter your display name: ");e.displayName=o||`user-${e.participantId.slice(0,6)}`,t=true;}e.relayUrl||(e.relayUrl=js,t=true),(!e.avatarColor||_e(e.avatarColor)===null)&&(e.avatarColor=Wo(e.participantId),t=true),t&&F(e);let n=process.env.HNCH_RELAY_URL||e.relayUrl;return n=Vs(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 Ct(e){br();let n={...Ve()};for(let[o,r]of Object.entries(e))r===""?delete n[o]:r!==void 0&&(n[o]=r);writeFileSync(Gn(),JSON.stringify(n,null,2)+`
20
+ `,"utf-8");}async function Tr(e){let t,n=await nr(e.relayUrl);e.password&&(t=await je(e.password,n.uuid),await Hn(e.relayUrl,n.uuid,t));let o=new Ue.Doc,r=new Awareness(o),i=Date.now();return Rn(o,{roomUuid:n.uuid,createdAt:i,participantId:e.participantId,displayName:e.displayName,defaultScale:e.defaultScale??Vt,...e.sessionName!==void 0&&{sessionName:e.sessionName},...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}),r.setLocalStateField(Ee,e.participantId),rt({doc:o,awareness:r,roomCode:n.code,roomUuid:n.uuid,participantId:e.participantId,relayUrl:e.relayUrl,passwordHash:t})}async function Er(e){let t=await ae(e.relayUrl,e.roomCode),n;if(t.accessMode==="password"){if(!e.password)throw new Error("Room requires a password");n=await je(e.password,t.uuid);}let o=new Ue.Doc,r=new Awareness(o);return He(o,{participantId:e.participantId,displayName:e.displayName,joinedAt:Date.now(),...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}),r.setLocalStateField(Ee,e.participantId),rt({doc:o,awareness:r,roomCode:e.roomCode,roomUuid:t.uuid,participantId:e.participantId,relayUrl:e.relayUrl,passwordHash:n,onRejection:e.onRejection,clearLeftStatusOnSync:true})}function rt(e){let{doc:t,awareness:n,participantId:o,relayUrl:r,roomUuid:i}=e,s=new Set,a=new Set,c=new Set,u=or({httpBaseUrl:e.relayUrl,roomUuid:e.roomUuid,doc:t,credentials:{roomCode:e.roomCode,deviceId:o,...e.passwordHash!==void 0&&{passwordHash:e.passwordHash}},awareness:n,WebSocketPolyfill:Ys,onStatusChange(f){s.forEach(I=>I(f));},onRejectionChange(f){f!==null&&(console.error(`Connection rejected: ${f}`),e.onRejection?.(f));},onRepeatRejection(){console.error("Trouble reaching the room \u2014 retrying.");},...e.clearLeftStatusOnSync===true&&{onSynced:()=>{cr(t,o);}}}),d=()=>{a.forEach(f=>f());};t.getMap("meta").observeDeep(d),t.getMap("settings").observeDeep(d),t.getMap("participants").observeDeep(d),t.getArray("rounds").observeDeep(d);function l(){return Ko(n.getStates())}let p=Jo({projection:()=>_(t),onlineIds:l,myId:()=>o,subscribe(f){return a.add(f),n.on("change",f),()=>{a.delete(f),n.off("change",f);}},promote(f){ur(t,f);}}),A=Yo({projection:()=>_(t),onlineIds:l,subscribe(f){return a.add(f),n.on("change",f),()=>{a.delete(f),n.off("change",f);}},reveal(){jn(t);}}),k=t.getMap("settings").get("hostParticipantId"),R=()=>{let f=t.getMap("settings").get("hostParticipantId");f!==k&&f!==void 0&&c.forEach(I=>I(f)),k=f;};t.getMap("settings").observe(R);let T=false;return {doc:t,awareness:n,roomCode:e.roomCode,roomUuid:e.roomUuid,projection(){return _(t)},current(){return ie(_(t))},isHost(){return _(t).settings.hostParticipantId===o},onlineIds:l,toggleCurrentVote(f){return wr(t,o,f)},clearCurrentVote(){return yr(t,o)},reveal(){jn(t);},skip(){fr(t);},newRound(f,I,S){let v=randomUUID(),y=Date.now();return _t(t,{id:v,createdAt:y,createdBy:o,...f!==void 0&&{title:f},...I!==void 0&&{ticketId:I},...S!==void 0&&{agendaItemId:S}}),v},discardCurrentRound(){mr(t,o);},revote(){let f=ie(_(t)),I=randomUUID();return _t(t,{id:I,createdAt:Date.now(),createdBy:o,...f?.id!==void 0&&{parentRoundId:f.id},...f?.title!==void 0&&{title:f.title},...f?.description!==void 0&&{description:f.description},...f?.ticketId!==void 0&&{ticketId:f.ticketId},...f?.agendaItemId!==void 0&&{agendaItemId:f.agendaItemId}}),I},updateRoundDescriptor(f,I){En(t,f,I);},updateName(f){Bt(t,{name:f});},updateScale(f){Bt(t,{defaultScale:f});},updateDisplayName(f){return ar(t,o,f)},async updateAccess(f,I){let S=null;if(f==="password"){if(!I)throw new Error("Password required for password mode");S=await je(I,i);}await Hn(r,i,S),u.updateCredentials({passwordHash:S});},handoffHost(f){return lr(t,o,f,l())},toggleRole(){return dr(t,o)},endSessionForEveryone(){return pr(t,o)},onChange(f){return a.add(f),()=>a.delete(f)},onStatusChange(f){return s.add(f),()=>s.delete(f)},onHostChange(f){return c.add(f),()=>c.delete(f)},disconnect(){T||(T=true,A.stop(),p.stop(),t.getMap("meta").unobserveDeep(d),t.getMap("settings").unobserveDeep(d),t.getMap("settings").unobserve(R),t.getMap("participants").unobserveDeep(d),t.getArray("rounds").unobserveDeep(d),u.disconnect());}}}function kr(e){let t=Ln(e);return t===""?null:t}function Ye(){return join(St(),"last-session.json")}function qs(e,t){let n=St();mkdirSync(n,{recursive:true,mode:448}),chmodSync(n,448),writeFileSync(e,t,{encoding:"utf-8",mode:384}),chmodSync(e,384);}function qn(){let e=Ye();try{unlinkSync(e);}catch(t){if(t.code!=="ENOENT")throw t}}function zn(){let e=Ye();if(!existsSync(e))return {};try{let t=JSON.parse(readFileSync(e,"utf-8"));return {...Un(t).entries}}catch{return {}}}function Xn(e){let t={version:2,entries:e};qs(Ye(),JSON.stringify(t,null,2)+`
21
+ `);}function zt(e){let t=Date.now();if(!existsSync(Ye()))return [];let n;try{n=JSON.parse(readFileSync(Ye(),"utf-8"));}catch{return []}let o=Un(n),r=zo(o,t),i=Object.values(r.entries);return i.length===0?(qn(),[]):i.toSorted((s,a)=>a.lastSeenAt-s.lastSeenAt)}function zs(e,t){return e!==void 0?{passwordHash:e}:t!==void 0?{passwordHash:t}:{}}function Qn(e){let t=Date.now(),n=zn(),o=n[e.roomUuid];n[e.roomUuid]={roomCode:e.roomCode,roomUuid:e.roomUuid,lastSeenAt:e.lastSeenAt??t,...zs(e.passwordHash,o?.passwordHash)};let r=Object.keys(n);if(r.length>5){let i=r.toSorted((s,a)=>(n[s]?.lastSeenAt??0)-(n[a]?.lastSeenAt??0)).slice(0,r.length-5);for(let s of i)delete n[s];}Xn(n);}function wt(e){if(!existsSync(Ye()))return;let t=zn();if(delete t[e],Object.keys(t).length===0){qn();return}Xn(t);}function Xs(){qn();}function Zn(e){if(!existsSync(Ye()))return;let t=zn(),n=t[e];if(!n)return;let{passwordHash:o,...r}=n;t[e]=r,Xn(t);}function eo(e){Qn(e);}function Ce(){Xs();}async function Xt(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 Qt(e){let t=e.doc.getMap("meta"),n=null,o=false;function r(){if(o)return;let i=t.get("sessionEndedAt");if(i==null||i===n)return;n=i;let s=t.get("createdBy"),a=s===e.localParticipantId,c=e.doc.getMap("participants"),u=e.doc.getMap("settings").get("hostParticipantId")??s,d="host";if(u){let p=c.get(u)?.get("displayName");typeof p=="string"&&p.length>0&&(d=p);}setImmediate(()=>{o||e.onEnded({isLocal:a,hostName:d,timestamp:i});});}return t.observe(r),r(),()=>{o=true,t.unobserve(r);}}var Qs="@xauyxau/hnch";function Zt(e){return ir(e)}function en(e){return `${process.env.HNCH_SHARE_ORIGIN??"https://hnch.dev"}/join?code=${e}`}function tn(e){return `npx ${Qs} join ${e}`}function to(e){let t=e.trim();return t===""?void 0:t}function nn(e){return e?{title:e.title??"",ticketId:e.ticketId??"",agendaItemId:e.id}:{title:"",ticketId:"",agendaItemId:void 0}}function Or(e,t,n){return [e,to(t),n]}var Zs={connecting:"yellow",connected:"green",disconnected:"red"};function Ur({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:Zs[n],children:n})]})]})}function ge({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(a=>!a.disabled),[i,s]=useState(Math.max(r,0));return useInput((a,c)=>{if(c.upArrow)s(u=>{let d=(u-1+e.length)%e.length,l=0;for(;e[d]?.disabled&&l<e.length;)d=(d-1+e.length)%e.length,l++;return d});else if(c.downArrow)s(u=>{let d=(u+1)%e.length,l=0;for(;e[d]?.disabled&&l<e.length;)d=(d+1)%e.length,l++;return d});else if(c.return){let u=e[i];u&&!u.disabled&&t(u.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((a,c)=>{let u=c===i,d=a.disabled??false;return jsxs(Box,{gap:1,children:[jsx(Text,{...u&&{color:"cyan"},dimColor:d,children:u?">":" "}),jsx(Text,{bold:u,dimColor:d,children:a.label}),a.detail&&jsx(Text,{dimColor:true,children:a.detail})]},a.value)})}),jsx(Text,{dimColor:true,children:"\u2191\u2193 select \u23CE confirm esc close"})]})}function j({value:e,onChange:t,onSubmit:n,onCancel:o,placeholder:r,isActive:i=true,mask:s=false}){useInput((d,l)=>{l.escape?o?.():l.return?n(e):l.backspace||l.delete?t(e.slice(0,-1)):d&&!l.ctrl&&!l.meta&&t(e+d);},{isActive:i});let a=s&&e.length>0?"*".repeat(e.length):e,c=a.length>0?a:r??"",u=e.length===0&&r!==void 0;return jsxs(Text,{children:[jsx(Text,{dimColor:u,children:c}),jsx(Text,{inverse:true,children:" "})]})}function _r({mode:e,password:t,onModeChange:n,onPasswordChange:o,onClose:r}){let[i,s]=useState(e==="open"?0:1),[a,c]=useState(false);return useEffect(()=>{s(e==="open"?0:1);},[e]),useInput((u,d)=>{if(d.leftArrow)s(l=>Math.max(0,l-1));else if(d.rightArrow)s(l=>Math.min(1,l+1));else if(d.return){let l=i===0?"open":"password";l!==e&&n(l),l==="password"&&c(true);}else d.escape&&r?.();},{isActive:!a}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Box,{gap:1,children:["open","password"].map((u,d)=>{let l=d===i,p=u===e,A=u==="open"?"Open":"Password";return jsx(Text,{inverse:l,bold:p,...p&&{color:"cyan"},children:p?`[${A}]`:` ${A} `},u)})}),e==="password"&&jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{children:"Password: "}),jsx(j,{value:t,onChange:o,onSubmit:()=>c(false),onCancel:()=>c(false),placeholder:"(required to join)",isActive:a,mask:true}),!a&&jsx(Text,{dimColor:true,children:"\u23CE edit \u2190 \u2192 switch mode esc close"}),a&&jsx(Text,{dimColor:true,children:"\u23CE done esc cancel"})]}),e==="open"&&jsx(Text,{dimColor:true,children:"\u2190\u2192 toggle \u23CE confirm esc close"})]})}function Vr({scaleId:e,cards:t,disabledIndices:n,onOverrideChange:o,onClose:r}){let i=useMemo(()=>new Set(n),[n]),[s,a]=useState(0),c=u=>{let d=new Set(i);if(d.has(u))d.delete(u);else {if(d.size>=t.length-1)return;d.add(u);}let l=Array.from(d).toSorted((p,A)=>p-A);o(e,l);};return useInput((u,d)=>{d.leftArrow?a(l=>Math.max(0,l-1)):d.rightArrow?a(l=>Math.min(t.length-1,l+1)):u===" "?c(s):(d.return||d.escape)&&r();}),jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Box,{gap:1,children:t.map((u,d)=>{let l=d===s,p=i.has(d);return jsx(Text,{inverse:l,bold:!p,...!p&&{color:"cyan"},strikethrough:p,dimColor:p,children:u},u)})}),jsx(Text,{dimColor:true,children:" \u2190\u2192 navigate space toggle \u23CE/esc done"})]})}function lo({initialName:e="",initialCards:t=[],onSave:n,onCancel:o}){let r=e.length>0,[i,s]=useState(e),[a,c]=useState(t.length>0?t:[""]),[u,d]=useState(0),[l,p]=useState("editing-name"),[A,k]=useState(""),R=()=>{let I=i.trim();if(I.length===0||I.length>40){k("Name must be 1-40 characters");return}s(I),k(""),p("editing-cards");},T=()=>{let I=i.trim();if(I.length===0||I.length>40){k("Name must be 1-40 characters");return}let S=a.map(y=>y.trim()).filter(y=>y.length>0),v=Array.from(new Set(S));if(v.length<2){k("Need at least 2 unique non-empty cards");return}k(""),n(I,v);};return useInput((I,S)=>{if(l==="editing-cards"){if(S.leftArrow)d(v=>Math.max(0,v-1));else if(S.rightArrow)d(v=>{let y=v+1;return y>=a.length&&a.length<25?(c(L=>[...L,""]),y):Math.min(y,a.length-1)});else if(S.return)T();else if(S.escape)o();else if(S.tab)p("editing-name");else if(S.backspace){let v=a[u]||"";if(v.length===0){if(a.length>2){let y=a.filter((L,b)=>b!==u);c(y),d(Math.max(0,u-1));}}else {let y=[...a];y[u]=v.slice(0,-1),c(y);}}else if(I&&!S.ctrl&&!S.meta){let v=a[u]||"";if(v.length<10){let y=[...a];y[u]=v+I,c(y);}}}},{isActive:l==="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(j,{value:i,onChange:s,onSubmit:R,onCancel:o,placeholder:"Scale name",isActive:l==="editing-name"})]}),l==="editing-cards"&&jsxs(Box,{flexDirection:"column",gap:0,children:[jsx(Text,{children:"Cards:"}),jsx(Box,{gap:1,flexWrap:"wrap",children:a.map((I,S)=>{let v=S===u;return jsx(Text,{inverse:v,...!v&&{color:"cyan"},children:I.length>0?I:"\xB7"},S)})})]}),A&&jsx(Text,{color:"red",children:A}),jsx(Text,{dimColor:true,children:l==="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:s,onCustomScaleEdit:a,onCustomScaleDelete:c,onClose:u,showNoneOption:d=false}){let[l,p]=useState(0),[A,k]=useState(null),[R,T]=useState("browsing"),[f,I]=useState(null),[S,v]=useState(null),y=s?[...e,{id:"__create-custom__",cards:[]}]:e,L=y.length;if(useInput((b,M)=>{if(R==="browsing"){if(M.escape){u();return}if(L===0)return;if(M.upArrow)p(E=>(E-1+L)%L);else if(M.downArrow)p(E=>(E+1)%L);else if(M.return){let E=y[l];if(!E)return;if(E.id==="__create-custom__"){T("creating");return}E.id in se?k(A===E.id?null:E.id):r(E.id);}else if(b===" "){let E=y[l];E&&E.id!=="__create-custom__"&&r(E.id);}else if(b==="e"||b==="E"){let E=y[l];a&&E?.id.startsWith("custom-")&&(I(E.id),T("editing"));}else if(b==="d"||b==="D"){let E=y[l];c&&E?.id.startsWith("custom-")&&(v(E.id),T("confirming-delete"));}}else R==="confirming-delete"&&(b==="y"||b==="Y"?(S&&c&&c(S),v(null),T("browsing")):(b==="n"||b==="N"||M.escape)&&(v(null),T("browsing")));},{isActive:R==="browsing"&&A===null||R==="confirming-delete"}),R==="creating")return jsx(lo,{onSave:(b,M)=>{s&&s(b,M),T("browsing");},onCancel:()=>T("browsing")});if(R==="editing"&&f){let b=o?.find(E=>E.id===f);if(e.find(E=>E.id===f)&&b)return jsx(lo,{initialName:b.label,initialCards:b.cards,onSave:(E,D)=>{a&&a(f,E,D),I(null),T("browsing");},onCancel:()=>{I(null),T("browsing");}})}if(R==="confirming-delete"&&S){let b=y.find(E=>E.id===S),M=b?Fe(b.id,o):"Unknown";return jsxs(Box,{flexDirection:"column",gap:1,children:[jsxs(Text,{children:["Delete ",M,"? "]}),jsx(Text,{children:"[y] yes [n] no esc cancel"})]})}return y.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:y.map((b,M)=>{let E=M===l,D=b.id===t,ce=A===b.id,ne=b.id in se,oe=b.id==="__create-custom__",V=b.cards.join(", "),z=d&&b.id==="",X=z?"(none)":oe?"[+ Create custom scale]":Fe(b.id,o);return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{...E&&{color:"cyan"},children:E?">":" "}),jsx(Text,{bold:E,children:X}),!z&&!oe&&jsx(Text,{dimColor:true,children:V}),D&&jsx(Text,{color:"cyan",children:"[current]"})]}),ce&&!z&&!oe&&jsx(Box,{paddingLeft:2,children:ne?jsx(Vr,{scaleId:b.id,cards:se[b.id]?.cards??[],disabledIndices:n?.[b.id]??[],onOverrideChange:i,onClose:()=>k(null)}):null})]},b.id||"none")})}),jsx(Text,{dimColor:true,children:(()=>{let b=l<y.length?y[l]:null;return b?.id.startsWith("custom-")?`\u2191\u2193 navigate space select${a?" [e] edit":""}${c?" [d] delete":""} esc back`:b&&b.id in se?"\u2191\u2193 navigate \u23CE customize space select esc back":"\u2191\u2193 navigate \u23CE/space select esc back"})()})]})}function fa(e,t){return t?[...e]:e.filter(n=>n.value==="display-name")}function Yr({sessionName:e,displayName:t,currentScale:n,accessMode:o,presetOverrides:r,customScales:i,isHost:s=true,onChangeName:a,onChangeScale:c,onChangeDisplayName:u,onChangeAccess:d,onClose:l}){let[p,A]=useState(r??{}),k=useMemo(()=>Jt(p,i),[p,i]),[R,T]=useState("main-menu"),[f,I]=useState(e??""),[S,v]=useState(t),[y,L]=useState(o==="password"?"password":"open"),[b,M]=useState(""),[E,D]=useState(false),ce=[{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}]`}],ne=fa(ce,s);function oe(m){!s&&m!=="display-name"||(m==="room-name"?(I(e??""),T("editing-room-name")):m==="scale"?T("picking-scale"):m==="access"?T("picking-access"):m==="display-name"&&(v(t),T("editing-display-name")));}function V(m){let x=m.trim()===""?void 0:m.trim();a(x),T("main-menu");}function z(m){let x=m.trim();x.length>0&&(u(x),process.nextTick(()=>F({displayName:x}))),T("main-menu");}function X(m){let x=k.find(P=>P.id===m);x&&c(x),T("main-menu");}function Ie(m,x){let P={...p};x.length===0?delete P[m]:P[m]=x,A(P),F({presetOverrides:Object.keys(P).length>0?P:void 0});}async function he(m,x){D(true);try{await d(m,x),L(m),M(m==="password"?x??"":"");}catch(P){console.error(`Failed to update access: ${P}`);}finally{D(false),T("main-menu");}}return R==="main-menu"?jsx(ge,{title:"\u2500\u2500 Settings \u2500\u2500",items:ne,onSelect:oe,onClose:l}):R==="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(j,{value:f,onChange:I,onSubmit:V,onCancel:()=>T("main-menu"),placeholder:"(leave empty to remove)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]}):R==="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(j,{value:S,onChange:v,onSubmit:z,onCancel:()=>T("main-menu"),placeholder:"(required)",isActive:true}),jsx(Text,{dimColor:true,children:"\u23CE confirm esc back"})]}):R==="picking-scale"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),jsx(sn,{scales:k,selectedScaleId:n.id,presetOverrides:p,onSelect:X,onOverrideChange:Ie,onClose:()=>T("main-menu")})]}):R==="picking-access"?jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Settings \u2500\u2500"}),E&&jsx(Text,{dimColor:true,children:"Updating access..."}),!E&&jsx(_r,{mode:y,password:b,onModeChange:m=>{m==="open"&&he("open");},onPasswordChange:M,onClose:()=>T("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(s=>{let a=t.has(s.id),c=a?"\u25CF":"\u25CB",u=a?"green":"gray",d=s.id===n,l=me(s)==="viewer",p=s.id===i,A=s.id in o,k=l?" (viewer)":r?o[s.id]?` \u2192 ${o[s.id]}`:"":A?" \u2713":" \xB7",R=p&&!l&&!(r&&o[s.id]);return jsxs(Box,{gap:1,children:[jsx(Text,{color:u,children:c}),jsxs(Text,{children:[s.displayName,d?" (host)":""]}),R?jsx(Text,{color:"cyan",children:"(voter)"}):jsx(Text,{color:l?"gray":A?"green":"gray",children:k})]},s.id)})]})}var ma=[{label:"End session for everyone",value:"end-session",detail:"Disconnects all participants. Cannot be undone."}];function Kr({onPick:e,onClose:t}){return jsx(ge,{title:"Host Actions",items:ma,onSelect:e,onClose:t})}function ln({roomCode:e,onPick:t,onClose:n}){let o=[{label:"Copy code",value:"code",detail:Zt(e)},{label:"Copy share link",value:"url",detail:en(e)},{label:"Copy npx command",value:"npx",detail:tn(e)}];return jsx(ge,{title:"Share",items:o,onSelect:r=>t(r),onClose:n})}function xa(e){let t=e.rounds.filter(o=>fe(o.status)),n=Object.fromEntries(e.participants.map(o=>[o.id,o]));return Sr({rounds:t,participants:n})}async function Gr(e,t,n){let o=xa(e);try{await t(o),n("Results copied to clipboard");}catch{n("Clipboard write failed");}}function Jr(e,t){let n=Vn(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 qr(e,t){let n=Vn(e,t);if(e.status==="skipped"){let l=e.title?` ${e.title}`:"",p=e.ticketId?` [${e.ticketId}]`:"";return `${n}:${l}${p} \u2014 Skipped`}let o=new Map;for(let l of Object.values(e.votes))G(l)||o.set(l,(o.get(l)??0)+1);let r=[...o.entries()].toSorted((l,p)=>p[1]-l[1]||l[0].localeCompare(p[0])).map(([l,p])=>`${l}\xD7${p}`).join(", "),i=Object.values(e.votes).filter(G).length,s=i>0?` (${i} abstained)`:"",a=e.title?` ${e.title}`:"",c=e.ticketId?` [${e.ticketId}]`:"",u=ot(e),d=u!==null?` \u2014 ${u}`:"";return `${n}:${a}${c} \u2014 ${r||"(no votes)"}${s}${d}`}function zr({projection:e,onlineIds:t,isHost:n,participantId:o,rounds:r,currentRound:i,settingsOpen:s,onStartRound:a,onNewRound:c,onRevote:u,onOpenSettings:d,onHandoffHost:l,onEndSession:p,onShare:A,shareOpen:k,onSetShareOpen:R,roomCode:T,confirmingQuit:f,myRole:I,onToggleRole:S,roundTitlePromptActive:v,roundTitleInput:y,onRoundTitleChange:L,onRoundTitleSubmit:b,onRoundTitleCancel:M,roundTicketIdPromptActive:E,roundTicketIdInput:D,onRoundTicketIdChange:ce,onRoundTicketIdSubmit:ne,onRoundTicketIdCancel:oe,descriptorPromptActive:V,descriptorInput:z,onDescriptorChange:X,onDescriptorSubmit:Ie,onDescriptorCancel:he,onEditDescriptor:m,canExport:x,onExportResults:P,onAgendaAdd:Y,agendaAddPromptActive:le,agendaAddTitleInput:ct,onAgendaAddTitleChange:Sn,onAgendaAddTitleSubmit:ze,onAgendaAddTitleCancel:Pt,agendaAddTicketIdPromptActive:be,agendaAddTicketIdInput:Cn,onAgendaAddTicketIdChange:Xe,onAgendaAddTicketIdSubmit:Qe,onAgendaAddTicketIdCancel:Oe}){let[Q,Z]=un.useState("idle"),[xe,Ae]=un.useState(null),[lt,re]=un.useState(false),[ue,Se]=un.useState(false);useEffect(()=>{n||(Z("idle"),Ae(null),re(false),Se(false));},[n]),useInput(C=>{if(C==="c"||C==="C"){R(true);return}if(C==="w"||C==="W"){S();return}if((C==="x"||C==="X")&&x){P();return}if(n){if(C==="a"||C==="A"){Y();return}(C==="e"||C==="E")&&d(),(C==="s"||C==="S")&&a(),(C==="h"||C==="H")&&Z("picking"),(C==="m"||C==="M")&&re(true),i!==null&&fe(i.status)&&((C==="n"||C==="N")&&c(),(C==="v"||C==="V")&&i.status!=="skipped"&&u(),(C==="t"||C==="T")&&m());}},{isActive:!s&&!f&&Q==="idle"&&!v&&!E&&!lt&&!ue&&!k&&!V&&!le&&!be}),useInput((C,pe)=>{C==="y"||C==="Y"?(p(),Se(false)):(C==="n"||C==="N"||pe.escape)&&Se(false);},{isActive:ue});let Re=e.participants.filter(C=>C.id!==o&&t.has(C.id));useInput(C=>{if(Q==="picking"){let pe=parseInt(C,10);!isNaN(pe)&&pe>=1&&pe<=Re.length?(Ae(Re[pe-1].id),Z("confirming")):(C==="Escape"||C==="q"||C==="Q")&&Z("idle");}},{isActive:Q==="picking"}),useInput(C=>{Q==="confirming"&&xe&&(C==="y"||C==="Y"?(l(xe),Z("idle"),Ae(null)):(C==="n"||C==="N"||C==="Escape")&&(Z("idle"),Ae(null)));},{isActive:Q==="confirming"});let ut=r.length>0,Me=r.filter(C=>fe(C.status)),Nt=i!==null?Me.slice(0,-1):Me;return lt?jsx(Kr,{onPick:C=>{re(false),C==="end-session"&&Se(true);},onClose:()=>re(false)}):k?jsx(ln,{roomCode:T,onPick:C=>{R(false),A(C);},onClose:()=>R(false)}):jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:ut?"Session":"Waiting for participants..."}),!ut&&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(va,{items:e.agenda,nextPending:Be(e)}),i!==null&&fe(i.status)&&jsx(Ca,{projection:e,round:i,rounds:r}),Nt.length>0&&jsxs(Box,{flexDirection:"column",children:[jsx(Text,{dimColor:true,children:"\u2500\u2500 History \u2500\u2500"}),Nt.map(C=>jsx(Text,{dimColor:true,children:qr(C,r)},C.id))]}),Q==="picking"&&Re.length>0&&jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{children:"Hand off to:"}),Re.map((C,pe)=>jsxs(Text,{children:["[",pe+1,"] ",C.displayName]},C.id)),jsx(Text,{dimColor:true,children:"[q] Cancel"})]}),Q==="picking"&&Re.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"})]}),Q==="confirming"&&xe&&jsx(Box,{flexDirection:"column",children:jsxs(Text,{children:["Hand off to ",e.participants.find(C=>C.id===xe)?.displayName,"? [y/n]"]})}),v&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Round title (optional, Enter to skip):"}),jsx(j,{value:y,onChange:L,onSubmit:b,onCancel:M,placeholder:"Enter to skip",isActive:v})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),E&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Ticket ID (optional, Enter to skip):"}),jsx(j,{value:D,onChange:ce,onSubmit:ne,onCancel:oe,placeholder:"e.g. PROJ-1234",isActive:E})]}),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(j,{value:z,onChange:X,onSubmit:Ie,onCancel:he,placeholder:"Enter to save",isActive:V})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel \xB7 empty submit cancels"})]}),ue&&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"})]}),le&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Agenda title (optional, Enter to skip):"}),jsx(j,{value:ct,onChange:Sn,onSubmit:ze,onCancel:Pt,placeholder:"Enter to skip",isActive:le})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),be&&jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{gap:1,children:[jsx(Text,{children:"Agenda ticket ID (optional, Enter to skip):"}),jsx(j,{value:Cn,onChange:Xe,onSubmit:Qe,onCancel:Oe,placeholder:"e.g. PROJ-1234",isActive:be})]}),jsx(Text,{dimColor:true,children:"[Esc] Cancel"})]}),Q==="idle"&&!v&&!E&&!V&&!ue&&!le&&!be&&jsxs(Box,{gap:2,children:[n?jsx(Fragment,{children:i!==null&&fe(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] ",I==="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] ",I==="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] ",I==="viewer"?"Vote":"Observe"]})]}),jsx(Text,{children:"[q] Quit"})]})]})}function Ca({projection:e,round:t,rounds:n}){let o=Jr(t,n);if(t.status==="skipped")return jsx(Box,{flexDirection:"column",gap:1,children:jsx(Text,{bold:true,children:o})});let r=Kt(Wt(t)),i=new Map(e.participants.map(l=>[l.id,l.displayName])),s=ot(t),a=Object.entries(t.votes),c=a.filter(([,l])=>!G(l)),u=a.filter(([,l])=>G(l)).map(([l])=>l),d=c[0]?.[1];return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:o}),Nn(t)&&d!==void 0&&jsxs(Text,{bold:true,color:"green",children:["Consensus! Everyone voted ",d]}),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(([l,p])=>jsxs(Box,{gap:2,children:[jsx(Text,{children:(i.get(l)??l).padEnd(20)}),jsx(Text,{color:"cyan",bold:true,children:p.padEnd(10)})]},l)),u.map(l=>jsxs(Box,{gap:2,children:[jsx(Text,{dimColor:true,children:(i.get(l)??l).padEnd(20)}),jsx(Text,{dimColor:true,children:"(abstained)".padEnd(10)})]},l)),e.participants.filter(l=>!(l.id in t.votes)).map(l=>jsxs(Box,{gap:2,children:[jsx(Text,{dimColor:true,children:l.displayName.padEnd(20)}),jsx(Text,{dimColor:true,children:"(no vote)".padEnd(10)})]},l.id))]}),(r!==null||s!==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"&&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})]}),s!==null&&jsxs(Text,{dimColor:true,children:["\u23F1 ",s]})]})]})}var wa={pending:"\u2022",consumed:"\u2713",skipped:"~",cancelled:"\u2717"},ya={consumed:"green",skipped:"yellow",cancelled:"red"};function va({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=wa[o.state]??"?",i=ya[o.state],s=t!==null&&o.id===t.id,a=[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:a}):jsx(Text,{children:a}),s&&jsx(Text,{color:"cyan",children:"(next)"})]},o.id)}),n.length===0&&jsx(Text,{dimColor:true,children:"No pending items."})]})}function Zr({scale:e,selected:t,onToggleCurrentVote:n,onClearCurrentVote:o,disabled:r}){let[i,s]=useState(0);return useInput((a,c)=>{r||(c.leftArrow?s(u=>Math.max(0,u-1)):c.rightArrow?s(u=>Math.min(e.cards.length-1,u+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((a,c)=>{let u=c===i,d=a===t;return jsx(Text,{inverse:u,bold:d,...d&&{color:"cyan"},children:d?`[${a}]`:` ${a} `},a)})}),jsx(Text,{dimColor:true,children:" \u2190\u2192 navigate \u23CE select \u232B clear"})]})}function ei({projection:e,round:t,onlineIds:n,isHost:o,myId:r,myRole:i,elapsedMs:s,roomCode:a,shareOpen:c,settingsOpen:u,onToggleCurrentVote:d,onClearCurrentVote:l,onReveal:p,onSkip:A,onDiscard:k,onToggleRole:R,onShare:T,onSetShareOpen:f,onOpenSettings:I,confirmingQuit:S}){let v=t.votes[r],y=v!==void 0&&G(v);if(useInput(D=>{if(D==="e"||D==="E"){I();return}if(D==="c"||D==="C"){f(true);return}if(i==="voter"&&(D==="a"||D==="A")){d(Mt);return}o&&(D==="r"||D==="R")&&p(),o&&(D==="s"||D==="S")&&A(),o&&(D==="d"||D==="D")&&k(),(D==="w"||D==="W")&&R();},{isActive:!S&&!u&&!c}),c)return jsx(ln,{roomCode:a,onPick:D=>{f(false),T(D);},onClose:()=>f(false)});let L=v,b=e.rounds.indexOf(t)+1,M=t.title?` \u2014 ${t.title}`:"",E=t.ticketId?` [${t.ticketId}]`:"";return jsxs(Box,{flexDirection:"column",gap:1,children:[jsxs(Box,{gap:2,children:[jsxs(Text,{bold:true,children:["Round ",b,M,E]}),s!==void 0&&jsxs(Text,{dimColor:true,children:["\u23F1 ",Yt(s)]})]}),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:[y&&jsx(Text,{dimColor:true,children:"(abstaining this round \u2014 press [a] to vote)"}),jsx(Zr,{scale:t.scale,selected:y?void 0:L,onToggleCurrentVote:d,onClearCurrentVote:l,disabled:S||y})]})]}),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] ",y?"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 Pa=3e3;function Rt(e=Pa){let[t,n]=useState(null),o=useRef(null),r=useCallback(()=>{o.current!==null&&(clearTimeout(o.current),o.current=null);},[]),i=useCallback(a=>{r(),n(a),o.current=setTimeout(()=>{n(null),o.current=null;},e);},[r,e]),s=useCallback(()=>{r(),n(null);},[r]);return useEffect(()=>()=>{r();},[r]),{notice:t,show:i,dismiss:s}}var Oa={"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 mn({session:e,participantId:t,displayName:n,accessMode:o,presetOverrides:r,customScales:i}){let{exit:s}=useApp(),[a,c]=useState(e.projection()),[u,d]=useState("connecting"),[l,p]=useState(e.onlineIds()),[A,k]=useState(),[R,T]=useState(false),[f,I]=useState(o==="password"?"password":"open"),[S,v]=useState(n),[y,L]=useState(false),[b,M]=useState(false),[E,D]=useState(""),[ce,ne]=useState(false),[oe,V]=useState(""),[z,X]=useState(),[Ie,he]=useState(false),[m,x]=useState(""),[P,Y]=useState(null),[le,ct]=useState(false),[Sn,ze]=useState(""),[Pt,be]=useState(false),[Cn,Xe]=useState(""),[Qe,Oe]=useState(),[Q,Z]=useState(),xe=Rt(3e3),[Ae,lt]=useState(false),re=Rt(3e3),ue=Rt(3e3),Se=Rt(3e3);useEffect(()=>{let w=e.onChange(()=>{c(e.projection()),p(e.onlineIds());}),U=e.onStatusChange(d),$e=e.onHostChange(Dt=>{let Yi=e.projection().participants.find(Ki=>Ki.id===Dt),Wi=Dt===t?"You are now the host":`${Yi?.displayName||"Unknown"} is now the host`;xe.show(Wi);}),yn=setInterval(()=>{p(e.onlineIds());let Dt=e.projection(),Ot=ie(Dt);Ot?.timerStartedAt!==void 0&&Ze(Ot.status)?k(Date.now()-Ot.timerStartedAt):k(void 0);},1e3);return ()=>{w(),U(),$e(),clearInterval(yn);}},[e,t,xe.show]),useInput(w=>{(w==="q"||w==="Q")&&L(true);},{isActive:!R&&!y&&!b&&!ce&&!Ie&&!Ae&&!le&&!Pt}),useInput((w,U)=>{w==="y"||w==="Y"?(e.disconnect(),s()):(w==="n"||w==="N"||U.escape)&&L(false);},{isActive:y});let Re=Cr(a),ut=ie(a),Me=a.settings.hostParticipantId===t,Nt=a.participants.find(w=>w.id===t),C=me(Nt??{}),pe=useCallback(()=>{let w=nn(Be(a));D(w.title),Z(w.agendaItemId),M(true);},[a]),gi=useCallback(w=>{M(false),D(""),X(to(w));let U=nn(Be(a));V(U.ticketId),ne(true);},[a]),hi=useCallback(()=>{M(false),D(""),X(void 0),Z(void 0);},[]),xi=useCallback(w=>{ne(false),V("");let[U,$e,yn]=Or(z,w,Q);e.newRound(U,$e,yn),X(void 0),Z(void 0);},[e,z,Q]),Si=useCallback(()=>{ne(false),V(""),X(void 0),Z(void 0);},[]),Ci=useCallback(()=>{let w=e.current();!w||w.status!=="revealed"||(Y(w.id),x(w.title??""),he(true));},[e]),wi=useCallback(w=>{let U=P;if(he(false),Y(null),!U)return;let $e=w.trim();$e!==""&&e.updateRoundDescriptor(U,{title:$e});},[e,P]),yi=useCallback(()=>{he(false),Y(null);},[]),vi=useCallback(w=>{e.toggleCurrentVote(w);},[e]),Ii=useCallback(()=>{e.clearCurrentVote();},[e]),bi=useCallback(()=>{e.reveal();},[e]),Ai=useCallback(()=>{e.skip();},[e]),Ri=useCallback(()=>{e.discardCurrentRound();},[e]),Ti=useCallback(()=>{let w=nn(Be(a));D(w.title),Z(w.agendaItemId),M(true);},[a]),Ei=useCallback(()=>{e.revote();},[e]),ho=useCallback(()=>{e.toggleRole();},[e]),ki=useCallback(w=>{e.updateName(w);},[e]),Pi=useCallback(w=>{e.updateScale(w);},[e]),Ni=useCallback(w=>{e.updateDisplayName(w),v(w);},[e]),Di=useCallback(async(w,U)=>{await e.updateAccess(w,U),I(w);},[e]),Oi=useCallback(w=>{let U=e.handoffHost(w);U.applied||console.error(`Handoff failed: ${Oa[U.reason]}`);},[e]),xo=useCallback(()=>{T(true);},[]),Mi=useCallback(()=>{T(false);},[]),$i=useCallback(()=>{e.endSessionForEveryone();},[e]),So=useCallback(async w=>{let U=w==="code"?Zt(e.roomCode):w==="url"?en(e.roomCode):tn(e.roomCode);try{await ni.write(U),re.show("Copied!");}catch{re.show(`Copy failed \u2014 ${U}`);}},[e.roomCode,re]),wn=a.rounds.filter(w=>fe(w.status)),Ui=wn.length>0?wn.at(-1):null,Hi=wn.length>0,Li=useCallback(()=>Gr(a,w=>ni.write(w),ue.show),[a,ue.show]),Bi=useCallback(()=>{ze(""),ct(true);},[]),_i=useCallback(w=>{ct(false),ze("");let U=w.trim()===""?void 0:w.trim();Oe(U),Xe(""),be(true);},[]),ji=useCallback(()=>{ct(false),ze(""),Oe(void 0);},[]),Fi=useCallback(w=>{be(false),Xe("");let U=w.trim()===""?void 0:w.trim();if(!Qe&&!U){Oe(void 0);return}if(!Ft(e.doc,{...Qe!==void 0&&{title:Qe},...U!==void 0&&{ticketId:U}}).applied){Se.show("Add failed \u2014 an agenda item needs a title or a ticket id");return}Oe(void 0);},[e.doc,Qe,Se]),Vi=useCallback(()=>{be(false),Xe(""),Oe(void 0);},[]);return jsxs(Box,{flexDirection:"column",children:[jsx(Ur,{roomCode:e.roomCode,sessionName:a.settings.name,status:u,isHost:Me}),xe.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:"yellow",children:xe.notice})}),re.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:re.notice.startsWith("Copy failed")?"red":"green",children:re.notice})}),ue.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:ue.notice.startsWith("Clipboard write failed")?"red":"green",children:ue.notice})}),Se.notice&&jsx(Box,{paddingX:1,children:jsx(Text,{color:"red",children:Se.notice})}),R?jsx(Yr,{sessionName:a.settings.name,displayName:S,currentScale:a.settings.defaultScale,accessMode:f,presetOverrides:r,customScales:i,isHost:Me,onChangeName:ki,onChangeScale:Pi,onChangeDisplayName:Ni,onChangeAccess:Di,onClose:Mi}):Re==="lobby"?jsx(zr,{projection:a,onlineIds:l,isHost:Me,participantId:t,rounds:a.rounds,currentRound:Ui,settingsOpen:R,onStartRound:pe,onNewRound:Ti,roundTitlePromptActive:b,roundTitleInput:E,onRoundTitleChange:D,onRoundTitleSubmit:gi,onRoundTitleCancel:hi,roundTicketIdPromptActive:ce,roundTicketIdInput:oe,onRoundTicketIdChange:V,onRoundTicketIdSubmit:xi,onRoundTicketIdCancel:Si,onRevote:Ei,onOpenSettings:xo,onHandoffHost:Oi,onEndSession:$i,onShare:So,shareOpen:Ae,onSetShareOpen:lt,roomCode:e.roomCode,confirmingQuit:y,myRole:C,onToggleRole:ho,descriptorPromptActive:Ie,descriptorInput:m,onDescriptorChange:x,onDescriptorSubmit:wi,onDescriptorCancel:yi,onEditDescriptor:Ci,canExport:Hi,onExportResults:Li,onAgendaAdd:Bi,agendaAddPromptActive:le,agendaAddTitleInput:Sn,onAgendaAddTitleChange:ze,onAgendaAddTitleSubmit:_i,onAgendaAddTitleCancel:ji,agendaAddTicketIdPromptActive:Pt,agendaAddTicketIdInput:Cn,onAgendaAddTicketIdChange:Xe,onAgendaAddTicketIdSubmit:Fi,onAgendaAddTicketIdCancel:Vi}):Re==="estimating"&&ut?jsx(ei,{projection:a,round:ut,onlineIds:l,isHost:Me,myId:t,myRole:C,elapsedMs:A,onToggleCurrentVote:vi,onClearCurrentVote:Ii,onReveal:bi,onSkip:Ai,onDiscard:Ri,onToggleRole:ho,onShare:So,onSetShareOpen:lt,shareOpen:Ae,settingsOpen:R,onOpenSettings:xo,roomCode:e.roomCode,confirmingQuit:y}):null,y&&jsx(Box,{children:jsx(Text,{dimColor:true,children:"Leave session? y/n"})})]})}function oi({presetOverrides:e,customScales:t}){let{exit:n}=useApp(),[o,r]=useState("main-menu"),[i,s]=useState(Ve()),[a,c]=useState(i.displayName??""),[u,d]=useState(i.relayUrl??""),[l,p]=useState(i.defaultSessionName??""),[A,k]=useState(i.avatarColor?.startsWith("#")?i.avatarColor:""),[R,T]=useState(t??[]),[f,I]=useState(e??{});useInput(m=>{(m==="q"||m==="Q")&&n();},{isActive:o==="main-menu"});let S=useMemo(()=>Jt(f,R),[f,R]),v=i.defaultScale,y=v?S.find(m=>m.id===v):void 0,L=[{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:`[${y?Fe(y.id,R):"(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:`[${Ba(i.avatarColor)}]`}];function b(m){m==="display-name"?(c(i.displayName??""),r("editing-display-name")):m==="relay-url"?(d(i.relayUrl??""),r("editing-relay-url")):m==="default-scale"?r("picking-scale"):m==="default-session-name"?(p(i.defaultSessionName??""),r("editing-session-name")):m==="default-password"?r("picking-default-password"):m==="avatar-color"&&r("picking-avatar-color");}function M(m){if(m==="custom-hex"){k(i.avatarColor?.startsWith("#")?i.avatarColor:""),r("editing-avatar-hex");return}if(_e(m)===null){r("main-menu");return}s({...i,avatarColor:m}),F({avatarColor:m}),r("main-menu");}function E(m){let x=m.trim();if(x.length===0){r("picking-avatar-color");return}let P=x.startsWith("#")?x.toLowerCase():`#${x.toLowerCase()}`;_e(P)!==null&&(s({...i,avatarColor:P}),F({avatarColor:P}),r("main-menu"));}function D(m){let x=m.trim();if(x.length>0){let P={...i,displayName:x};s(P),F({displayName:x});}r("main-menu");}function ce(m){let x=m.trim();if(x.length>0){let P={...i,relayUrl:x};s(P),F({relayUrl:x});}r("main-menu");}function ne(m){let x=m.trim(),P=x.length>0?{...i,defaultSessionName:x}:{...i};x.length===0?(delete P.defaultSessionName,s(P),Ct({defaultSessionName:""})):(s(P),F({defaultSessionName:x})),r("main-menu");}function oe(m){let x=m.length>0?{...i,defaultScale:m}:{...i};m.length===0?(delete x.defaultScale,s(x),Ct({defaultScale:""})):(s(x),F({defaultScale:m})),r("main-menu");}function V(m,x){let P={...f};x.length===0?delete P[m]:P[m]=x,I(P),F({presetOverrides:Object.keys(P).length>0?P:void 0});}function z(m){let x=m==="on",P={...i,defaultPassword:x};s(P),F({defaultPassword:x}),r("main-menu");}function X(m,x){let P=`custom-${randomUUID()}`,Y=[...R,{id:P,label:m,cards:x}];T(Y),s({...i,customScales:Y}),F({customScales:Y});}function Ie(m,x,P){let Y=R.map(le=>le.id===m?{id:m,label:x,cards:P}:le);T(Y),s({...i,customScales:Y}),F({customScales:Y});}function he(m){let x=R.filter(Y=>Y.id!==m);T(x);let P={...i,customScales:x};i.defaultScale===m?(P.defaultScale="fibonacci",F({customScales:x,defaultScale:"fibonacci"})):F({customScales:x}),s(P);}if(o==="main-menu")return jsx(ge,{title:"\u2500\u2500 Config Settings \u2500\u2500",items:L,onSelect:b,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(j,{value:a,onChange:c,onSubmit:D,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(j,{value:u,onChange:d,onSubmit:ce,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(j,{value:l,onChange:p,onSubmit:ne,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:[]},...S];return jsxs(Box,{flexDirection:"column",gap:1,children:[jsx(Text,{bold:true,children:"\u2500\u2500 Config Settings \u2500\u2500"}),jsx(sn,{scales:m,selectedScaleId:v??"",presetOverrides:f,customScales:R,onSelect:oe,onOverrideChange:V,onCustomScaleCreate:X,onCustomScaleEdit:Ie,onCustomScaleDelete:he,onClose:()=>r("main-menu"),showNoneOption:true})]})}if(o==="picking-avatar-color"){let m=ht.map(x=>({label:nt[x].label,value:x,detail:i.avatarColor===x?"[current]":nt[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(ge,{title:"Avatar color:",items:m,onSelect:M,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(j,{value:A,onChange:k,onSubmit:E,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(ge,{title:"Default password:",items:m,onSelect:z,onClose:()=>r("main-menu")})]})}return jsx(Box,{})}function Ba(e){return e?e.startsWith("#")?e:ht.includes(e)?nt[e].label:e:"(auto)"}var ja={pending:"\u2022",consumed:"\u2713",skipped:"~",cancelled:"\u2717"};function Fa(e){let t=ja[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 gn(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 Et(e){let t=new Ue.Doc,n=new Awareness(t);He(t,{participantId:e.participantId,displayName:e.displayName,joinedAt:Date.now()}),n.setLocalStateField(Ee,e.participantId);let o=rt({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),s=o.onStatusChange(a=>{a==="connected"&&setTimeout(()=>{clearTimeout(i),s(),r();},200);});}),{doc:t,disconnect:()=>o.disconnect()}}async function kt(){let e=zt();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 ii(e){!e.title?.trim()&&!e.ticket?.trim()&&(console.error("At least one of --title or --ticket is required"),process.exit(1));let t=await de(),n=await kt();try{await ae(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 Et({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=Ft(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: ${gn(i.reason)}`),process.exit(1)),await new Promise(s=>{setTimeout(s,300);}),console.log(`Added agenda item: ${i.id}`);}finally{r();}}async function si(){let e=await de(),t=await kt();try{await ae(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 Et({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=_(n).agenda;if(i.length===0){console.log("No agenda items.");return}i.forEach((s,a)=>{console.log(`${String(a+1).padStart(2)}. ${Fa(s)}`);});}finally{o();}}async function ai(e){let t=await de(),n=await kt();try{await ae(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 Et({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=Mo(o,e.id);i.applied||(console.error(`Skip failed: ${gn(i.reason)}`),process.exit(1)),await new Promise(s=>{setTimeout(s,300);}),console.log(`Skipped agenda item: ${e.id}`);}finally{r();}}async function di(e){let t=await de(),n=await kt();try{await ae(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 Et({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=$o(o,e.id);i.applied||(console.error(`Cancel failed: ${gn(i.reason)}`),process.exit(1)),await new Promise(s=>{setTimeout(s,300);}),console.log(`Cancelled agenda item: ${e.id}`);}finally{r();}}async function ci(e){let t=await de(),n=await kt();try{await ae(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 Et({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=Uo(o,e.id,e.before,e.after);i.applied||(console.error(`Move failed: ${gn(i.reason)}`),process.exit(1)),await new Promise(s=>{setTimeout(s,300);}),console.log(`Reordered agenda item: ${e.id}`);}finally{r();}}async function go(){return new Promise(e=>{let t=createInterface({input:process.stdin,output:process.stderr});process.stderr.write("Password: "),t.question("",n=>{t.close(),e(n);});})}async function Wa(e){let t=await de(),n=e.scale??t.defaultScale??"fibonacci",o=e.name??t.defaultSessionName,r=e.password??t.defaultPassword??false,i;r&&(i=await go());let s=Gt(n,t.presetOverrides,t.customScales);if(!s){let l=Object.keys(se).join(", ");console.error(`Unknown or fully-disabled scale: "${n}". Builtin IDs: ${l}`),process.exit(1);}let a=await Tr({participantId:t.participantId,displayName:t.displayName,relayUrl:t.relayUrl,sessionName:o,password:i,defaultScale:s,...t.avatarColor!==void 0&&{avatarColor:t.avatarColor}}),c;i&&(c=await je(i,a.roomUuid)),eo({roomCode:a.roomCode,roomUuid:a.roomUuid,lastSeenAt:Date.now(),...c!==void 0&&{passwordHash:c}}),console.error(`Room created: ${a.roomCode}`),console.error(`Share: hnch join ${a.roomCode}`),console.error("");let{waitUntilExit:u,unmount:d}=render(un.createElement(mn,{session:a,participantId:t.participantId,displayName:t.displayName,accessMode:i?"password":"open",presetOverrides:t.presetOverrides,customScales:t.customScales}));Qt({doc:a.doc,localParticipantId:t.participantId,onEnded:async l=>{console.error(l.isLocal?"Session ended.":`Session ended by ${l.hostName}.`),d();try{await Ce();}catch(p){console.error(`Failed to clear cached session: ${p instanceof Error?p.message:String(p)}`);}a.disconnect(),process.exit(0);}}),await u(),a.disconnect(),Ce(),process.exit(0);}async function Ka(e){let t=await de(),n=kr(e.code);n===null&&(console.error("invalid room code"),process.exit(1));let o;e.password&&(o=await go());let r=await ae(t.relayUrl,n),i;r.accessMode==="password"&&!e.password?i=await go():e.password&&(i=o);let s,a=false,c=await Er({participantId:t.participantId,displayName:t.displayName,relayUrl:t.relayUrl,roomCode:n,password:i,...t.avatarColor!==void 0&&{avatarColor:t.avatarColor},onRejection(l){if(l==="unknown-room"){Xt({clearLastSession:Ce,logger:console,exit:process.exit});return}l==="room-full"&&(a=true,s?.());}}),u;i&&(u=await je(i,c.roomUuid)),eo({roomCode:c.roomCode,roomUuid:c.roomUuid,lastSeenAt:Date.now(),...u!==void 0&&{passwordHash:u}}),console.error(`Joined room: ${c.roomCode}`),console.error("");let d=render(un.createElement(mn,{session:c,participantId:t.participantId,displayName:t.displayName,accessMode:r.accessMode,presetOverrides:t.presetOverrides,customScales:t.customScales}));s=d.unmount,Qt({doc:c.doc,localParticipantId:t.participantId,onEnded:async l=>{console.error(l.isLocal?"Session ended.":`Session ended by ${l.hostName}.`),s?.();try{await Ce();}catch(p){console.error(`Failed to clear cached session: ${p instanceof Error?p.message:String(p)}`);}c.disconnect(),process.exit(0);}}),await d.waitUntilExit(),a&&(console.error("This room is full (max 20 participants)."),c.disconnect(),Ce(),process.exit(1)),c.disconnect(),Ce(),process.exit(0);}function Ga(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 Ja(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 s=parseInt(i.trim(),10);Number.isInteger(s)&&s>=1&&s<=e?(o.close(),t(s)):(process.stderr.write(`Invalid choice \u2014 enter a number between 1 and ${e}.
22
+ `),r());});};o.on("close",()=>n(new Error("stdin closed"))),r();})}async function li(e,t){let n;try{n=await ae(e.relayUrl,t.roomCode);}catch(d){if(d instanceof xt&&d.reason==="unknown-room")return wt(t.roomUuid),await Xt({clearLastSession:Ce,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`),Zn(t.roomUuid),process.exit(0)),console.error(`Rejoining room ${t.roomCode}\u2026`),console.error("");let o=new Ue.Doc,r=new Awareness(o);He(o,{participantId:e.participantId,displayName:e.displayName,joinedAt:Date.now(),...e.avatarColor!==void 0&&{avatarColor:e.avatarColor}}),r.setLocalStateField(Ee,e.participantId);let i=false,s=false,a,c=rt({doc:o,awareness:r,roomCode:t.roomCode,roomUuid:t.roomUuid,participantId:e.participantId,relayUrl:e.relayUrl,passwordHash:t.passwordHash,clearLeftStatusOnSync:true,onRejection(d){if(d==="unknown-room"){wt(t.roomUuid),Xt({clearLastSession:Ce,logger:console,exit:process.exit});return}d==="wrong-password"&&(i=true,a?.()),d==="room-full"&&(s=true,a?.());}});Qn({roomCode:c.roomCode,roomUuid:c.roomUuid,lastSeenAt:Date.now(),...t.passwordHash!==void 0&&{passwordHash:t.passwordHash}});let u=render(un.createElement(mn,{session:c,participantId:e.participantId,displayName:e.displayName,accessMode:n.accessMode,presetOverrides:e.presetOverrides,customScales:e.customScales}));a=u.unmount,Qt({doc:c.doc,localParticipantId:e.participantId,onEnded:async d=>{console.error(d.isLocal?"Session ended.":`Session ended by ${d.hostName}.`),a?.();try{wt(t.roomUuid);}catch(l){console.error(`Failed to clear cached session: ${l instanceof Error?l.message:String(l)}`);}c.disconnect(),process.exit(0);}}),await u.waitUntilExit(),s&&(console.error("This room is full (max 20 participants)."),c.disconnect(),process.exit(1)),i&&(Zn(t.roomUuid),console.error(`Password changed \u2014 rejoin with: hnch join ${t.roomCode} --password`),c.disconnect(),process.exit(0)),c.disconnect(),wt(t.roomUuid),process.exit(0);}async function qa(){let e=await de(),t=zt();if(t.length===0&&(console.error("No recent session to resume."),process.exit(0)),t.length===1)return li(e,t[0]);let n=Date.now();process.stderr.write(`Recent rooms:
23
+ `);for(let[r,i]of t.entries()){let s=Ga(i.lastSeenAt,n);process.stderr.write(` ${r+1}. ${i.roomCode} (${s})
24
24
  `);}process.stderr.write(`
25
- `);let o;try{o=await Sa(t.length);}catch{console.error("No selection made."),process.exit(1);}return Vr(e,t[o-1])}async function wa(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 ce(),{waitUntilExit:r}=render(on.createElement(Ur,{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=Fe();if(!Lt(e.scale,o.presetOverrides,o.customScales)){console.error(`Unknown scale: "${e.scale}". Builtin IDs: ${Object.keys(se).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!==""&&$e(o)===null&&(console.error(`Invalid color: "${e.color}". Pass a palette key or #rrggbb hex literal.`),process.exit(1)),n.avatarColor=o;}ht(n),console.log("Config updated.");}var Jr=pa(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=>{ma(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=>{ga(e).catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1);});}).command("resume","Rejoin your last session",e=>e,()=>{xa().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=>{wa(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=>{Hr(t).catch(n=>{console.error(n instanceof Error?n.message:n),process.exit(1);});}).command("list","List agenda items in order",t=>t,()=>{_r().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=>{Lr(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=>{jr(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=>{Fr(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(),ro=hideBin(process.argv);(ro.length===0||ro.length===1&&ro[0]==="--")&&(Jr.showHelp(),process.exit(0));Jr.parse();
25
+ `);let o;try{o=await Ja(t.length);}catch{console.error("No selection made."),process.exit(1);}return li(e,t[o-1])}async function za(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 de(),{waitUntilExit:r}=render(un.createElement(oi,{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(!Gt(e.scale,o.presetOverrides,o.customScales)){console.error(`Unknown scale: "${e.scale}". Builtin IDs: ${Object.keys(se).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!==""&&_e(o)===null&&(console.error(`Invalid color: "${e.color}". Pass a palette key or #rrggbb hex literal.`),process.exit(1)),n.avatarColor=o;}Ct(n),console.log("Config updated.");}var mi=Va(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=>{Wa(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=>{Ka(e).catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1);});}).command("resume","Rejoin your last session",e=>e,()=>{qa().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=>{za(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=>{ii(t).catch(n=>{console.error(n instanceof Error?n.message:n),process.exit(1);});}).command("list","List agenda items in order",t=>t,()=>{si().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=>{ai(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=>{di(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=>{ci(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(),mo=hideBin(process.argv);(mo.length===0||mo.length===1&&mo[0]==="--")&&(mi.showHelp(),process.exit(0));mi.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xauyxau/hnch",
3
- "version": "1.16.0",
3
+ "version": "1.16.1",
4
4
  "description": "Pointing poker CLI for agile teams",
5
5
  "keywords": [
6
6
  "pointing-poker",
@@ -67,6 +67,6 @@
67
67
  "tsup": "^8.3.0",
68
68
  "tsx": "^4.19.0",
69
69
  "typescript": "^5.5.0",
70
- "vitest": "^3.2.6"
70
+ "vitest": "^3.2.7"
71
71
  }
72
72
  }