camox 0.75.0 → 0.76.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 (72) hide show
  1. package/dist/core/editing/createEditableBlock.js +1077 -1681
  2. package/dist/core/editing/fieldSlot.js +251 -0
  3. package/dist/core/editing/useFieldSlot.js +159 -0
  4. package/dist/core/layoutContext.d.ts +2 -0
  5. package/dist/core/layoutContext.js +27 -1
  6. package/dist/features/canvas/CanvasPageFrame.js +2 -2
  7. package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -1
  8. package/dist/features/canvas/canvasCameraController.js +595 -0
  9. package/dist/features/canvas/useCanvasCamera.js +141 -587
  10. package/dist/features/canvas/useCanvasFrame.js +1 -1
  11. package/dist/features/page/DerivedPageContent.js +4 -8
  12. package/dist/features/preview/components/AssetLightbox.js +6 -65
  13. package/dist/features/preview/components/CanvasPreview.js +2 -2
  14. package/dist/features/preview/components/Frame.js +3 -3
  15. package/dist/features/preview/components/ItemFieldsEditor.js +376 -460
  16. package/dist/features/preview/components/Overlays.js +4 -9
  17. package/dist/features/preview/components/PreviewPanel.js +3 -3
  18. package/dist/features/preview/components/RemovedBlockPlaceholder.js +2 -2
  19. package/dist/features/preview/components/SelectionEditor.js +285 -339
  20. package/dist/features/preview/components/ZoomableImage.js +105 -0
  21. package/dist/features/preview/components/contentFieldSchema.js +3 -1
  22. package/dist/features/preview/components/useFieldWriter.js +30 -51
  23. package/dist/features/preview/components/useRecordView.js +3 -3
  24. package/dist/features/preview/overlayMessages.js +20 -58
  25. package/dist/features/preview/previewStore.js +6 -123
  26. package/dist/features/preview/repeatableItemPath.js +47 -0
  27. package/dist/features/provider/AuthenticatedCamoxProvider.js +75 -63
  28. package/dist/features/renderer/RendererApp.js +6 -6
  29. package/dist/features/renderer/RendererFrames.js +2 -2
  30. package/dist/features/renderer/rendererHost.js +1 -1
  31. package/dist/features/routes/pageRuntime.d.ts +8 -12
  32. package/dist/features/routes/pageRuntime.js +26 -106
  33. package/dist/features/runtime/pageApp.js +1 -1
  34. package/dist/features/runtime/pageRead.js +105 -0
  35. package/dist/features/runtime/reader.d.ts +25 -0
  36. package/dist/features/runtime/reader.js +142 -0
  37. package/dist/features/runtime/runtime.d.ts +9 -3
  38. package/dist/features/runtime/runtime.js +608 -776
  39. package/dist/features/sdkBundle/buildSdkBundle.d.ts +5 -0
  40. package/dist/features/sdkBundle/buildSdkBundle.js +9 -3
  41. package/dist/features/studio/components/ChatWidget.js +137 -121
  42. package/dist/features/studio/components/ClearThread.js +121 -0
  43. package/dist/features/studio/components/DeleteDraftDialog.js +67 -65
  44. package/dist/features/studio/components/DraftBar.js +60 -49
  45. package/dist/features/studio/components/DraftNotices.js +149 -0
  46. package/dist/features/studio/components/DraftsControl.js +217 -180
  47. package/dist/features/studio/components/DraftsSheet.js +446 -0
  48. package/dist/features/studio/components/PublishedTab.js +511 -0
  49. package/dist/features/studio/components/ReviewDraftDialog.js +104 -89
  50. package/dist/features/studio/components/SheetTable.js +46 -0
  51. package/dist/features/studio/components/Specialists.js +1 -1
  52. package/dist/features/studio/components/ThreadMessages.js +227 -176
  53. package/dist/features/studio/draftLabel.js +15 -1
  54. package/dist/features/studio/draftNotice.js +1 -0
  55. package/dist/features/studio/showInCanvas.js +9 -19
  56. package/dist/features/studio/studioStore.js +5 -5
  57. package/dist/features/studio/useArchiveDraft.js +60 -0
  58. package/dist/features/studio/useEditorSelection.js +8 -19
  59. package/dist/features/studio/useRestoreDraft.js +70 -0
  60. package/dist/features/studio/viewSwitch.js +19 -11
  61. package/dist/lib/draft-scope.d.ts +1 -1
  62. package/dist/lib/draft-scope.js +6 -3
  63. package/dist/lib/queries.js +12 -1
  64. package/dist/lib/studio-reads.js +22 -0
  65. package/dist/lib/use-project-room.js +19 -13
  66. package/dist/lib/use-thread.js +1 -1
  67. package/dist/package.js +1 -1
  68. package/dist/studio.css +1 -1
  69. package/package.json +4 -4
  70. package/dist/core/hooks/useFieldSelection.js +0 -67
  71. package/dist/core/hooks/useIsEditable.js +0 -21
  72. package/dist/core/hooks/useOverlayMessage.js +0 -70
