@bud.sh/app 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/client/assets/bud/design.js +1 -1
  2. package/dist/client/assets/canvas-C8hyPWoT.js +1 -0
  3. package/dist/client/assets/difference-worker-BfF4_N3e.js +8 -0
  4. package/dist/client/assets/files-D_Tm7gCK.js +1 -0
  5. package/dist/client/assets/i18n-BtfXum8P.js +1 -0
  6. package/dist/client/assets/index-Dpxjiok1.js +2 -0
  7. package/dist/client/assets/pages-B-_CKvDS.js +1 -0
  8. package/dist/client/assets/project-branches-DzXdaT9L.js +1 -0
  9. package/dist/client/assets/project-comments-CQkB2jbE.js +1 -0
  10. package/dist/client/assets/project-thread-links-BN7zL0AX.js +1 -0
  11. package/dist/client/assets/{project-threads-DezXiVK6.js → project-threads-CHGG-6fo.js} +104 -104
  12. package/dist/client/assets/{project-work-CB1JHqGW.js → project-work-L5fYMSOu.js} +1 -1
  13. package/dist/client/assets/task-design-DYqcqq1b.js +23 -0
  14. package/dist/client/assets/tasks-A2FKo3_h.js +1 -0
  15. package/dist/client/assets/tasks-request-DGigNdyK.js +1 -0
  16. package/dist/client/assets/workspace-CvWmU2RK.js +2 -0
  17. package/dist/client/index.html +2 -1
  18. package/dist/hosted/assets/{canvas-C69-96GR.js → canvas-MWtOwaWm.js} +69 -41
  19. package/dist/hosted/assets/{comment-data-CiDuvXi2.js → comment-data-DsgJWq4n.js} +7195 -1067
  20. package/dist/hosted/assets/{files-DQL5hzs3.js → files-Wvo11G2A.js} +92 -89
  21. package/dist/hosted/assets/{pages-DFs7jB6M.js → pages-BAmRFVtU.js} +31 -22
  22. package/dist/hosted/assets/{project-branches-CffV4IS1.js → project-branches-BNloVosX.js} +5 -5
  23. package/dist/hosted/assets/{project-thread-links-B1Y2bDUx.js → project-thread-links-BmY8HQXt.js} +12 -12
  24. package/dist/hosted/assets/{screen-BroBb1Z_.js → screen-QmqmI2Aq.js} +18 -18
  25. package/dist/hosted/assets/{tasks-mzmNhe2d.js → tasks-C8iWPrWg.js} +29 -29
  26. package/dist/hosted/assets/{tasks-request-Dcrpd2_8.js → tasks-request-C89fN1dK.js} +7 -7
  27. package/dist/hosted/hosted.js +48 -29
  28. package/dist/node/design.js +6235 -139
  29. package/dist/node/index.js +4 -2
  30. package/dist/node-host/assets/{canvas-BZhzizzt.js → canvas-D_F8SIlm.js} +70 -42
  31. package/dist/node-host/assets/{comment-data-nUlI0szN.js → comment-data-q_8INiZz.js} +7221 -1093
  32. package/dist/node-host/assets/{files-CTzcWGjb.js → files-xazOrNCX.js} +92 -89
  33. package/dist/node-host/assets/{pages-0aWH7z1j.js → pages-D6VkmdfQ.js} +31 -22
  34. package/dist/node-host/assets/{project-branches-1zs_0J_y.js → project-branches-C26hwmo3.js} +5 -5
  35. package/dist/node-host/assets/{project-thread-links-LpUAGcDr.js → project-thread-links-BOzjws5W.js} +12 -12
  36. package/dist/node-host/assets/{screen-DQoTOWYR.js → screen-Dog-YByu.js} +18 -18
  37. package/dist/node-host/assets/{tasks-C0WqnM7Q.js → tasks-A1_bpb3_.js} +30 -30
  38. package/dist/node-host/assets/{tasks-request-Bwky5ORf.js → tasks-request-Bie1PpQP.js} +7 -7
  39. package/dist/node-host/node-host.js +48 -29
  40. package/dist/server/assets/{branch-previews-BryeA_kA.js → branch-previews-ClkoJ0lM.js} +4 -2
  41. package/dist/server/assets/{canvas-D6tIkONI.js → canvas-Dn4RYoU2.js} +70 -42
  42. package/dist/server/assets/{comment-data-BuArfgcc.js → comment-data-B0OLHBGp.js} +7219 -1091
  43. package/dist/server/assets/{files-DkrEB48U.js → files-C5Vilfe4.js} +92 -89
  44. package/dist/server/assets/{listener-oKd5ETMj.js → listener-o1STuLju.js} +43 -29
  45. package/dist/server/assets/{pages-iEdmK_o2.js → pages-BNa0MHEc.js} +31 -22
  46. package/dist/server/assets/{project-branches-B7rtrvMl.js → project-branches-GtQYyOH5.js} +5 -5
  47. package/dist/server/assets/{project-thread-links-ue_ad9IX.js → project-thread-links-Nfz9NIny.js} +12 -12
  48. package/dist/server/assets/{project-work-6aOyja4v.js → project-work-Cy_BpHwR.js} +2 -2
  49. package/dist/server/assets/{screen-DMUB9a-K.js → screen-BtcJmZwj.js} +18 -18
  50. package/dist/server/assets/{server-DN5uwE4k.js → server-CYvuOSBA.js} +1 -1
  51. package/dist/server/assets/{services-Ber8opFE.js → services-DK4fqrlF.js} +2 -2
  52. package/dist/server/assets/{tasks-C2oa2wSC.js → tasks-B82tHwyQ.js} +31 -31
  53. package/dist/server/assets/{tasks-request-Bk5EoY_p.js → tasks-request-BtJBlkxV.js} +7 -6
  54. package/dist/server/capture.js +1 -1
  55. package/dist/server/migration.js +3 -3
  56. package/dist/server/runtime.js +4 -4
  57. package/dist/server/server.js +3 -3
  58. package/dist/types/assets/{config-Cuauq8xY.d.ts → config-DIC2cf_S.d.ts} +3 -0
  59. package/dist/types/assets/{contract-BsCQbbxD.d.ts → contract-CAT-XFNq.d.ts} +3 -1
  60. package/dist/types/companion.d.ts +1 -1
  61. package/dist/types/hosted.d.ts +2 -2
  62. package/dist/types/index.d.ts +1 -1
  63. package/dist/types/node-host.d.ts +2 -2
  64. package/dist/types/screen.d.ts +1 -1
  65. package/package.json +1 -1
  66. package/dist/client/assets/canvas-DxaIItAs.js +0 -1
  67. package/dist/client/assets/difference-worker-BpqPBs5g.js +0 -8
  68. package/dist/client/assets/files-C-7xoSt4.js +0 -1
  69. package/dist/client/assets/index-GPPa1XPO.js +0 -2
  70. package/dist/client/assets/pages-BVrTX_Eq.js +0 -1
  71. package/dist/client/assets/project-branches-DpxQx-T4.js +0 -1
  72. package/dist/client/assets/project-comments-D897aU5O.js +0 -1
  73. package/dist/client/assets/project-thread-links-Bp_TseD0.js +0 -1
  74. package/dist/client/assets/task-design-bktfn_Ok.js +0 -23
  75. package/dist/client/assets/tasks-Cqfj4fQN.js +0 -1
  76. package/dist/client/assets/tasks-request-mWMk9pBo.js +0 -1
  77. package/dist/client/assets/workspace-CznMN7F6.js +0 -2
