@bud.sh/app 0.3.0 → 0.4.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 (77) hide show
  1. package/dist/client/assets/bud/design.js +1 -1
  2. package/dist/client/assets/canvas-DIKX_HCJ.js +1 -0
  3. package/dist/client/assets/difference-worker-CwQNxTJL.js +8 -0
  4. package/dist/client/assets/files-BQ9O3Z8-.js +1 -0
  5. package/dist/client/assets/i18n-CL0jBP7Y.js +1 -0
  6. package/dist/client/assets/index-COvyj5zV.js +2 -0
  7. package/dist/client/assets/pages-BGl2Yuza.js +1 -0
  8. package/dist/client/assets/project-branches-DwKjCwZv.js +1 -0
  9. package/dist/client/assets/project-comments-Cdip2Y10.js +1 -0
  10. package/dist/client/assets/project-thread-links-BGIkGQeU.js +1 -0
  11. package/dist/client/assets/{project-threads-DezXiVK6.js → project-threads-DeKXNqeP.js} +104 -104
  12. package/dist/client/assets/{project-work-CB1JHqGW.js → project-work-B7PGQtV9.js} +1 -1
  13. package/dist/client/assets/task-design-DJp5yho1.js +23 -0
  14. package/dist/client/assets/tasks-BHXj727C.js +1 -0
  15. package/dist/client/assets/tasks-request-CsUB5__X.js +1 -0
  16. package/dist/client/assets/workspace-CbO7RsI2.js +2 -0
  17. package/dist/client/index.html +2 -1
  18. package/dist/hosted/assets/{canvas-C69-96GR.js → canvas-gWj_ocKK.js} +69 -41
  19. package/dist/hosted/assets/{comment-data-CiDuvXi2.js → comment-data-C-rNCB1n.js} +7323 -1068
  20. package/dist/hosted/assets/{files-DQL5hzs3.js → files-CAPvbavY.js} +92 -89
  21. package/dist/hosted/assets/{pages-DFs7jB6M.js → pages-DJiOvT-l.js} +31 -22
  22. package/dist/hosted/assets/{project-branches-CffV4IS1.js → project-branches-BgrfdvtL.js} +5 -5
  23. package/dist/hosted/assets/{project-thread-links-B1Y2bDUx.js → project-thread-links-B7uzThL9.js} +12 -12
  24. package/dist/hosted/assets/{screen-BroBb1Z_.js → screen-D4D9nh4V.js} +18 -18
  25. package/dist/hosted/assets/{tasks-mzmNhe2d.js → tasks-C7aGLzBw.js} +29 -29
  26. package/dist/hosted/assets/{tasks-request-Dcrpd2_8.js → tasks-request-CikFdCgP.js} +7 -7
  27. package/dist/hosted/hosted.js +58 -31
  28. package/dist/node/design.js +6355 -139
  29. package/dist/node/index.js +4 -2
  30. package/dist/node-host/assets/{canvas-BZhzizzt.js → canvas-kXzp80a5.js} +70 -42
  31. package/dist/node-host/assets/{comment-data-nUlI0szN.js → comment-data-CeuJbJKJ.js} +7349 -1094
  32. package/dist/node-host/assets/{files-CTzcWGjb.js → files-0YIuvKzb.js} +92 -89
  33. package/dist/node-host/assets/{pages-0aWH7z1j.js → pages-DOF22SyG.js} +31 -22
  34. package/dist/node-host/assets/{project-branches-1zs_0J_y.js → project-branches-BeEwMBIw.js} +5 -5
  35. package/dist/node-host/assets/{project-thread-links-LpUAGcDr.js → project-thread-links-Bs_MtfBC.js} +12 -12
  36. package/dist/node-host/assets/{screen-DQoTOWYR.js → screen-DRTAKkn3.js} +18 -18
  37. package/dist/node-host/assets/{tasks-C0WqnM7Q.js → tasks-BA_hcbj5.js} +30 -30
  38. package/dist/node-host/assets/{tasks-request-Bwky5ORf.js → tasks-request-Doc9y_20.js} +7 -7
  39. package/dist/node-host/node-host.js +58 -31
  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-CiN6jNIZ.js} +70 -42
  42. package/dist/server/assets/{comment-data-BuArfgcc.js → comment-data-9SqALQjT.js} +7347 -1092
  43. package/dist/server/assets/{files-DkrEB48U.js → files-DBVqeLdL.js} +92 -89
  44. package/dist/server/assets/{listener-oKd5ETMj.js → listener-DGWKUc2o.js} +53 -31
  45. package/dist/server/assets/{pages-iEdmK_o2.js → pages-DJMLr6j9.js} +31 -22
  46. package/dist/server/assets/{project-branches-B7rtrvMl.js → project-branches-DbKEmiQT.js} +5 -5
  47. package/dist/server/assets/{project-thread-links-ue_ad9IX.js → project-thread-links-C0kV_Pcl.js} +12 -12
  48. package/dist/server/assets/{project-work-6aOyja4v.js → project-work-C0FN3w5Y.js} +2 -2
  49. package/dist/server/assets/{screen-DMUB9a-K.js → screen-BtvzEiIa.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-DX71x8f9.js} +31 -31
  53. package/dist/server/assets/{tasks-request-Bk5EoY_p.js → tasks-request-C3jk9Jyu.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
@@ -1,5 +1,5 @@
1
1
  import { D as parseThreadId, E as parseThreadFilter, i as routes, j as parseThreadSnapshot, w as parseThread } from "./events-6z5v7Uca.js";
2
- import { _ as requestComments, a as saveThreads, b as writeOptimistically, bn as toast, g as CommentsRequestError, i as saveThread, l as projectStore, n as unavailableComments, o as threadMatches, y as plainRow } from "./comment-data-BuArfgcc.js";
2
+ import { En as t, _ as requestComments, a as saveThreads, b as writeOptimistically, bn as toast, g as CommentsRequestError, i as saveThread, l as projectStore, n as unavailableComments, o as threadMatches, y as plainRow } from "./comment-data-9SqALQjT.js";
3
3
  //#region ../work/src/lib/predict.ts
4
4
  /**
5
5
  * How a new task shows until its adapter confirms it: the requested values, and the creation
@@ -162,7 +162,7 @@ async function loadItemComments(token, itemId, signal, conversationId) {
162
162
  signal.throwIfAborted();
163
163
  return {
164
164
  snapshot: null,
165
- error: cause instanceof Error ? cause.message : "Could not load the discussion."
165
+ error: cause instanceof Error ? cause.message : t("app.client.projectComments.couldNotLoadDiscussion")
166
166
  };
167
167
  }
168
168
  }
@@ -221,7 +221,7 @@ async function loadComments(project, signal, fetcher = fetch) {
221
221
  signal.throwIfAborted();
222
222
  return {
223
223
  snapshot: null,
224
- error: cause instanceof Error ? cause.message : "Could not load comments."
224
+ error: cause instanceof Error ? cause.message : t("app.client.projectComments.couldNotLoadComments")
225
225
  };
226
226
  }
227
227
  }
@@ -308,7 +308,7 @@ function createProjectComments(options) {
308
308
  error = "";
309
309
  }
310
310
  } catch (cause) {
311
- if (!signal.aborted && turn === generation) error = cause instanceof Error ? cause.message : "Could not load comments.";
311
+ if (!signal.aborted && turn === generation) error = cause instanceof Error ? cause.message : t("app.client.projectComments.couldNotLoadComments");
312
312
  } finally {
313
313
  if (turn === generation) {
314
314
  loading = false;
@@ -328,16 +328,16 @@ function createProjectComments(options) {
328
328
  changed();
329
329
  try {
330
330
  let thread = await request(routes.comments.get.href({ id }), signal, parseThread);
331
- if (thread.id !== id) throw new CommentsRequestError("The comments service returned another discussion.");
331
+ if (thread.id !== id) throw new CommentsRequestError(t("app.client.projectComments.serviceReturnedAnotherDiscussion"));
332
332
  if (!signal.aborted && turn === generation) {
333
333
  await merge(thread);
334
- if (!includes(thread)) throw new CommentsRequestError("This discussion is no longer part of this view.");
334
+ if (!includes(thread)) throw new CommentsRequestError(t("app.client.projectComments.discussionNoLongerInView"));
335
335
  if (!detailFailures.size) error = "";
336
336
  }
337
337
  } catch (cause) {
338
338
  if (!signal.aborted && turn === generation) {
339
339
  detailFailures.add(id);
340
- error = cause instanceof Error ? cause.message : "Could not load the discussion.";
340
+ error = cause instanceof Error ? cause.message : t("app.client.projectComments.couldNotLoadDiscussion");
341
341
  }
342
342
  } finally {
343
343
  if (details.get(id) === controller) {
@@ -347,10 +347,10 @@ function createProjectComments(options) {
347
347
  }
348
348
  }
349
349
  function requireCapability(capability) {
350
- if (busy) throw new Error("Wait for the current comment operation to finish.");
351
- if (!loaded) throw new Error("Load comments before saving.");
352
- if (snapshot.connection.state !== "ready") throw new Error(snapshot.connection.message ?? "The comment adapter is unavailable.");
353
- if (!snapshot.capabilities[capability]) throw new Error("The comment adapter does not support this operation.");
350
+ if (busy) throw new Error(t("app.client.projectComments.waitForCurrentOperation"));
351
+ if (!loaded) throw new Error(t("app.client.projectComments.loadCommentsBeforeSaving"));
352
+ if (snapshot.connection.state !== "ready") throw new Error(snapshot.connection.message ?? t("app.client.projectComments.adapterUnavailable"));
353
+ if (!snapshot.capabilities[capability]) throw new Error(t("app.client.projectComments.adapterDoesNotSupportOperation"));
354
354
  }
355
355
  async function operate(url, body, parse, apply, success, threadId, predict) {
356
356
  cancelReads();
@@ -372,13 +372,13 @@ function createProjectComments(options) {
372
372
  return snapshot;
373
373
  } catch (cause) {
374
374
  if (!options.signal.aborted) {
375
- error = cause instanceof Error ? cause.message : "The comment write was not confirmed.";
376
- if (predict) toast.error("Bud undid a comment change", { description: error });
375
+ error = cause instanceof Error ? cause.message : t("app.client.projectComments.commentWriteNotConfirmed");
376
+ if (predict) toast.error(t("app.client.projectComments.budUndidCommentChange"), { description: error });
377
377
  if (cause instanceof CommentsRequestError && cause.code === "conflict") try {
378
378
  await adopt(await request(listHref(filter), options.signal, parseThreadSnapshot));
379
379
  if (threadId) {
380
380
  let detail = await request(routes.comments.get.href({ id: threadId }), options.signal, parseThread);
381
- if (detail.id !== threadId) throw new CommentsRequestError("The comments service returned another discussion.");
381
+ if (detail.id !== threadId) throw new CommentsRequestError(t("app.client.projectComments.serviceReturnedAnotherDiscussion"));
382
382
  await merge(detail);
383
383
  }
384
384
  } catch {}
@@ -423,7 +423,7 @@ function createProjectComments(options) {
423
423
  let pending = `pending-${crypto.randomUUID()}`;
424
424
  if (change.id) {
425
425
  let id = parseThreadId(change.id), thread = snapshot.threads.find((item) => item.id === id);
426
- if (!thread?.revision) throw new Error("Reload this discussion before saving.");
426
+ if (!thread?.revision) throw new Error(t("app.client.projectComments.reloadDiscussionBeforeSaving"));
427
427
  let next;
428
428
  if (change.status !== void 0) {
429
429
  url = routes.comments.status.href({ id });
@@ -468,16 +468,16 @@ function createProjectComments(options) {
468
468
  let saved;
469
469
  return {
470
470
  ...await operate(url, body, parseThread, (thread) => {
471
- if (change.id && thread.id !== change.id) throw new CommentsRequestError("The comment write could not be confirmed. Refresh before trying again.", 409, "uncertain");
471
+ if (change.id && thread.id !== change.id) throw new CommentsRequestError(t("app.client.projectComments.refreshBeforeTryingAgain"), 409, "uncertain");
472
472
  saved = thread;
473
473
  return merge(thread);
474
- }, "Comment saved", change.id, predict),
474
+ }, t("app.client.projectComments.commentSaved"), change.id, predict),
475
475
  thread: saved
476
476
  };
477
477
  },
478
478
  async sync() {
479
479
  requireCapability("sync");
480
- return operate(routes.comments.sync.href(), { direction: "both" }, parseThreadSnapshot, adopt, "Comments synced");
480
+ return operate(routes.comments.sync.href(), { direction: "both" }, parseThreadSnapshot, adopt, t("app.client.projectComments.commentsSynced"));
481
481
  }
482
482
  };
483
483
  }
@@ -1,4 +1,4 @@
1
- import { $ as publishAll, $n as forkUnsafe, $t as provideContext, An as uninterruptible, At as catch_, Bn as effectDiscard, Bt as forever, Cn as tap, Ct as as$1, D as as, Dn as tryPromise, E as FileSystem, Fn as currentTimeMillis, Ft as fail$1, G as make$3, Gn as mergeAll, Gt as map, H as runForEach, Hn as isLayer, Ht as forkScoped, I as fromPubSub, In as build, It as filterOrFail, J as offerUnsafe, Jn as succeed$1, Jt as option, Kn as provide$1, Kt as mapError, L as ignore$1, Ln as buildWithMemoMap, Lt as flatMap, Mn as void_$1, N as empty$1, Nn as withFiber, Nt as die, O as callback, On as try_, Ot as catchIf, P as filter, Pn as yieldNow, Pt as ensuring, Q as publish, Qn as close, R as make$2, Rn as effect, Rt as flatten, S as writeTextAtomic, Sn as sync, St as andThen, T as Path, Tn as timeoutOption, Tt as asVoid, U as tap$1, Un as makeMemoMapUnsafe, Ut as gen, V as merge, Vn as empty, Vt as forkIn, W as unwrap$1, Wt as ignore, X as sliding$1, Xn as sync$1, Xt as orElseSucceed, Y as shutdown$1, Yt as orDie, Z as take, Zn as unwrap, Zt as promise, _n as serviceOption, _t as bytes$1, an as runFork, ar as void_, at as runIn, bn as succeedNone, bt as addFinalizer, cn as runPromiseExit, cr as add, dn as runSync, dr as getOrNull, en as provideService, er as makeUnsafe, et as shutdown, fn as runSyncExit, fr as getOrUndefined, gn as scoped, gr as TaggedError, hn as scope, hr as some, in as runCallbackWith, ir as succeed$2, it as interrupt, j as debounce, jn as uninterruptibleMask, jt as clockWith, kn as undefined_$1, kt as catchTag, ln as runPromiseExitWith, lr as getOption, m as projectModuleFile, mn as runSyncWith, mr as none, nr as doneUnsafe, nt as unbounded, on as runForkWith, or as scopeRemoveFinalizerUnsafe, pn as runSyncExitWith, pr as isNone, q as offer, rn as runCallback, rr as make$4, rt as await_, sn as runPromise, sr as Service, tn as result, tr as _await, tt as sliding, u as Git, un as runPromiseWith, ur as make$1, vn as sleep, vt as acquireRelease, w as RuntimePolicy, wn as tapError, wt as asSome, xn as suspend, xt as all, yn as succeed, zn as effectContext, zt as forEach } from "./branch-previews-BryeA_kA.js";
1
+ import { $ as publishAll, $n as forkUnsafe, $t as provideContext, An as uninterruptible, At as catch_, Bn as effectDiscard, Bt as forever, Cn as tap, Ct as as$1, D as as, Dn as tryPromise, E as FileSystem, Fn as currentTimeMillis, Ft as fail$1, G as make$3, Gn as mergeAll, Gt as map, H as runForEach, Hn as isLayer, Ht as forkScoped, I as fromPubSub, In as build, It as filterOrFail, J as offerUnsafe, Jn as succeed$1, Jt as option, Kn as provide$1, Kt as mapError, L as ignore$1, Ln as buildWithMemoMap, Lt as flatMap, Mn as void_$1, N as empty$1, Nn as withFiber, Nt as die, O as callback, On as try_, Ot as catchIf, P as filter, Pn as yieldNow, Pt as ensuring, Q as publish, Qn as close, R as make$2, Rn as effect, Rt as flatten, S as writeTextAtomic, Sn as sync, St as andThen, T as Path, Tn as timeoutOption, Tt as asVoid, U as tap$1, Un as makeMemoMapUnsafe, Ut as gen, V as merge, Vn as empty, Vt as forkIn, W as unwrap$1, Wt as ignore, X as sliding$1, Xn as sync$1, Xt as orElseSucceed, Y as shutdown$1, Yt as orDie, Z as take, Zn as unwrap, Zt as promise, _n as serviceOption, _t as bytes$1, an as runFork, ar as void_, at as runIn, bn as succeedNone, bt as addFinalizer, cn as runPromiseExit, cr as add, dn as runSync, dr as getOrNull, en as provideService, er as makeUnsafe, et as shutdown, fn as runSyncExit, fr as getOrUndefined, gn as scoped, gr as TaggedError, hn as scope, hr as some, in as runCallbackWith, ir as succeed$2, it as interrupt, j as debounce, jn as uninterruptibleMask, jt as clockWith, kn as undefined_$1, kt as catchTag, ln as runPromiseExitWith, lr as getOption, m as projectModuleFile, mn as runSyncWith, mr as none, nr as doneUnsafe, nt as unbounded, on as runForkWith, or as scopeRemoveFinalizerUnsafe, pn as runSyncExitWith, pr as isNone, q as offer, rn as runCallback, rr as make$4, rt as await_, sn as runPromise, sr as Service, tn as result, tr as _await, tt as sliding, u as Git, un as runPromiseWith, ur as make$1, vn as sleep, vt as acquireRelease, w as RuntimePolicy, wn as tapError, wt as asSome, xn as suspend, xt as all, yn as succeed, zn as effectContext, zt as forEach } from "./branch-previews-ClkoJ0lM.js";
2
2
  import { $ as parseReviewActionRecovery, A as parseThreadReplyInput, An as iconNames, At as filterFileEntries, Bt as isWithinDirectory, Cn as WorkValidationError, Ct as compileSearchPattern, Dn as record$1, Dt as parseFileSearchQuery, E as parseThreadFilter, En as parseWork, Et as searchPathMatches, Gt as list, Ht as parseFilePath, Jt as strict$1, Kt as parseContract, L as applyReviewSelection, N as parseThreadStatusInput, O as parseThreadInput, On as strict, Rt as parseFileIndexQuery, Sn as statusCategory, St as parseReviewSourceQuery, T as parseThreadCapabilities, Tn as nonempty, Ut as pathHierarchy, Vt as parentPath, Wt as integer, X as parseReviewActionIntent, Y as parseReviewActionApply, Zt as parseWorkWorkspace, _n as parseMessage, _t as parseReviewHistoryQuery, an as parseWorkDetail, at as parseMutationIntent, b as MAX_THREADS, bn as fieldByRole, cn as parseWorkMutationResult, dn as parseWorkSnapshot, dt as validateMutationSelection, en as parseSectionData, gn as valueByRole, hn as parseWorkValue, ht as parseReviewDiffQuery, i as routes, in as parseWorkCreate, it as parseMutationApply, j as parseThreadSnapshot, jt as orderFileEntries, k as parseThreadLinkInput, kt as classifyText, lt as parseRecovery, mn as parseWorkUpdate, on as parseWorkItem, pt as parseReviewComparison, qt as revision, r as parseLiveId, rn as parseWorkConnection, sn as parseWorkItemRef, t as RESYNC, tn as parseWorkActionInput, tt as parseFileSaveRequest, un as parseWorkQuery, ut as pathCollisionKey, vn as parseMessageAuthor, w as parseThread, wn as identifier, wt as matchFileText, xn as parseWorkSchema, zt as isProtectedPath } from "./events-6z5v7Uca.js";
3
3
  import { pathToFileURL } from "node:url";
4
4
  import { createHash, randomBytes, randomUUID } from "node:crypto";
@@ -1,5 +1,5 @@
1
- import { A as concat, At as catch_, B as mapError$1, Bn as effectDiscard, C as ProcessRunner, Cn as tap, Ct as as, D as as$1, E as FileSystem, En as timeoutOrElse, Et as cached, F as fromEffect, Fn as currentTimeMillis, Ft as fail, Gn as mergeAll, Gt as map, H as runForEach, Ht as forkScoped, It as filterOrFail, Jn as succeed$1, K as makeUnsafe, Kn as provide, Kt as mapError, Lt as flatMap, M as drop, Mn as void_, Mt as context, N as empty, Nt as die, On as try_, Ot as catchIf, Pt as ensuring, R as make, Rn as effect, Sn as sync, St as andThen, T as Path, Tt as asVoid, Ut as gen, W as unwrap, Wn as merge, Wt as ignore, Xt as orElseSucceed, Yn as succeedContext, Zn as unwrap$1, _n as serviceOption, b as nodeLayer, c as previewsLayer, cr as add, ct as String$1, d as gitLayer, dt as Union, f as Project, fr as getOrUndefined, ft as decodeEffect, gn as scoped, gr as TaggedError, gt as optional, ht as isPattern, i as projectFlows, j as debounce, k as changes, kt as catchTag, lt as Struct, mt as isNonEmpty, nn as retry, ot as ArraySchema, pt as isMaxLength, qn as provideMerge, r as branchPreviewsLayer, s as Previews, sr as Service, st as Record, t as BranchPreviews, tn as result, u as Git, ur as make$1, ut as Undefined, w as RuntimePolicy, xn as suspend, xt as all, yn as succeed, yt as acquireUseRelease, z as mapEffect, zn as effectContext, zt as forEach } from "./branch-previews-BryeA_kA.js";
2
- import { A as adapterRegistryLayer, D as publishChanges, E as liveChannelLayer, F as WorkAdapter, I as WorkError, M as memoryAdapterLayer, N as parseThreadImport, O as AdapterRegistry, P as ThreadAdapter, R as bundledScreensLayer, T as LiveChannel, _ as storeActivityLayer, c as FileReview, d as fileSearchLayer, f as Files, g as StoreActivity, i as fileSavesLayer, j as defineAdapter, k as adapterModuleLoaderLayer, l as fileReviewLayer, n as fileReviewActionsLayer, o as fileMutationsLayer, p as filesLayer, s as fileWriteLockLayer, v as storeLiveLayer, z as sourceScreensLayer } from "./server-DN5uwE4k.js";
1
+ import { A as concat, At as catch_, B as mapError$1, Bn as effectDiscard, C as ProcessRunner, Cn as tap, Ct as as, D as as$1, E as FileSystem, En as timeoutOrElse, Et as cached, F as fromEffect, Fn as currentTimeMillis, Ft as fail, Gn as mergeAll, Gt as map, H as runForEach, Ht as forkScoped, It as filterOrFail, Jn as succeed$1, K as makeUnsafe, Kn as provide, Kt as mapError, Lt as flatMap, M as drop, Mn as void_, Mt as context, N as empty, Nt as die, On as try_, Ot as catchIf, Pt as ensuring, R as make, Rn as effect, Sn as sync, St as andThen, T as Path, Tt as asVoid, Ut as gen, W as unwrap, Wn as merge, Wt as ignore, Xt as orElseSucceed, Yn as succeedContext, Zn as unwrap$1, _n as serviceOption, b as nodeLayer, c as previewsLayer, cr as add, ct as String$1, d as gitLayer, dt as Union, f as Project, fr as getOrUndefined, ft as decodeEffect, gn as scoped, gr as TaggedError, gt as optional, ht as isPattern, i as projectFlows, j as debounce, k as changes, kt as catchTag, lt as Struct, mt as isNonEmpty, nn as retry, ot as ArraySchema, pt as isMaxLength, qn as provideMerge, r as branchPreviewsLayer, s as Previews, sr as Service, st as Record, t as BranchPreviews, tn as result, u as Git, ur as make$1, ut as Undefined, w as RuntimePolicy, xn as suspend, xt as all, yn as succeed, yt as acquireUseRelease, z as mapEffect, zn as effectContext, zt as forEach } from "./branch-previews-ClkoJ0lM.js";
2
+ import { A as adapterRegistryLayer, D as publishChanges, E as liveChannelLayer, F as WorkAdapter, I as WorkError, M as memoryAdapterLayer, N as parseThreadImport, O as AdapterRegistry, P as ThreadAdapter, R as bundledScreensLayer, T as LiveChannel, _ as storeActivityLayer, c as FileReview, d as fileSearchLayer, f as Files, g as StoreActivity, i as fileSavesLayer, j as defineAdapter, k as adapterModuleLoaderLayer, l as fileReviewLayer, n as fileReviewActionsLayer, o as fileMutationsLayer, p as filesLayer, s as fileWriteLockLayer, v as storeLiveLayer, z as sourceScreensLayer } from "./server-CYvuOSBA.js";
3
3
  import { A as parseThreadReplyInput, C as parseAnchor, Cn as WorkValidationError, E as parseThreadFilter, M as parseThreadStatus, N as parseThreadStatusInput, O as parseThreadInput, _n as parseMessage, a as CommentMergeError, an as parseWorkDetail, b as MAX_THREADS, c as parseCommentInput, cn as parseWorkMutationResult, d as parseCommentThread, dn as parseWorkSnapshot, en as parseSectionData, f as revision, fn as parseWorkSync, in as parseWorkCreate, j as parseThreadSnapshot, k as parseThreadLinkInput, l as conversationId, mn as parseWorkUpdate, nn as parseWorkActivity, o as mergeThreads, on as parseWorkItem, p as text$2, pn as parseWorkSyncResult, rn as parseWorkConnection, s as stableJson, tn as parseWorkActionInput, u as object$1, un as parseWorkQuery, vn as parseMessageAuthor, w as parseThread, xn as parseWorkSchema } from "./events-6z5v7Uca.js";
4
4
  import { n as PICKER_MODULE_URL, t as pickerPageScript } from "./bridge-B_Blt55E.js";
5
5
  import { createHash, randomUUID } from "node:crypto";
@@ -1,9 +1,9 @@
1
1
  import { _ as taskRoutes, an as parseWorkDetail, cn as parseWorkMutationResult, en as parseSectionData, i as routes, pn as parseWorkSyncResult } from "./events-6z5v7Uca.js";
2
- import { Bt as Button, Cn as Text, Ft as CommentThreadDetail, It as CommentThreadItem, K as CommentThreadHeading, Lt as CommentComposer, S as ThreadTaskLinks, _t as taskHref, b as writeOptimistically, bn as toast, dt as conversationLabel, gt as selectedTask, h as storedWorkspace, ht as readConversationLocation, l as projectStore, t as commentsUnavailable, vt as taskRole, w as ItemDiscussion, x as writeRows, y as plainRow, z as TaskWorkspace } from "./comment-data-BuArfgcc.js";
3
- import { a as predictWorkAction, i as loadItemComments, n as createProjectComments, o as predictWorkCreate, s as predictWorkUpdate, t as defineScreen } from "./screen-DMUB9a-K.js";
4
- import { n as requestTasks, t as TaskRequestError } from "./tasks-request-Bk5EoY_p.js";
5
- import { t as projectWork } from "./project-work-6aOyja4v.js";
6
- import { n as ProjectTaskPicker, t as ProjectThreadLinks } from "./project-thread-links-ue_ad9IX.js";
2
+ import { Bt as Button, En as t, Ft as CommentThreadDetail, It as CommentThreadItem, K as CommentThreadHeading, Lt as CommentComposer, On as Text, S as ThreadTaskLinks, _t as taskHref, b as writeOptimistically, bn as toast, dt as conversationLabel, gt as selectedTask, h as storedWorkspace, ht as readConversationLocation, l as projectStore, vt as taskRole, w as ItemDiscussion, x as writeRows, y as plainRow, z as TaskWorkspace } from "./comment-data-9SqALQjT.js";
3
+ import { a as predictWorkAction, i as loadItemComments, n as createProjectComments, o as predictWorkCreate, s as predictWorkUpdate, t as defineScreen } from "./screen-BtvzEiIa.js";
4
+ import { n as requestTasks, t as TaskRequestError } from "./tasks-request-C3jk9Jyu.js";
5
+ import { t as projectWork } from "./project-work-C0FN3w5Y.js";
6
+ import { n as ProjectTaskPicker, t as ProjectThreadLinks } from "./project-thread-links-C0kV_Pcl.js";
7
7
  import { on, ref } from "remix/component";
8
8
  import { Fragment, jsx, jsxs } from "remix/component/jsx-runtime";
9
9
  //#region app/client/task-discussion.tsx
@@ -73,13 +73,13 @@ function TaskDiscussion(handle) {
73
73
  creating = false;
74
74
  handle.update();
75
75
  }),
76
- children: "Reply"
76
+ children: t("app.client.taskDiscussion.reply")
77
77
  }) : null]
78
78
  });
79
79
  }
80
80
  function heading(thread) {
81
81
  return /* @__PURE__ */ jsx(CommentThreadHeading, {
82
- location: thread.anchor ? conversationLabel(thread) : "Discussion",
82
+ location: thread.anchor ? conversationLabel(thread) : t("app.client.taskDiscussion.discussion"),
83
83
  actions: handle.props.renderThreadLinks ? void 0 : /* @__PURE__ */ jsx(ProjectThreadLinks, {
84
84
  part: "action",
85
85
  ...threadLinks(thread)
@@ -113,7 +113,7 @@ function TaskDiscussion(handle) {
113
113
  let count = threads.reduce((sum, thread) => sum + thread.messageCount, 0);
114
114
  return /* @__PURE__ */ jsxs("section", {
115
115
  class: "flex min-w-0 flex-col gap-3",
116
- "aria-label": "Task discussion",
116
+ "aria-label": t("app.client.taskDiscussion.taskDiscussion"),
117
117
  mix: mount,
118
118
  children: [
119
119
  /* @__PURE__ */ jsxs("div", {
@@ -123,7 +123,7 @@ function TaskDiscussion(handle) {
123
123
  as: "h3",
124
124
  variant: "ui",
125
125
  weight: "medium",
126
- children: "Discussion"
126
+ children: t("app.client.taskDiscussion.discussion")
127
127
  }),
128
128
  count ? /* @__PURE__ */ jsx(Text, {
129
129
  variant: "ui-caption",
@@ -139,7 +139,7 @@ function TaskDiscussion(handle) {
139
139
  creating = true;
140
140
  handle.update();
141
141
  }),
142
- children: "New discussion"
142
+ children: t("app.client.taskDiscussion.newDiscussion")
143
143
  }) : null
144
144
  ]
145
145
  }),
@@ -155,18 +155,18 @@ function TaskDiscussion(handle) {
155
155
  mix: on("click", () => {
156
156
  comments.load().then(() => selected ? comments.loadThread(selected, true) : void 0);
157
157
  }),
158
- children: "Reload comments"
158
+ children: t("app.client.taskDiscussion.reloadComments")
159
159
  })]
160
160
  }) : null,
161
161
  !comments.loaded ? /* @__PURE__ */ jsx(Text, {
162
162
  variant: "ui-caption",
163
163
  tone: "muted",
164
164
  role: "status",
165
- children: "Loading discussion…"
165
+ children: t("app.client.taskDiscussion.loadingDiscussion")
166
166
  }) : !comments.ready ? /* @__PURE__ */ jsx(Text, {
167
167
  variant: "ui-caption",
168
168
  tone: "muted",
169
- children: commentsUnavailable
169
+ children: t("app.client.taskDiscussion.commentsUnavailable")
170
170
  }) : /* @__PURE__ */ jsxs(Fragment, { children: [threads.length ? threads.map((thread) => !thread.anchor ? /* @__PURE__ */ jsx(ItemDiscussion, {
171
171
  thread,
172
172
  links: links(thread)
@@ -201,12 +201,12 @@ function TaskDiscussion(handle) {
201
201
  }, thread.id)) : /* @__PURE__ */ jsx(Text, {
202
202
  variant: "ui-caption",
203
203
  tone: "muted",
204
- children: "No discussion yet."
204
+ children: t("app.client.taskDiscussion.noDiscussionYet")
205
205
  }), capabilities.create || capabilities.reply && (explicit || threads.some((thread) => !thread.anchor)) ? /* @__PURE__ */ jsxs("div", {
206
206
  class: "flex min-w-0 flex-col gap-2",
207
207
  children: [capabilities.create && (creating || !explicit && !threads.length) ? /* @__PURE__ */ jsxs("div", {
208
208
  class: "flex items-start justify-between gap-2",
209
- "aria-label": "New discussion tasks",
209
+ "aria-label": t("app.client.taskDiscussion.newDiscussionTasks"),
210
210
  children: [/* @__PURE__ */ jsx(ThreadTaskLinks, {
211
211
  itemIds: draftItemIds,
212
212
  items: handle.props.items ?? [],
@@ -224,19 +224,19 @@ function TaskDiscussion(handle) {
224
224
  creating = false;
225
225
  handle.update();
226
226
  }),
227
- children: "Cancel"
227
+ children: t("app.client.taskDiscussion.cancel")
228
228
  }) : null]
229
- }) : threads.length > 1 ? /* @__PURE__ */ jsxs(Text, {
229
+ }) : threads.length > 1 ? /* @__PURE__ */ jsx(Text, {
230
230
  variant: "ui-caption",
231
231
  tone: "muted",
232
- children: ["Replying to ", reply?.messages[0]?.author.name ?? "the discussion"]
232
+ children: t("app.client.taskDiscussion.replyingTo", { name: reply?.messages[0]?.author.name ?? t("app.client.taskDiscussion.theDiscussion") })
233
233
  }) : null, /* @__PURE__ */ jsx(CommentComposer, {
234
- label: "Add task comment",
235
- placeholder: "Add context for your team…",
234
+ label: t("app.client.taskDiscussion.addTaskComment"),
235
+ placeholder: t("app.client.taskDiscussion.addContextPlaceholder"),
236
236
  busy: comments.busy || replyPending,
237
237
  class: "w-full",
238
238
  onSubmit: async (body) => {
239
- if (replyPending) throw new Error("Load the selected discussion before replying.");
239
+ if (replyPending) throw new Error(t("app.client.taskDiscussion.loadBeforeReplying"));
240
240
  if (reply && capabilities.reply) {
241
241
  await write({
242
242
  id: reply.id,
@@ -286,7 +286,7 @@ async function loadTask(token, id, schema, signal, conversationId) {
286
286
  schema
287
287
  ]);
288
288
  let detail = parseWorkDetail(value, resolved);
289
- if (detail.item.id !== id) throw new Error("The task service returned a different task. Refresh and try again.");
289
+ if (detail.item.id !== id) throw new Error(t("app.client.projectTasks.differentTaskRefresh"));
290
290
  return {
291
291
  detail,
292
292
  discussion
@@ -313,7 +313,7 @@ async function loadTasks(project, signal, href, conversationId) {
313
313
  if (!stored || cause instanceof TaskRequestError) throw cause;
314
314
  return open(projectWork(project).refresh(signal).then((value) => value.schema));
315
315
  }).catch((cause) => {
316
- taskError = cause instanceof Error ? cause.message : "Could not load this task.";
316
+ taskError = cause instanceof Error ? cause.message : t("app.client.projectTasks.couldNotLoadTask");
317
317
  return null;
318
318
  }) : null;
319
319
  try {
@@ -331,7 +331,7 @@ async function loadTasks(project, signal, href, conversationId) {
331
331
  return {
332
332
  store,
333
333
  stored: false,
334
- error: cause instanceof Error ? cause.message : "Could not load tasks."
334
+ error: cause instanceof Error ? cause.message : t("app.client.projectTasks.couldNotLoadTasks")
335
335
  };
336
336
  }
337
337
  }
@@ -385,7 +385,7 @@ function ProjectTasks(handle) {
385
385
  };
386
386
  }
387
387
  function currentSchema() {
388
- if (!workspace) throw new Error("Refresh tasks before making changes.");
388
+ if (!workspace) throw new Error(t("app.client.projectTasks.refreshBeforeChanges"));
389
389
  return workspace.schema;
390
390
  }
391
391
  async function write(url, body, parse) {
@@ -422,7 +422,7 @@ function ProjectTasks(handle) {
422
422
  ...body,
423
423
  expectedRevision: prior.to
424
424
  } : body, (value) => parseWorkMutationResult(value, currentSchema()));
425
- if (id && result.item.id !== id) throw new Error("The task service returned a different task. Refresh before retrying.");
425
+ if (id && result.item.id !== id) throw new Error(t("app.client.projectTasks.differentTaskRefreshRetry"));
426
426
  await accepted(result.item);
427
427
  settled.resolve(from ? {
428
428
  from,
@@ -434,7 +434,7 @@ function ProjectTasks(handle) {
434
434
  return item;
435
435
  } catch (cause) {
436
436
  settled.resolve(null);
437
- if (!handle.signal.aborted) toast.error("Bud undid a task change", { description: cause instanceof Error ? cause.message : "The write was not confirmed." });
437
+ if (!handle.signal.aborted) toast.error(t("app.client.projectTasks.undidTaskChange"), { description: cause instanceof Error ? cause.message : t("app.client.projectTasks.writeNotConfirmed") });
438
438
  refreshAfterWrite();
439
439
  throw cause;
440
440
  } finally {
@@ -459,7 +459,7 @@ function ProjectTasks(handle) {
459
459
  act: (id, action) => save(routes.tasksApi.mutate.href({ id }), action, predicted(id, (item) => predictWorkAction(currentSchema(), item, action)), id),
460
460
  get: async (id) => {
461
461
  let next = await requestTasks(routes.tasksApi.show.href({ id }), project.token, handle.signal, (value) => parseWorkDetail(value, currentSchema()));
462
- if (next.item.id !== id) throw new Error("The task service returned a different task. Refresh and try again.");
462
+ if (next.item.id !== id) throw new Error(t("app.client.projectTasks.differentTaskRefresh"));
463
463
  return next.item;
464
464
  },
465
465
  section: (id, section, signal = handle.signal) => requestTasks(routes.tasksApi.section.href({
@@ -490,7 +490,7 @@ function ProjectTasks(handle) {
490
490
  try {
491
491
  await work.refresh(AbortSignal.any([handle.signal, controller.signal]));
492
492
  } catch (cause) {
493
- if (!controller.signal.aborted && !handle.signal.aborted) error = cause instanceof Error ? cause.message : "Could not load tasks.";
493
+ if (!controller.signal.aborted && !handle.signal.aborted) error = cause instanceof Error ? cause.message : t("app.client.projectTasks.couldNotLoadTasks");
494
494
  } finally {
495
495
  if (listRequest === controller) {
496
496
  loading = false;
@@ -526,10 +526,10 @@ function ProjectTasks(handle) {
526
526
  }
527
527
  let next = await requestTasks(routes.tasksApi.show.href({ id }), project.token, signal, (value) => parseWorkDetail(value, currentSchema()));
528
528
  if (controller.signal.aborted || id !== selectedId) return;
529
- if (next.item.id !== id) throw new Error("The task service returned a different task. Refresh and try again.");
529
+ if (next.item.id !== id) throw new Error(t("app.client.projectTasks.differentTaskRefresh"));
530
530
  detail = next;
531
531
  } catch (cause) {
532
- if (!controller.signal.aborted && !handle.signal.aborted && id === selectedId) detailError = cause instanceof Error ? cause.message : "Could not load this task.";
532
+ if (!controller.signal.aborted && !handle.signal.aborted && id === selectedId) detailError = cause instanceof Error ? cause.message : t("app.client.projectTasks.couldNotLoadTask");
533
533
  } finally {
534
534
  if (detailRequest === controller) {
535
535
  detailLoading = false;
@@ -1,4 +1,5 @@
1
1
  import { i as routes, sn as parseWorkItemRef, un as parseWorkQuery } from "./events-6z5v7Uca.js";
2
+ import { En as t } from "./comment-data-9SqALQjT.js";
2
3
  import { createMultiMatcher } from "remix/route-pattern/match";
3
4
  //#region app/client/tasks-request.ts
4
5
  var reads = createMultiMatcher();
@@ -38,7 +39,7 @@ function validEndpoint(url, write) {
38
39
  * @returns A validated DTO; error responses never become an empty successful view.
39
40
  */
40
41
  async function requestTasks(url, token, signal, parse, fetcher = fetch, write) {
41
- if (!validEndpoint(url, Boolean(write))) throw new Error("Invalid task endpoint.");
42
+ if (!validEndpoint(url, Boolean(write))) throw new Error(t("app.client.tasksRequest.invalidEndpoint"));
42
43
  signal.throwIfAborted();
43
44
  let response = await fetcher(url, {
44
45
  method: write ? "POST" : "GET",
@@ -53,7 +54,7 @@ async function requestTasks(url, token, signal, parse, fetcher = fetch, write) {
53
54
  signal
54
55
  });
55
56
  let reader = response.body?.getReader();
56
- if (!reader) throw new Error("The task service returned an empty response.");
57
+ if (!reader) throw new Error(t("app.client.tasksRequest.emptyResponse"));
57
58
  let chunks = [];
58
59
  let size = 0;
59
60
  try {
@@ -62,7 +63,7 @@ async function requestTasks(url, token, signal, parse, fetcher = fetch, write) {
62
63
  let part = await reader.read();
63
64
  if (part.done) break;
64
65
  size += part.value.byteLength;
65
- if (size > 4194304) throw new Error("The task response is too large to display. Narrow the results and try again.");
66
+ if (size > 4194304) throw new Error(t("app.client.tasksRequest.responseTooLarge"));
66
67
  chunks.push(part.value);
67
68
  }
68
69
  } catch (cause) {
@@ -81,15 +82,15 @@ async function requestTasks(url, token, signal, parse, fetcher = fetch, write) {
81
82
  try {
82
83
  value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
83
84
  } catch {
84
- throw new Error("The task service returned an invalid response. Refresh and try again.");
85
+ throw new Error(t("app.client.tasksRequest.invalidResponse"));
85
86
  }
86
87
  if (!response.ok) {
87
- let error = value && typeof value === "object" && "error" in value && typeof value.error === "string" ? value.error.slice(0, 1e3) : "Could not load tasks. Try again.";
88
+ let error = value && typeof value === "object" && "error" in value && typeof value.error === "string" ? value.error.slice(0, 1e3) : t("app.client.tasksRequest.loadFailed");
88
89
  let code = value && typeof value === "object" && "code" in value && typeof value.code === "string" && /^[a-z][a-z-]{0,63}$/.test(value.code) ? value.code : "request";
89
90
  let currentRevision;
90
91
  if (value && typeof value === "object" && "currentRevision" in value) {
91
92
  let revision = value.currentRevision;
92
- if (revision !== null && (typeof revision !== "string" || !revision.trim() || revision.length > 256 || revision.includes("\0"))) throw new Error("The task service returned an invalid conflict response.");
93
+ if (revision !== null && (typeof revision !== "string" || !revision.trim() || revision.length > 256 || revision.includes("\0"))) throw new Error(t("app.client.tasksRequest.invalidConflictResponse"));
93
94
  currentRevision = revision;
94
95
  }
95
96
  throw new TaskRequestError(error, code, currentRevision);
@@ -1,4 +1,4 @@
1
- import { Qt as provide, Sn as sync, Ut as gen, Zt as promise, a as followCapture, b as nodeLayer, bt as addFinalizer, d as gitLayer, gn as scoped, i as projectFlows, l as PreviewSession, n as branchIndexName, o as startBranchBuild, p as createProjectContext, qn as provideMerge, sn as runPromise } from "./assets/branch-previews-BryeA_kA.js";
1
+ import { Qt as provide, Sn as sync, Ut as gen, Zt as promise, a as followCapture, b as nodeLayer, bt as addFinalizer, d as gitLayer, gn as scoped, i as projectFlows, l as PreviewSession, n as branchIndexName, o as startBranchBuild, p as createProjectContext, qn as provideMerge, sn as runPromise } from "./assets/branch-previews-ClkoJ0lM.js";
2
2
  import { t as pickerPageScript } from "./assets/bridge-B_Blt55E.js";
3
3
  //#region ../previews/src/server/storage.ts
4
4
  /**
@@ -1,7 +1,7 @@
1
- import { Kt as mapError, Lt as flatMap, On as try_, Ut as gen, _ as resolveStorage, f as Project, p as createProjectContext, sn as runPromise, u as Git } from "./assets/branch-previews-BryeA_kA.js";
2
- import { H as make, I as WorkError, O as AdapterRegistry } from "./assets/server-DN5uwE4k.js";
1
+ import { Kt as mapError, Lt as flatMap, On as try_, Ut as gen, _ as resolveStorage, f as Project, p as createProjectContext, sn as runPromise, u as Git } from "./assets/branch-previews-ClkoJ0lM.js";
2
+ import { H as make, I as WorkError, O as AdapterRegistry } from "./assets/server-CYvuOSBA.js";
3
3
  import { j as parseThreadSnapshot, w as parseThread } from "./assets/events-6z5v7Uca.js";
4
- import { n as storageLayer, r as readGitThreadImports } from "./assets/services-Ber8opFE.js";
4
+ import { n as storageLayer, r as readGitThreadImports } from "./assets/services-DK4fqrlF.js";
5
5
  //#region app/server/comment-migration.ts
6
6
  function identity(metadata) {
7
7
  if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) return null;
@@ -1,7 +1,7 @@
1
- import { An as uninterruptible, Dn as tryPromise, Kt as mapError, Rn as effect, Ut as gen, Zt as promise, p as createProjectContext, qn as provideMerge, sn as runPromise, sr as Service, vt as acquireRelease, x as readText } from "./assets/branch-previews-BryeA_kA.js";
2
- import { B as sharedModules, H as make } from "./assets/server-DN5uwE4k.js";
3
- import { n as listen, r as createApp, t as ServerError } from "./assets/listener-oKd5ETMj.js";
4
- import { t as applicationLayer } from "./assets/services-Ber8opFE.js";
1
+ import { An as uninterruptible, Dn as tryPromise, Kt as mapError, Rn as effect, Ut as gen, Zt as promise, p as createProjectContext, qn as provideMerge, sn as runPromise, sr as Service, vt as acquireRelease, x as readText } from "./assets/branch-previews-ClkoJ0lM.js";
2
+ import { B as sharedModules, H as make } from "./assets/server-CYvuOSBA.js";
3
+ import { n as listen, r as createApp, t as ServerError } from "./assets/listener-DGWKUc2o.js";
4
+ import { t as applicationLayer } from "./assets/services-DK4fqrlF.js";
5
5
  import { fileURLToPath } from "node:url";
6
6
  //#region app/server/runtime.ts
7
7
  var BudListener = class extends Service()("bud/Listener") {};
@@ -1,6 +1,6 @@
1
- import { Kn as provide, Rn as effect, Ut as gen, b as nodeLayer, sr as Service, x as readText } from "./assets/branch-previews-BryeA_kA.js";
2
- import { H as make } from "./assets/server-DN5uwE4k.js";
3
- import { n as listen, r as createApp } from "./assets/listener-oKd5ETMj.js";
1
+ import { Kn as provide, Rn as effect, Ut as gen, b as nodeLayer, sr as Service, x as readText } from "./assets/branch-previews-ClkoJ0lM.js";
2
+ import { H as make } from "./assets/server-CYvuOSBA.js";
3
+ import { n as listen, r as createApp } from "./assets/listener-DGWKUc2o.js";
4
4
  import { fileURLToPath } from "node:url";
5
5
  //#region server.ts
6
6
  var Listener = class extends Service()("bud/StandaloneListener") {};
@@ -347,6 +347,8 @@ interface BudConfig {
347
347
  * `{ light: { primary: '#f5b700' } }`. Anything left out keeps Bud's own.
348
348
  */
349
349
  theme?: BudTheme;
350
+ /** The language of Bud's interface: `en` (the default) or `de`. */
351
+ locale?: "en" | "de";
350
352
  /**
351
353
  * What finds the element under a comment: `bud:dom` (the default), `bud:react-grab` for React
352
354
  * projects with React Grab installed, or a ./ module in your project exporting a picker adapter.
@@ -407,6 +409,7 @@ interface ResolvedBudConfig {
407
409
  files: ResolvedFiles;
408
410
  logo: ResolvedLogo | null;
409
411
  theme: ResolvedTheme;
412
+ locale: "en" | "de";
410
413
  picker: ResolvedPicker;
411
414
  branches: ResolvedBranches;
412
415
  }
@@ -1,4 +1,4 @@
1
- import { i as ResolvedBudConfig } from "./config-Cuauq8xY.js";
1
+ import { i as ResolvedBudConfig } from "./config-DIC2cf_S.js";
2
2
  //#region app/server/hosted/contract.d.ts
3
3
  /** How a hosted Bud's captures stand, as its host reports them. */
4
4
  interface RemoteBranchState {
@@ -92,6 +92,8 @@ interface HostedRequestContext {
92
92
  * browser never chooses one.
93
93
  */
94
94
  author?: HostedAuthor;
95
+ /** The person's language for Bud's interface, `en` or `de`; the project's when absent. */
96
+ locale?: string;
95
97
  }
96
98
  /** A running hosted Bud. */
97
99
  interface HostedApp {
@@ -1,4 +1,4 @@
1
- import { i as ResolvedBudConfig } from "./assets/config-Cuauq8xY.js";
1
+ import { i as ResolvedBudConfig } from "./assets/config-DIC2cf_S.js";
2
2
  //#region src/companion.d.ts
3
3
  /**
4
4
  * The contract between a host, such as `@bud.sh/app-vite-plugin` and its CLI, and the companion
@@ -1,5 +1,5 @@
1
- import { i as ResolvedBudConfig } from "./assets/config-Cuauq8xY.js";
2
- import { a as HostedAuthor, c as HostedStorage, i as HostedAppOptions, l as RemoteBranchState, n as CreateHostedApp, o as HostedDatabase, r as HostedApp, s as HostedRequestContext, t as BranchRemote, u as hostedScreenModules } from "./assets/contract-BsCQbbxD.js";
1
+ import { i as ResolvedBudConfig } from "./assets/config-DIC2cf_S.js";
2
+ import { a as HostedAuthor, c as HostedStorage, i as HostedAppOptions, l as RemoteBranchState, n as CreateHostedApp, o as HostedDatabase, r as HostedApp, s as HostedRequestContext, t as BranchRemote, u as hostedScreenModules } from "./assets/contract-CAT-XFNq.js";
3
3
  //#region src/hosted.server.d.ts
4
4
  /**
5
5
  * Creates a hosted Bud: Bud's own routes for the canvas and tasks on the host's stores.
@@ -1,5 +1,5 @@
1
1
  import { n as ElementSource } from "./assets/canvas-anchor-CYU3qBPx.js";
2
- import { a as defineConfig, c as files, l as pages, n as BudRoute, o as BudScreen, s as canvas, t as BudConfig, u as tasks } from "./assets/config-Cuauq8xY.js";
2
+ import { a as defineConfig, c as files, l as pages, n as BudRoute, o as BudScreen, s as canvas, t as BudConfig, u as tasks } from "./assets/config-DIC2cf_S.js";
3
3
  //#region ../picker/src/lib/types.d.ts
4
4
  /** What a framework adds about an element, beyond what the page's DOM shows. */
5
5
  interface PickerDescription {
@@ -1,5 +1,5 @@
1
- import { d as BudTheme } from "./assets/config-Cuauq8xY.js";
2
- import { a as HostedAuthor, s as HostedRequestContext } from "./assets/contract-BsCQbbxD.js";
1
+ import { d as BudTheme } from "./assets/config-DIC2cf_S.js";
2
+ import { a as HostedAuthor, s as HostedRequestContext } from "./assets/contract-CAT-XFNq.js";
3
3
  //#region src/node-host.server.d.ts
4
4
  /** Where the project's Bud on Cloudflare is, and the secret its remote API takes. */
5
5
  export interface NodeHostOptions {
@@ -1,4 +1,4 @@
1
- import { r as ProjectInfo } from "./assets/config-Cuauq8xY.js";
1
+ import { r as ProjectInfo } from "./assets/config-DIC2cf_S.js";
2
2
  import { i as TaskDesign } from "./assets/task-design-xJOhRNWh.js";
3
3
  import { RequestMethod, Route, RouteMap } from "remix/routes";
4
4
  import { Handle, Props, RemixNode } from "remix/component";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bud.sh/app",
3
3
  "description": "The app, its config, screen and design APIs",
4
- "version": "0.3.0",
4
+ "version": "0.4.1",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "publishConfig": {
@@ -1 +0,0 @@
1
- import{t as e}from"./jsx-B4XNFIzB.js";import{t}from"./component-DWct-Tq6.js";import{n}from"./on-mixin-iWnqUzq5.js";import{n as r}from"./attrs-mixin-CmlG_FtV.js";import{c as i,l as a,t as o}from"./loader-Q6-HPKft.js";import{t as s}from"./screen-Dfvzj6n2.js";import{A as c,L as l,R as u,j as d,u as f,xt as p}from"./task-design-bktfn_Ok.js";import{At as m,G as h,H as g,U as _,jt as v,s as y,st as b}from"./project-threads-DezXiVK6.js";import{i as x,n as S,t as C}from"./project-comments-D897aU5O.js";import{i as w,n as T,t as E}from"./project-branches-DpxQx-T4.js";import{t as D}from"./project-thread-links-Bp_TseD0.js";var O=760,k=n(`pointerdown`,e=>e.stopPropagation());function A(e,t,n){let r=e.capture.width*t,i=e.capture.thumbnails.map(e=>e.width),a=e=>{let t=i.findIndex(t=>r<=t*e);return t<0?`slices`:t},o=e=>e===`slices`?i.length:e,s=a(1);return n===void 0||o(s)>=o(n)||o(a(.85))<o(n)?s:n}function j(e,t){return e?.get(t)??{visible:!0,top:0,bottom:1/0,density:1}}function M(e,t){let n=0;return e.capture.tiles.map((r,i)=>{let a={tile:r,index:i,top:n,src:e.srcs[i]};return n+=r.height,{...a,shownTo:Math.min(n,t)}})}function N(t){let{route:r,previews:s}=t.props,c=r.pageId??r.id,l=()=>w(t.props.theme,t.props.size),u=``,d,f,m=``;function h(e){return t.props.topOnly?e.capture.tiles[0]?.height??e.capture.height:e.capture.height}function g(){let{preview:e,images:n}=s.get(c),r=n[l()]??f,i=r?h(r):e?.captures[0]?.height??(e?.state===`failed`?O:0);if(!e||!i)return;let a=`${i}:${e.path}:${r?.capture.hash??``}`;u!==a&&(u=a,t.props.onLayout({height:i,path:e.path,pins:r?.capture.pins}))}function v(e){let n=j(t.props.viewport,r.id);if(!n.visible||d===void 0)return{thumbnail:void 0,slices:[]};if(d===`slices`&&e.srcs.length){let t=Math.min(n.bottom,h(e));return{thumbnail:e.thumbnails.at(-1),slices:M(e,t).filter(({src:e,top:t,shownTo:r})=>e&&t<r&&r>n.top)}}let i=d===`slices`?e.thumbnails.length-1:d;return{thumbnail:e.thumbnails[i]??e.thumbnails.at(-1),slices:[]}}function y(){let e=s.get(c).images[l()];if(!e||e===f)return;if(!f||f.capture.hash===e.capture.hash){f=e;return}if(d===`slices`&&!e.srcs.length){s.slices(c,t.props.theme,t.props.size);return}let n=`${e.capture.hash}:${d}`;if(m===n)return;m=n;let r=e,{thumbnail:i,slices:a}=v(r);Promise.all([i,...a.map(({src:e})=>e)].flatMap(e=>{if(!e)return[];let t=new Image;return t.src=e,[t.decode().catch(()=>{})]})).then(()=>{m!==n||t.signal.aborted||(m=``,f=s.get(c).images[l()]??r,g(),t.update())})}let b=s.watch(c,()=>{y(),g(),t.update()}),x=t.props.viewport?.watch(r.id,()=>void t.update());return t.signal.addEventListener(`abort`,()=>{b(),x?.()},{once:!0}),()=>{let{mode:l,origin:u,theme:m,viewport:b,size:x}=t.props,{preview:S,images:C,refreshing:T,error:E}=s.get(c);t.queueTask(()=>{s.show(c,m,x),g()});let D=C[w(m,x)]??C[w(m===`dark`?`light`:`dark`,x)];D&&(!f||f.capture.theme!==D.capture.theme)?f=D:y();let O=f,M=E||(S?.captures.length?null:S?.error),N=new URL(r.path,u).href;if(O){let i=j(b,r.id);if(d=A(O,i.density,d),i.visible&&d===`slices`&&!O.srcs.length){let{theme:e}=O.capture;t.queueTask(()=>s.slices(c,e,x))}let a=h(O),{width:o}=O.capture,{thumbnail:u,slices:f}=v(O);return e(`div`,{role:`img`,"aria-label":`${r.title} preview`,"data-detail":i.visible?f.length?`slices`:u?`thumbnail`:`pending`:`hidden`,class:`relative select-none overflow-hidden ${l===`comment`?`cursor-crosshair`:``}`,style:{height:a},mix:[n(`pointerdown`,e=>{l!==`pan`&&e.stopPropagation()}),n(`click`,e=>{if(l!==`comment`||S?.path!==r.path)return;e.stopPropagation();let n=e.currentTarget.getBoundingClientRect(),i={x:(e.clientX-n.left)*o/n.width,y:(e.clientY-n.top)*a/n.height};t.props.onPick({element:null,path:r.path,..._(i,o),found:s.describe(c,O.capture,i.x,i.y)})})],children:[u?e(`img`,{src:u,alt:``,decoding:`async`,draggable:!1,class:`absolute inset-x-0 top-0 block w-full max-w-none`,style:{height:O.capture.height}}):null,f.map(({tile:t,index:n,top:r,src:i})=>e(`img`,{src:i,alt:``,decoding:`async`,draggable:!1,class:`absolute inset-x-0 block w-full max-w-none`,style:{top:r,height:t.height+ +(n<O.capture.tiles.length-1)}},t.hash))]})}return S?.state===`failed`||M&&!T?e(`div`,{class:`absolute inset-0 flex flex-col items-center justify-center gap-3 p-12 text-center`,role:`status`,children:[e(p,{name:`circle-alert`,size:24,class:`text-muted`}),e(a,{variant:`title`,weight:`semibold`,class:`text-ink`,children:[r.title,` couldn't be captured`]}),M?e(a,{variant:`ui`,class:`max-w-md text-muted`,children:M}):null,e(`div`,{class:`mt-2 flex gap-2`,children:[e(i,{variant:`secondary`,disabled:T,mix:[k,n(`click`,()=>void s.refresh(c))],children:e(a,{variant:`ui`,children:`Try again`})}),e(`a`,{href:N,target:`_blank`,rel:`noreferrer`,class:`bud-interaction bud-control flex h-control items-center rounded-lg px-3 text-ink`,mix:k,children:e(a,{variant:`ui`,children:`Open page`})})]})]}):e(`div`,{class:`absolute inset-0 flex items-center justify-center`,children:e(o,{label:`Capturing ${r.title}…`})})}}function ee(r){let{route:i,previews:a}=r.props,o=i.pageId??i.id,s=a.watch(o,()=>void r.update());return r.signal.addEventListener(`abort`,s,{once:!0}),()=>{let{preview:r,refreshing:s}=a.get(o),c=s||!!r?.updating,d=r?.state===`ready`?r.error:null;return e(t,{children:[d?e(u,{label:d,children:e(`span`,{tabIndex:0,role:`img`,"aria-label":d,class:`pointer-events-auto ms-1 inline-flex text-amber-500`,mix:k,children:e(p,{name:`circle-alert`,size:13})})}):null,e(l,{icon:`sync`,label:`Refresh ${i.title}`,tooltip:!0,size:`small`,iconSize:13,disabled:s,"aria-busy":c?`true`:void 0,class:`pointer-events-auto ms-0.5 text-muted hover:text-ink ${c?`[&_svg]:animate-spin`:``}`,mix:[k,n(`click`,()=>void a.refresh(o))]})]})}}var P=new Map;function F(){return new Worker(new URL(`/assets/difference-worker-BpqPBs5g.js`,``+import.meta.url),{type:`module`})}function I(e){let{routes:t,before:n,after:r,theme:i,signal:a}=e,o=new Map,s={get:e=>o.get(e)??{state:`pending`,regions:[]},progress:{compared:0,total:t.length},done:t.length===0},c,l=0,u=new Map;function d(e){c??=F(),c.onmessage=e=>{u.get(e.data.id)?.(e.data),u.delete(e.data.id)};let t=l++;return new Promise(n=>{u.set(t,n),c.postMessage({...e,id:t})})}a.addEventListener(`abort`,()=>c?.terminate(),{once:!0});async function f(e,t){let[a,o]=await Promise.all([n.picture(e,i,t),r.picture(e,i,t)]);if(!a||!o)return{state:`missing`,regions:[],before:a?.capture,after:o?.capture};let s={before:a.capture,after:o.capture};if(a.capture.hash===o.capture.hash)return{state:`same`,regions:[],...s};let c=`${a.capture.hash}\0${o.capture.hash}`,l=P.get(c);if(!l){let e=e=>({images:e.images,heights:e.capture.tiles.map(e=>e.height),scale:e.capture.scale}),t=await d({width:a.capture.width,before:e(a),after:e(o)});if(`error`in t)return{state:`failed`,regions:[],error:t.error,...s};l=t.regions,P.set(c,l)}return{state:l.length?`different`:`same`,regions:l,...s}}return(async()=>{for(let n of t){if(a.aborted)return;let r=await f(n.page,n.size).catch(e=>({state:`failed`,regions:[],error:e instanceof Error?e.message:`The pictures could not be compared.`}));if(a.aborted)return;o.set(n.id,r),s.progress={compared:s.progress.compared+1,total:t.length},e.onChange(n.id)}s.done=!0,c?.terminate(),c=void 0,e.onChange(null)})(),s}var L=40,R=48;function z(e){let t=0;return{slots:e.map(e=>{let n={top:t,height:L+Math.max(e.before.height,e.after.height,1)};return t+=n.height+R,n}),height:Math.max(1,t-R)}}var B={changed:`Changed`,added:`Added`,removed:`Removed`};function V(e){let t=new Map;return e.addEventListener(`abort`,()=>{for(let e of t.values())URL.revokeObjectURL(e)},{once:!0}),e=>{let n=t.get(e);return n||t.set(e,n=URL.createObjectURL(e)),n}}function te(t){let n=V(t.signal),r=0;return()=>{let{route:i,side:o,label:s,regions:c,viewport:l}=t.props,{slots:u,height:d}=z(c);r!==d&&(r=d,t.queueTask(()=>t.props.onLayout({height:d,path:i.path})));let f=l?.get(i.id)?.visible??!0;return e(`div`,{role:`img`,"aria-label":`${i.title}, ${s}`,"data-difference":o,"data-changes":c.length,class:`relative select-none bg-[var(--bud-main)]`,style:{height:`${d}px`},children:c.map((t,r)=>{let i=t[o],c=t.crops[o],l=u[r];return e(`div`,{"data-kind":t.kind,"data-span":`${i.y} ${i.height}`,class:`absolute inset-x-0`,style:{top:`${l.top}px`,height:`${l.height}px`},children:[e(`div`,{class:`flex items-center gap-2 px-1`,style:{height:`${L}px`},children:[e(a,{variant:`ui`,weight:`medium`,children:`Change ${r+1}`}),e(a,{variant:`ui`,tone:`muted`,children:B[t.kind]})]}),c&&i.height>0?e(`div`,{class:`relative overflow-hidden`,style:{height:`${i.height}px`},children:[f?e(`img`,{alt:``,src:n(c),draggable:!1,class:`block h-full w-full`}):null,t.kind===`changed`?e(`div`,{"aria-hidden":`true`,class:`pointer-events-none absolute inset-y-0 rounded-sm outline-2 outline-red-500/70`,style:{left:`${t.x}px`,width:`${Math.max(2,t.width)}px`}}):null]}):e(`div`,{class:`grid h-24 place-items-center rounded-lg border border-dashed border-line`,children:e(a,{variant:`ui`,tone:`muted`,children:`Not in ${s}`})})]},r)})})}}function ne(t){let i=V(t.signal),o=e=>{let{slides:n,index:r}=t.props;n.length&&t.props.onIndex((r+e+n.length)%n.length)};return()=>{let{slides:s,index:c,beforeLabel:u,afterLabel:d}=t.props,f=s[Math.min(c,s.length-1)],p=(t,n)=>{let r=f?.region.crops[t];return e(`figure`,{class:`m-0 flex min-w-0 flex-col gap-2`,children:[e(`figcaption`,{children:e(a,{variant:`ui`,tone:`muted`,children:n})}),r&&f.region[t].height>0?e(`div`,{class:`relative`,children:[e(`img`,{alt:`${f.route.title}, ${n}`,src:i(r),class:`block w-full rounded-lg ring-1 ring-line`}),f.region.kind===`changed`?e(`div`,{"aria-hidden":`true`,class:`pointer-events-none absolute inset-y-0 rounded-sm outline-2 outline-red-500/70`,style:{left:`${f.region.x/f.width*100}%`,width:`max(2px, ${f.region.width/f.width*100}%)`}}):null]}):e(`div`,{class:`grid h-32 place-items-center rounded-lg border border-dashed border-line`,children:e(a,{variant:`ui`,tone:`muted`,children:`Not in ${n}`})})]})};return e(`section`,{role:`dialog`,"aria-label":`Differences slideshow`,class:`bud-surface absolute inset-0 z-40 flex flex-col bg-[var(--bud-main)]`,mix:r((e,n)=>{e.focus(),e.ownerDocument.addEventListener(`keydown`,e=>{if(e.key===`ArrowRight`)o(1);else if(e.key===`ArrowLeft`)o(-1);else if(e.key===`Escape`)t.props.onClose();else return;e.preventDefault()},{signal:n})}),tabindex:-1,children:[e(`header`,{class:`flex h-12 shrink-0 items-center gap-2 border-b border-line ps-4 pe-2`,children:[e(`div`,{class:`flex min-w-0 flex-1 items-baseline gap-2`,children:[e(a,{variant:`ui`,weight:`medium`,class:`truncate`,children:f?.route.title??`No differences`}),f?e(a,{variant:`ui`,tone:`muted`,class:`shrink-0 tabular-nums`,role:`status`,children:`${B[f.region.kind]} · change ${f.index+1} of ${f.count} · ${c+1} / ${s.length}`}):null]}),e(l,{tooltip:!0,icon:`chevron-left`,label:`Previous change`,disabled:s.length<2,mix:n(`click`,()=>o(-1))}),e(l,{tooltip:!0,icon:`chevron-right`,label:`Next change`,disabled:s.length<2,mix:n(`click`,()=>o(1))}),e(l,{tooltip:!0,icon:`close`,label:`Close slideshow`,shortcut:`escape`,mix:n(`click`,()=>t.props.onClose())})]}),e(`div`,{class:`min-h-0 flex-1 overflow-auto p-4`,children:f?e(`div`,{class:`grid gap-4 md:grid-cols-2`,children:[p(`before`,u),p(`after`,d)]}):null})]})}}function H(e){return!(!e.anchor||`type`in e.anchor)}function U(e,t){let{themes:n}=e.previews,r=m(t),i=document.documentElement.dataset.theme;return n.find(e=>e===r)??n.find(e=>e===i)??n[0]}function W(r){let i=r.props.project,a,s=C({store:y(i),token:i.token,signal:r.signal,initial:r.props.comments,onChange:()=>{r.update()}});r.props.comments.stored&&s.load();let u=i.workingTree?null:i.main??`main`,p=`bud:canvas-branch:${i.id}`,_=m(p),S=typeof _==`string`?_:u,w=!0,O=!1,k=E({project:i,signal:r.signal,onChange:()=>{S&&S!==u&&k.loaded&&!k.list.branches.some(e=>e.name===S&&e.active)?M(u):r.update()}}),A=new AbortController;r.signal.addEventListener(`abort`,()=>A.abort(),{once:!0});let j=T({project:i,signal:A.signal,branch:S});function M(e){if(O=!1,e===S)return void r.update();S=e,v(p,e),A.abort(),A=new AbortController,j=T({project:i,signal:A.signal,branch:e}),r.update()}let P=`bud:preview-theme:${i.id}`,F=U(i,P),L=`bud:preview-top-only:${i.id}`,R=m(L)===!0,z=i.previews.viewports,B=z.length>1,V=`bud:canvas-viewport:${i.id}`,W=m(V),G=B&&typeof W==`string`&&(W===`all`||z.some(e=>e.id===W))?W:B?`all`:z[0].id;function K(e){e!==G&&(G=e,v(V,e),r.update())}function q(){let e=G===`all`?z:z.filter(e=>e.id===G);return i.routes.flatMap(t=>e.map(e=>({route:t,size:e,artboard:B?{...t,id:`${t.id}@${e.id}`,pageId:t.id,width:e.width,caption:String(e.width)}:t})))}let J=`bud:canvas-compare:${i.id}`,Y=null,X,Z;function Q(){let e=i.workingTree?[{value:``,label:`Working tree`}]:[];for(let t of k.list.branches)t.active&&t.captured&&e.push({value:t.name,label:t.name});return e.filter(e=>e.value!==(S??``))}function $(e){return e||`Working tree`}function re(){let e=Q(),t=m(J);Y=e.find(e=>e.value===t)?.value??e.find(e=>e.value===(k.list.main??`main`))?.value??e[0]?.value??null,Z=void 0,r.update()}function ie(){Y=null,Z=void 0,X?.controller.abort(),X=void 0,r.update()}function ae(e){if(Y===null||(Q().some(e=>e.value===Y)||(Y=Q()[0]?.value??null),Y===null))return;let t=`${Y}\0${S??``}\0${F}\0${G}`;if(X?.key===t)return X.result;X?.controller.abort();let n=new AbortController;r.signal.addEventListener(`abort`,()=>n.abort(),{once:!0});let a=T({project:i,signal:n.signal,branch:Y||null}),o=I({routes:q().map(({route:e,size:t,artboard:n})=>({id:n.id,page:e.id,size:t})),before:a,after:e,theme:F,signal:n.signal,onChange:()=>{r.update()}});return X={key:t,controller:n,result:o},o}function oe(e){return!B||G===`all`||(z.find(t=>t.width===e.anchor.viewport)??z[0]).id===G}function se(e){return e.filter(H).filter(e=>(e.anchor.branch??u)===S).filter(oe)}return()=>{if(a!==r.props.threadId){a=r.props.threadId;let e=a;e&&r.queueTask(()=>{s.loadThread(e)})}if(!k.loaded&&!k.error)return e(o,{label:`Loading branches…`});let u=`${i.id}:${i.targetOrigin}:${i.routes.map(e=>e.path).join(`|`)}`,p={...s.snapshot,threads:se(s.snapshot.threads)},m=q(),_=new Map(m.map(({artboard:e,size:t})=>[e.id,t])),y=ae(j),C=$(Y),T=$(S),E=y?m.map(({artboard:e})=>e).filter(e=>y.get(e.id).state===`different`):[],A=new Map,I=E.flatMap(e=>[`before`,`after`].map(t=>{let n=`${e.id}#${t}`;return A.set(n,{route:e,side:t}),{id:n,path:e.path,title:e.title,width:e.width,caption:e.caption,compare:{groupId:e.id,groupTitle:e.title,versionLabel:t===`before`?C:T}}})),V=E.flatMap(e=>{let{regions:t,after:n}=y.get(e.id),r=n?.width??e.width??z[0].width;return t.map((n,i)=>({route:e,region:n,index:i,count:t.length,width:r}))}),H=``;if(y){let{compared:e,total:t}=y.progress,n=m.filter(({artboard:e})=>y.get(e.id).state===`missing`).length;H=y.done?E.length?`${E.length} of ${t} pages differ from ${C}`:`No differences from ${C}`:`Comparing with ${C}… ${e} of ${t} pages`,y.done&&n&&(H+=` · ${n} without pictures on both sides`)}let U=Q(),W=e=>e.mobile||e.width<600?`mobile`:e.width<1100?`tablet`:`desktop`,oe=e(t,{children:[B?e(t,{children:[z.map(t=>e(l,{tooltip:!0,icon:W(t),label:`Show ${t.name} (${t.width})`,active:G===t.id,mix:n(`click`,()=>K(t.id))})),e(l,{tooltip:!0,icon:`columns`,label:`Show every viewport side by side`,active:G===`all`,mix:n(`click`,()=>K(`all`))}),e(c,{})]}):null,e(l,{tooltip:!0,icon:`compare`,label:y?`Stop comparing`:`Show differences with another branch`,active:!!y,disabled:!y&&!U.length,mix:n(`click`,()=>y?ie():re())}),y?e(t,{children:[e(f,{label:`Compare with`,value:Y??``,options:U,class:`max-w-48`,onChange:e=>{Y=e,Z=void 0,v(J,e),r.update()}}),e(l,{tooltip:!0,icon:`play`,label:`Step through the differences`,disabled:!V.length,mix:n(`click`,()=>{Z=0,r.update()})})]}):null]});return e(d,{class:`h-full min-h-0`,sidebarLabel:`Branches`,mainLabel:`Canvas`,drawerOpen:O,onDrawerOpenChange:e=>{O=e,r.update()},onWideChange:e=>{w!==e&&(w=e,r.update())},sidebar:e(h,{working:k.list.working,workingTree:i.workingTree,branches:k.list.branches,selected:S,busy:k.busy||!k.loaded,loaded:k.loaded,error:k.error,mobile:!w,onSelect:M,onActivate:(e,t)=>{k.activate(e,t)},onCapture:e=>{k.capture(e)},onClose:()=>{O=!1,r.update()}}),children:e(g,{artboards:y?I:m.map(({artboard:e})=>e),width:z[0].width,storageKey:y?`bud:camera:${u}:differences:${G}`:`bud:camera:${u}:${B?G:z[0].width}`,tools:oe,overlay:y&&Z!==void 0?e(ne,{slides:V,index:Z,beforeLabel:C,afterLabel:T,onIndex:e=>{Z=e,r.update()},onClose:()=>{Z=void 0,r.update()}}):null,snapshot:p,capabilities:s.snapshot.capabilities,commentsUnavailable:y?H:(s.loaded?!s.ready:i.storage.threads?.state!==`ready`)?x:void 0,onLoadThread:s.loadThread,renderThreadLinks:t=>e(D,{part:`links`,project:i,thread:t,canLink:s.snapshot.capabilities.link,busy:s.busy,onChange:async()=>{await s.load(),await s.loadThread(t.id,!0)}}),renderThreadActions:t=>e(D,{part:`action`,project:i,thread:t,canLink:s.snapshot.capabilities.link,busy:s.busy,onChange:async()=>{await s.load(),await s.loadThread(t.id,!0)}}),initialThreadId:a,loaded:s.loaded,busy:s.busy,error:s.error,now:s.now,onWrite:async e=>{let t=await s.write(e);return{...t,threads:se(t.threads)}},onSync:()=>s.sync().catch(()=>{}),onReload:s.load,onCopyThreadLink:e=>navigator.clipboard.writeText(new URL(b(e.id),window.location.origin).href),interactive:!1,branch:S,theme:F,onThemeChange:i.previews.themes.length>1?e=>{F=e,v(P,e),r.update()}:void 0,topOnly:R,onTopOnlyChange:y?void 0:e=>{R=e,v(L,e),r.update()},onShowSidebar:w?void 0:()=>{O=!0,r.update()},sidebarLabel:`Branches`,renderArtboard:(t,n)=>{let r=A.get(t.id);return r?e(te,{route:t,side:r.side,label:r.side===`before`?C:T,regions:y.get(r.route.id).regions,...n},`${X?.key??``}\0${t.id}`):e(N,{route:t,origin:i.targetOrigin,theme:F,size:_.get(t.id)??z[0],topOnly:R,previews:j,...n},`${S??``}\0${t.id}`)},renderArtboardActions:t=>S||y?null:e(ee,{route:t,previews:j})},`${y?`${u}:differences`:u}:${G}`)})}}var G=s({load:({project:e,signal:t})=>S(e,t),render:(t,{project:n,conversation:r})=>e(W,{project:n,comments:t,threadId:r?.id})});export{G as default};