@@ -1,4 +1,5 @@
1
1
  import { cn } from "../../../lib/utils.js";
2
+ import { ZoomableImage } from "../../preview/components/ZoomableImage.js";
2
3
  import { Squareling } from "./Squareling.js";
3
4
  import { ThreadMarkdown } from "./ThreadMarkdown.js";
4
5
  import { c } from "react/compiler-runtime";
@@ -21,12 +22,12 @@ import { MessageScroller, MessageScrollerButton, MessageScrollerContent, Message
21
22
  * agent does, never how: thinking, looking around, making changes, building, fixing the build,
22
23
  * or starting a draft. Each editor's message shows its
23
24
  * sender's avatar, without their name. A Live turn handed off to a draft ends on the draft's
24
- * card, which `onOpenDraft` opens, and the draft's thread shows the hand-off's Brief collapsed
25
- * under the editor's messages. The thread keeps its end in view, unless the editor scrolls up.
25
+ * card, which `onOpenDraft` opens, or `onRestoreDraft` restores while the draft is archived, and
26
+ * the draft's thread shows the hand-off's Brief collapsed under the editor's messages. The thread keeps its end in view, unless the editor scrolls up.
26
27
  */
27
28
  function ThreadMessages(t0) {
28
- const $ = c(20);
29
- const { view, sending: t1, onOpenDraft } = t0;
29
+ const $ = c(21);
30
+ const { view, sending: t1, onOpenDraft, onRestoreDraft } = t0;
30
31
  const sending = t1 === void 0 ? false : t1;
31
32
  const working = view.running || sending;
32
33
  const empty = view.messages.length === 0 && !working;
@@ -60,14 +61,15 @@ function ThreadMessages(t0) {
60
61
  return t4;
61
62
  }
62
63
  let t2;
63
- if ($[5] !== onOpenDraft || $[6] !== squareling || $[7] !== view || $[8] !== working) {
64
+ if ($[5] !== onOpenDraft || $[6] !== onRestoreDraft || $[7] !== squareling || $[8] !== view || $[9] !== working) {
64
65
  t2 = view.messages.map((message, index) => /* @__PURE__ */ jsxs(MessageScrollerItem, {
65
66
  messageId: message.id,
66
67
  scrollAnchor: message.from === "editor",
67
68
  className: "flex flex-col gap-4",
68
69
  children: [/* @__PURE__ */ jsx(ThreadMessageRow, {
69
70
  message,
70
- onOpenDraft
71
+ onOpenDraft,
72
+ onRestoreDraft
71
73
  }), index === view.messages.length - 1 && /* @__PURE__ */ jsx(AgentPresence, {
72
74
  view,
73
75
  working,
@@ -75,40 +77,41 @@ function ThreadMessages(t0) {
75
77
  })]
76
78
  }, message.id));
77
79
  $[5] = onOpenDraft;
78
- $[6] = squareling;
79
- $[7] = view;
80
- $[8] = working;
81
- $[9] = t2;
82
- } else t2 = $[9];
80
+ $[6] = onRestoreDraft;
81
+ $[7] = squareling;
82
+ $[8] = view;
83
+ $[9] = working;
84
+ $[10] = t2;
85
+ } else t2 = $[10];
83
86
  let t3;
84
- if ($[10] !== squareling || $[11] !== view || $[12] !== working) {
87
+ if ($[11] !== squareling || $[12] !== view || $[13] !== working) {
85
88
  t3 = view.messages.length === 0 && /* @__PURE__ */ jsx(AgentPresence, {
86
89
  view,
87
90
  working,
88
91
  squareling
89
92
  });
90
- $[10] = squareling;
91
- $[11] = view;
92
- $[12] = working;
93
- $[13] = t3;
94
- } else t3 = $[13];
93
+ $[11] = squareling;
94
+ $[12] = view;
95
+ $[13] = working;
96
+ $[14] = t3;
97
+ } else t3 = $[14];
95
98
  let t4;
96
- if ($[14] !== t2 || $[15] !== t3) {
99
+ if ($[15] !== t2 || $[16] !== t3) {
97
100
  t4 = /* @__PURE__ */ jsx(MessageScrollerViewport, { children: /* @__PURE__ */ jsxs(MessageScrollerContent, {
98
101
  className: "flex flex-col gap-4 px-2 py-3",
99
102
  children: [t2, t3]
100
103
  }) });
101
- $[14] = t2;
102
- $[15] = t3;
103
- $[16] = t4;
104
- } else t4 = $[16];
104
+ $[15] = t2;
105
+ $[16] = t3;
106
+ $[17] = t4;
107
+ } else t4 = $[17];
105
108
  let t5;
106
- if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
109
+ if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
107
110
  t5 = /* @__PURE__ */ jsx(MessageScrollerButton, {});
108
- $[17] = t5;
109
- } else t5 = $[17];
111
+ $[18] = t5;
112
+ } else t5 = $[18];
110
113
  let t6;
111
- if ($[18] !== t4) {
114
+ if ($[19] !== t4) {
112
115
  t6 = /* @__PURE__ */ jsx(MessageScrollerProvider, {
113
116
  autoScroll: true,
114
117
  children: /* @__PURE__ */ jsxs(MessageScroller, {
@@ -116,9 +119,9 @@ function ThreadMessages(t0) {
116
119
  children: [t4, t5]
117
120
  })
118
121
  });
119
- $[18] = t4;
120
- $[19] = t6;
121
- } else t6 = $[19];
122
+ $[19] = t4;
123
+ $[20] = t6;
124
+ } else t6 = $[20];
122
125
  return t6;
123
126
  }
124
127
  /** How long the greeting's squareling takes to reach the end of the thread, in ms. */
@@ -301,111 +304,113 @@ const PUSH_OUTCOMES = {
301
304
  notPreviewed: "Built, but the preview can’t show it."
302
305
  };
303
306
  function ThreadMessageRow(t0) {
304
- const $ = c(56);
305
- const { message, onOpenDraft } = t0;
307
+ const $ = c(57);
308
+ const { message, onOpenDraft, onRestoreDraft } = t0;
306
309
  if (message.from === "draft") {
307
310
  let t1;
308
- if ($[0] !== message || $[1] !== onOpenDraft) {
311
+ if ($[0] !== message || $[1] !== onOpenDraft || $[2] !== onRestoreDraft) {
309
312
  t1 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(DraftCard, {
310
313
  message,
311
- onOpenDraft
314
+ onOpenDraft,
315
+ onRestoreDraft
312
316
  }) }) });
313
317
  $[0] = message;
314
318
  $[1] = onOpenDraft;
315
- $[2] = t1;
316
- } else t1 = $[2];
319
+ $[2] = onRestoreDraft;
320
+ $[3] = t1;
321
+ } else t1 = $[3];
317
322
  return t1;