@@ -0,0 +1 @@
1
+ import{n as e}from"./i18n-BtfXum8P.js";import{t}from"./jsx-B4XNFIzB.js";import{t as n}from"./component-DWct-Tq6.js";import{n as r}from"./on-mixin-iWnqUzq5.js";import{n as i}from"./attrs-mixin-CmlG_FtV.js";import{c as a,l as o}from"./loader-Q6-HPKft.js";import{t as s}from"./screen-Dfvzj6n2.js";import{Cn as c,H as l,J as u,T as d,U as f,_t as p,bt as m,dt as h,ot as g,vn as _,xn as v,yn as y}from"./task-design-DYqcqq1b.js";import{C as b,E as x,S,V as C,b as w,ct as T,dt as E,p as D,q as O,s as k,w as A,x as j}from"./project-threads-CHGG-6fo.js";import{a as ee,o as te,r as M,s as ne,t as N}from"./project-comments-CQkB2jbE.js";import{n as P,t as F}from"./tasks-request-DGigNdyK.js";import{t as I}from"./project-work-L5fYMSOu.js";import{n as L,t as R}from"./project-thread-links-BN7zL0AX.js";function re(s){let c=s.props.conversationId,d=c,p=!!c,m=!1,g=!1,_=[s.props.itemId],v=N({store:k(s.props.project),token:s.props.project.token,signal:s.signal,filter:{itemId:s.props.itemId},initial:s.props.initial,onChange(){s.signal.aborted||s.update()}});v.loaded&&(d??=v.snapshot.threads[0]?.id);let y=i(()=>{v.loaded||v.load().then(()=>{d??=v.snapshot.threads[0]?.id,s.signal.aborted||s.update()})});async function b(e){let t=await v.write(e);return await s.props.onChange?.(),t}function S(e){return{project:s.props.project,thread:e,items:s.props.items,canLink:v.snapshot.capabilities.link,busy:v.busy,onChange:async()=>{await v.load(),v.snapshot.threads.some(t=>t.id===e.id)&&await v.loadThread(e.id,!0),await s.props.onChange?.()}}}function C(n){return t(`div`,{class:`flex items-start justify-between gap-2`,children:[s.props.renderThreadLinks?s.props.renderThreadLinks(n):t(R,{part:n.anchor?`links`:void 0,...S(n)}),!n.anchor&&v.snapshot.capabilities.reply&&v.snapshot.threads.length>1?t(a,{variant:`ghost`,size:`small`,disabled:v.busy,"aria-pressed":!m&&d===n.id,mix:r(`click`,()=>{d=n.id,p=!0,m=!1,s.update()}),children:e(`app.client.taskDiscussion.reply`)}):null]})}function w(n){return t(O,{location:n.anchor?T(n):e(`app.client.taskDiscussion.discussion`),actions:s.props.renderThreadLinks?void 0:t(R,{part:`action`,...S(n)}),status:n.status,busy:v.busy,onStatusChange:v.snapshot.capabilities.status?e=>{b({id:n.id,status:e}).catch(()=>{})}:void 0})}return()=>{c!==s.props.conversationId&&(c=s.props.conversationId,p=!!c,c&&(d=c,m=!1));let{threads:i,capabilities:S}=v.snapshot,T=m?void 0:i.find(e=>e.id===d&&!e.anchor)??(p?void 0:i.find(e=>!e.anchor&&e.status!==`resolved`)??(S.create?void 0:i.find(e=>!e.anchor))),E=!m&&(p&&(!T||!S.reply)||!(!T||T.messagesLoaded));v.ready&&!v.busy&&!v.loading&&s.queueTask(()=>{p&&d&&v.loadThread(d);for(let e of v.snapshot.threads)!e.messagesLoaded&&(!e.anchor||e.id===d)&&v.loadThread(e.id)});let D=i.reduce((e,t)=>e+t.messageCount,0);return t(`section`,{class:`flex min-w-0 flex-col gap-3`,"aria-label":e(`app.client.taskDiscussion.taskDiscussion`),mix:y,children:[t(`div`,{class:`flex items-center gap-2`,children:[t(o,{as:`h3`,variant:`ui`,weight:`medium`,children:e(`app.client.taskDiscussion.discussion`)}),D?t(o,{variant:`ui-caption`,tone:`muted`,children:D}):null,v.ready&&S.create&&i.length?t(a,{variant:`ghost`,size:`small`,class:`ms-auto`,disabled:v.busy||m,mix:r(`click`,()=>{m=!0,s.update()}),children:e(`app.client.taskDiscussion.newDiscussion`)}):null]}),v.error?t(`div`,{class:`flex flex-col items-start gap-2`,children:[t(o,{variant:`ui-caption`,role:`alert`,children:v.error}),t(a,{variant:`secondary`,size:`small`,mix:r(`click`,()=>{v.load().then(()=>d?v.loadThread(d,!0):void 0)}),children:e(`app.client.taskDiscussion.reloadComments`)})]}):null,v.loaded?v.ready?t(n,{children:[i.length?i.map(e=>e.anchor?t(f,{id:e.id,expanded:d===e.id,heading:w(e),messages:e.messages,messageCount:e.messageCount,now:v.now,onExpand:()=>{d=e.id,p=!1,v.loadThread(e.id),s.update()},renderDetail:()=>t(l,{heading:w(e),messages:e.messages,messageCount:e.messageCount,messagesLoaded:e.messagesLoaded,messagesTruncated:e.messagesTruncated,now:v.now,busy:v.busy,links:C(e),onReply:S.reply?(t,n)=>b({id:e.id,body:t,parentId:n}):void 0})},e.id):t(x,{thread:e,links:C(e)},e.id)):t(o,{variant:`ui-caption`,tone:`muted`,children:e(`app.client.taskDiscussion.noDiscussionYet`)}),S.create||S.reply&&(p||i.some(e=>!e.anchor))?t(`div`,{class:`flex min-w-0 flex-col gap-2`,children:[S.create&&(m||!p&&!i.length)?t(`div`,{class:`flex items-start justify-between gap-2`,"aria-label":e(`app.client.taskDiscussion.newDiscussionTasks`),children:[t(A,{itemIds:_,items:s.props.items??[],href:h,busy:v.busy,onEdit:S.link?()=>{g=!0,s.update()}:void 0}),m?t(a,{variant:`ghost`,size:`small`,disabled:v.busy,mix:r(`click`,()=>{m=!1,s.update()}),children:e(`app.client.taskDiscussion.cancel`)}):null]}):i.length>1?t(o,{variant:`ui-caption`,tone:`muted`,children:e(`app.client.taskDiscussion.replyingTo`,{name:T?.messages[0]?.author.name??e(`app.client.taskDiscussion.theDiscussion`)})}):null,t(u,{label:e(`app.client.taskDiscussion.addTaskComment`),placeholder:e(`app.client.taskDiscussion.addContextPlaceholder`),busy:v.busy||E,class:`w-full`,onSubmit:async t=>{if(E)throw Error(e(`app.client.taskDiscussion.loadBeforeReplying`));T&&S.reply?await b({id:T.id,body:t}):(d=(await b({anchor:null,itemIds:_,body:t})).thread.id,p=!!d,m=!1,_=[s.props.itemId],s.update())}},`task-composer`)]}):null]}):t(o,{variant:`ui-caption`,tone:`muted`,children:e(`app.client.taskDiscussion.commentsUnavailable`)}):t(o,{variant:`ui-caption`,tone:`muted`,role:`status`,children:e(`app.client.taskDiscussion.loadingDiscussion`)}),g?t(L,{project:s.props.project,selected:_,required:[s.props.itemId],onSave:async e=>{_=e,s.update()},onClose:()=>{g=!1,s.update()}}):null]})}}function ie(e,t){return e.revision===null?Object.entries(e.values).some(([e,n])=>JSON.stringify(n)!==JSON.stringify(t.values[e])):e.revision!==t.revision}async function z(t,n,r,i,a){let[o,s,c]=await Promise.all([P(w.tasksApi.show.href({id:n}),t,i,e=>e),M(t,n,i,a),r]),l=y(o,c);if(l.item.id!==n)throw Error(e(`app.client.projectTasks.differentTaskRefresh`));return{detail:l,discussion:s}}async function B(t,n,r,i){let a=await k(t),o=D(a),s=o?Promise.resolve(o):I(t).refresh(n),c=r?g(r):null,l=e=>z(t.token,c,e,n,i),u=``,d=c?l(s.then(e=>e.schema)).catch(e=>{if(!o||e instanceof F)throw e;return l(I(t).refresh(n).then(e=>e.schema))}).catch(t=>(u=t instanceof Error?t.message:e(`app.client.projectTasks.couldNotLoadTask`),null)):null;try{await s;let e=await d;return{store:a,stored:!!o,error:``,task:e,taskError:u}}catch(t){return n.throwIfAborted(),{store:a,stored:!1,error:t instanceof Error?t.message:e(`app.client.projectTasks.couldNotLoadTasks`)}}}function V(n){let r=n.props.project,a=n.props.initial.store,o=I(r),s=D(a),l=()=>{let e=s?.snapshot.schemaVersion;s=D(a);let t=x?a.work.get(x.item.id):void 0;(t&&!t.$hasPendingWrites&&ie(j(t),x.item)||!x&&k&&s?.snapshot.schemaVersion!==e)&&Z(),Y()},u=[a.boards.subscribeChanges(l),a.work.subscribeChanges(l)],f=g(n.props.href),p=n.props.initial.task,x=p?.detail.item.id===f?p.detail:null,T=x?p.discussion:void 0,O=!1,k=n.props.initial.task?``:n.props.initial.taskError??``,A=f!==null&&!x&&!k,M=n.props.initial.error,N=null,F=null,L=new Set,R=n.props.href,B,V=!1,H=!1;function ae(e){let t=e?a.work.get(e.item.id):void 0;if(!e||!t?.$hasPendingWrites)return e;let n={...e.item.values,...j(t).values};return{...e,item:{...e.item,values:n}}}function U(){if(!s)throw Error(e(`app.client.projectTasks.refreshBeforeChanges`));return s.schema}async function W(e,t,i){let a=new AbortController;L.add(a);try{return await P(e,r.token,AbortSignal.any([n.signal,a.signal]),i,fetch,{body:t})}finally{L.delete(a)}}async function oe(e){await b(a.work,{upsert:[e]}),x?.item.id===e.id&&(x={...x,item:e}),Y()}async function G(){await X(),f&&await Z()}let K=new Map;async function q(t,r,i,a){let o=a?K.get(a):void 0,s=Promise.withResolvers();a&&K.set(a,s.promise);try{let n=await S(i,async()=>{let n=await o,i=`expectedRevision`in r?r.expectedRevision:void 0,c=await W(t,n&&i===n.from&&n.to?{...r,expectedRevision:n.to}:r,e=>v(e,U()));if(a&&c.item.id!==a)throw Error(e(`app.client.projectTasks.differentTaskRefreshRetry`));return await oe(c.item),s.resolve(i?{from:i,to:c.item.revision}:null),c.item});return f&&await Z(),n}catch(t){throw s.resolve(null),n.signal.aborted||d.error(e(`app.client.projectTasks.undidTaskChange`),{description:t instanceof Error?t.message:e(`app.client.projectTasks.writeNotConfirmed`)}),G(),t}finally{a&&K.get(a)===s.promise&&K.delete(a)}}function J(e,t){return()=>{let n=a.work.get(e);if(!n)return;let{values:r}=t(j(n));a.work.update(e,e=>{e.values=r})}}let se={create:e=>q(w.tasksApi.create.href(),e,()=>{a.work.insert(te(U(),`pending-${crypto.randomUUID()}`,e))}),update:(e,t)=>q(w.tasksApi.update.href({id:e}),t,J(e,e=>ne(e,t)),e),act:(e,t)=>q(w.tasksApi.mutate.href({id:e}),t,J(e,e=>ee(U(),e,t)),e),get:async t=>{let i=await P(w.tasksApi.show.href({id:t}),r.token,n.signal,e=>y(e,U()));if(i.item.id!==t)throw Error(e(`app.client.projectTasks.differentTaskRefresh`));return i.item},section:(e,t,i=n.signal)=>P(w.tasksApi.section.href({id:e,section:t}),r.token,AbortSignal.any([n.signal,i]),e=>_(e,U())),sync:async e=>{try{let t=await W(w.tasksApi.sync.href(),e,c);return await G(),t}catch(e){throw G(),e}}};function Y(){n.signal.aborted||n.update()}async function X(){N?.abort();let t=new AbortController;N=t,O=!0,M=``,Y();try{await o.refresh(AbortSignal.any([n.signal,t.signal]))}catch(r){!t.signal.aborted&&!n.signal.aborted&&(M=r instanceof Error?r.message:e(`app.client.projectTasks.couldNotLoadTasks`))}finally{N===t&&(O=!1,Y())}}async function Z(){if(F?.abort(),!f){x=null,A=!1,k=``,Y();return}let t=f,i=new AbortController;F=i;let a=x?.item.id!==t;a&&(x=null),A=!0,k=``,Y();try{let o=AbortSignal.any([n.signal,i.signal]);if(a){let e=await z(r.token,t,U(),o,n.props.conversationId);if(i.signal.aborted||t!==f)return;x=e.detail,T=e.discussion;return}let s=await P(w.tasksApi.show.href({id:t}),r.token,o,e=>y(e,U()));if(i.signal.aborted||t!==f)return;if(s.item.id!==t)throw Error(e(`app.client.projectTasks.differentTaskRefresh`));x=s}catch(r){!i.signal.aborted&&!n.signal.aborted&&t===f&&(k=r instanceof Error?r.message:e(`app.client.projectTasks.couldNotLoadTask`))}finally{F===i&&(A=!1,Y())}}function Q(e,t=!0){e!==f&&(f=e,t&&$(!1),Z(),Y())}function $(e){let t=h(null);if(!n.props.active||!E(window.location.href)&&window.location.pathname!==t&&!window.location.pathname.startsWith(`${t}/`)){V=!0;return}V=!1;let r=h(f);window.location.pathname+window.location.search+window.location.hash!==r&&(B=new URL(r,window.location.origin).href,window.history[e?`replaceState`:`pushState`]({...window.history.state,budTask:f},``,r))}let ce=i((e,t)=>{H=!0;let r=f;f=g(n.props.href),x?.item.id!==f&&!(k&&r===f)&&Z(),n.props.initial.stored&&X(),t.addEventListener(`abort`,()=>{for(let e of u)e.unsubscribe();N?.abort(),F?.abort();for(let e of L)e.abort()},{once:!0})});return()=>{if(H&&R!==n.props.href){if(R=n.props.href,B!==R){V=!1;let e=g(R);e!==f&&n.queueTask(()=>Q(e,!1))}B=void 0}V&&n.props.active&&n.queueTask(()=>$(!0));let e=s,i=e?.snapshot.items.map(t=>({id:t.id,title:m(t,e.schema,`title`)||void 0}));return t(`div`,{class:`h-full min-h-0`,mix:ce,children:t(C,{projectName:r.name,project:{id:r.id,name:r.name},design:n.props.design,storageKey:`bud:tasks:${r.id}:v1`,snapshot:e?.snapshot??null,schema:e?.schema??null,loading:O,error:M,selectedId:f,detail:ae(x),discussion:x?t(re,{project:r,itemId:x.item.id,initial:T,items:i,conversationId:n.props.conversationId,onChange:G},x.item.id):void 0,detailLoading:A,detailError:k,operations:se,onSelect:Q,onReload:()=>{X()},onReloadDetail:()=>{Z()}})})}}var H=s({routes:p,load:({project:e,signal:t,url:n,conversation:r})=>B(e,t,n.href,r?.id),render:(e,{project:n,url:r,active:i,taskDesign:a,conversation:o})=>t(V,{project:n,initial:e,design:a,href:r.href,active:i,conversationId:o?.id})});export{H as default};
@@ -0,0 +1 @@
1
+ import{n as e}from"./i18n-BtfXum8P.js";import{Sn as t,bn as n,yt as r}from"./task-design-DYqcqq1b.js";import{b as i}from"./project-threads-CHGG-6fo.js";var a=r(),o=r();for(let[e,t]of Object.entries(i.tasksApi))(t.method===`GET`?a:o).add(t.pattern,e);function s(e,r){if(!e.startsWith(`/`)||e.startsWith(`//`)||e.length>7e3||/[\\#\u0000-\u0020]/.test(e))return!1;try{let i=(r?o:a).match(e,{baseURL:`http://bud.invalid`});if(!i||i.url.pathname!==e.split(`?`)[0])return!1;for(let[e,t]of Object.entries(i.params))(e===`id`||e===`section`)&&n({id:t});if(i.data!==`index`&&i.data!==`workspace`)return!i.url.search;let s={};for(let[e,t]of i.url.searchParams){if(![`search`,`status`,`limit`].includes(e)||Object.hasOwn(s,e))return!1;s[e]=e===`limit`?Number(t):t}return t(s),!0}catch{return!1}}async function c(t,n,r,i,a=fetch,o){if(!s(t,!!o))throw Error(e(`app.client.tasksRequest.invalidEndpoint`));r.throwIfAborted();let c=await a(t,{method:o?`POST`:`GET`,headers:{"X-Bud-Token":n,...o?{"Content-Type":`application/json`}:{}},...o?{body:JSON.stringify(o.body)}:{},credentials:`same-origin`,redirect:`error`,cache:`no-store`,signal:r}),u=c.body?.getReader();if(!u)throw Error(e(`app.client.tasksRequest.emptyResponse`));let d=[],f=0;try{for(;;){r.throwIfAborted();let t=await u.read();if(t.done)break;if(f+=t.value.byteLength,f>4194304)throw Error(e(`app.client.tasksRequest.responseTooLarge`));d.push(t.value)}}catch(e){throw await u.cancel().catch(()=>{}),e}finally{u.releaseLock()}let p=new Uint8Array(f),m=0;for(let e of d)p.set(e,m),m+=e.byteLength;let h;try{h=JSON.parse(new TextDecoder(`utf-8`,{fatal:!0}).decode(p))}catch{throw Error(e(`app.client.tasksRequest.invalidResponse`))}if(!c.ok){let t=h&&typeof h==`object`&&`error`in h&&typeof h.error==`string`?h.error.slice(0,1e3):e(`app.client.tasksRequest.loadFailed`),n=h&&typeof h==`object`&&`code`in h&&typeof h.code==`string`&&/^[a-z][a-z-]{0,63}$/.test(h.code)?h.code:`request`,r;if(h&&typeof h==`object`&&`currentRevision`in h){let t=h.currentRevision;if(t!==null&&(typeof t!=`string`||!t.trim()||t.length>256||t.includes(`\0`)))throw Error(e(`app.client.tasksRequest.invalidConflictResponse`));r=t}throw new l(t,n,r)}return i(h)}var l=class extends Error{code;currentRevision;constructor(e,t,n){super(e),this.name=`TaskRequestError`,this.code=t,this.currentRevision=n}};export{c as n,l as t};
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/pages-B-_CKvDS.js","assets/i18n-BtfXum8P.js","assets/jsx-B4XNFIzB.js","assets/component-DWct-Tq6.js","assets/on-mixin-iWnqUzq5.js","assets/children-N0l0v7XI.js","assets/attrs-mixin-CmlG_FtV.js","assets/create-element--E6NJ0nh.js","assets/loader-Q6-HPKft.js","assets/screen-Dfvzj6n2.js","assets/task-design-DYqcqq1b.js","assets/lru-BkhKJhvt.js","assets/method-DybmO5PB.js","assets/project-threads-CHGG-6fo.js","assets/frame-D6XmK4Df.js","assets/preload-helper-BLdHbfdN.js","assets/cloneFileDiffMetadata-CWfw01dG.js","assets/project-comments-CQkB2jbE.js","assets/workspace-tab-Bg2MFdMB.js","assets/project-branches-DzXdaT9L.js","assets/canvas-C8hyPWoT.js","assets/project-thread-links-BN7zL0AX.js","assets/tasks-request-DGigNdyK.js","assets/tasks-A2FKo3_h.js","assets/project-work-L5fYMSOu.js","assets/files-D_Tm7gCK.js"])))=>i.map(i=>d[i]);
2
+ import{n as e}from"./i18n-BtfXum8P.js";import{t}from"./jsx-B4XNFIzB.js";import{n}from"./on-mixin-iWnqUzq5.js";import{n as r}from"./run-B2H4brp5.js";import{n as i}from"./attrs-mixin-CmlG_FtV.js";import{t as a}from"./preload-helper-BLdHbfdN.js";import{c as o,i as s,l as c,o as l,r as u,t as ee}from"./loader-Q6-HPKft.js";import{Et as d,Fn as f,Gn as p,Hn as m,In as h,Kn as g,Ln as _,Mn as v,Nn as y,Ot as b,Pn as x,Q as S,Un as C,Vn as w,jn as T,yt as E}from"./task-design-DYqcqq1b.js";import{$ as te,At as ne,Dt as re,J as D,Ot as O,Q as k,X as ie,Y as ae,Z as A,b as j,dt as M,et as N,jt as oe,kt as se,nt as ce,ot as P,rt as le,t as F,tt as ue,v as de,y as fe}from"./project-threads-CHGG-6fo.js";import{d as pe}from"./method-DybmO5PB.js";import{t as me}from"./project-work-L5fYMSOu.js";import{n as he}from"./workspace-tab-Bg2MFdMB.js";function ge(e){let n=`connecting`,r=i((t,r)=>{let{project:i}=e.props;me(i),F(i);let a=fe(i.token);n=a.status;let o=a.watchStatus(t=>{n=t,e.update()});r.addEventListener(`abort`,o,{once:!0}),e.update()});return()=>t(`span`,{class:`contents`,mix:r,children:t(O,{status:n})})}var I=new WeakMap;function L(e,t){let n=p(e,t,{abortEarly:!0});if(n.success)return n.value;let r=n.issues[0];throw I.get(r)??Error(r.message)}function R(e,t){return x((n,r)=>{let i=e[`~run`](n,r);return i.issues?_(t,r.path):i})}function z(e,t){return x((n,r)=>{let i=e[`~run`](n,r);if(i.issues)return i;let a=t(i.value);return a===void 0?i:_(a,r.path)})}function B(e,t){return x((n,r)=>{let i=e[`~run`](n,r);if(i.issues)return i;try{return{value:t(i.value)}}catch(e){if(!(e instanceof Error))throw e;let t=_(e.message,r.path);return I.set(t.issues[0],e),t}})}function _e(e){return x((t,n)=>e(t)[`~run`](t,n))}function V(e,t){return x((n,r)=>n==null?{value:t()}:e[`~run`](n,r))}function H(e,t){let n=m(t);return x((r,i)=>{if(!r||typeof r!=`object`||Array.isArray(r))return _(`${e} must be an object.`,i.path);for(let n of Object.keys(r))if(!Object.hasOwn(t,n))return _(`${e}.${n} is not a supported setting.`,[...i.path,n]);return n[`~run`](r,i)})}function ve(e,t,n=0){let r=v(e);return x((e,i)=>!Array.isArray(e)||e.length<n?_(t,i.path):r[`~run`](e,i))}var ye=f(H(`files`,{edit:V(R(y(),`files.edit must be true or false.`),()=>!0)}),()=>({edit:!0})),U=`flows must be [{ id, title, start, script, steps: [{ id, title }], block? }] with short ids, local paths and unique steps.`,be=e=>typeof e==`string`&&/^[a-z0-9][a-z0-9-]{0,62}$/.test(e),W=e=>typeof e==`string`&&e.trim()!==``&&e.length<=200;function xe(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let{id:t,title:n,start:r,script:i,steps:a,block:o=[]}=e;if(!be(t)||!W(n)||!W(i)||i.includes(`\0`)||typeof r!=`string`||!r.startsWith(`/`)||r.startsWith(`//`)||new URL(r,`http://bud.invalid`).origin!==`http://bud.invalid`||!Array.isArray(a)||!a.length||a.length>50)return null;let s=a.map(e=>{let{id:t,title:n}=e??{};return be(t)&&W(n)?{id:t,title:n.trim()}:null});if(s.some(e=>!e))return null;let c=s.map(e=>e.id);return new Set(c).size!==c.length||!Array.isArray(o)||o.some(e=>!W(e))?null:{id:t,title:n.trim(),start:r,script:i.trim(),steps:s,block:o}}var Se=x((e,t)=>{if(e===void 0)return{value:[]};if(!Array.isArray(e))return _(U,t.path);let n=e.map(xe);if(n.some(e=>!e))return _(U,t.path);let r=n.map(e=>e.id);return new Set(r).size===r.length?{value:n}:_(U,t.path)});function Ce(e,t){return{id:`${e.id}/${t.id}`,path:`${e.start.replace(/#.*$/,``)}#${e.id}-${t.id}`,title:t.title,group:e.title,flow:{id:e.id,step:t.id}}}var we=Object.freeze({".svg":`image/svg+xml`,".png":`image/png`,".webp":`image/webp`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".gif":`image/gif`,".ico":`image/x-icon`}),Te=`logo must be an image path inside the project (.svg, .png, .webp, .jpg, .gif or .ico), or { light, dark }.`;function Ee(e){if(typeof e!=`string`||e.length>1024||e.includes(`\0`))return null;let t=e.trim().replaceAll(`\\`,`/`);if(!t||t.startsWith(`/`)||/^[a-z]:/i.test(t)||t.split(`/`).includes(`..`))return null;let n=t.slice(t.lastIndexOf(`.`)).toLowerCase();return Object.hasOwn(we,n)?t:null}var De=x((e,t)=>{if(e===void 0)return{value:null};let n=Ee(typeof e==`object`&&e?e.light:e),r=typeof e==`object`&&e?e.dark:void 0,i=r===void 0?null:Ee(r),a=typeof e==`object`&&e?Object.keys(e):[];return n&&(r===void 0||i)&&a.every(e=>e===`light`||e===`dark`)?{value:{light:n,dark:i}}:_(Te,t.path)}),Oe=Object.freeze(`background.shell.main.canvas.panel.board.editor.editor-tabs.foreground.muted.primary.primary-hover.primary-foreground.border.tab-divider.hover.selected.control.control-active.control-selected.card.menu.menu-hover.card-frame.card-surface.card-border.card-frame-border.card-badge.overlay-shadow.tooltip.board-control.board-control-hover.board-card.control-elevation.board-elevation.board-card-elevation.card-elevation.board-card-lift.frame-control.modal-elevation.segment-elevation.control-open-elevation.board-segment.scrollbar.focus.scrollbar-hover.tooltip-border.tooltip-shadow`.split(`.`)),ke=`theme must be { light, dark }, each mapping Bud's tokens (${Oe.slice(0,3).join(`, `)}, …) to CSS colors or shadows.`;function Ae(e){if(typeof e!=`string`)return null;let t=e.trim();return!t||t.length>300||!/^[#a-zA-Z0-9(),.%\s/+-]+$/.test(t)||/url\s*\(/i.test(t)?null:t}function je(e){if(e===void 0)return{};if(!e||typeof e!=`object`||Array.isArray(e))return null;let t={};for(let[n,r]of Object.entries(e)){let e=Ae(r);if(!Oe.includes(n)||e===null)return null;t[n]=e}return Object.freeze(t)}var Me=x((e,t)=>{if(e===void 0)return{value:{light:{},dark:{}}};if(!e||typeof e!=`object`||Array.isArray(e))return _(ke,t.path);let{light:n,dark:r,...i}=e,a={light:je(n),dark:je(r)};return Object.keys(i).length||!a.light||!a.dark?_(ke,t.path):{value:{light:a.light,dark:a.dark}}}),G=`branches must be { main?, build?: { install?, build?, serve? } } with a branch name and nonempty shell commands.`;function Ne(e){return typeof e==`string`&&e.length<=255&&/^[A-Za-z0-9._/-]+$/.test(e)&&!e.startsWith(`-`)&&!e.startsWith(`/`)&&!e.endsWith(`/`)&&!e.endsWith(`.lock`)&&!e.includes(`..`)&&!e.includes(`//`)?e:null}function K(e){return typeof e==`string`&&e.trim()&&e.length<=4096&&!e.includes(`\0`)?e.trim():null}var Pe=x((e,t)=>{let n={main:null,install:null,build:null,serve:null};if(e===void 0)return{value:n};if(!e||typeof e!=`object`||Array.isArray(e))return _(G,t.path);let r=e,i=r.build??{};if(!i||typeof i!=`object`||Array.isArray(i)||Object.keys(r).some(e=>e!==`main`&&e!==`build`))return _(G,t.path);let a=i;if(Object.keys(a).some(e=>![`install`,`build`,`serve`].includes(e)))return _(G,t.path);let o={main:r.main===void 0?null:Ne(r.main),install:a.install===void 0?null:K(a.install),build:a.build===void 0?null:K(a.build),serve:a.serve===void 0?null:K(a.serve)};return r.main!==void 0&&!o.main||[`install`,`build`,`serve`].some(e=>a[e]!==void 0&&!o[e])?_(G,t.path):{value:o}});function q(e,t,n){let r=t?/\.server\.ts$/:/\.(?:ts|tsx|js|jsx)$/;return R(g().refine(e=>e.length<=1024&&e.startsWith(`./`)&&!/[\u0000-\u001f\u007f\\?#%]/.test(e)&&r.test(e)&&(t||!/\.server\.[cm]?[jt]sx?$/.test(e))&&!e.slice(2).split(`/`).some(e=>!e||e===`.`||e===`..`||e===`node_modules`)),n??(t?`${e} must be a built-in adapter or a ./ module ending in .server.ts inside the project.`:`${e} must be bud:beads or a ./ browser module ending in .ts, .tsx, .js or .jsx inside the project.`))}var Fe=h([!1,`bud:beads`,`bud:memory`,`bud:git-comments`]);function Ie(e){let t=q(`storage.${e}`,!0);return f(z(_e(e=>e===!1||e===`bud:beads`||e===`bud:memory`||e===`bud:git-comments`?Fe:t),t=>e===`work`&&t===`bud:git-comments`?`storage.work cannot use bud:git-comments; it only stores threads.`:void 0),`bud:beads`)}var Le=f(H(`storage`,{work:Ie(`work`),threads:Ie(`threads`)}),()=>({work:`bud:beads`,threads:`bud:beads`})),Re=f(H(`designs`,{tasks:f(_e(e=>e===`bud:beads`?h([`bud:beads`]):q(`designs.tasks`,!1)),`bud:beads`),pages:f(h([`path`,`title`]),`path`)}),()=>({tasks:`bud:beads`,pages:`path`})),ze=new Set([`bud:dom`,`bud:react`,`bud:react-grab`]),Be=q(`picker`,!1,`picker must be bud:dom, bud:react, bud:react-grab or a ./ browser module ending in .ts, .tsx, .js or .jsx inside the project.`),Ve=x((e,t)=>{if(e===void 0)return{value:{name:`bud:dom`,module:null}};if(typeof e==`string`&&ze.has(e))return{value:{name:e,module:null}};let n=Be[`~run`](e,t);return n.issues?n:{value:{name:n.value,module:n.value}}}),He=`ready must be a CSS selector, { selector } or { expression }.`,J=x((e,t)=>{let n=typeof e==`string`?{selector:e}:e;if(n&&typeof n==`object`&&!Array.isArray(n)){let e=Object.entries(n),[t,r]=e[0]??[];if(e.length===1&&(t===`selector`||t===`expression`)&&typeof r==`string`&&r.trim()&&r.length<=4096)return{value:t===`selector`?{selector:r.trim()}:{expression:r.trim()}}}return _(He,t.path)}),Ue=()=>[`light`,`dark`],We=()=>[{id:`desktop`,name:`Desktop`,width:1440,height:900,mobile:!1}],Y=`previews.viewports must list up to 4 { name, width, height?, mobile? } with distinct names, widths from 240 to 3840 and heights from 240 to 4000.`;function Ge(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,32)}var Ke=x((e,t)=>{if(!Array.isArray(e)||e.length===0||e.length>4)return _(Y,t.path);let n=[];for(let r of e){if(!r||typeof r!=`object`||Array.isArray(r))return _(Y,t.path);let{name:e,width:i,height:a,mobile:o,...s}=r,c=(e,t,n)=>typeof e==`number`&&Number.isInteger(e)&&e>=t&&e<=n;if(Object.keys(s).length||typeof e!=`string`||!e.trim()||e.length>40||!Ge(e)||!c(i,240,3840)||a!==void 0&&!c(a,240,4e3)||o!==void 0&&typeof o!=`boolean`)return _(Y,t.path);let l=o??i<800;n.push({id:Ge(e),name:e.trim(),width:i,height:a??(l?Math.round(i*844/390):900),mobile:l})}return new Set(n.map(e=>e.id)).size===n.length?{value:n}:_(Y,t.path)}),qe=f(H(`previews`,{scale:V(R(w().refine(e=>Number.isInteger(e)&&e>=1&&e<=3),`previews.scale must be 1, 2 or 3.`),()=>2),themes:V(R(v(h([`light`,`dark`])).refine(e=>e.length>0&&new Set(e).size===e.length),`previews.themes must list light, dark or both, once each.`),Ue),viewports:V(Ke,We),ready:V(J,()=>null),readyTimeout:V(R(w().refine(e=>Number.isInteger(e)&&e>=1e3&&e<=6e5),`previews.readyTimeout must be whole milliseconds from 1000 to 600000.`),()=>6e4),css:V(R(g().refine(e=>e.length<=2e4&&!e.includes(`<`)),`previews.css must be CSS text without <, up to 20000 characters.`),()=>``)}),()=>({scale:2,themes:Ue(),viewports:We(),ready:null,readyTimeout:6e4,css:``}));function Je(e,t){let n=[],r=new Set;function i(e,a){if(!e||typeof e!=`object`||Array.isArray(e)||r.has(e))throw Error(`Screen routes must be a Remix route map.`);r.add(e);for(let[r,o]of Object.entries(e)){let e=a?`${a}.${r}`:r;if(!o||typeof o!=`object`)throw Error(`Screen route ${e} must be a Remix route.`);if(!(`pattern`in o)){i(o,e);continue}if(![`GET`,`ANY`].includes(o.method)||typeof o.href!=`function`||typeof o.pattern?.source!=`string`)throw Error(`Screen route ${e} must be a GET route.`);let s=pe.parse(o.pattern.source),c=s.toJSON(),l=`/${c.pathname}`;if(c.protocol||c.hostname||c.port||c.pathname.split(`/`).some(e=>/^\.{1,2}$/.test(decodeURIComponent(e)))||l!==t&&!l.startsWith(`${t}/`)&&!l.startsWith(`${t}(/`))throw Error(`Screen route ${e} must stay under ${t}.`);n.push({name:e,pattern:s.source})}r.delete(e)}if(i(e,``),!n.length)throw Error(`Screen routes must contain at least one route.`);return n}function Ye(){return{id:`pages`,label:`Pages`,icon:`browser`,path:`/pages`,module:`bud:pages`}}function Xe(){return{id:`canvas`,label:`Canvas`,icon:`grid`,path:`/canvas`,module:`bud:canvas`}}function Ze(){return{id:`tasks`,label:`Tasks`,icon:`tasks`,path:`/tasks`,module:`bud:tasks`}}function Qe(){return{id:`files`,label:`Files`,icon:`files`,path:`/files`,module:`bud:files`}}var X=[Ye(),Xe(),Ze(),Qe()],$e=new Map(X.map(e=>[e.module,e])),et=[`/comments`,...X.map(e=>e.path),`/api`,`/health`,`/__bud`,`/assets`,`/app`,`/src`,`/node_modules`,`/agents`,`/brand`,`/fonts`,`/frameworks`,`/licenses`],tt=z(R(T().refine(e=>!!e&&typeof e==`object`),`Each screen must be an object.`),({id:e,label:t,icon:n=`layers`,module:r,path:i})=>{if(typeof e!=`string`||!/^[a-z][a-z0-9-]{0,31}$/.test(e))return`Screen ids are 1-32 lowercase letters, digits and hyphens.`;if(typeof t!=`string`||!t.trim())return`Screen ${e} needs a label.`;if(typeof n!=`string`||!n)return`Screen ${e} needs an icon name.`;if(typeof r!=`string`)return`Screen ${e} needs a module.`;let a=$e.get(r);if(i??=a?.path??`/${e}`,a)return e!==a.id||i!==a.path?`${r} keeps id "${a.id}" and path "${a.path}".`:void 0;if(!/^\.\/[^\0\\]+\.(?:ts|tsx|js|jsx)$/.test(r))return`Screen ${e} must be a ./ module ending in .ts, .tsx, .js or .jsx.`;if(typeof i!=`string`||!/^\/[a-z0-9][a-z0-9-]*$/.test(i))return`Screen ${e} needs one static path segment, such as /${e}.`;if(X.some(t=>t.id===e))return`Screen id "${e}" is reserved for a built-in screen.`;if(et.includes(i))return`Bud reserves the path ${i}.`}),nt=f(B(R(v(T()).refine(e=>e.length>0),`screens must list at least one screen.`),e=>{let t=new Set,n=new Set;return e.map(e=>{let r=L(tt,e),{id:i,label:a,icon:o=`layers`,module:s}=r,c=r.path??$e.get(s)?.path??`/${i}`;if(t.has(i)||n.has(c))throw Error(`Screen ids and paths must be unique.`);return t.add(i),n.add(c),r.routes!==void 0&&Je(r.routes,c),{id:i,label:a,icon:o,path:c,module:s,...r.routes===void 0?{}:{routes:r.routes}}})}),()=>X.map(e=>({...e}))),rt=e=>!!e&&typeof e==`object`;function Z(e,t){let n=m(t);return x((t,r)=>rt(t)?n[`~run`](Array.isArray(t)?{...t}:t,r):_(e,r.path))}var it=z(Z(`Bud config must export an object.`,{routes:R(v(T()).refine(e=>e.length>0),`bud.config must define at least one route.`),name:C(R(g().refine(e=>!!e.trim()),`name must be a nonempty string.`)),target:C(Z(`target must be an object.`,{origin:T(),port:T()})),comments:C(Z(`comments must be an object.`,{remote:T()})),port:T(),screens:T(),storage:T(),designs:T(),previews:T(),files:T(),logo:T(),theme:T(),locale:T(),picker:T(),branches:T(),flows:T()}),({target:e})=>{if(e?.port===0)return`target.port must be a listening port, not zero.`;if(e?.origin!==void 0&&(typeof e.origin!=`string`||!e.origin.trim()))return`target.origin must be an HTTP(S) origin.`}),at=z(T().transform(e=>typeof e==`string`?{path:e,title:e===`/`?`Home`:e}:e),e=>{if(!e||typeof e.path!=`string`||!e.path.startsWith(`/`)||e.path.startsWith(`//`))return`Canvas routes must be local paths beginning with a single /.`;if(new URL(e.path,`http://bud.invalid`).origin!==`http://bud.invalid`||e.path.includes(`\\`))return`Canvas routes must stay on the target origin.`;let t=e.id??Q(e.path);if(typeof t!=`string`||!t.trim())return`Canvas route IDs and paths must be unique.`;if(typeof e.title!=`string`||!e.title.trim())return`Each route needs a title.`;if(e.pattern!==void 0&&(typeof e.pattern!=`string`||!e.pattern.startsWith(`/`)))return`A route pattern must be a path beginning with /.`;if(e.group!==void 0&&(typeof e.group!=`string`||!e.group.trim()||e.group.length>120))return`A route group must be a short name.`;if(e.ready!==void 0&&e.ready!==!1&&!p(J,e.ready).success)return`A route ready must be false, a CSS selector, { selector } or { expression }.`}).transform(e=>{let t=Q(e.path);return{id:e.id??t,path:t,title:e.title,...e.pattern===void 0?{}:{pattern:e.pattern},...e.group===void 0?{}:{group:e.group.trim()},...e.ready===void 0?{}:{ready:e.ready===!1?null:L(J,e.ready)}}});function Q(e){let t=new URL(e,`http://bud.invalid`),n=t.searchParams.toString();return`${t.pathname}${n?`?${n}`:``}${t.hash}`}var ot=z(ve(at,`bud.config must define at least one route.`,1),e=>new Set(e.map(e=>e.id)).size!==e.length||new Set(e.map(e=>e.path)).size!==e.length?`Canvas route IDs and paths must be unique.`:void 0),st=e=>e===void 0||Number.isInteger(e)&&e>=0&&e<=65535,ct=e=>typeof e==`string`&&/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(e);B(z(B(z(z(B(z(B(it,e=>({...e,routes:L(ot,e.routes)})),({port:e,target:t})=>st(e??0)&&st(t?.port)?void 0:`Ports must be integers between 0 and 65535.`),({target:e,...t})=>{let n=e?.origin??(e?.port?`http://127.0.0.1:${e.port}`:void 0);return{...t,targetOrigin:n&&lt(n,`target.origin must be an HTTP(S) origin without a path or credentials.`)}}),({locale:e})=>e===void 0||e===`en`||e===`de`?void 0:`locale must be "en" or "de".`),({comments:e})=>ct(e?.remote??`origin`)?void 0:`comments.remote must be a Git remote name.`),e=>{let t=L(Se,e.flows),n=t.flatMap(e=>e.steps.map(t=>Ce(e,t))),r=e.routes.findIndex(e=>e.path===`/`)+1;return{...e,flows:t,routes:[...e.routes.slice(0,r),...n,...e.routes.slice(r)]}}),({routes:e})=>new Set(e.map(e=>e.id)).size!==e.length||new Set(e.map(e=>e.path)).size!==e.length?`A flow step must not reuse a route’s id or path.`:void 0),e=>({name:e.name??`Your project`,routes:e.routes,flows:e.flows,port:e.port??0,targetOrigin:e.targetOrigin,remote:e.comments?.remote??`origin`,screens:L(nt,e.screens),storage:L(Le,e.storage),designs:L(Re,e.designs),previews:L(qe,e.previews),files:L(ye,e.files),logo:L(De,e.logo),theme:L(Me,e.theme),locale:e.locale===void 0?`en`:e.locale,picker:L(Ve,e.picker),branches:L(Pe,e.branches)}));function lt(e,t){let n=new URL(e);if(![`http:`,`https:`].includes(n.protocol)||n.username||n.password||n.pathname!==`/`||n.search||n.hash)throw Error(t);return n.origin}function $(e,t){let n=E();for(let t of e)n.add(t.pattern,t.name);let r=n.match(t,{baseURL:`http://bud.invalid`});return r?{route:r.data,params:r.params}:null}function ut(e,t){let n=e?$(Je(e,t.path),t.url):{route:null,params:{}};if(!n)throw Error(`No screen route matches ${t.url.pathname}.`);return{...t,...n}}var dt={"bud:pages":()=>a(()=>import(`./pages-B-_CKvDS.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19])),"bud:canvas":()=>a(()=>import(`./canvas-C8hyPWoT.js`),__vite__mapDeps([20,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,19,21,22])),"bud:tasks":()=>a(()=>import(`./tasks-A2FKo3_h.js`),__vite__mapDeps([23,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,22,24,21])),"bud:files":()=>a(()=>import(`./files-D_Tm7gCK.js`),__vite__mapDeps([25,11,1,2,6,4,3,5,7,15,8,9,10,12,16,13,14,17,21,22]))};function ft(e){return Object.hasOwn(dt,e)?dt[e]():a(()=>import(e),[])}async function pt(e,t,n=ft){let r=(await n(e)).default;if(typeof r?.render!=`function`)throw Error(`A screen module must export defineScreen({ render }) as its default.`);let i=await r.load?.(ut(r.routes,t));return t.signal.throwIfAborted(),{screen:r,data:i}}async function mt(e,t,n=e=>a(()=>import(e),[])){if(t.throwIfAborted(),!e)return;if(`error`in e)throw Error(e.error);let r=await n(e.url);return t.throwIfAborted(),S(r.default)}function ht(r){let a,d=``;async function f(){let{module:t,project:n,label:i}=r.props;a=void 0,d=``,r.update();let{location:o}=r.props,s={project:n,signal:r.signal,path:o.path,url:new URL(o.href,window.location.origin),active:r.props.active,conversation:o.conversation,route:null,params:{}};try{if(`error`in t)throw Error(t.error);s.taskDesign=await mt(r.props.taskDesign,r.signal),a={...await pt(t.url,s),context:s}}catch(t){if(r.signal.aborted)return;console.error(t),d=t instanceof Error&&t.message?t.message:e(`app.client.screenHost.couldNotOpen`,{label:i})}r.update()}let p=i(()=>{f()});return()=>{let{label:i,module:m,location:h}=r.props,g=a?.context,_=``;if(a&&g)try{if(h.routes&&!$(h.routes,h.href))throw Error(e(`app.client.screenHost.noRouteMatches`,{href:h.href}));g=ut(a.screen.routes,{...g,active:r.props.active,conversation:h.conversation,url:new URL(h.href,g.url.origin)})}catch(t){_=t instanceof Error?t.message:e(`app.client.screenHost.invalidRoute`)}return t(`div`,{class:`h-full min-h-0`,mix:p,children:_?t(`div`,{class:`p-3 md:p-4`,children:t(c,{role:`alert`,children:_})}):a&&g?a.screen.render(a.data,g):d?t(`div`,{class:`h-full overflow-y-auto p-3 md:p-4`,children:t(u,{class:`max-w-2xl`,role:`alert`,children:[t(l,{title:e(`app.client.screenHost.didntOpen`,{label:i}),subtitle:d}),t(s,{class:`flex-col items-start gap-3`,children:[t(c,{as:`p`,variant:`ui`,tone:`muted`,children:e(`app.client.screenHost.fixAndRetry`)}),t(o,{mix:n(`click`,()=>{`error`in m||r.props.taskDesign&&`error`in r.props.taskDesign?window.location.reload():f()}),children:e(`app.client.screenHost.retry`)})]})]})}):t(ee,{label:e(`app.client.screenHost.loading`,{label:i})})})}}async function gt(t,n,r,i,a=fetch){t=b(t);let o=await de(j.comments.get.href({id:t}),r,i,d,a);if(i.throwIfAborted(),o.id!==t)throw Error(e(`app.client.conversationRoute.anotherDiscussion`));let s=P(o),c=n.find(e=>e.module===s.module);if(!c)throw Error(e(`app.client.conversationRoute.enableOwningScreen`));if(c.routes&&!$(c.routes,s.href))throw Error(e(`app.client.conversationRoute.locationUnavailable`));return{active:c.id,module:{url:c.module},location:{path:c.path,href:s.href,...c.routes?{routes:c.routes}:{},conversation:{id:t,original:s.original}}}}function _t(a){let d=new Map,f=a.props,p=``,m=a.props.conversation,h,g=!!m,_=``,v=!1;function y(){a.signal.aborted||a.update()}async function b(t){if(m!==t)return;h?.abort();let n=new AbortController;h=n;let r=AbortSignal.any([a.signal,n.signal]);g=!0,_=``,y();try{let n=a.props.project;if(!n)throw Error(e(`app.client.workspace.connectProjectToOpenDiscussion`));let i=await gt(t,a.props.conversationTargets??[],n.token,r);!r.aborted&&m===t&&(f=i,x.set(i.active,window.location.pathname))}catch(t){r.aborted||(_=t instanceof Error?t.message:e(`app.client.workspace.couldNotOpenDiscussion`))}finally{h===n&&!r.aborted&&(g=!1,y())}}let x=new Map,S,C,w=()=>`bud:tabs:${a.props.project?.id}:v1`,T=()=>`${window.location.pathname}${window.location.search}${window.location.hash}`;function E(e){S=e,oe(w(),e);let t=a.props.project;t&&(document.cookie=`${ue(t.id)}=${ce(e)}; Path=/; Max-Age=31536000; SameSite=Strict`),y()}function O(){if(!S)return;let e=T();C===e?C=void 0:N(D(S))!==e&&E(le(S,e))}function P(e){let t=N(D(e));E(e),t!==T()&&(C=t,r(t,{history:`replace`,resetScroll:!1}))}function F(t){let{pathname:n}=new URL(t,`http://bud.local`);if(M(t))return{href:t,title:e(`app.client.workspace.discussion`),icon:`message`};let r=a.props.screens.map(e=>({item:e,root:new URL(e.href,`http://bud.local`).pathname})).filter(({root:e})=>e===`/`||n===e||n.startsWith(`${e}/`)).sort((e,t)=>t.root.length-e.root.length)[0],i=r?.item??a.props.screens[0];if(i.id===`pages`&&r&&n.startsWith(`${r.root}/`)){let e=n.slice(r.root.length);return{href:t,title:a.props.project?.routes.find(t=>t.path===e)?.title??e,icon:i.icon}}let o=(r&&r.root!==`/`?n.slice(r.root.length):n).split(`/`).filter(Boolean).at(-1);return{href:t,title:(o&&r?.root!==`/`?decodeURIComponent(o):void 0)??i.label,icon:i.icon}}let de=i((e,t)=>{v=!0,m&&b(m);function n(){let{pathname:e,search:t,hash:n}=window.location,r=`${e}${t}${n}`,i=M(r);if(i)return i!==m&&(m=i,b(i)),f.location.conversation?.id===i&&x.set(f.active,r),!0;let a=d.get(f.active);if(!a)return!1;let o=a.location.path;return e!==o&&(o===`/`||!e.startsWith(`${o}/`))?!1:(h?.abort(),m=void 0,g=!1,_=``,x.set(f.active,r),a.location={...a.location,href:r,conversation:void 0},f={...f,location:a.location},!0)}n(),a.props.project&&E(k(ne(w()),T(),crypto.randomUUID())),a.update(),window.addEventListener(`click`,e=>{if(!S||!(e.metaKey||e.ctrlKey)||e.shiftKey||e.button!==0)return;let t=e.target?.closest?.(`a[href]`);if(!(t instanceof HTMLAnchorElement)||t.target||t.hasAttribute(`download`))return;let n=new URL(t.href);n.origin!==window.location.origin||n.pathname.startsWith(`/api/`)||(e.preventDefault(),e.stopPropagation(),E(A(S,`${n.pathname}${n.search}${n.hash}`,crypto.randomUUID(),!1)))},{capture:!0,signal:t}),window.addEventListener(`popstate`,()=>{!n()&&!window.navigation?.currentEntry?.getState()&&r(window.location.href,{history:`replace`,resetScroll:!1}),window.navigation||O(),a.update()},{signal:t}),window.navigation?.addEventListener(`navigate`,n,{signal:t}),window.navigation?.addEventListener(`currententrychange`,()=>{n(),O(),a.update()},{signal:t}),window.navigation?.addEventListener(`navigatesuccess`,()=>{n(),a.update()},{signal:t})});return()=>{let{screens:i,project:y,taskDesign:w}=a.props,T=JSON.stringify([a.props.active,a.props.location.href,a.props.conversation]);if(p!==T){if(p=T,m=a.props.conversation,h?.abort(),_=``,g=!!m,m){let e=m;v&&a.queueTask(()=>{b(e)})}else f=a.props}let{active:E,module:ne,location:O}=f,k=i.find(e=>e.id===E)??i[0];y&&!g&&!_&&d.set(k.id,{module:ne,location:O,taskDesign:k.id===`tasks`?w:void 0});let M=S??a.props.initialTabs??(y?ie(O.href,`current`):void 0);M&&a.queueTask(()=>he(M.active));let oe=i.map(e=>e.id===k.id?e:{...e,href:x.get(e.id)??e.href});return t(se,{items:oe,activeId:k.id,title:k.label,canvas:!!y,logo:y?.logo?{light:j.logo.href({theme:`light`}),dark:y.logo.dark?j.logo.href({theme:`dark`}):void 0,label:y.name}:void 0,status:y?t(ge,{project:y}):void 0,tabs:y&&M?t(re,{tabs:M.tabs.map(e=>({id:e.id,...F(N(e))})),active:M.active,recent:D(M).recent.filter(e=>e!==N(D(M))).map(F),canBack:D(M).index>0,canForward:D(M).index<D(M).entries.length-1,onSelect:e=>P({...M,active:e}),onClose:e=>P(ae(M,e)),onBack:()=>P(te(M,-1)),onForward:()=>P(te(M,1)),onNew:()=>P(A(M,i[0]?.href??`/`,crypto.randomUUID(),!0)),onOpen:e=>{C=void 0,r(e)}}):void 0,children:y?t(`div`,{class:`h-full min-h-0`,mix:de,children:[g?t(ee,{label:e(`app.client.workspace.openingDiscussion`)}):_?t(`div`,{class:`p-3 md:p-4`,children:t(u,{class:`max-w-2xl`,role:`alert`,children:[t(l,{title:e(`app.client.workspace.discussionDidntOpen`),subtitle:_}),t(s,{children:t(o,{mix:n(`click`,()=>{m&&b(m)}),children:e(`app.client.workspace.retry`)})})]})}):null,[...d].map(([e,{module:n,taskDesign:r,location:a}])=>t(`div`,{class:`h-full min-h-0`,hidden:g||!!_||e!==k.id,children:t(ht,{label:i.find(t=>t.id===e)?.label??e,module:n,taskDesign:r,project:y,location:a,active:!g&&!_&&e===k.id})},`${e}:${y.token}`))]}):t(u,{class:`max-w-2xl`,children:[t(l,{title:e(`app.client.workspace.yourProjectSideBySide`),subtitle:e(`app.client.workspace.openBudBesideLocalProject`)}),t(s,{children:t(c,{as:`p`,variant:`ui`,children:e(`app.client.workspace.startProjectWithBudVitePlugin`)})})]})})}}export{_t as Workspace};
@@ -33,7 +33,8 @@
33
33
  </script>
34
34
  <!--bud-import-map-->
35
35
  <title>bud.sh</title>
36
- <script data-rmx-preserve-dom type="module" crossorigin src="/assets/index-GPPa1XPO.js"></script>
36
+ <script data-rmx-preserve-dom type="module" crossorigin src="/assets/index-Dpxjiok1.js"></script>
37
+ <link data-rmx-preserve-dom rel="modulepreload" crossorigin href="/assets/i18n-BtfXum8P.js">
37
38
  <link data-rmx-preserve-dom rel="modulepreload" crossorigin href="/assets/component-DWct-Tq6.js">
38
39
  <link data-rmx-preserve-dom rel="modulepreload" crossorigin href="/assets/jsx-B4XNFIzB.js">
39
40
  <link data-rmx-preserve-dom rel="modulepreload" crossorigin href="/assets/children-N0l0v7XI.js">
@@ -1,7 +1,7 @@
1
- import { $t as Button, H as CanvasWorkspace, Nn as jsx, U as captureCanvasPoint, Zt as Loader, bt as conversationHref, dn as Text, en as ToolbarSeparator, et as BranchSidebar, fn as Icon, gn as on, in as IconButton, kn as Fragment, l as projectStore, ln as readPreference, on as Tooltip, pn as ref, rn as Select, t as commentsUnavailable, tn as WorkspaceLayout, un as writePreference } from "./comment-data-CiDuvXi2.js";
2
- import { n as createProjectComments, r as loadComments, t as defineScreen } from "./screen-BroBb1Z_.js";
3
- import { i as pictureKey, n as createProjectPreviews, t as createProjectBranches } from "./project-branches-CffV4IS1.js";
4
- import { t as ProjectThreadLinks } from "./project-thread-links-B1Y2bDUx.js";
1
+ import { $t as Button, H as CanvasWorkspace, Ln as jsx, Nn as Fragment, U as captureCanvasPoint, Zt as Loader, _n as ref, bn as on, bt as conversationHref, en as ToolbarSeparator, et as BranchSidebar, gn as Icon, hn as Text, in as IconButton, l as projectStore, ln as readPreference, on as Tooltip, pn as t, rn as Select, t as commentsUnavailable, tn as WorkspaceLayout, un as writePreference } from "./comment-data-DsgJWq4n.js";
2
+ import { n as createProjectComments, r as loadComments, t as defineScreen } from "./screen-QmqmI2Aq.js";
3
+ import { i as pictureKey, n as createProjectPreviews, t as createProjectBranches } from "./project-branches-BNloVosX.js";
4
+ import { t as ProjectThreadLinks } from "./project-thread-links-BmY8HQXt.js";
5
5
  //#region app/client/preview-image.tsx
6
6
  var failedHeight = 760;
7
7
  var stopPan = on("pointerdown", (event) => event.stopPropagation());
@@ -157,7 +157,7 @@ function PreviewImage(handle) {
157
157
  let { thumbnail, slices } = drawn(picture);
158
158
  return /* @__PURE__ */ jsx("div", {
159
159
  role: "img",
160
- "aria-label": `${route.title} preview`,
160
+ "aria-label": t("app.client.previewImage.preview", { title: route.title }),
161
161
  "data-detail": !view.visible ? "hidden" : slices.length ? "slices" : thumbnail ? "thumbnail" : "pending",
162
162
  class: `relative select-none overflow-hidden ${mode === "comment" ? "cursor-crosshair" : ""}`,
163
163
  style: { height },
@@ -211,7 +211,7 @@ function PreviewImage(handle) {
211
211
  variant: "title",
212
212
  weight: "semibold",
213
213
  class: "text-ink",
214
- children: [route.title, " couldn't be captured"]
214
+ children: t("app.client.previewImage.captureFailed", { title: route.title })
215
215
  }),
216
216
  failure ? /* @__PURE__ */ jsx(Text, {
217
217
  variant: "ui",
@@ -226,7 +226,7 @@ function PreviewImage(handle) {
226
226
  mix: [stopPan, on("click", () => void previews.refresh(page))],
227
227
  children: /* @__PURE__ */ jsx(Text, {
228
228
  variant: "ui",
229
- children: "Try again"
229
+ children: t("app.client.previewImage.tryAgain")
230
230
  })
231
231
  }), /* @__PURE__ */ jsx("a", {
232
232
  href: pageUrl,
@@ -236,7 +236,7 @@ function PreviewImage(handle) {
236
236
  mix: stopPan,
237
237
  children: /* @__PURE__ */ jsx(Text, {
238
238
  variant: "ui",
239
- children: "Open page"
239
+ children: t("app.client.previewImage.openPage")
240
240
  })
241
241
  })]
242
242
  })
@@ -244,7 +244,7 @@ function PreviewImage(handle) {
244
244
  });
245
245
  return /* @__PURE__ */ jsx("div", {
246
246
  class: "absolute inset-0 flex items-center justify-center",
247
- children: /* @__PURE__ */ jsx(Loader, { label: `Capturing ${route.title}…` })
247
+ children: /* @__PURE__ */ jsx(Loader, { label: t("app.client.previewImage.capturing", { title: route.title }) })
248
248
  });
249
249
  };
250
250
  }
@@ -277,7 +277,7 @@ function PreviewRefresh(handle) {
277
277
  })
278
278
  }) : null, /* @__PURE__ */ jsx(IconButton, {
279
279
  icon: "sync",
280
- label: `Refresh ${route.title}`,
280
+ label: t("app.client.previewImage.refresh", { title: route.title }),
281
281
  tooltip: true,
282
282
  size: "small",
283
283
  iconSize: 13,
@@ -386,7 +386,7 @@ function compareProjectPictures(options) {
386
386
  let result = await compare(route.page, route.size).catch((cause) => ({
387
387
  state: "failed",
388
388
  regions: [],
389
- error: cause instanceof Error ? cause.message : "The pictures could not be compared."
389
+ error: cause instanceof Error ? cause.message : t("app.client.projectDifferences.comparisonFailed")
390
390
  }));
391
391
  if (signal.aborted) return;
392
392
  states.set(route.id, result);
@@ -426,11 +426,9 @@ function differenceSlots(regions) {
426
426
  height: Math.max(1, top - gap)
427
427
  };
428
428
  }
429
- var kinds = {
430
- changed: "Changed",
431
- added: "Added",
432
- removed: "Removed"
433
- };
429
+ function kindLabel(kind) {
430
+ return kind === "changed" ? t("app.client.differenceView.changed") : kind === "added" ? t("app.client.differenceView.added") : t("app.client.differenceView.removed");
431
+ }
434
432
  function crops(signal) {
435
433
  let urls = /* @__PURE__ */ new Map();
436
434
  signal.addEventListener("abort", () => {
@@ -465,7 +463,10 @@ function DifferenceArtboard(handle) {
465
463
  let visible = viewport?.get(route.id)?.visible ?? true;
466
464
  return /* @__PURE__ */ jsx("div", {
467
465
  role: "img",
468
- "aria-label": `${route.title}, ${label}`,
466
+ "aria-label": t("app.client.differenceView.artboardLabel", {
467
+ title: route.title,
468
+ label
469
+ }),
469
470
  "data-difference": side,
470
471
  "data-changes": regions.length,
471
472
  class: "relative select-none bg-[var(--bud-main)]",
@@ -488,11 +489,11 @@ function DifferenceArtboard(handle) {
488
489
  children: [/* @__PURE__ */ jsx(Text, {
489
490
  variant: "ui",
490
491
  weight: "medium",
491
- children: `Change ${index + 1}`
492
+ children: t("app.client.differenceView.changeNumber", { count: index + 1 })
492
493
  }), /* @__PURE__ */ jsx(Text, {
493
494
  variant: "ui",
494
495
  tone: "muted",
495
- children: kinds[region.kind]
496
+ children: kindLabel(region.kind)
496
497
  })]
497
498
  }), crop && span.height > 0 ? /* @__PURE__ */ jsx("div", {
498
499
  class: "relative overflow-hidden",
@@ -515,7 +516,7 @@ function DifferenceArtboard(handle) {
515
516
  children: /* @__PURE__ */ jsx(Text, {
516
517
  variant: "ui",
517
518
  tone: "muted",
518
- children: `Not in ${label}`
519
+ children: t("app.client.differenceView.notIn", { label })
519
520
  })
520
521
  })]
521
522
  }, index);
@@ -549,7 +550,10 @@ function DifferenceSlideshow(handle) {
549
550
  }) }), crop && slide.region[which].height > 0 ? /* @__PURE__ */ jsx("div", {
550
551
  class: "relative",
551
552
  children: [/* @__PURE__ */ jsx("img", {
552
- alt: `${slide.route.title}, ${label}`,
553
+ alt: t("app.client.differenceView.artboardLabel", {
554
+ title: slide.route.title,
555
+ label
556
+ }),
553
557
  src: url(crop),
554
558
  class: "block w-full rounded-lg ring-1 ring-line"
555
559
  }), slide.region.kind === "changed" ? /* @__PURE__ */ jsx("div", {
@@ -565,14 +569,14 @@ function DifferenceSlideshow(handle) {
565
569
  children: /* @__PURE__ */ jsx(Text, {
566
570
  variant: "ui",
567
571
  tone: "muted",
568
- children: `Not in ${label}`
572
+ children: t("app.client.differenceView.notIn", { label })
569
573
  })
570
574
  })]
571
575
  });
572
576
  };
573
577
  return /* @__PURE__ */ jsx("section", {
574
578
  role: "dialog",
575
- "aria-label": "Differences slideshow",
579
+ "aria-label": t("app.client.differenceView.slideshowLabel"),
576
580
  class: "bud-surface absolute inset-0 z-40 flex flex-col bg-[var(--bud-main)]",
577
581
  mix: ref((node, signal) => {
578
582
  node.focus();
@@ -594,33 +598,39 @@ function DifferenceSlideshow(handle) {
594
598
  variant: "ui",
595
599
  weight: "medium",
596
600
  class: "truncate",
597
- children: slide?.route.title ?? "No differences"
601
+ children: slide?.route.title ?? t("app.client.differenceView.noDifferences")
598
602
  }), slide ? /* @__PURE__ */ jsx(Text, {
599
603
  variant: "ui",
600
604
  tone: "muted",
601
605
  class: "shrink-0 tabular-nums",
602
606
  role: "status",
603
- children: `${kinds[slide.region.kind]} · change ${slide.index + 1} of ${slide.count} · ${index + 1} / ${slides.length}`
607
+ children: t("app.client.differenceView.slideStatus", {
608
+ kind: kindLabel(slide.region.kind),
609
+ change: slide.index + 1,
610
+ count: slide.count,
611
+ index: index + 1,
612
+ total: slides.length
613
+ })
604
614
  }) : null]
605
615
  }),
606
616
  /* @__PURE__ */ jsx(IconButton, {
607
617
  tooltip: true,
608
618
  icon: "chevron-left",
609
- label: "Previous change",
619
+ label: t("app.client.differenceView.previousChange"),
610
620
  disabled: slides.length < 2,
611
621
  mix: on("click", () => step(-1))
612
622
  }),
613
623
  /* @__PURE__ */ jsx(IconButton, {
614
624
  tooltip: true,
615
625
  icon: "chevron-right",
616
- label: "Next change",
626
+ label: t("app.client.differenceView.nextChange"),
617
627
  disabled: slides.length < 2,
618
628
  mix: on("click", () => step(1))
619
629
  }),
620
630
  /* @__PURE__ */ jsx(IconButton, {
621
631
  tooltip: true,
622
632
  icon: "close",
623
- label: "Close slideshow",
633
+ label: t("app.client.differenceView.closeSlideshow"),
624
634
  shortcut: "escape",
625
635
  mix: on("click", () => handle.props.onClose())
626
636
  })
@@ -734,7 +744,7 @@ function ProjectCanvas(handle) {
734
744
  function others() {
735
745
  let sets = project.workingTree ? [{
736
746
  value: "",
737
- label: "Working tree"
747
+ label: t("app.client.projectCanvas.workingTree")
738
748
  }] : [];
739
749
  for (let branch of branches.list.branches) if (branch.active && branch.captured) sets.push({
740
750
  value: branch.name,
@@ -743,7 +753,7 @@ function ProjectCanvas(handle) {
743
753
  return sets.filter((set) => set.value !== (selected ?? ""));
744
754
  }
745
755
  function label(set) {
746
- return set ? set : "Working tree";
756
+ return set ? set : t("app.client.projectCanvas.workingTree");
747
757
  }
748
758
  function startComparing() {
749
759
  let sets = others();
@@ -809,7 +819,7 @@ function ProjectCanvas(handle) {
809
819
  comments.loadThread(id);
810
820
  });
811
821
  }
812
- if (!branches.loaded && !branches.error) return /* @__PURE__ */ jsx(Loader, { label: "Loading branches…" });
822
+ if (!branches.loaded && !branches.error) return /* @__PURE__ */ jsx(Loader, { label: t("app.client.projectCanvas.loadingBranches") });
813
823
  let projectKey = `${project.id}:${project.targetOrigin}:${project.routes.map((route) => route.path).join("|")}`;
814
824
  let snapshot = {
815
825
  ...comments.snapshot,
@@ -856,8 +866,23 @@ function ProjectCanvas(handle) {
856
866
  if (differences) {
857
867
  let { compared: done, total } = differences.progress;
858
868
  let missing = artboards.filter(({ artboard }) => differences.get(artboard.id).state === "missing").length;
859
- status = !differences.done ? `Comparing with ${beforeLabel}… ${done} of ${total} pages` : changed.length ? `${changed.length} of ${total} pages differ from ${beforeLabel}` : `No differences from ${beforeLabel}`;
860
- if (differences.done && missing) status += ` · ${missing} without pictures on both sides`;
869
+ status = !differences.done ? t("app.client.projectCanvas.comparingPages", {
870
+ name: beforeLabel,
871
+ done,
872
+ count: total
873
+ }) : changed.length ? missing ? t("app.client.projectCanvas.differentPagesWithMissing", {
874
+ changed: changed.length,
875
+ count: total,
876
+ name: beforeLabel,
877
+ missing
878
+ }) : t("app.client.projectCanvas.differentPages", {
879
+ changed: changed.length,
880
+ count: total,
881
+ name: beforeLabel
882
+ }) : missing ? t("app.client.projectCanvas.noDifferencesWithMissing", {
883
+ name: beforeLabel,
884
+ count: missing
885
+ }) : t("app.client.projectCanvas.noDifferences", { name: beforeLabel });
861
886
  }
862
887
  let sets = others();
863
888
  let icon = (size) => size.mobile || size.width < 600 ? "mobile" : size.width < 1100 ? "tablet" : "desktop";
@@ -866,14 +891,17 @@ function ProjectCanvas(handle) {
866
891
  sizes.map((size) => /* @__PURE__ */ jsx(IconButton, {
867
892
  tooltip: true,
868
893
  icon: icon(size),
869
- label: `Show ${size.name} (${size.width})`,
894
+ label: t("app.client.projectCanvas.showViewport", {
895
+ name: size.name,
896
+ width: size.width
897
+ }),
870
898
  active: viewport === size.id,
871
899
  mix: on("click", () => show(size.id))
872
900
  })),
873
901
  /* @__PURE__ */ jsx(IconButton, {
874
902
  tooltip: true,
875
903
  icon: "columns",
876
- label: "Show every viewport side by side",
904
+ label: t("app.client.projectCanvas.showEveryViewport"),
877
905
  active: viewport === "all",
878
906
  mix: on("click", () => show("all"))
879
907
  }),
@@ -882,13 +910,13 @@ function ProjectCanvas(handle) {
882
910
  /* @__PURE__ */ jsx(IconButton, {
883
911
  tooltip: true,
884
912
  icon: "compare",
885
- label: differences ? "Stop comparing" : "Show differences with another branch",
913
+ label: differences ? t("app.client.projectCanvas.stopComparing") : t("app.client.projectCanvas.showDifferences"),
886
914
  active: Boolean(differences),
887
915
  disabled: !differences && !sets.length,
888
916
  mix: on("click", () => differences ? stopComparing() : startComparing())
889
917
  }),
890
918
  differences ? /* @__PURE__ */ jsx(Fragment, { children: [/* @__PURE__ */ jsx(Select, {
891
- label: "Compare with",
919
+ label: t("app.client.projectCanvas.compareWith"),
892
920
  value: comparing ?? "",
893
921
  options: sets,
894
922
  class: "max-w-48",
@@ -901,7 +929,7 @@ function ProjectCanvas(handle) {
901
929
  }), /* @__PURE__ */ jsx(IconButton, {
902
930
  tooltip: true,
903
931
  icon: "play",
904
- label: "Step through the differences",
932
+ label: t("app.client.projectCanvas.stepThroughDifferences"),
905
933
  disabled: !slides.length,
906
934
  mix: on("click", () => {
907
935
  slide = 0;
@@ -911,8 +939,8 @@ function ProjectCanvas(handle) {
911
939
  ] });
912
940
  return /* @__PURE__ */ jsx(WorkspaceLayout, {
913
941
  class: "h-full min-h-0",
914
- sidebarLabel: "Branches",
915
- mainLabel: "Canvas",
942
+ sidebarLabel: t("app.client.projectCanvas.branches"),
943
+ mainLabel: t("app.client.projectCanvas.canvas"),
916
944
  drawerOpen: drawer,
917
945
  onDrawerOpenChange: (open) => {
918
946
  drawer = open;
@@ -1022,7 +1050,7 @@ function ProjectCanvas(handle) {
1022
1050
  drawer = true;
1023
1051
  handle.update();
1024
1052
  },
1025
- sidebarLabel: "Branches",
1053
+ sidebarLabel: t("app.client.projectCanvas.branches"),
1026
1054
  renderArtboard: (route, state) => {
1027
1055
  let side = sides.get(route.id);
1028
1056
  if (side) return /* @__PURE__ */ jsx(DifferenceArtboard, {