318
323
  }
319
324
  if (message.from === "stopped" || message.from === "failed") {
320
325
  const t1 = message.from === "stopped" ? `Stopped by ${message.sender.name}` : "Camox couldn’t finish this. Send your message again to retry.";
321
326
  let t2;
322
- if ($[3] !== t1) {
327
+ if ($[4] !== t1) {
323
328
  t2 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx("p", {
324
329
  className: "text-muted-foreground text-sm",
325
330
  children: t1
326
331
  }) }) });
327
- $[3] = t1;
328
- $[4] = t2;
329
- } else t2 = $[4];
332
+ $[4] = t1;
333
+ $[5] = t2;
334
+ } else t2 = $[5];
330
335
  return t2;
331
336
  }
332
337
  if (message.from === "agent") {
333
338
  let t1;
334
- if ($[5] !== message.text) {
339
+ if ($[6] !== message.text) {
335
340
  t1 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(ThreadMarkdown, { text: message.text }) }) });
336
- $[5] = message.text;
337
- $[6] = t1;
338
- } else t1 = $[6];
341
+ $[6] = message.text;
342
+ $[7] = t1;
343
+ } else t1 = $[7];
339
344
  return t1;
340
345
  }
341
346
  if (message.from === "push") {
342
347
  const commits = message.subjects.length;
343
348
  let t1;
344
- if ($[7] !== message.sender) {
349
+ if ($[8] !== message.sender) {
345
350
  t1 = /* @__PURE__ */ jsx(MessageAvatar, { children: /* @__PURE__ */ jsx(SenderAvatar, { sender: message.sender }) });
346
- $[7] = message.sender;
347
- $[8] = t1;
348
- } else t1 = $[8];
351
+ $[8] = message.sender;
352
+ $[9] = t1;
353
+ } else t1 = $[9];
349
354
  const t2 = `${message.sender.name} pushed ${commits} ${commits === 1 ? "commit" : "commits"}`;
350
355
  let t3;
351
- if ($[9] !== t2) {
356
+ if ($[10] !== t2) {
352
357
  t3 = /* @__PURE__ */ jsx(MessageHeader, {
353
358
  className: "text-muted-foreground text-xs",
354
359
  children: t2
355
360
  });
356
- $[9] = t2;
357
- $[10] = t3;
358
- } else t3 = $[10];
361
+ $[10] = t2;
362
+ $[11] = t3;
363
+ } else t3 = $[11];
359
364
  let t4;
360
- if ($[11] !== message.subjects) {
365
+ if ($[12] !== message.subjects) {
361
366
  t4 = message.subjects.map(_temp);
362
- $[11] = message.subjects;
363
- $[12] = t4;
364
- } else t4 = $[12];
367
+ $[12] = message.subjects;
368
+ $[13] = t4;
369
+ } else t4 = $[13];
365
370
  let t5;
366
- if ($[13] !== t4) {
371
+ if ($[14] !== t4) {
367
372
  t5 = /* @__PURE__ */ jsx("ul", {
368
373
  className: "flex flex-col gap-0.5",
369
374
  children: t4
370
375
  });
371
- $[13] = t4;
372
- $[14] = t5;
373
- } else t5 = $[14];
376
+ $[14] = t4;
377
+ $[15] = t5;
378
+ } else t5 = $[15];
374
379
  const t6 = PUSH_OUTCOMES[message.outcome];
375
380
  let t7;
376
- if ($[15] !== t6) {
381
+ if ($[16] !== t6) {
377
382
  t7 = /* @__PURE__ */ jsx("span", {
378
383
  className: "text-muted-foreground text-xs",
379
384
  children: t6
380
385
  });
381
- $[15] = t6;
382
- $[16] = t7;
383
- } else t7 = $[16];
386
+ $[16] = t6;
387
+ $[17] = t7;
388
+ } else t7 = $[17];
384
389
  let t8;
385
- if ($[17] !== t5 || $[18] !== t7) {
390
+ if ($[18] !== t5 || $[19] !== t7) {
386
391
  t8 = /* @__PURE__ */ jsxs("div", {
387
392
  "data-thread-push": true,
388
393
  className: DRAFT_CARD_CLASSES,
389
394
  children: [t5, t7]
390
395
  });
391
- $[17] = t5;
392
- $[18] = t7;
393
- $[19] = t8;
394
- } else t8 = $[19];
396
+ $[18] = t5;
397
+ $[19] = t7;
398
+ $[20] = t8;
399
+ } else t8 = $[20];
395
400
  let t9;
396
- if ($[20] !== t3 || $[21] !== t8) {
401
+ if ($[21] !== t3 || $[22] !== t8) {
397
402
  t9 = /* @__PURE__ */ jsxs(MessageContent, { children: [t3, t8] });
398
- $[20] = t3;
399
- $[21] = t8;
400
- $[22] = t9;
401
- } else t9 = $[22];
403
+ $[21] = t3;
404
+ $[22] = t8;
405
+ $[23] = t9;
406
+ } else t9 = $[23];
402
407
  let t10;
403
- if ($[23] !== t1 || $[24] !== t9) {
408
+ if ($[24] !== t1 || $[25] !== t9) {
404
409
  t10 = /* @__PURE__ */ jsxs(Message, { children: [t1, t9] });
405
- $[23] = t1;
406
- $[24] = t9;
407
- $[25] = t10;
408
- } else t10 = $[25];
410
+ $[24] = t1;
411
+ $[25] = t9;
412
+ $[26] = t10;
413
+ } else t10 = $[26];
409
414
  return t10;
410
415
  }
411
416
  if (message.from === "connectedAgent") {
@@ -415,13 +420,13 @@ function ThreadMessageRow(t0) {
415
420
  const t1 = `${sender} added context`;
416
421
  const t2 = client.verified ? void 0 : client.name;
417
422
  let t3;
418
- if ($[26] !== message.attachments) {
423
+ if ($[27] !== message.attachments) {
419
424
  t3 = message.attachments && /* @__PURE__ */ jsx(AttachmentThumbnails, { attachments: message.attachments });
420
- $[26] = message.attachments;
421
- $[27] = t3;
422
- } else t3 = $[27];
425
+ $[27] = message.attachments;
426
+ $[28] = t3;
427
+ } else t3 = $[28];
423
428
  let t4;
424
- if ($[28] !== message.text || $[29] !== t1 || $[30] !== t2 || $[31] !== t3) {
429
+ if ($[29] !== message.text || $[30] !== t1 || $[31] !== t2 || $[32] !== t3) {
425
430
  t4 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(CollapsedNote, {
426
431
  label: t1,
427
432
  hideLabel: "Hide the context",
@@ -429,117 +434,117 @@ function ThreadMessageRow(t0) {
429
434
  text: message.text,
430
435
  children: t3
431
436
  }) }) });
432
- $[28] = message.text;
433
- $[29] = t1;
434
- $[30] = t2;
435
- $[31] = t3;
436
- $[32] = t4;
437
- } else t4 = $[32];
437
+ $[29] = message.text;
438
+ $[30] = t1;
439
+ $[31] = t2;
440
+ $[32] = t3;
441
+ $[33] = t4;
442
+ } else t4 = $[33];
438
443
  return t4;
439
444
  }
440
445
  const t1 = client.verified ? void 0 : client.name;
441
446
  let t2;
442
- if ($[33] !== sender || $[34] !== t1) {
447
+ if ($[34] !== sender || $[35] !== t1) {
443
448
  t2 = /* @__PURE__ */ jsx(MessageHeader, {
444
449
  className: "text-muted-foreground text-xs",
445
450
  title: t1,
446
451
  children: sender
447
452
  });
448
- $[33] = sender;
449
- $[34] = t1;
450
- $[35] = t2;
451
- } else t2 = $[35];
453
+ $[34] = sender;
454
+ $[35] = t1;
455
+ $[36] = t2;
456
+ } else t2 = $[36];
452
457
  let t3;
453
- if ($[36] !== message.text) {
458
+ if ($[37] !== message.text) {
454
459
  t3 = /* @__PURE__ */ jsx(Bubble, {
455
460
  variant: "muted",
456
461
  className: "max-w-full",
457
462
  children: /* @__PURE__ */ jsx(BubbleContent, { children: /* @__PURE__ */ jsx(CroppedText, { text: message.text }) })
458
463
  });
459
- $[36] = message.text;
460
- $[37] = t3;
461
- } else t3 = $[37];
464
+ $[37] = message.text;
465
+ $[38] = t3;
466
+ } else t3 = $[38];
462
467
  let t4;
463
- if ($[38] !== message.attachments) {
468
+ if ($[39] !== message.attachments) {
464
469
  t4 = message.attachments && /* @__PURE__ */ jsx(AttachmentThumbnails, { attachments: message.attachments });
465
- $[38] = message.attachments;
466
- $[39] = t4;
467
- } else t4 = $[39];
470
+ $[39] = message.attachments;
471
+ $[40] = t4;
472
+ } else t4 = $[40];
468
473
  let t5;
469
- if ($[40] !== t2 || $[41] !== t3 || $[42] !== t4) {
474
+ if ($[41] !== t2 || $[42] !== t3 || $[43] !== t4) {
470
475
  t5 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsxs(MessageContent, { children: [
471
476
  t2,
472
477
  t3,
473
478
  t4
474
479
  ] }) });
475
- $[40] = t2;
476
- $[41] = t3;
477
- $[42] = t4;
478
- $[43] = t5;
479
- } else t5 = $[43];
480
+ $[41] = t2;
481
+ $[42] = t3;
482
+ $[43] = t4;
483
+ $[44] = t5;
484
+ } else t5 = $[44];
480
485
  return t5;
481
486
  }
482
487
  if (message.from === "brief") {
483
488
  let t1;
484
- if ($[44] !== message.text) {
489
+ if ($[45] !== message.text) {
485
490
  t1 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(CollapsedNote, {
486
491
  label: "Camox briefed the agent",
487
492
  hideLabel: "Hide the brief",
488
493
  text: message.text
489
494
  }) }) });
490
- $[44] = message.text;
491
- $[45] = t1;
492
- } else t1 = $[45];
495
+ $[45] = message.text;
496
+ $[46] = t1;
497
+ } else t1 = $[46];
493
498
  return t1;
494
499
  }
495
500
  if (message.from === "camox") {
496
501
  let t1;
497
- if ($[46] === Symbol.for("react.memo_cache_sentinel")) {
502
+ if ($[47] === Symbol.for("react.memo_cache_sentinel")) {
498
503
  t1 = /* @__PURE__ */ jsx(MessageHeader, {
499
504
  className: "text-muted-foreground text-xs",
500
505
  children: "Camox"
501
506
  });
502
- $[46] = t1;
503
- } else t1 = $[46];
507
+ $[47] = t1;
508
+ } else t1 = $[47];
504
509
  let t2;
505
- if ($[47] !== message.text) {
510
+ if ($[48] !== message.text) {
506
511
  t2 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsxs(MessageContent, { children: [t1, /* @__PURE__ */ jsx(Bubble, {
507
512
  variant: "muted",
508
513
  className: "max-w-full",
509
514
  children: /* @__PURE__ */ jsx(BubbleContent, { children: /* @__PURE__ */ jsx(CroppedText, { text: message.text }) })
510
515
  })] }) });
511
- $[47] = message.text;
512
- $[48] = t2;
513
- } else t2 = $[48];
516
+ $[48] = message.text;
517
+ $[49] = t2;
518
+ } else t2 = $[49];
514
519
  return t2;
515
520
  }
516
521
  let t1;
517
- if ($[49] !== message.sender) {
522
+ if ($[50] !== message.sender) {
518
523
  t1 = /* @__PURE__ */ jsx(MessageAvatar, { children: /* @__PURE__ */ jsx(SenderAvatar, { sender: message.sender }) });
519
- $[49] = message.sender;
520
- $[50] = t1;
521
- } else t1 = $[50];
524
+ $[50] = message.sender;
525
+ $[51] = t1;
526
+ } else t1 = $[51];
522
527
  let t2;
523
- if ($[51] !== message.text) {
528
+ if ($[52] !== message.text) {
524
529
  t2 = /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(Bubble, {
525
530
  align: "end",
526
531
  variant: "muted",
527
532
  className: "max-w-full",
528
533
  children: /* @__PURE__ */ jsx(BubbleContent, { children: /* @__PURE__ */ jsx(CroppedText, { text: message.text }) })
529
534
  }) });
530
- $[51] = message.text;
531
- $[52] = t2;
532
- } else t2 = $[52];
535
+ $[52] = message.text;
536
+ $[53] = t2;
537
+ } else t2 = $[53];
533
538
  let t3;
534
- if ($[53] !== t1 || $[54] !== t2) {
539
+ if ($[54] !== t1 || $[55] !== t2) {
535
540
  t3 = /* @__PURE__ */ jsxs(Message, {
536
541
  align: "end",
537
542
  children: [t1, t2]
538
543
  });
539
- $[53] = t1;
540
- $[54] = t2;
541
- $[55] = t3;
542
- } else t3 = $[55];
544
+ $[54] = t1;
545
+ $[55] = t2;
546
+ $[56] = t3;
547
+ } else t3 = $[56];
543
548
  return t3;
544
549
  }
545
550
  function _temp(subject, index) {
@@ -702,15 +707,10 @@ function AttachmentThumbnails(t0) {
702
707
  } else t7 = $[8];
703
708
  let t8;
704
709
  if ($[9] !== opened) {
705
- t8 = opened && /* @__PURE__ */ jsx("div", {
706
- className: "checkered absolute inset-0 flex items-center justify-center overflow-hidden p-6",
707
- children: /* @__PURE__ */ jsx("img", {
708
- src: opened.url,
709
- alt: opened.filename,
710
- className: "max-h-full max-w-full object-contain shadow-lg",
711
- draggable: false
712
- })
713
- });
710
+ t8 = opened && /* @__PURE__ */ jsx(ZoomableImage, {
711
+ src: opened.url,
712
+ alt: opened.filename
713
+ }, opened.url);
714
714
  $[9] = opened;
715
715
  $[10] = t8;
716
716
  } else t8 = $[10];
@@ -822,10 +822,11 @@ const DRAFT_CARD_CLASSES = "bg-muted/50 flex w-full flex-col items-start gap-0.5
822
822
  /**
823
823
  * The card of the draft the agent on Live handed the request off to, where its agent does the
824
824
  * work: it opens the draft. Once the draft ended, there's nothing to open: it says how it ended.
825
+ * While the draft is archived, it says so and offers to restore it (ADR 0046).
825
826
  */
826
827
  function DraftCard(t0) {
827
- const $ = c(15);
828
- const { message, onOpenDraft } = t0;
828
+ const $ = c(27);
829
+ const { message, onOpenDraft, onRestoreDraft } = t0;
829
830
  let t1;
830
831
  if ($[0] !== message.name) {
831
832
  t1 = /* @__PURE__ */ jsx("span", {
@@ -836,65 +837,115 @@ function DraftCard(t0) {
836
837
  $[1] = t1;
837
838
  } else t1 = $[1];
838
839
  const name = t1;
840
+ if (message.archived) {
841
+ let t2;
842
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
843
+ t2 = cn(DRAFT_CARD_CLASSES, "flex-row items-center gap-3");
844
+ $[2] = t2;
845
+ } else t2 = $[2];
846
+ let t3;
847
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
848
+ t3 = /* @__PURE__ */ jsx("span", {
849
+ className: "text-muted-foreground text-xs",
850
+ children: "Archived"
851
+ });
852
+ $[3] = t3;
853
+ } else t3 = $[3];
854
+ let t4;
855
+ if ($[4] !== name) {
856
+ t4 = /* @__PURE__ */ jsxs("div", {
857
+ className: "flex min-w-0 flex-1 flex-col gap-0.5",
858
+ children: [t3, name]
859
+ });
860
+ $[4] = name;
861
+ $[5] = t4;
862
+ } else t4 = $[5];
863
+ let t5;
864
+ if ($[6] !== message.draftId || $[7] !== onRestoreDraft) {
865
+ t5 = /* @__PURE__ */ jsx(Button, {
866
+ variant: "outline",
867
+ size: "sm",
868
+ onClick: () => onRestoreDraft?.(message.draftId),
869
+ children: "Restore"
870
+ });
871
+ $[6] = message.draftId;
872
+ $[7] = onRestoreDraft;
873
+ $[8] = t5;
874
+ } else t5 = $[8];
875
+ let t6;
876
+ if ($[9] !== t4 || $[10] !== t5) {
877
+ t6 = /* @__PURE__ */ jsxs("div", {
878
+ "data-thread-draft-card": true,
879
+ className: t2,
880
+ children: [t4, t5]
881
+ });
882
+ $[9] = t4;
883
+ $[10] = t5;
884
+ $[11] = t6;
885
+ } else t6 = $[11];
886
+ return t6;
887
+ }
839
888
  if (message.ended) {
840
889
  const t2 = message.ended === "published" ? "Published" : "Deleted";
841
890
  let t3;
842
- if ($[2] !== t2) {
891
+ if ($[12] !== t2) {
843
892
  t3 = /* @__PURE__ */ jsx("span", {
844
893
  className: "text-muted-foreground text-xs",
845
894
  children: t2
846
895
  });
847
- $[2] = t2;
848
- $[3] = t3;
849
- } else t3 = $[3];
896
+ $[12] = t2;
897
+ $[13] = t3;
898
+ } else t3 = $[13];
850
899
  let t4;
851
- if ($[4] !== name || $[5] !== t3) {
900
+ if ($[14] !== name || $[15] !== t3) {
852
901
  t4 = /* @__PURE__ */ jsxs("div", {
853
902
  "data-thread-draft-card": true,
854
903
  className: DRAFT_CARD_CLASSES,
855
904
  children: [t3, name]
856
905
  });
857
- $[4] = name;
858
- $[5] = t3;
859
- $[6] = t4;
860
- } else t4 = $[6];
906
+ $[14] = name;
907
+ $[15] = t3;
908
+ $[16] = t4;
909
+ } else t4 = $[16];
861
910
  return t4;
862
911
  }
863
912
  let t2;
864
- if ($[7] !== message.draftId || $[8] !== onOpenDraft) {
913
+ if ($[17] !== message.draftId || $[18] !== onOpenDraft) {
865
914
  t2 = () => onOpenDraft?.(message.draftId);
866
- $[7] = message.draftId;
867
- $[8] = onOpenDraft;
868
- $[9] = t2;
869
- } else t2 = $[9];
915
+ $[17] = message.draftId;
916
+ $[18] = onOpenDraft;
917
+ $[19] = t2;
918
+ } else t2 = $[19];
870
919
  let t3;
871
- let t4;
872
- if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
920
+ if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
873
921
  t3 = cn(DRAFT_CARD_CLASSES, "hover:bg-muted focus-visible:ring-ring transition-colors focus-visible:ring-2 focus-visible:outline-none");
874
- t4 = /* @__PURE__ */ jsx("span", {
922
+ $[20] = t3;
923
+ } else t3 = $[20];
924
+ const t4 = message.restored ? "Restored a draft" : "Started a draft";
925
+ let t5;
926
+ if ($[21] !== t4) {
927
+ t5 = /* @__PURE__ */ jsx("span", {
875
928
  className: "text-muted-foreground text-xs",
876
- children: "Started a draft"
929
+ children: t4
877
930
  });
878
- $[10] = t3;
879
- $[11] = t4;
880
- } else {
881
- t3 = $[10];
882
- t4 = $[11];
883
- }
884
- let t5;
885
- if ($[12] !== name || $[13] !== t2) {
886
- t5 = /* @__PURE__ */ jsxs("button", {
931
+ $[21] = t4;
932
+ $[22] = t5;
933
+ } else t5 = $[22];
934
+ let t6;
935
+ if ($[23] !== name || $[24] !== t2 || $[25] !== t5) {
936
+ t6 = /* @__PURE__ */ jsxs("button", {
887
937
  type: "button",
888
938
  "data-thread-draft-card": true,
889
939
  onClick: t2,
890
940
  className: t3,
891
- children: [t4, name]
941
+ children: [t5, name]
892
942
  });
893
- $[12] = name;
894
- $[13] = t2;
895
- $[14] = t5;
896
- } else t5 = $[14];
897
- return t5;
943
+ $[23] = name;
944
+ $[24] = t2;
945
+ $[25] = t5;
946
+ $[26] = t6;
947
+ } else t6 = $[26];
948
+ return t6;
898
949
  }
899
950
  function SenderAvatar(t0) {
900
951
  const $ = c(10);
@@ -11,6 +11,14 @@ function draftLabel(draft) {
11
11
  if (draft.name) return draft.name;
12
12
  return `${draft.createdBy.name}, ${dayFormat.format(draft.createdAt)}`;
13
13
  }
14
+ /**
15
+ * A Publication's name: its draft's, or for a draft published before it was named, who published
16
+ * it and when, e.g. "Rémi, Oct 13".
17
+ */
18
+ function publicationLabel(publication) {
19
+ if (publication.name) return publication.name;
20
+ return `${publication.publishedBy.name}, ${dayFormat.format(publication.publishedAt)}`;
21
+ }
14
22
  const relative = new Intl.RelativeTimeFormat(void 0, { numeric: "auto" });
15
23
  const units = [
16
24
  ["year", 31536e6],
@@ -26,7 +34,13 @@ function timeAgo(at, now = Date.now()) {
26
34
  for (const [unit, size] of units) if (elapsed >= size) return relative.format(-Math.round(elapsed / size), unit);
27
35
  return relative.format(0, "minute");
28
36
  }
37
+ const DAY_MS = 864e5;
38
+ /** How long until a moment, in whole days: "12 days", or "Less than a day" on its last day. */
39
+ function daysLeft(until, now = Date.now()) {
40
+ const days = Math.floor((until - now) / DAY_MS);
41
+ return days < 1 ? "Less than a day" : plural(days, "day");
42
+ }
29
43
  const plural = (count, word) => `${count} ${word}${count === 1 ? "" : "s"}`;
30
44
 
31
45
  //#endregion
32
- export { draftLabel, plural, timeAgo };
46
+ export { daysLeft, draftLabel, plural, publicationLabel, timeAgo };
@@ -5,6 +5,7 @@ function draftNoticeMessage(notice) {
5
5
  case "missing": return "This draft doesn't exist, so you're viewing Live.";
6
6
  case "forbidden": return "You can't open this draft, so you're viewing Live.";
7
7
  case "ended": return `${notice.endedBy.name} ${notice.outcome} this draft, so you're viewing Live.`;
8
+ case "archived": return `${notice.archivedBy.name} archived this draft, so you're viewing Live.`;
8
9
  }
9
10
  }
10
11