camox 0.48.0 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/core/layoutContext.d.ts +1 -0
  2. package/dist/features/canvas/sidebar/CanvasInspector.js +1 -1
  3. package/dist/features/content/ContentAssets.js +84 -88
  4. package/dist/features/preview/CamoxPreview.js +1 -1
  5. package/dist/features/preview/EditablePageExperience.js +17 -9
  6. package/dist/features/preview/components/BlockActionsPopover.js +11 -35
  7. package/dist/features/preview/components/FieldToolbar.js +1 -1
  8. package/dist/features/preview/components/MobilePreviewDrawer.js +6 -9
  9. package/dist/features/preview/components/PreviewPanel.js +10 -64
  10. package/dist/features/preview/components/PreviewToolbar.js +1 -1
  11. package/dist/features/preview/previewConstants.js +2 -8
  12. package/dist/features/preview/usePreviewViewportActions.js +1 -1
  13. package/dist/features/provider/AuthenticatedCamoxProvider.js +1 -1
  14. package/dist/features/provider/components/CommandPalette.js +2 -5
  15. package/dist/features/provider/signInShortcut.js +1 -2
  16. package/dist/features/provider/useAdminShortcuts.js +47 -53
  17. package/dist/features/routes/pageRuntime.d.ts +2 -1
  18. package/dist/features/routes/pageRuntime.js +27 -20
  19. package/dist/features/runtime/publicCache.js +83 -0
  20. package/dist/features/runtime/runtime.d.ts +13 -3
  21. package/dist/features/runtime/runtime.js +173 -79
  22. package/dist/features/runtime/worker.d.ts +5 -1
  23. package/dist/features/runtime/worker.js +20 -3
  24. package/dist/features/settings/AnalyticsSettings.js +622 -0
  25. package/dist/features/settings/CamoxSettings.js +95 -0
  26. package/dist/features/settings/FaviconSettings.js +254 -0
  27. package/dist/features/settings/ProjectNameSettings.js +145 -0
  28. package/dist/features/settings/SettingsPart.js +73 -0
  29. package/dist/features/settings/SocialProfilesSettings.js +245 -0
  30. package/dist/features/settings/useProjectMutation.js +61 -0
  31. package/dist/features/studio/components/DraftsControl.js +136 -131
  32. package/dist/features/studio/components/LocalePicker.js +178 -174
  33. package/dist/features/studio/components/Navbar.js +107 -66
  34. package/dist/features/studio/components/ProjectMenu.js +118 -170
  35. package/dist/features/studio/components/ReviewDraftSheet.js +1046 -990
  36. package/dist/features/studio/components/UserButton.js +1 -1
  37. package/dist/features/studio/routes.js +3 -1
  38. package/dist/features/studio/showInCanvas.js +129 -0
  39. package/dist/features/vite/definitionsSync.js +4 -5
  40. package/dist/features/vite/runtimeDev.js +32 -17
  41. package/dist/features/vite/staticAssetHeaders.js +52 -0
  42. package/dist/features/vite/vite.d.ts +1 -1
  43. package/dist/features/vite/vite.js +16 -4
  44. package/dist/lib/api-client-server.d.ts +1 -1
  45. package/dist/lib/api-client.d.ts +2 -1
  46. package/dist/lib/draft-scope.d.ts +1 -0
  47. package/dist/lib/locale-path.d.ts +3 -11
  48. package/dist/lib/locale-path.js +3 -27
  49. package/dist/lib/queries.js +7 -1
  50. package/dist/lib/shortcuts.js +29 -0
  51. package/dist/lib/studio-reads.d.ts +1 -0
  52. package/dist/lib/utils.js +1 -104
  53. package/dist/package.js +1 -1
  54. package/dist/studio.css +1 -1
  55. package/package.json +5 -4
  56. package/dist/features/studio/components/FaviconDialog.js +0 -318
  57. package/dist/features/studio/components/SocialProfilesDialog.js +0 -342
@@ -5,6 +5,7 @@ import { draftMutations } from "../../../lib/queries.js";
5
5
  import { localeLabel } from "../localeOptions.js";
6
6
  import { draftLabel, plural, timeAgo } from "../draftLabel.js";
7
7
  import { useRenameDraft } from "./RenameDraftDialog.js";
8
+ import { useShowInCanvas } from "../showInCanvas.js";
8
9
  import { c } from "react/compiler-runtime";
9
10
  import * as React from "react";
10
11
  import { CONFLICTS_CHANGED_ERROR, TRANSLATIONS_PENDING_ERROR } from "@camox/api-contract/drafts";
@@ -12,17 +13,21 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
13
  import { useMutation } from "@tanstack/react-query";
13
14
  import { Button } from "@camox/ui/button";
14
15
  import { Sheet, SheetContent, SheetDescription, SheetTitle } from "@camox/ui/sheet";
15
- import { Blocks, ChevronRight, CircleCheck, Database, FileText, History, Image, Info, Languages, OctagonX, PanelsTopLeft, Shapes, Trash2, TriangleAlert, Unlink } from "lucide-react";
16
+ import { CircleCheck, OctagonX, Replace, Trash2, Unlink } from "lucide-react";
16
17
  import { toast } from "@camox/ui/toaster";
18
+ import { Skeleton } from "@camox/ui/skeleton";
17
19
  import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@camox/ui/alert-dialog";
18
20
  import { Spinner } from "@camox/ui/spinner";
19
- import { Accordion, AccordionHeader, AccordionItem, AccordionPanel, AccordionTrigger } from "@camox/ui/accordion";
20
21
 
21
22
  //#region src/features/studio/components/ReviewDraftSheet.tsx
22
23
  const dateFormat = new Intl.DateTimeFormat(void 0, {
23
24
  month: "short",
24
25
  day: "numeric"
25
26
  });
27
+ const listFormat = new Intl.ListFormat("en", {
28
+ style: "long",
29
+ type: "conjunction"
30
+ });
26
31
  /** Where a subject sits: its page or layout, or the files, which belong to neither. */
27
32
  function ownerName(owner, entity) {
28
33
  if (!owner) return entity === "file" ? "Files" : "Elsewhere";
@@ -39,75 +44,52 @@ function problemPlace(problem) {
39
44
  if (!problem.owner && problem.entity !== "file") return null;
40
45
  return ownerName(problem.owner, problem.entity);
41
46
  }
42
- const groupKind = ({ owner, entity }) => {
43
- if (owner) return owner.kind;
44
- if (entity === "file") return "files";
45
- return entity === "locale" ? "languages" : "elsewhere";
46
- };
47
- /** Where a change is listed: its page or layout, the files, or the languages for a locale. */
48
- const placeOf = (change) => change.entity === "locale" ? "Languages" : ownerName(change.owner, change.entity);
49
- /** What a change is listed as: a locale added or removed by its name, anything else its label. */
50
- const changeLabel = (change) => change.entity === "locale" ? localeLabel(change.label) : change.label;
51
- const GROUPS = {
52
- page: {
53
- rank: 0,
54
- icon: FileText
55
- },
56
- layout: {
57
- rank: 1,
58
- icon: PanelsTopLeft
59
- },
60
- syncedBlock: {
61
- rank: 2,
62
- icon: Blocks
63
- },
64
- collection: {
65
- rank: 3,
66
- icon: Database
67
- },
68
- files: {
69
- rank: 4,
70
- icon: Image
71
- },
72
- languages: {
73
- rank: 5,
74
- icon: Languages
75
- },
76
- elsewhere: {
77
- rank: 6,
78
- icon: Shapes
79
- }
80
- };
81
- const CHANGES = {
82
- created: {
83
- sign: "+",
84
- className: "text-green-600 dark:text-green-400"
85
- },
86
- changed: {
87
- sign: "~",
88
- className: "text-muted-foreground"
89
- },
90
- deleted: {
91
- sign: "−",
92
- className: "text-destructive"
47
+ /**
48
+ * Where a conflict or lost change sits: its page, layout or collection, and its locale when the
49
+ * draft's change is in another than the default.
50
+ */
51
+ function placeInLocale(subject, defaultLocale) {
52
+ const place = ownerName(subject.owner, subject.entity);
53
+ if (!subject.locale || subject.locale === defaultLocale) return place;
54
+ return `${place} · ${localeLabel(subject.locale)}`;
55
+ }
56
+ /** Where in the Canvas a blocker is, or null when it sits on no page, like a definition. */
57
+ function blockerTarget(problem) {
58
+ if (problem.owner?.kind !== "page") return null;
59
+ return {
60
+ pageId: problem.owner.id,
61
+ locale: problem.locale,
62
+ blockId: problem.blockId,
63
+ itemId: problem.entity === "repeatableItem" ? problem.id : null,
64
+ field: problem.blockId && problem.field ? {
65
+ name: problem.field,
66
+ kind: problem.fieldKind
67
+ } : null
68
+ };
69
+ }
70
+ const isImage = (problem) => problem.fieldKind === "Image" || problem.fieldKind === "ImageList";
71
+ /** What a blocker's action does, named by the fix where it's obvious. */
72
+ function blockerActionLabel(problem) {
73
+ switch (problem.code) {
74
+ case "emptyRequiredFile": return isImage(problem) ? "Choose an image" : "Choose a file";
75
+ case "missingFile":
76
+ case "unacceptedFileType": return isImage(problem) ? "Choose another image" : "Choose another file";
77
+ case "emptyRequiredReference": return "Choose a record";
78
+ case "danglingReference": return "Choose another record";
79
+ case "danglingPageLink": return "Fix the link";
80
+ case "duplicatePath": return "Fix the path";
81
+ case "missingMetaTitle": return "Write a meta title";
82
+ default: return "Show in Canvas";
93
83
  }
94
- };
84
+ }
95
85
  const TONES = {
96
86
  danger: {
97
87
  card: "border-destructive/30 bg-destructive/5",
98
- icon: "bg-destructive/10 text-destructive"
88
+ icon: "text-destructive"
99
89
  },
100
90
  warning: {
101
91
  card: "border-amber-500/30 bg-amber-500/5",
102
- icon: "bg-amber-500/15 text-amber-600 dark:text-amber-400"
103
- },
104
- success: {
105
- card: "border-green-500/30 bg-green-500/5",
106
- icon: "bg-green-500/15 text-green-600 dark:text-green-400"
107
- },
108
- neutral: {
109
- card: "bg-muted/40",
110
- icon: "bg-muted text-muted-foreground"
92
+ icon: "text-amber-600 dark:text-amber-400"
111
93
  }
112
94
  };
113
95
  /** A conflict as Live's version of an entity in a locale, to tell a new one from those shown. */
@@ -117,697 +99,768 @@ const conflictKey = (conflict) => JSON.stringify([
117
99
  conflict.locale,
118
100
  conflict.liveVersion
119
101
  ]);
120
- /** Who made Live's version of a conflicting entity: a member, a release, or nobody known. */
121
- function changedBy(conflict) {
122
- if (conflict.release) return " by a release";
123
- if (conflict.publishedBy) return ` by ${conflict.publishedBy.name}`;
124
- return "";
125
- }
126
102
  const LOST_REASONS = {
127
- parentGone: "What it belongs to is gone from Live and from this draft, so it's dropped.",
128
- writtenAfterDeletion: "This draft deletes what it was added to, so it goes too."
103
+ parentGone: "What it belongs to is gone from Live and from this draft, so publishing drops this change.",
104
+ writtenAfterDeletion: "This draft deletes what it was added to, so publishing deletes it too."
129
105
  };
130
- /** The verdict at the top of the review: can this draft go to Live, and is there a catch? */
131
- function Verdict(t0) {
132
- const $ = c(23);
133
- const { preview } = t0;
134
- const { blockers, conflicts, lost } = preview;
135
- const catches = conflicts.length + lost.length;
136
- let t1;
137
- if ($[0] !== blockers.length || $[1] !== catches) {
138
- t1 = blockers.length ? [
139
- "danger",
140
- OctagonX,
141
- "Not ready to publish",
142
- `Fix ${blockers.length === 1 ? "this problem" : `these ${blockers.length} problems`} in the draft first.`
143
- ] : catches ? [
144
- "warning",
145
- TriangleAlert,
146
- `Ready, with ${plural(catches, "thing")} to know`,
147
- "Publishing replaces Live's version wherever the two differ."
148
- ] : [
149
- "success",
150
- CircleCheck,
151
- "Ready to publish",
152
- "Nothing on Live changed since this draft did."
153
- ];
154
- $[0] = blockers.length;
155
- $[1] = catches;
156
- $[2] = t1;
157
- } else t1 = $[2];
158
- const [tone, Icon, title, description] = t1;
159
- const t2 = TONES[tone];
160
- let t3;
161
- if ($[3] !== t2.card) {
162
- t3 = cn("flex gap-3 rounded-xl border p-4", t2.card);
163
- $[3] = t2.card;
164
- $[4] = t3;
165
- } else t3 = $[4];
166
- const t4 = TONES[tone];
167
- let t5;
168
- if ($[5] !== t4.icon) {
169
- t5 = cn("flex size-9 shrink-0 items-center justify-center rounded-lg", t4.icon);
170
- $[5] = t4.icon;
171
- $[6] = t5;
172
- } else t5 = $[6];
173
- let t6;
174
- if ($[7] !== Icon) {
175
- t6 = /* @__PURE__ */ jsx(Icon, { className: "size-5" });
176
- $[7] = Icon;
177
- $[8] = t6;
178
- } else t6 = $[8];
179
- let t7;
180
- if ($[9] !== t5 || $[10] !== t6) {
181
- t7 = /* @__PURE__ */ jsx("span", {
182
- className: t5,
183
- children: t6
184
- });
185
- $[9] = t5;
186
- $[10] = t6;
187
- $[11] = t7;
188
- } else t7 = $[11];
189
- let t8;
190
- if ($[12] !== title) {
191
- t8 = /* @__PURE__ */ jsx("p", {
192
- className: "font-medium",
193
- children: title
194
- });
195
- $[12] = title;
196
- $[13] = t8;
197
- } else t8 = $[13];
198
- let t9;
199
- if ($[14] !== description) {
200
- t9 = /* @__PURE__ */ jsx("p", {
201
- className: "text-foreground/70 text-sm",
202
- children: description
203
- });
204
- $[14] = description;
205
- $[15] = t9;
206
- } else t9 = $[15];
207
- let t10;
208
- if ($[16] !== t8 || $[17] !== t9) {
209
- t10 = /* @__PURE__ */ jsxs("div", {
210
- className: "flex flex-col gap-0.5",
211
- children: [t8, t9]
212
- });
213
- $[16] = t8;
214
- $[17] = t9;
215
- $[18] = t10;
216
- } else t10 = $[18];
217
- let t11;
218
- if ($[19] !== t10 || $[20] !== t3 || $[21] !== t7) {
219
- t11 = /* @__PURE__ */ jsxs("div", {
220
- className: t3,
221
- children: [t7, t10]
222
- });
223
- $[19] = t10;
224
- $[20] = t3;
225
- $[21] = t7;
226
- $[22] = t11;
227
- } else t11 = $[22];
228
- return t11;
229
- }
230
- const INSIGHT_LIST = "bg-background divide-y overflow-hidden rounded-lg border";
231
- function Insight(t0) {
232
- const $ = c(23);
233
- const { tone, icon: Icon, title, hint, count, children } = t0;
106
+ /**
107
+ * A card for something to know before publishing: blockers in red, conflicts and lost changes in
108
+ * amber.
109
+ */
110
+ function Card(t0) {
111
+ const $ = c(22);
112
+ const { tone, icon: Icon, title, action, children } = t0;
234
113
  const t1 = TONES[tone];
235
114
  let t2;
236
- if ($[0] !== t1.icon) {
237
- t2 = cn("flex size-6 shrink-0 items-center justify-center rounded-md", t1.icon);
238
- $[0] = t1.icon;
115
+ if ($[0] !== t1.card) {
116
+ t2 = cn("flex items-start gap-2 rounded-lg border p-3", t1.card);
117
+ $[0] = t1.card;
239
118
  $[1] = t2;
240
119
  } else t2 = $[1];
241
- let t3;
242
- if ($[2] !== Icon) {
243
- t3 = /* @__PURE__ */ jsx(Icon, { className: "size-3.5" });
244
- $[2] = Icon;
245
- $[3] = t3;
246
- } else t3 = $[3];
120
+ const t3 = TONES[tone];
247
121
  let t4;
248
- if ($[4] !== t2 || $[5] !== t3) {
249
- t4 = /* @__PURE__ */ jsx("span", {
250
- className: t2,
251
- children: t3
252
- });
253
- $[4] = t2;
254
- $[5] = t3;
255
- $[6] = t4;
256
- } else t4 = $[6];
122
+ if ($[2] !== t3.icon) {
123
+ t4 = cn("mt-0.5 size-4 shrink-0", t3.icon);
124
+ $[2] = t3.icon;
125
+ $[3] = t4;
126
+ } else t4 = $[3];
257
127
  let t5;
128
+ if ($[4] !== Icon || $[5] !== t4) {
129
+ t5 = /* @__PURE__ */ jsx(Icon, { className: t4 });
130
+ $[4] = Icon;
131
+ $[5] = t4;
132
+ $[6] = t5;
133
+ } else t5 = $[6];
134
+ let t6;
258
135
  if ($[7] !== title) {
259
- t5 = /* @__PURE__ */ jsx("h3", {
136
+ t6 = /* @__PURE__ */ jsx("p", {
260
137
  className: "text-sm font-medium",
138
+ "data-card-title": true,
261
139
  children: title
262
140
  });
263
141
  $[7] = title;
264
- $[8] = t5;
265
- } else t5 = $[8];
266
- let t6;
267
- if ($[9] !== count) {
268
- t6 = /* @__PURE__ */ jsx("span", {
269
- className: "text-muted-foreground bg-muted rounded-full px-1.5 text-xs tabular-nums",
270
- children: count
271
- });
272
- $[9] = count;
273
- $[10] = t6;
274
- } else t6 = $[10];
142
+ $[8] = t6;
143
+ } else t6 = $[8];
275
144
  let t7;
276
- if ($[11] !== t4 || $[12] !== t5 || $[13] !== t6) {
277
- t7 = /* @__PURE__ */ jsxs("div", {
278
- className: "flex items-center gap-2",
279
- children: [
280
- t4,
281
- t5,
282
- t6
283
- ]
145
+ if ($[9] !== children) {
146
+ t7 = /* @__PURE__ */ jsx("div", {
147
+ className: "text-muted-foreground text-sm",
148
+ children
284
149
  });
285
- $[11] = t4;
286
- $[12] = t5;
287
- $[13] = t6;
288
- $[14] = t7;
289
- } else t7 = $[14];
150
+ $[9] = children;
151
+ $[10] = t7;
152
+ } else t7 = $[10];
290
153
  let t8;
291
- if ($[15] !== hint) {
292
- t8 = /* @__PURE__ */ jsx("p", {
293
- className: "text-muted-foreground text-xs",
294
- children: hint
154
+ if ($[11] !== action) {
155
+ t8 = action && /* @__PURE__ */ jsx("div", {
156
+ className: "pt-1",
157
+ children: action
295
158
  });
296
- $[15] = hint;
297
- $[16] = t8;
298
- } else t8 = $[16];
159
+ $[11] = action;
160
+ $[12] = t8;
161
+ } else t8 = $[12];
299
162
  let t9;
300
- if ($[17] !== children) {
301
- t9 = /* @__PURE__ */ jsx("ul", {
302
- className: INSIGHT_LIST,
303
- children
304
- });
305
- $[17] = children;
306
- $[18] = t9;
307
- } else t9 = $[18];
308
- let t10;
309
- if ($[19] !== t7 || $[20] !== t8 || $[21] !== t9) {
310
- t10 = /* @__PURE__ */ jsxs("section", {
311
- className: "flex flex-col gap-2",
163
+ if ($[13] !== t6 || $[14] !== t7 || $[15] !== t8) {
164
+ t9 = /* @__PURE__ */ jsxs("div", {
165
+ className: "flex min-w-0 flex-1 flex-col gap-1",
312
166
  children: [
167
+ t6,
313
168
  t7,
314
- t8,
315
- t9
169
+ t8
316
170
  ]
317
171
  });
318
- $[19] = t7;
319
- $[20] = t8;
320
- $[21] = t9;
321
- $[22] = t10;
322
- } else t10 = $[22];
323
- return t10;
324
- }
325
- function InsightItem(t0) {
326
- const $ = c(12);
327
- const { label, place, detail } = t0;
328
- let t1;
329
- if ($[0] !== label) {
330
- t1 = /* @__PURE__ */ jsx("span", {
331
- className: "truncate text-sm font-medium",
332
- children: label
333
- });
334
- $[0] = label;
335
- $[1] = t1;
336
- } else t1 = $[1];
337
- let t2;
338
- if ($[2] !== place) {
339
- t2 = place && /* @__PURE__ */ jsx("span", {
340
- className: "text-muted-foreground truncate text-xs",
341
- children: place
342
- });
343
- $[2] = place;
344
- $[3] = t2;
345
- } else t2 = $[3];
346
- let t3;
347
- if ($[4] !== t1 || $[5] !== t2) {
348
- t3 = /* @__PURE__ */ jsxs("div", {
349
- className: "flex min-w-0 items-baseline gap-2",
350
- children: [t1, t2]
351
- });
352
- $[4] = t1;
353
- $[5] = t2;
354
- $[6] = t3;
355
- } else t3 = $[6];
356
- let t4;
357
- if ($[7] !== detail) {
358
- t4 = /* @__PURE__ */ jsx("p", {
359
- className: "text-muted-foreground text-sm",
360
- children: detail
361
- });
362
- $[7] = detail;
363
- $[8] = t4;
364
- } else t4 = $[8];
365
- let t5;
366
- if ($[9] !== t3 || $[10] !== t4) {
367
- t5 = /* @__PURE__ */ jsxs("li", {
368
- className: "flex flex-col gap-0.5 px-3 py-2.5",
369
- children: [t3, t4]
172
+ $[13] = t6;
173
+ $[14] = t7;
174
+ $[15] = t8;
175
+ $[16] = t9;
176
+ } else t9 = $[16];
177
+ let t10;
178
+ if ($[17] !== t2 || $[18] !== t5 || $[19] !== t9 || $[20] !== tone) {
179
+ t10 = /* @__PURE__ */ jsxs("li", {
180
+ className: t2,
181
+ "data-card": tone,
182
+ children: [t5, t9]
370
183
  });
371
- $[9] = t3;
372
- $[10] = t4;
373
- $[11] = t5;
374
- } else t5 = $[11];
375
- return t5;
184
+ $[17] = t2;
185
+ $[18] = t5;
186
+ $[19] = t9;
187
+ $[20] = tone;
188
+ $[21] = t10;
189
+ } else t10 = $[21];
190
+ return t10;
376
191
  }
377
- /** From how many problems sharing a message they read as one item, naming each subject. */
192
+ /** From how many blockers sharing a message they fold into one card, naming each subject. */
378
193
  const SHARED_MESSAGE_MIN = 3;
379
194
  /**
380
- * Problems, with those sharing a message folded into one item: a draft can hold dozens of
381
- * definitions to release, and the message is the same for each.
195
+ * One card per blocker, saying what's wrong and where. Blockers sharing a message fold into one
196
+ * card naming each: a development draft can hold dozens of definitions to release, and the
197
+ * message is the same for each. A blocker on a page has an action that shows it in the Canvas.
382
198
  */
383
- function ProblemItems({ problems }) {
199
+ function BlockerCards({ blockers, onShow }) {
384
200
  const byMessage = /* @__PURE__ */ new Map();
385
- for (const problem of problems) byMessage.set(problem.message, [...byMessage.get(problem.message) ?? [], problem]);
201
+ for (const problem of blockers) byMessage.set(problem.message, [...byMessage.get(problem.message) ?? [], problem]);
386
202
  return [...byMessage].flatMap(([message, shared]) => {
387
- if (shared.length < SHARED_MESSAGE_MIN) return shared.map((problem) => /* @__PURE__ */ jsx(InsightItem, {
388
- label: problem.label,
389
- place: problemPlace(problem),
390
- detail: problem.message
391
- }, `${problem.code}:${problem.id}:${problem.field}`));
392
- return [/* @__PURE__ */ jsxs("li", {
393
- className: "flex flex-col gap-2 px-3 py-2.5",
394
- children: [/* @__PURE__ */ jsx("p", {
395
- className: "text-sm font-medium",
396
- children: message
397
- }), /* @__PURE__ */ jsx("ul", {
398
- className: "flex flex-wrap gap-1",
203
+ if (shared.length < SHARED_MESSAGE_MIN) return shared.map((problem) => {
204
+ const place = problemPlace(problem);
205
+ const target = blockerTarget(problem);
206
+ return /* @__PURE__ */ jsx(Card, {
207
+ tone: "danger",
208
+ icon: OctagonX,
209
+ title: problem.message,
210
+ action: target && /* @__PURE__ */ jsx(Button, {
211
+ variant: "outline",
212
+ size: "sm",
213
+ onClick: () => onShow(target),
214
+ children: blockerActionLabel(problem)
215
+ }),
216
+ children: place ? `${problem.label} · ${place}` : problem.label
217
+ }, `${problem.code}:${problem.id}:${problem.locale}:${problem.field}`);
218
+ });
219
+ return [/* @__PURE__ */ jsx(Card, {
220
+ tone: "danger",
221
+ icon: OctagonX,
222
+ title: message,
223
+ children: /* @__PURE__ */ jsx("ul", {
224
+ className: "flex flex-wrap gap-1 pt-0.5",
399
225
  children: shared.map((problem) => {
400
226
  const place = problemPlace(problem);
401
227
  return /* @__PURE__ */ jsxs("li", {
402
- className: "bg-muted text-muted-foreground rounded-md px-1.5 py-0.5 text-xs",
228
+ className: "bg-background rounded-md border px-1.5 py-0.5 text-xs",
403
229
  children: [/* @__PURE__ */ jsx("span", {
404
230
  className: "text-foreground",
405
231
  children: problem.label
406
232
  }), place && ` · ${place}`]
407
- }, `${problem.code}:${problem.id}:${problem.field}`);
233
+ }, `${problem.code}:${problem.id}:${problem.locale}:${problem.field}`);
408
234
  })
409
- })]
235
+ })
410
236
  }, `shared:${message}`)];
411
237
  });
412
238
  }
413
- /** What publishing will do, in the order ADR 0009 lists it. */
414
- function Insights(t0) {
415
- const $ = c(13);
416
- const { preview } = t0;
417
- const { blockers, conflicts, lost, warnings } = preview;
239
+ /** Who made Live's version of a conflict, as a sentence's subject: a member, a release, or none. */
240
+ function whoChanged(conflict) {
241
+ if (conflict.release) return "A release";
242
+ return conflict.publishedBy?.name ?? null;
243
+ }
244
+ /** Whose edit a conflict replaces, as its card's title: a member's, a release's, or nobody's. */
245
+ function conflictTitle(conflict) {
246
+ if (conflict.liveVersion === null) return `Brings back the ${conflict.label}`;
247
+ if (conflict.release) return `Replaces a release's change to the ${conflict.label}`;
248
+ if (conflict.publishedBy) return `Replaces ${conflict.publishedBy.name}'s edit to the ${conflict.label}`;
249
+ return `Replaces an edit to the ${conflict.label}`;
250
+ }
251
+ /** What publishing does to a conflict's entity, and when Live changed it. */
252
+ function conflictDetail(conflict, draftDeletes) {
253
+ const who = whoChanged(conflict);
254
+ const when = conflict.publishedAt ? ` on ${dateFormat.format(conflict.publishedAt)}` : "";
255
+ if (conflict.liveVersion === null) return `${who ? `${who} deleted it from Live${when}.` : `Live deleted it${when}.`} Publishing brings it back.`;
256
+ const changed = who ? `${who} changed it on Live${when}.` : `Live changed it${when}.`;
257
+ return draftDeletes ? `${changed} This draft deletes it, so publishing deletes it anyway.` : `${changed} Publishing replaces it with this draft's version.`;
258
+ }
259
+ /** Who made Live's version of a conflict and when, labelling Live's values: "On Live now · Ada, Oct 13". */
260
+ function liveValuesLabel(conflict) {
261
+ const made = [whoChanged(conflict), conflict.publishedAt ? dateFormat.format(conflict.publishedAt) : null].filter((part) => part !== null);
262
+ return made.length > 0 ? `On Live now · ${made.join(", ")}` : "On Live now";
263
+ }
264
+ /**
265
+ * The fields a conflict overwrites: Live's value crossed out, above the draft's, and how many
266
+ * more fields differ.
267
+ */
268
+ function ConflictFields(t0) {
269
+ const $ = c(12);
270
+ const { conflict } = t0;
271
+ if (conflict.fields.length === 0) return null;
418
272
  let t1;
419
- if ($[0] !== blockers) {
420
- t1 = blockers.length > 0 && /* @__PURE__ */ jsx("ul", {
421
- className: INSIGHT_LIST,
422
- children: /* @__PURE__ */ jsx(ProblemItems, { problems: blockers })
423
- });
424
- $[0] = blockers;
273
+ if ($[0] !== conflict) {
274
+ t1 = liveValuesLabel(conflict);
275
+ $[0] = conflict;
425
276
  $[1] = t1;
426
277
  } else t1 = $[1];
278
+ const liveLabel = t1;
427
279
  let t2;
428
- if ($[2] !== conflicts) {
429
- t2 = conflicts.length > 0 && /* @__PURE__ */ jsx(Insight, {
430
- tone: "warning",
431
- icon: History,
432
- title: "Changed on Live since this draft",
433
- hint: "This draft's version replaces Live's. Check nothing important gets overwritten.",
434
- count: conflicts.length,
435
- children: conflicts.map(_temp)
436
- });
437
- $[2] = conflicts;
438
- $[3] = t2;
439
- } else t2 = $[3];
280
+ if ($[2] !== conflict.fields || $[3] !== liveLabel) {
281
+ let t3;
282
+ if ($[5] !== liveLabel) {
283
+ t3 = (t4) => {
284
+ const { field, live, draft } = t4;
285
+ return /* @__PURE__ */ jsxs("div", {
286
+ className: "bg-background flex flex-col gap-1 rounded-md border p-2",
287
+ "data-conflict-field": true,
288
+ children: [
289
+ /* @__PURE__ */ jsx("p", {
290
+ className: "text-foreground text-xs font-medium",
291
+ "data-field-title": true,
292
+ children: field
293
+ }),
294
+ /* @__PURE__ */ jsxs("div", {
295
+ className: "flex flex-col",
296
+ children: [/* @__PURE__ */ jsx("span", {
297
+ className: "text-xs",
298
+ children: liveLabel
299
+ }), /* @__PURE__ */ jsx("del", {
300
+ className: "break-words",
301
+ "data-live-value": true,
302
+ children: live
303
+ })]
304
+ }),
305
+ /* @__PURE__ */ jsxs("div", {
306
+ className: "flex flex-col",
307
+ children: [/* @__PURE__ */ jsx("span", {
308
+ className: "text-xs",
309
+ children: "This draft"
310
+ }), /* @__PURE__ */ jsx("span", {
311
+ className: "text-foreground break-words",
312
+ "data-draft-value": true,
313
+ children: draft
314
+ })]
315
+ })
316
+ ]
317
+ }, field);
318
+ };
319
+ $[5] = liveLabel;
320
+ $[6] = t3;
321
+ } else t3 = $[6];
322
+ t2 = conflict.fields.map(t3);
323
+ $[2] = conflict.fields;
324
+ $[3] = liveLabel;
325
+ $[4] = t2;
326
+ } else t2 = $[4];
440
327
  let t3;
441
- if ($[4] !== lost) {
442
- t3 = lost.length > 0 && /* @__PURE__ */ jsx(Insight, {
443
- tone: "warning",
444
- icon: Unlink,
445
- title: "Changes that will be lost",
446
- hint: "These can't be kept, and can't be brought back after publishing.",
447
- count: lost.length,
448
- children: lost.map(_temp2)
328
+ if ($[7] !== conflict.moreFields) {
329
+ t3 = conflict.moreFields > 0 && /* @__PURE__ */ jsxs("p", {
330
+ className: "text-xs",
331
+ children: ["And ", plural(conflict.moreFields, "more field")]
449
332
  });
450
- $[4] = lost;
451
- $[5] = t3;
452
- } else t3 = $[5];
333
+ $[7] = conflict.moreFields;
334
+ $[8] = t3;
335
+ } else t3 = $[8];
453
336
  let t4;
454
- if ($[6] !== warnings) {
455
- t4 = warnings.length > 0 && /* @__PURE__ */ jsx(Insight, {
456
- tone: "neutral",
457
- icon: Info,
458
- title: "Already on Live",
459
- hint: "These don't block publishing, but are worth fixing.",
460
- count: warnings.length,
461
- children: /* @__PURE__ */ jsx(ProblemItems, { problems: warnings })
337
+ if ($[9] !== t2 || $[10] !== t3) {
338
+ t4 = /* @__PURE__ */ jsxs("div", {
339
+ className: "flex flex-col gap-2 pt-1",
340
+ children: [t2, t3]
462
341
  });
463
- $[6] = warnings;
464
- $[7] = t4;
465
- } else t4 = $[7];
466
- let t5;
467
- if ($[8] !== t1 || $[9] !== t2 || $[10] !== t3 || $[11] !== t4) {
468
- t5 = /* @__PURE__ */ jsxs(Fragment, { children: [
469
- t1,
470
- t2,
471
- t3,
472
- t4
473
- ] });
474
- $[8] = t1;
475
342
  $[9] = t2;
476
343
  $[10] = t3;
477
344
  $[11] = t4;
478
- $[12] = t5;
479
- } else t5 = $[12];
480
- return t5;
345
+ } else t4 = $[11];
346
+ return t4;
481
347
  }
482
- function _temp2(change) {
483
- return /* @__PURE__ */ jsx(InsightItem, {
484
- label: change.label,
485
- place: ownerName(change.owner, change.entity),
486
- detail: LOST_REASONS[change.reason]
487
- }, change.id);
488
- }
489
- function _temp(conflict) {
490
- return /* @__PURE__ */ jsx(InsightItem, {
491
- label: conflict.label,
492
- place: ownerName(conflict.owner, conflict.entity),
493
- detail: /* @__PURE__ */ jsxs(Fragment, { children: [
494
- conflict.liveVersion === null ? "Deleted" : "Changed",
495
- changedBy(conflict),
496
- conflict.publishedAt ? `, ${dateFormat.format(conflict.publishedAt)}` : ""
497
- ] })
498
- }, conflict.id);
499
- }
500
- /** Changes grouped by where they're listed: pages first, then layouts, then collections. */
501
- function placesOf(changes) {
502
- const places = /* @__PURE__ */ new Map();
503
- const sorted = [...changes].sort((a, b) => GROUPS[groupKind(a)].rank - GROUPS[groupKind(b)].rank);
504
- for (const change of sorted) {
505
- const name = placeOf(change);
506
- const place = places.get(name) ?? {
507
- kind: groupKind(change),
508
- changes: []
509
- };
510
- place.changes.push(change);
511
- places.set(name, place);
512
- }
513
- return places;
348
+ /** Whose version of a conflict's entity Live holds, for its "Use … version instead" action. */
349
+ function liveVersionName(conflict) {
350
+ if (conflict.release) return "a release's";
351
+ if (conflict.publishedBy) return `${conflict.publishedBy.name}'s`;
352
+ return "Live's";
514
353
  }
515
354
  /**
516
- * Changes grouped by locale, the default locale first, then what's stored once, like files,
517
- * under no locale. A draft changing only its default locale names no locale at all.
355
+ * Drops the draft's change to a conflict's entity, so the draft reads Live's version again, then
356
+ * reads the review again: the conflict is gone, and the preview has a new token.
518
357
  */
519
- function localesOf(changes, defaultLocale) {
520
- const tags = [...new Set(changes.flatMap((change) => change.locale ?? []))];
521
- if (defaultLocale ? tags.every((tag) => tag === defaultLocale) : tags.length <= 1) return [{
522
- locale: null,
523
- places: placesOf(changes)
524
- }];
525
- const rank = (tag) => tag === defaultLocale ? 0 : tag === null ? 2 : 1;
526
- return [...tags, null].sort((a, b) => rank(a) - rank(b) || localeLabel(a ?? "").localeCompare(localeLabel(b ?? ""))).map((locale) => ({
527
- locale,
528
- places: placesOf(changes.filter((change) => change.locale === locale))
529
- })).filter(({ places }) => places.size > 0);
358
+ function UseLiveVersionButton(t0) {
359
+ const $ = c(20);
360
+ const { projectId, conflict, onUsed } = t0;
361
+ let t1;
362
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
363
+ t1 = draftMutations.revertToLive();
364
+ $[0] = t1;
365
+ } else t1 = $[0];
366
+ let t2;
367
+ if ($[1] !== onUsed) {
368
+ t2 = (error) => {
369
+ toast.error(error.message || "Could not use Live's version");
370
+ onUsed();
371
+ };
372
+ $[1] = onUsed;
373
+ $[2] = t2;
374
+ } else t2 = $[2];
375
+ let t3;
376
+ if ($[3] !== onUsed || $[4] !== t2) {
377
+ t3 = {
378
+ ...t1,
379
+ onSuccess: onUsed,
380
+ onError: t2
381
+ };
382
+ $[3] = onUsed;
383
+ $[4] = t2;
384
+ $[5] = t3;
385
+ } else t3 = $[5];
386
+ const revert = useMutation(t3);
387
+ const t4 = revert.isPending;
388
+ let t5;
389
+ if ($[6] !== conflict.entity || $[7] !== conflict.id || $[8] !== projectId || $[9] !== revert) {
390
+ t5 = () => revert.mutate({
391
+ projectId,
392
+ entity: conflict.entity,
393
+ id: conflict.id
394
+ });
395
+ $[6] = conflict.entity;
396
+ $[7] = conflict.id;
397
+ $[8] = projectId;
398
+ $[9] = revert;
399
+ $[10] = t5;
400
+ } else t5 = $[10];
401
+ let t6;
402
+ if ($[11] !== revert.isPending) {
403
+ t6 = revert.isPending ? /* @__PURE__ */ jsx(Spinner, {}) : null;
404
+ $[11] = revert.isPending;
405
+ $[12] = t6;
406
+ } else t6 = $[12];
407
+ let t7;
408
+ if ($[13] !== conflict) {
409
+ t7 = liveVersionName(conflict);
410
+ $[13] = conflict;
411
+ $[14] = t7;
412
+ } else t7 = $[14];
413
+ let t8;
414
+ if ($[15] !== revert.isPending || $[16] !== t5 || $[17] !== t6 || $[18] !== t7) {
415
+ t8 = /* @__PURE__ */ jsxs(Button, {
416
+ variant: "outline",
417
+ size: "sm",
418
+ className: "mt-1",
419
+ disabled: t4,
420
+ onClick: t5,
421
+ children: [
422
+ t6,
423
+ "Use ",
424
+ t7,
425
+ " version instead"
426
+ ]
427
+ });
428
+ $[15] = revert.isPending;
429
+ $[16] = t5;
430
+ $[17] = t6;
431
+ $[18] = t7;
432
+ $[19] = t8;
433
+ } else t8 = $[19];
434
+ return t8;
530
435
  }
531
- /** The changes listed in one place. */
532
- function Place(t0) {
533
- const $ = c(12);
534
- const { name, place } = t0;
535
- const Icon = GROUPS[place.kind].icon;
436
+ /** Blockers first, then conflicts, then lost changes: one card each, with no section heading. */
437
+ function Cards(t0) {
438
+ const $ = c(25);
439
+ const { projectId, preview, onChanged, onShow } = t0;
440
+ const { blockers, conflicts, lost, changes, defaultLocale } = preview;
441
+ if (blockers.length + conflicts.length + lost.length === 0) return null;
536
442
  let t1;
537
- if ($[0] !== Icon) {
538
- t1 = /* @__PURE__ */ jsx(Icon, { className: "size-3.5" });
539
- $[0] = Icon;
443
+ if ($[0] !== changes) {
444
+ t1 = new Set(changes.filter(_temp).map(_temp2));
445
+ $[0] = changes;
540
446
  $[1] = t1;
541
447
  } else t1 = $[1];
448
+ const deleted = t1;
542
449
  let t2;
543
- if ($[2] !== name || $[3] !== t1) {
544
- t2 = /* @__PURE__ */ jsxs("h4", {
545
- className: "text-muted-foreground flex items-center gap-1.5 text-xs font-medium",
546
- children: [t1, name]
450
+ if ($[2] !== blockers || $[3] !== onShow) {
451
+ t2 = /* @__PURE__ */ jsx(BlockerCards, {
452
+ blockers,
453
+ onShow
547
454
  });
548
- $[2] = name;
549
- $[3] = t1;
455
+ $[2] = blockers;
456
+ $[3] = onShow;
550
457
  $[4] = t2;
551
458
  } else t2 = $[4];
552
459
  let t3;
553
- if ($[5] !== place.changes) {
554
- t3 = place.changes.map(_temp3);
555
- $[5] = place.changes;
556
- $[6] = t3;
557
- } else t3 = $[6];
460
+ if ($[5] !== conflicts || $[6] !== defaultLocale || $[7] !== deleted || $[8] !== onChanged || $[9] !== projectId) {
461
+ let t4;
462
+ if ($[11] !== defaultLocale || $[12] !== deleted || $[13] !== onChanged || $[14] !== projectId) {
463
+ t4 = (conflict) => /* @__PURE__ */ jsxs(Card, {
464
+ tone: "warning",
465
+ icon: Replace,
466
+ title: conflictTitle(conflict),
467
+ children: [
468
+ /* @__PURE__ */ jsx("p", { children: placeInLocale(conflict, defaultLocale) }),
469
+ /* @__PURE__ */ jsx("p", { children: conflictDetail(conflict, deleted.has(JSON.stringify([
470
+ conflict.entity,
471
+ conflict.id,
472
+ conflict.locale
473
+ ]))) }),
474
+ /* @__PURE__ */ jsx(ConflictFields, { conflict }),
475
+ conflict.revertible && /* @__PURE__ */ jsx(UseLiveVersionButton, {
476
+ projectId,
477
+ conflict,
478
+ onUsed: onChanged
479
+ })
480
+ ]
481
+ }, conflictKey(conflict));
482
+ $[11] = defaultLocale;
483
+ $[12] = deleted;
484
+ $[13] = onChanged;
485
+ $[14] = projectId;
486
+ $[15] = t4;
487
+ } else t4 = $[15];
488
+ t3 = conflicts.map(t4);
489
+ $[5] = conflicts;
490
+ $[6] = defaultLocale;
491
+ $[7] = deleted;
492
+ $[8] = onChanged;
493
+ $[9] = projectId;
494
+ $[10] = t3;
495
+ } else t3 = $[10];
558
496
  let t4;
559
- if ($[7] !== t3) {
560
- t4 = /* @__PURE__ */ jsx("ul", {
561
- className: "flex flex-col",
562
- children: t3
563
- });
564
- $[7] = t3;
565
- $[8] = t4;
566
- } else t4 = $[8];
497
+ if ($[16] !== defaultLocale || $[17] !== lost) {
498
+ let t5;
499
+ if ($[19] !== defaultLocale) {
500
+ t5 = (change_1) => /* @__PURE__ */ jsxs(Card, {
501
+ tone: "warning",
502
+ icon: Unlink,
503
+ title: change_1.reason === "writtenAfterDeletion" ? change_1.label : `Loses the change to the ${change_1.label}`,
504
+ children: [/* @__PURE__ */ jsx("p", { children: placeInLocale(change_1, defaultLocale) }), /* @__PURE__ */ jsx("p", { children: LOST_REASONS[change_1.reason] })]
505
+ }, JSON.stringify([
506
+ change_1.entity,
507
+ change_1.id,
508
+ change_1.locale
509
+ ]));
510
+ $[19] = defaultLocale;
511
+ $[20] = t5;
512
+ } else t5 = $[20];
513
+ t4 = lost.map(t5);
514
+ $[16] = defaultLocale;
515
+ $[17] = lost;
516
+ $[18] = t4;
517
+ } else t4 = $[18];
567
518
  let t5;
568
- if ($[9] !== t2 || $[10] !== t4) {
569
- t5 = /* @__PURE__ */ jsxs("section", {
570
- className: "flex flex-col gap-1",
571
- children: [t2, t4]
519
+ if ($[21] !== t2 || $[22] !== t3 || $[23] !== t4) {
520
+ t5 = /* @__PURE__ */ jsxs("ul", {
521
+ className: "flex flex-col gap-2",
522
+ children: [
523
+ t2,
524
+ t3,
525
+ t4
526
+ ]
572
527
  });
573
- $[9] = t2;
574
- $[10] = t4;
575
- $[11] = t5;
576
- } else t5 = $[11];
528
+ $[21] = t2;
529
+ $[22] = t3;
530
+ $[23] = t4;
531
+ $[24] = t5;
532
+ } else t5 = $[24];
577
533
  return t5;
578
534
  }
579
- function _temp3(change) {
580
- return /* @__PURE__ */ jsxs("li", {
581
- className: "flex items-center gap-2 py-0.5 pl-5 text-sm",
582
- title: change.change,
583
- children: [
584
- /* @__PURE__ */ jsx("span", {
585
- "aria-hidden": true,
586
- className: cn("w-2 text-center font-mono", CHANGES[change.change].className),
587
- children: CHANGES[change.change].sign
588
- }),
589
- /* @__PURE__ */ jsx("span", {
590
- className: "truncate",
591
- "data-change-label": true,
592
- children: changeLabel(change)
593
- }),
594
- /* @__PURE__ */ jsxs("span", {
595
- className: "sr-only",
596
- children: [
597
- "(",
598
- change.change,
599
- ")"
600
- ]
601
- })
602
- ]
603
- }, `${change.entity}:${change.id}`);
535
+ function _temp2(change_0) {
536
+ return JSON.stringify([
537
+ change_0.entity,
538
+ change_0.id,
539
+ change_0.locale
540
+ ]);
604
541
  }
605
- /**
606
- * The draft's changes, grouped by locale once the draft changes more than its default locale,
607
- * then by page, layout and collection. Collapsed at first: the insights above are what to read
608
- * before publishing.
609
- */
610
- function Changes(t0) {
611
- const $ = c(46);
612
- const { changes, defaultLocale } = t0;
542
+ function _temp(change) {
543
+ return change.change === "deleted";
544
+ }
545
+ /** A quiet line saying something is done, with a check, or still running, with a spinner. */
546
+ function StatusLine(t0) {
547
+ const $ = c(7);
548
+ const { done, children } = t0;
613
549
  let t1;
614
- if ($[0] !== changes) {
615
- t1 = new Set(changes.map(placeOf));
616
- $[0] = changes;
550
+ if ($[0] !== done) {
551
+ t1 = done ? /* @__PURE__ */ jsx(CircleCheck, { className: "mt-0.5 size-4 shrink-0" }) : /* @__PURE__ */ jsx(Spinner, {
552
+ "aria-hidden": true,
553
+ className: "mt-0.5 size-4 shrink-0"
554
+ });
555
+ $[0] = done;
617
556
  $[1] = t1;
618
557
  } else t1 = $[1];
619
- const groups = t1;
620
- let T0;
621
- let T1;
622
- let T2;
623
558
  let t2;
559
+ if ($[2] !== children) {
560
+ t2 = /* @__PURE__ */ jsx("span", { children });
561
+ $[2] = children;
562
+ $[3] = t2;
563
+ } else t2 = $[3];
624
564
  let t3;
625
- let t4;
626
- let t5;
627
- let t6;
628
- if ($[2] !== changes || $[3] !== defaultLocale || $[4] !== groups.size) {
629
- t6 = Symbol.for("react.early_return_sentinel");
630
- bb0: {
631
- const locales = localesOf(changes, defaultLocale);
632
- if (groups.size === 0) {
633
- let t7;
634
- if ($[13] === Symbol.for("react.memo_cache_sentinel")) {
635
- t7 = /* @__PURE__ */ jsx("p", {
636
- className: "text-muted-foreground text-sm",
637
- children: "This draft has no changes."
638
- });
639
- $[13] = t7;
640
- } else t7 = $[13];
641
- t6 = t7;
642
- break bb0;
643
- }
644
- let t7;
645
- if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
646
- t7 = Object.keys(CHANGES);
647
- $[14] = t7;
648
- } else t7 = $[14];
649
- let t8;
650
- if ($[15] !== changes) {
651
- t8 = t7.map((kind) => [kind, changes.filter((change) => change.change === kind).length]).filter(_temp4);
652
- $[15] = changes;
653
- $[16] = t8;
654
- } else t8 = $[16];
655
- const counts = t8;
656
- T2 = Accordion;
657
- t5 = "rounded-lg border";
658
- T1 = AccordionItem;
659
- let t9;
660
- if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
661
- t9 = /* @__PURE__ */ jsx(ChevronRight, { className: "text-muted-foreground size-4 shrink-0 transition-transform group-data-panel-open:rotate-90" });
662
- $[17] = t9;
663
- } else t9 = $[17];
664
- let t10;
665
- if ($[18] !== changes.length) {
666
- t10 = plural(changes.length, "change");
667
- $[18] = changes.length;
668
- $[19] = t10;
669
- } else t10 = $[19];
670
- let t11;
671
- if ($[20] !== t10) {
672
- t11 = /* @__PURE__ */ jsx("span", {
673
- className: "text-sm font-medium",
674
- children: t10
675
- });
676
- $[20] = t10;
677
- $[21] = t11;
678
- } else t11 = $[21];
679
- let t12;
680
- if ($[22] !== groups.size) {
681
- t12 = plural(groups.size, "place");
682
- $[22] = groups.size;
683
- $[23] = t12;
684
- } else t12 = $[23];
685
- let t13;
686
- if ($[24] !== t12) {
687
- t13 = /* @__PURE__ */ jsxs("span", {
688
- className: "text-muted-foreground text-sm",
689
- children: ["in ", t12]
690
- });
691
- $[24] = t12;
692
- $[25] = t13;
693
- } else t13 = $[25];
694
- let t14;
695
- if ($[26] !== counts) {
696
- t14 = /* @__PURE__ */ jsx("span", {
697
- className: "ml-auto flex items-center gap-2 text-xs tabular-nums",
698
- children: counts.map(_temp5)
699
- });
700
- $[26] = counts;
701
- $[27] = t14;
702
- } else t14 = $[27];
703
- if ($[28] !== t11 || $[29] !== t13 || $[30] !== t14) {
704
- t4 = /* @__PURE__ */ jsx(AccordionHeader, { children: /* @__PURE__ */ jsxs(AccordionTrigger, {
705
- className: "group hover:bg-muted/50 flex w-full items-center gap-2 rounded-lg px-3 py-2.5 text-left",
706
- children: [
707
- t9,
708
- t11,
709
- t13,
710
- t14
711
- ]
712
- }) });
713
- $[28] = t11;
714
- $[29] = t13;
715
- $[30] = t14;
716
- $[31] = t4;
717
- } else t4 = $[31];
718
- T0 = AccordionPanel;
719
- t2 = "flex flex-col gap-4 border-t px-3 py-3";
720
- t3 = locales.map(_temp7);
721
- }
722
- $[2] = changes;
723
- $[3] = defaultLocale;
724
- $[4] = groups.size;
725
- $[5] = T0;
726
- $[6] = T1;
727
- $[7] = T2;
728
- $[8] = t2;
729
- $[9] = t3;
730
- $[10] = t4;
731
- $[11] = t5;
732
- $[12] = t6;
565
+ if ($[4] !== t1 || $[5] !== t2) {
566
+ t3 = /* @__PURE__ */ jsxs("li", {
567
+ className: "text-muted-foreground flex items-start gap-2 text-sm",
568
+ "data-status-line": true,
569
+ children: [t1, t2]
570
+ });
571
+ $[4] = t1;
572
+ $[5] = t2;
573
+ $[6] = t3;
574
+ } else t3 = $[6];
575
+ return t3;
576
+ }
577
+ /**
578
+ * What's fine or still running: the draft is up to date with Live, its translations, and the
579
+ * page SEO being written.
580
+ */
581
+ function StatusLines(t0) {
582
+ const $ = c(20);
583
+ const { preview, locales, waiting } = t0;
584
+ const { conflicts, translating, warnings } = preview;
585
+ let seoPages;
586
+ let t1;
587
+ let t2;
588
+ let t3;
589
+ if ($[0] !== conflicts.length || $[1] !== locales || $[2] !== translating || $[3] !== waiting || $[4] !== warnings) {
590
+ const translations = locales.filter(_temp3).map(_temp4);
591
+ let t4;
592
+ if ($[9] !== warnings) {
593
+ t4 = new Set(warnings.filter(_temp5).map(_temp6));
594
+ $[9] = warnings;
595
+ $[10] = t4;
596
+ } else t4 = $[10];
597
+ seoPages = t4.size;
598
+ t1 = "flex flex-col gap-1.5";
599
+ if ($[11] !== conflicts.length) {
600
+ t2 = conflicts.length === 0 && /* @__PURE__ */ jsx(StatusLine, {
601
+ done: true,
602
+ children: "Includes everything published to Live since this draft started"
603
+ });
604
+ $[11] = conflicts.length;
605
+ $[12] = t2;
606
+ } else t2 = $[12];
607
+ t3 = translating.length > 0 ? /* @__PURE__ */ jsxs(StatusLine, {
608
+ done: false,
609
+ children: [
610
+ "Translating into ",
611
+ listFormat.format(translating.map(localeLabel)),
612
+ ".",
613
+ " ",
614
+ waiting ? "Publishing once translated." : "Publishing waits for it."
615
+ ]
616
+ }) : translations.length > 0 && /* @__PURE__ */ jsxs(StatusLine, {
617
+ done: true,
618
+ children: ["Translated into ", listFormat.format(translations.map(localeLabel))]
619
+ });
620
+ $[0] = conflicts.length;
621
+ $[1] = locales;
622
+ $[2] = translating;
623
+ $[3] = waiting;
624
+ $[4] = warnings;
625
+ $[5] = seoPages;
626
+ $[6] = t1;
627
+ $[7] = t2;
628
+ $[8] = t3;
733
629
  } else {
734
- T0 = $[5];
735
- T1 = $[6];
736
- T2 = $[7];
737
- t2 = $[8];
738
- t3 = $[9];
739
- t4 = $[10];
740
- t5 = $[11];
741
- t6 = $[12];
630
+ seoPages = $[5];
631
+ t1 = $[6];
632
+ t2 = $[7];
633
+ t3 = $[8];
742
634
  }
743
- if (t6 !== Symbol.for("react.early_return_sentinel")) return t6;
744
- let t7;
745
- if ($[32] !== t2 || $[33] !== t3) {
746
- t7 = /* @__PURE__ */ jsx("div", {
747
- className: t2,
748
- children: t3
635
+ let t4;
636
+ if ($[13] !== seoPages) {
637
+ t4 = seoPages > 0 && /* @__PURE__ */ jsxs(StatusLine, {
638
+ done: false,
639
+ children: [
640
+ "Writing SEO for ",
641
+ plural(seoPages, "page"),
642
+ "…"
643
+ ]
749
644
  });
750
- $[32] = t2;
751
- $[33] = t3;
752
- $[34] = t7;
753
- } else t7 = $[34];
754
- let t8;
755
- if ($[35] !== T0 || $[36] !== t7) {
756
- t8 = /* @__PURE__ */ jsx(T0, { children: t7 });
757
- $[35] = T0;
758
- $[36] = t7;
759
- $[37] = t8;
760
- } else t8 = $[37];
761
- let t9;
762
- if ($[38] !== T1 || $[39] !== t4 || $[40] !== t8) {
763
- t9 = /* @__PURE__ */ jsxs(T1, { children: [t4, t8] });
764
- $[38] = T1;
765
- $[39] = t4;
766
- $[40] = t8;
767
- $[41] = t9;
768
- } else t9 = $[41];
769
- let t10;
770
- if ($[42] !== T2 || $[43] !== t5 || $[44] !== t9) {
771
- t10 = /* @__PURE__ */ jsx(T2, {
772
- className: t5,
773
- children: t9
645
+ $[13] = seoPages;
646
+ $[14] = t4;
647
+ } else t4 = $[14];
648
+ let t5;
649
+ if ($[15] !== t1 || $[16] !== t2 || $[17] !== t3 || $[18] !== t4) {
650
+ t5 = /* @__PURE__ */ jsxs("ul", {
651
+ className: t1,
652
+ children: [
653
+ t2,
654
+ t3,
655
+ t4
656
+ ]
774
657
  });
775
- $[42] = T2;
776
- $[43] = t5;
777
- $[44] = t9;
778
- $[45] = t10;
779
- } else t10 = $[45];
780
- return t10;
658
+ $[15] = t1;
659
+ $[16] = t2;
660
+ $[17] = t3;
661
+ $[18] = t4;
662
+ $[19] = t5;
663
+ } else t5 = $[19];
664
+ return t5;
781
665
  }
782
- function _temp7(t0) {
783
- const { locale, places } = t0;
784
- return /* @__PURE__ */ jsxs("div", {
785
- className: "flex flex-col gap-4",
786
- children: [locale && /* @__PURE__ */ jsx("p", {
787
- className: "text-sm font-medium",
788
- "data-change-locale": true,
789
- children: localeLabel(locale)
790
- }), [...places].map(_temp6)]
791
- }, locale ?? "");
666
+ function _temp6(warning_0) {
667
+ return warning_0.id;
792
668
  }
793
- function _temp6(t0) {
794
- const [name, place] = t0;
795
- return /* @__PURE__ */ jsx(Place, {
796
- name,
797
- place
798
- }, name);
669
+ function _temp5(warning) {
670
+ return warning.code === "metaTitlePending";
799
671
  }
800
- function _temp5(t0) {
801
- const [kind_0, count_0] = t0;
802
- return /* @__PURE__ */ jsxs("span", {
803
- title: `${count_0} ${kind_0}`,
804
- className: CHANGES[kind_0].className,
805
- children: [CHANGES[kind_0].sign, count_0]
806
- }, kind_0);
672
+ function _temp4(locale_0) {
673
+ return locale_0.tag;
807
674
  }
808
- function _temp4(t0) {
809
- const [, count] = t0;
810
- return count > 0;
675
+ function _temp3(locale) {
676
+ return !locale.isDefault;
677
+ }
678
+ /**
679
+ * The draft's overview: the bullets AI wrote about its changes, in full, under the headline the
680
+ * header shows, saying it's updating while they describe an older version of the draft. While
681
+ * it's first written, skeleton lines; once it failed, a Retry and a plain count of the changes,
682
+ * so the draft can still be reviewed. Nothing for a draft that gets no overview, as a catch-up
683
+ * draft.
684
+ */
685
+ function DraftOverview(t0) {
686
+ const $ = c(34);
687
+ const { projectId, preview } = t0;
688
+ const { overview, changes } = preview;
689
+ let t1;
690
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
691
+ t1 = {
692
+ ...draftMutations.retryOverview(),
693
+ onError: _temp7
694
+ };
695
+ $[0] = t1;
696
+ } else t1 = $[0];
697
+ const retry = useMutation(t1);
698
+ if (changes.length === 0) {
699
+ let t2;
700
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
701
+ t2 = /* @__PURE__ */ jsx("p", {
702
+ className: "text-muted-foreground text-sm",
703
+ children: "This draft has no changes."
704
+ });
705
+ $[1] = t2;
706
+ } else t2 = $[1];
707
+ return t2;
708
+ }
709
+ if (overview.status === "ready") {
710
+ let t2;
711
+ if ($[2] !== overview.bullets) {
712
+ t2 = overview.bullets.map(_temp8);
713
+ $[2] = overview.bullets;
714
+ $[3] = t2;
715
+ } else t2 = $[3];
716
+ let t3;
717
+ if ($[4] !== t2) {
718
+ t3 = /* @__PURE__ */ jsx("ul", {
719
+ className: "text-foreground/85 flex list-disc flex-col gap-1.5 pl-5 leading-relaxed",
720
+ children: t2
721
+ });
722
+ $[4] = t2;
723
+ $[5] = t3;
724
+ } else t3 = $[5];
725
+ let t4;
726
+ if ($[6] !== overview.stale) {
727
+ t4 = overview.stale && /* @__PURE__ */ jsxs("p", {
728
+ className: "text-muted-foreground flex items-center gap-1.5 text-xs",
729
+ children: [/* @__PURE__ */ jsx(Spinner, {
730
+ "aria-hidden": true,
731
+ className: "size-3"
732
+ }), "Updating…"]
733
+ });
734
+ $[6] = overview.stale;
735
+ $[7] = t4;
736
+ } else t4 = $[7];
737
+ let t5;
738
+ if ($[8] !== t3 || $[9] !== t4) {
739
+ t5 = /* @__PURE__ */ jsxs("div", {
740
+ "data-overview": true,
741
+ className: "flex flex-col gap-2",
742
+ children: [t3, t4]
743
+ });
744
+ $[8] = t3;
745
+ $[9] = t4;
746
+ $[10] = t5;
747
+ } else t5 = $[10];
748
+ return t5;
749
+ }
750
+ if (overview.status === "failed") {
751
+ let t2;
752
+ if ($[11] !== changes) {
753
+ t2 = new Set(changes.map(_temp9));
754
+ $[11] = changes;
755
+ $[12] = t2;
756
+ } else t2 = $[12];
757
+ const places = t2.size;
758
+ let t3;
759
+ if ($[13] === Symbol.for("react.memo_cache_sentinel")) {
760
+ t3 = /* @__PURE__ */ jsx("p", {
761
+ className: "text-sm font-medium",
762
+ children: "Couldn't summarize this draft"
763
+ });
764
+ $[13] = t3;
765
+ } else t3 = $[13];
766
+ let t4;
767
+ if ($[14] !== projectId || $[15] !== retry) {
768
+ t4 = () => retry.mutate({ projectId });
769
+ $[14] = projectId;
770
+ $[15] = retry;
771
+ $[16] = t4;
772
+ } else t4 = $[16];
773
+ let t5;
774
+ if ($[17] !== retry.isPending) {
775
+ t5 = retry.isPending ? /* @__PURE__ */ jsx(Spinner, {}) : null;
776
+ $[17] = retry.isPending;
777
+ $[18] = t5;
778
+ } else t5 = $[18];
779
+ let t6;
780
+ if ($[19] !== retry.isPending || $[20] !== t4 || $[21] !== t5) {
781
+ t6 = /* @__PURE__ */ jsxs("div", {
782
+ className: "flex items-center gap-3",
783
+ children: [t3, /* @__PURE__ */ jsxs(Button, {
784
+ variant: "outline",
785
+ size: "sm",
786
+ className: "ml-auto",
787
+ disabled: retry.isPending,
788
+ onClick: t4,
789
+ children: [t5, "Retry"]
790
+ })]
791
+ });
792
+ $[19] = retry.isPending;
793
+ $[20] = t4;
794
+ $[21] = t5;
795
+ $[22] = t6;
796
+ } else t6 = $[22];
797
+ let t7;
798
+ if ($[23] !== changes.length) {
799
+ t7 = plural(changes.length, "change");
800
+ $[23] = changes.length;
801
+ $[24] = t7;
802
+ } else t7 = $[24];
803
+ let t8;
804
+ if ($[25] !== places) {
805
+ t8 = plural(places, "place");
806
+ $[25] = places;
807
+ $[26] = t8;
808
+ } else t8 = $[26];
809
+ let t9;
810
+ if ($[27] !== t7 || $[28] !== t8) {
811
+ t9 = /* @__PURE__ */ jsxs("p", {
812
+ className: "text-muted-foreground text-sm",
813
+ children: [
814
+ t7,
815
+ " in ",
816
+ t8
817
+ ]
818
+ });
819
+ $[27] = t7;
820
+ $[28] = t8;
821
+ $[29] = t9;
822
+ } else t9 = $[29];
823
+ let t10;
824
+ if ($[30] !== t6 || $[31] !== t9) {
825
+ t10 = /* @__PURE__ */ jsxs("div", {
826
+ "data-overview": true,
827
+ className: "flex flex-col gap-2",
828
+ children: [t6, t9]
829
+ });
830
+ $[30] = t6;
831
+ $[31] = t9;
832
+ $[32] = t10;
833
+ } else t10 = $[32];
834
+ return t10;
835
+ }
836
+ if (overview.status === "none") return null;
837
+ let t2;
838
+ if ($[33] === Symbol.for("react.memo_cache_sentinel")) {
839
+ t2 = /* @__PURE__ */ jsxs("div", {
840
+ "data-overview": true,
841
+ className: "flex flex-col gap-2",
842
+ children: [
843
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-11/12" }),
844
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-4/5" }),
845
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-2/3" }),
846
+ /* @__PURE__ */ jsx("p", {
847
+ className: "text-muted-foreground text-sm",
848
+ children: "Summarizing this draft…"
849
+ })
850
+ ]
851
+ });
852
+ $[33] = t2;
853
+ } else t2 = $[33];
854
+ return t2;
855
+ }
856
+ function _temp9(change) {
857
+ return change.entity === "locale" ? "Languages" : ownerName(change.owner, change.entity);
858
+ }
859
+ function _temp8(bullet, index) {
860
+ return /* @__PURE__ */ jsx("li", { children: bullet }, index);
861
+ }
862
+ function _temp7(error) {
863
+ return toast.error(error.message || "Could not summarize the draft");
811
864
  }
812
865
  /**
813
866
  * Switches the studio to Live once its draft ended here, replacing the draft's URL entry. A
@@ -833,8 +886,8 @@ function useLeaveDraft() {
833
886
  * blur, and a blank name clears it; Escape puts the name back.
834
887
  */
835
888
  function DraftNameInput(t0) {
836
- const $ = c(20);
837
- const { projectId, draft, ref } = t0;
889
+ const $ = c(23);
890
+ const { projectId, draft, ref, className } = t0;
838
891
  const rename = useRenameDraft(projectId);
839
892
  const name = draft.name ?? "";
840
893
  let t1;
@@ -872,14 +925,20 @@ function DraftNameInput(t0) {
872
925
  $[8] = t3;
873
926
  } else t3 = $[8];
874
927
  let t4;
875
- if ($[9] !== save) {
876
- t4 = (event) => save(event.currentTarget);
877
- $[9] = save;
928
+ if ($[9] !== className) {
929
+ t4 = cn("hover:border-input focus-visible:border-ring focus-visible:ring-ring/50 placeholder:text-foreground focus:placeholder:text-muted-foreground -mx-1.5 h-8 w-full min-w-0 truncate rounded-md border border-transparent bg-transparent px-1.5 text-base font-medium transition-[color,box-shadow,border-color] outline-none hover:shadow-xs focus-visible:ring-3", className);
930
+ $[9] = className;
878
931
  $[10] = t4;
879
932
  } else t4 = $[10];
880
933
  let t5;
881
- if ($[11] !== name) {
882
- t5 = (event_0) => {
934
+ if ($[11] !== save) {
935
+ t5 = (event) => save(event.currentTarget);
936
+ $[11] = save;
937
+ $[12] = t5;
938
+ } else t5 = $[12];
939
+ let t6;
940
+ if ($[13] !== name) {
941
+ t6 = (event_0) => {
883
942
  if (event_0.key === "Enter") {
884
943
  event_0.preventDefault();
885
944
  event_0.currentTarget.blur();
@@ -889,31 +948,32 @@ function DraftNameInput(t0) {
889
948
  event_0.currentTarget.value = name;
890
949
  event_0.currentTarget.blur();
891
950
  };
892
- $[11] = name;
893
- $[12] = t5;
894
- } else t5 = $[12];
895
- let t6;
896
- if ($[13] !== name || $[14] !== ref || $[15] !== t2 || $[16] !== t3 || $[17] !== t4 || $[18] !== t5) {
897
- t6 = /* @__PURE__ */ jsx("input", {
951
+ $[13] = name;
952
+ $[14] = t6;
953
+ } else t6 = $[14];
954
+ let t7;
955
+ if ($[15] !== name || $[16] !== ref || $[17] !== t2 || $[18] !== t3 || $[19] !== t4 || $[20] !== t5 || $[21] !== t6) {
956
+ t7 = /* @__PURE__ */ jsx("input", {
898
957
  ref,
899
958
  "aria-label": "Draft name",
900
959
  defaultValue: name,
901
960
  placeholder: t2,
902
961
  title: t3,
903
962
  maxLength: 200,
904
- className: "hover:border-input focus-visible:border-ring focus-visible:ring-ring/50 placeholder:text-foreground focus:placeholder:text-muted-foreground -mx-1.5 h-8 w-full min-w-0 truncate rounded-md border border-transparent bg-transparent px-1.5 text-base font-medium transition-[color,box-shadow,border-color] outline-none hover:shadow-xs focus-visible:ring-3",
905
- onBlur: t4,
906
- onKeyDown: t5
963
+ className: t4,
964
+ onBlur: t5,
965
+ onKeyDown: t6
907
966
  }, name);
908
- $[13] = name;
909
- $[14] = ref;
910
- $[15] = t2;
911
- $[16] = t3;
912
- $[17] = t4;
913
- $[18] = t5;
914
- $[19] = t6;
915
- } else t6 = $[19];
916
- return t6;
967
+ $[15] = name;
968
+ $[16] = ref;
969
+ $[17] = t2;
970
+ $[18] = t3;
971
+ $[19] = t4;
972
+ $[20] = t5;
973
+ $[21] = t6;
974
+ $[22] = t7;
975
+ } else t7 = $[22];
976
+ return t7;
917
977
  }
918
978
  /**
919
979
  * Reviews a draft before publishing it whole, or discards it (ADR 0009). Publishing sends back
@@ -921,7 +981,7 @@ function DraftNameInput(t0) {
921
981
  * preview is shown. Once the draft ends, the studio switches to Live.
922
982
  */
923
983
  function ReviewDraftSheet(t0) {
924
- const $ = c(106);
984
+ const $ = c(101);
925
985
  const { projectId, draftId, open, startRenaming: t1, onOpenChange } = t0;
926
986
  const startRenaming = t1 === void 0 ? false : t1;
927
987
  const [confirmingDiscard, setConfirmingDiscard] = React.useState(false);
@@ -959,79 +1019,93 @@ function ReviewDraftSheet(t0) {
959
1019
  $[9] = t5;
960
1020
  } else t5 = $[9];
961
1021
  const draft = useReadQuery(t4, t5);
1022
+ let t6;
1023
+ if ($[10] !== projectId) {
1024
+ t6 = reads.localeList({ projectId });
1025
+ $[10] = projectId;
1026
+ $[11] = t6;
1027
+ } else t6 = $[11];
1028
+ let t7;
1029
+ if ($[12] !== open) {
1030
+ t7 = { enabled: open };
1031
+ $[12] = open;
1032
+ $[13] = t7;
1033
+ } else t7 = $[13];
1034
+ const locales = useReadQuery(t6, t7);
962
1035
  const leaveDraft = useLeaveDraft();
1036
+ const showInCanvas = useShowInCanvas();
963
1037
  const popup = React.useRef(null);
964
1038
  const nameInput = React.useRef(null);
965
- let t6;
966
- if ($[10] !== startRenaming) {
967
- t6 = () => {
1039
+ let t8;
1040
+ if ($[14] !== startRenaming) {
1041
+ t8 = () => {
968
1042
  if (startRenaming && nameInput.current) {
969
1043
  nameInput.current.select();
970
1044
  return nameInput.current;
971
1045
  }
972
1046
  return popup.current;
973
1047
  };
974
- $[10] = startRenaming;
975
- $[11] = t6;
976
- } else t6 = $[11];
977
- const initialFocus = t6;
978
- let t7;
979
- if ($[12] !== draft.data?.translatingLocales) {
980
- t7 = draft.data?.translatingLocales.join(",");
981
- $[12] = draft.data?.translatingLocales;
982
- $[13] = t7;
983
- } else t7 = $[13];
984
- const pending = t7;
1048
+ $[14] = startRenaming;
1049
+ $[15] = t8;
1050
+ } else t8 = $[15];
1051
+ const initialFocus = t8;
1052
+ let t9;
1053
+ if ($[16] !== draft.data?.translatingLocales) {
1054
+ t9 = draft.data?.translatingLocales.join(",");
1055
+ $[16] = draft.data?.translatingLocales;
1056
+ $[17] = t9;
1057
+ } else t9 = $[17];
1058
+ const pending = t9;
985
1059
  const seenPending = React.useRef(pending);
986
1060
  const { refetch } = preview;
987
- let t8;
988
- let t9;
989
- if ($[14] !== pending || $[15] !== refetch) {
990
- t8 = () => {
1061
+ let t10;
1062
+ let t11;
1063
+ if ($[18] !== pending || $[19] !== refetch) {
1064
+ t10 = () => {
991
1065
  if (seenPending.current !== void 0 && seenPending.current !== pending) refetch();
992
1066
  seenPending.current = pending;
993
1067
  };
994
- t9 = [pending, refetch];
995
- $[14] = pending;
996
- $[15] = refetch;
997
- $[16] = t8;
998
- $[17] = t9;
1068
+ t11 = [pending, refetch];
1069
+ $[18] = pending;
1070
+ $[19] = refetch;
1071
+ $[20] = t10;
1072
+ $[21] = t11;
999
1073
  } else {
1000
- t8 = $[16];
1001
- t9 = $[17];
1074
+ t10 = $[20];
1075
+ t11 = $[21];
1002
1076
  }
1003
- React.useEffect(t8, t9);
1004
- let t10;
1005
- if ($[18] !== leaveDraft || $[19] !== onOpenChange) {
1006
- t10 = (ended) => {
1077
+ React.useEffect(t10, t11);
1078
+ let t12;
1079
+ if ($[22] !== leaveDraft || $[23] !== onOpenChange) {
1080
+ t12 = (ended) => {
1007
1081
  onOpenChange(false);
1008
1082
  leaveDraft(ended);
1009
1083
  };
1010
- $[18] = leaveDraft;
1011
- $[19] = onOpenChange;
1012
- $[20] = t10;
1013
- } else t10 = $[20];
1014
- const leave = t10;
1015
- let t11;
1016
- if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
1017
- t11 = draftMutations.publish();
1018
- $[21] = t11;
1019
- } else t11 = $[21];
1020
- let t12;
1021
- if ($[22] !== leave || $[23] !== preview) {
1022
- t12 = (t13) => {
1023
- const { empty, ended: ended_0 } = t13;
1084
+ $[22] = leaveDraft;
1085
+ $[23] = onOpenChange;
1086
+ $[24] = t12;
1087
+ } else t12 = $[24];
1088
+ const leave = t12;
1089
+ let t13;
1090
+ if ($[25] === Symbol.for("react.memo_cache_sentinel")) {
1091
+ t13 = draftMutations.publish();
1092
+ $[25] = t13;
1093
+ } else t13 = $[25];
1094
+ let t14;
1095
+ if ($[26] !== leave || $[27] !== preview) {
1096
+ t14 = (t15) => {
1097
+ const { empty, ended: ended_0 } = t15;
1024
1098
  if (!empty) return leave(ended_0);
1025
1099
  toast.info("This draft has no changes, so there is nothing to publish.");
1026
1100
  preview.refetch();
1027
1101
  };
1028
- $[22] = leave;
1029
- $[23] = preview;
1030
- $[24] = t12;
1031
- } else t12 = $[24];
1032
- let t13;
1033
- if ($[25] !== preview) {
1034
- t13 = (error) => {
1102
+ $[26] = leave;
1103
+ $[27] = preview;
1104
+ $[28] = t14;
1105
+ } else t14 = $[28];
1106
+ let t15;
1107
+ if ($[29] !== preview) {
1108
+ t15 = (error) => {
1035
1109
  if (error.code === CONFLICTS_CHANGED_ERROR) {
1036
1110
  toast.error("Live changed since you opened this review. Check the new list.");
1037
1111
  preview.refetch();
@@ -1045,31 +1119,32 @@ function ReviewDraftSheet(t0) {
1045
1119
  toast.error(error.message || "Could not publish the draft");
1046
1120
  preview.refetch();
1047
1121
  };
1048
- $[25] = preview;
1049
- $[26] = t13;
1050
- } else t13 = $[26];
1051
- let t14;
1052
- if ($[27] !== t12 || $[28] !== t13) {
1053
- t14 = {
1054
- ...t11,
1055
- onSuccess: t12,
1056
- onError: t13
1122
+ $[29] = preview;
1123
+ $[30] = t15;
1124
+ } else t15 = $[30];
1125
+ let t16;
1126
+ if ($[31] !== t14 || $[32] !== t15) {
1127
+ t16 = {
1128
+ ...t13,
1129
+ onSuccess: t14,
1130
+ onError: t15
1057
1131
  };
1058
- $[27] = t12;
1059
- $[28] = t13;
1060
- $[29] = t14;
1061
- } else t14 = $[29];
1062
- const publish = useMutation(t14);
1132
+ $[31] = t14;
1133
+ $[32] = t15;
1134
+ $[33] = t16;
1135
+ } else t16 = $[33];
1136
+ const publish = useMutation(t16);
1063
1137
  const data = preview.data;
1138
+ const headline = data?.overview.status === "ready" ? data.overview.headline : null;
1064
1139
  const busy = publish.isPending;
1065
1140
  const ready = !!data && data.blockers.length === 0 && !busy && !preview.isFetching;
1066
- let t15;
1067
- if ($[30] !== data?.translating) {
1068
- t15 = data?.translating ?? [];
1069
- $[30] = data?.translating;
1070
- $[31] = t15;
1071
- } else t15 = $[31];
1072
- const translating = t15;
1141
+ let t17;
1142
+ if ($[34] !== data?.translating) {
1143
+ t17 = data?.translating ?? [];
1144
+ $[34] = data?.translating;
1145
+ $[35] = t17;
1146
+ } else t17 = $[35];
1147
+ const translating = t17;
1073
1148
  const [waiting, setWaiting] = React.useState(null);
1074
1149
  const translated = !!data && !preview.isFetching && data.translating.length === 0;
1075
1150
  if (waiting && translated) {
@@ -1077,17 +1152,17 @@ function ReviewDraftSheet(t0) {
1077
1152
  if (data.blockers.length > 0 || appeared) setWaiting(null);
1078
1153
  }
1079
1154
  const { mutate } = publish;
1080
- let t16;
1081
- let t17;
1082
- if ($[32] !== busy || $[33] !== data || $[34] !== mutate || $[35] !== projectId || $[36] !== translated || $[37] !== waiting) {
1083
- t16 = () => {
1155
+ let t18;
1156
+ let t19;
1157
+ if ($[36] !== busy || $[37] !== data || $[38] !== mutate || $[39] !== projectId || $[40] !== translated || $[41] !== waiting) {
1158
+ t18 = () => {
1084
1159
  if (!waiting || !translated || !data || busy) return;
1085
1160
  mutate({
1086
1161
  projectId,
1087
1162
  token: data.token
1088
1163
  }, { onSettled: () => setWaiting(null) });
1089
1164
  };
1090
- t17 = [
1165
+ t19 = [
1091
1166
  waiting,
1092
1167
  translated,
1093
1168
  data,
@@ -1095,22 +1170,22 @@ function ReviewDraftSheet(t0) {
1095
1170
  mutate,
1096
1171
  projectId
1097
1172
  ];
1098
- $[32] = busy;
1099
- $[33] = data;
1100
- $[34] = mutate;
1101
- $[35] = projectId;
1102
- $[36] = translated;
1103
- $[37] = waiting;
1104
- $[38] = t16;
1105
- $[39] = t17;
1173
+ $[36] = busy;
1174
+ $[37] = data;
1175
+ $[38] = mutate;
1176
+ $[39] = projectId;
1177
+ $[40] = translated;
1178
+ $[41] = waiting;
1179
+ $[42] = t18;
1180
+ $[43] = t19;
1106
1181
  } else {
1107
- t16 = $[38];
1108
- t17 = $[39];
1182
+ t18 = $[42];
1183
+ t19 = $[43];
1109
1184
  }
1110
- React.useEffect(t16, t17);
1111
- let t18;
1112
- if ($[40] !== data || $[41] !== projectId || $[42] !== publish || $[43] !== translating.length) {
1113
- t18 = () => {
1185
+ React.useEffect(t18, t19);
1186
+ let t20;
1187
+ if ($[44] !== data || $[45] !== projectId || $[46] !== publish || $[47] !== translating.length) {
1188
+ t20 = () => {
1114
1189
  if (!data) return;
1115
1190
  if (translating.length === 0) return publish.mutate({
1116
1191
  projectId,
@@ -1118,126 +1193,119 @@ function ReviewDraftSheet(t0) {
1118
1193
  });
1119
1194
  setWaiting({ conflicts: new Set(data.conflicts.map(conflictKey)) });
1120
1195
  };
1121
- $[40] = data;
1122
- $[41] = projectId;
1123
- $[42] = publish;
1124
- $[43] = translating.length;
1125
- $[44] = t18;
1126
- } else t18 = $[44];
1127
- const publishAll = t18;
1128
- let t19;
1129
- if ($[45] !== draft.data || $[46] !== projectId) {
1130
- t19 = draft.data?.kind === "regular" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SheetTitle, {
1131
- className: "sr-only",
1132
- children: draftLabel(draft.data)
1133
- }), /* @__PURE__ */ jsx(DraftNameInput, {
1134
- ref: nameInput,
1135
- projectId,
1136
- draft: draft.data
1137
- })] }) : /* @__PURE__ */ jsx(SheetTitle, {
1138
- className: "text-base",
1139
- children: draft.data ? draftLabel(draft.data) : "Draft"
1140
- });
1141
- $[45] = draft.data;
1142
- $[46] = projectId;
1143
- $[47] = t19;
1144
- } else t19 = $[47];
1145
- let t20;
1146
- if ($[48] !== draft.data) {
1147
- t20 = draft.data ? `${draft.data.createdBy.name} · started ${timeAgo(draft.data.createdAt)}` : "Publishing applies this whole draft to Live.";
1148
- $[48] = draft.data;
1149
- $[49] = t20;
1150
- } else t20 = $[49];
1196
+ $[44] = data;
1197
+ $[45] = projectId;
1198
+ $[46] = publish;
1199
+ $[47] = translating.length;
1200
+ $[48] = t20;
1201
+ } else t20 = $[48];
1202
+ const publishWhole = t20;
1151
1203
  let t21;
1152
- if ($[50] !== t20) {
1153
- t21 = /* @__PURE__ */ jsx(SheetDescription, { children: t20 });
1154
- $[50] = t20;
1155
- $[51] = t21;
1156
- } else t21 = $[51];
1157
- let t22;
1158
- if ($[52] !== t19 || $[53] !== t21) {
1159
- t22 = /* @__PURE__ */ jsxs("div", {
1204
+ if ($[49] !== draft.data || $[50] !== headline || $[51] !== projectId) {
1205
+ t21 = /* @__PURE__ */ jsx("div", {
1160
1206
  className: "flex flex-col gap-1 border-b p-4 pr-12",
1161
- children: [t19, t21]
1207
+ children: headline ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(SheetDescription, {
1208
+ className: "flex min-w-0 items-center gap-1",
1209
+ children: [draft.data?.kind === "regular" ? /* @__PURE__ */ jsx(DraftNameInput, {
1210
+ ref: nameInput,
1211
+ projectId,
1212
+ draft: draft.data,
1213
+ className: "placeholder:text-muted-foreground text-muted-foreground field-sizing-content h-6 w-auto max-w-full text-sm font-normal"
1214
+ }) : draft.data && /* @__PURE__ */ jsx("span", {
1215
+ className: "truncate",
1216
+ children: draftLabel(draft.data)
1217
+ }), draft.data && /* @__PURE__ */ jsxs("span", {
1218
+ className: "shrink-0",
1219
+ children: [
1220
+ "· ",
1221
+ draft.data.createdBy.name,
1222
+ ", started ",
1223
+ timeAgo(draft.data.createdAt)
1224
+ ]
1225
+ })]
1226
+ }), /* @__PURE__ */ jsx(SheetTitle, {
1227
+ className: "text-lg leading-snug font-semibold",
1228
+ children: headline
1229
+ })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [draft.data?.kind === "regular" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SheetTitle, {
1230
+ className: "sr-only",
1231
+ children: draftLabel(draft.data)
1232
+ }), /* @__PURE__ */ jsx(DraftNameInput, {
1233
+ ref: nameInput,
1234
+ projectId,
1235
+ draft: draft.data
1236
+ })] }) : /* @__PURE__ */ jsx(SheetTitle, {
1237
+ className: "text-base",
1238
+ children: draft.data ? draftLabel(draft.data) : "Draft"
1239
+ }), /* @__PURE__ */ jsx(SheetDescription, { children: draft.data ? `${draft.data.createdBy.name} · started ${timeAgo(draft.data.createdAt)}` : "Publishing applies this whole draft to Live." })] })
1162
1240
  });
1163
- $[52] = t19;
1164
- $[53] = t21;
1165
- $[54] = t22;
1166
- } else t22 = $[54];
1167
- let t23;
1168
- if ($[55] !== data) {
1169
- t23 = data ? /* @__PURE__ */ jsxs("div", {
1241
+ $[49] = draft.data;
1242
+ $[50] = headline;
1243
+ $[51] = projectId;
1244
+ $[52] = t21;
1245
+ } else t21 = $[52];
1246
+ let t22;
1247
+ if ($[53] !== data || $[54] !== locales || $[55] !== onOpenChange || $[56] !== preview || $[57] !== projectId || $[58] !== showInCanvas || $[59] !== waiting) {
1248
+ t22 = data ? /* @__PURE__ */ jsxs("div", {
1170
1249
  className: "flex min-h-0 flex-1 flex-col gap-6 overflow-y-auto p-4",
1171
1250
  children: [
1172
- /* @__PURE__ */ jsx(Verdict, { preview: data }),
1173
- /* @__PURE__ */ jsx(Insights, { preview: data }),
1174
- /* @__PURE__ */ jsx(Changes, {
1175
- changes: data.changes,
1176
- defaultLocale: data.defaultLocale ?? void 0
1251
+ /* @__PURE__ */ jsx(DraftOverview, {
1252
+ projectId,
1253
+ preview: data
1254
+ }),
1255
+ /* @__PURE__ */ jsx(Cards, {
1256
+ projectId,
1257
+ preview: data,
1258
+ onChanged: () => void preview.refetch(),
1259
+ onShow: (target) => {
1260
+ onOpenChange(false);
1261
+ showInCanvas(target);
1262
+ }
1263
+ }),
1264
+ /* @__PURE__ */ jsx(StatusLines, {
1265
+ preview: data,
1266
+ locales: locales.data ?? [],
1267
+ waiting: !!waiting
1177
1268
  })
1178
1269
  ]
1179
1270
  }) : /* @__PURE__ */ jsx("div", {
1180
1271
  className: "flex flex-1 items-center justify-center",
1181
1272
  children: /* @__PURE__ */ jsx(Spinner, { className: "text-muted-foreground" })
1182
1273
  });
1183
- $[55] = data;
1184
- $[56] = t23;
1185
- } else t23 = $[56];
1274
+ $[53] = data;
1275
+ $[54] = locales;
1276
+ $[55] = onOpenChange;
1277
+ $[56] = preview;
1278
+ $[57] = projectId;
1279
+ $[58] = showInCanvas;
1280
+ $[59] = waiting;
1281
+ $[60] = t22;
1282
+ } else t22 = $[60];
1283
+ let t23;
1186
1284
  let t24;
1187
- if ($[57] !== translating || $[58] !== waiting) {
1188
- t24 = translating.length > 0 && /* @__PURE__ */ jsxs("p", {
1189
- className: "text-muted-foreground flex items-center gap-2 text-sm",
1190
- children: [
1191
- /* @__PURE__ */ jsx(Spinner, {
1192
- "aria-hidden": true,
1193
- className: "size-3.5 shrink-0"
1194
- }),
1195
- "Translating into ",
1196
- translating.map(localeLabel).join(", "),
1197
- "…",
1198
- " ",
1199
- waiting ? "Publishing once translated." : "Publishing waits for it."
1200
- ]
1201
- });
1202
- $[57] = translating;
1203
- $[58] = waiting;
1204
- $[59] = t24;
1205
- } else t24 = $[59];
1206
- let t25;
1207
- if ($[60] !== data) {
1208
- t25 = data && data.conflicts.length > 0 && /* @__PURE__ */ jsxs("p", {
1209
- className: "text-muted-foreground text-sm",
1210
- children: [plural(data.conflicts.length, "Live change"), " will be overwritten"]
1211
- });
1212
- $[60] = data;
1213
- $[61] = t25;
1214
- } else t25 = $[61];
1215
- let t26;
1216
- let t27;
1217
- if ($[62] === Symbol.for("react.memo_cache_sentinel")) {
1218
- t26 = () => setConfirmingDiscard(true);
1219
- t27 = /* @__PURE__ */ jsx(Trash2, {});
1220
- $[62] = t26;
1221
- $[63] = t27;
1285
+ if ($[61] === Symbol.for("react.memo_cache_sentinel")) {
1286
+ t23 = () => setConfirmingDiscard(true);
1287
+ t24 = /* @__PURE__ */ jsx(Trash2, {});
1288
+ $[61] = t23;
1289
+ $[62] = t24;
1222
1290
  } else {
1223
- t26 = $[62];
1224
- t27 = $[63];
1291
+ t23 = $[61];
1292
+ t24 = $[62];
1225
1293
  }
1226
- let t28;
1227
- if ($[64] !== busy) {
1228
- t28 = /* @__PURE__ */ jsxs(Button, {
1294
+ let t25;
1295
+ if ($[63] !== busy) {
1296
+ t25 = /* @__PURE__ */ jsxs(Button, {
1229
1297
  variant: "ghost",
1230
1298
  className: "text-destructive",
1231
1299
  disabled: busy,
1232
- onClick: t26,
1233
- children: [t27, "Discard draft"]
1300
+ onClick: t23,
1301
+ children: [t24, "Discard draft"]
1234
1302
  });
1235
- $[64] = busy;
1236
- $[65] = t28;
1237
- } else t28 = $[65];
1238
- let t29;
1239
- if ($[66] !== data || $[67] !== projectId || $[68] !== publish || $[69] !== ready || $[70] !== translating.length) {
1240
- t29 = translating.length > 0 && /* @__PURE__ */ jsx(Button, {
1303
+ $[63] = busy;
1304
+ $[64] = t25;
1305
+ } else t25 = $[64];
1306
+ let t26;
1307
+ if ($[65] !== data || $[66] !== projectId || $[67] !== publish || $[68] !== ready || $[69] !== translating.length) {
1308
+ t26 = translating.length > 0 && /* @__PURE__ */ jsx(Button, {
1241
1309
  variant: "outline",
1242
1310
  className: "ml-auto",
1243
1311
  disabled: !ready,
@@ -1248,124 +1316,112 @@ function ReviewDraftSheet(t0) {
1248
1316
  }),
1249
1317
  children: "Publish anyway"
1250
1318
  });
1251
- $[66] = data;
1252
- $[67] = projectId;
1253
- $[68] = publish;
1254
- $[69] = ready;
1255
- $[70] = translating.length;
1256
- $[71] = t29;
1257
- } else t29 = $[71];
1258
- const t30 = translating.length === 0 && "ml-auto";
1319
+ $[65] = data;
1320
+ $[66] = projectId;
1321
+ $[67] = publish;
1322
+ $[68] = ready;
1323
+ $[69] = translating.length;
1324
+ $[70] = t26;
1325
+ } else t26 = $[70];
1326
+ const t27 = translating.length === 0 && "ml-auto";
1327
+ let t28;
1328
+ if ($[71] !== t27) {
1329
+ t28 = cn(t27);
1330
+ $[71] = t27;
1331
+ $[72] = t28;
1332
+ } else t28 = $[72];
1333
+ const t29 = !ready || !!waiting;
1334
+ let t30;
1335
+ if ($[73] !== publish.isPending || $[74] !== waiting) {
1336
+ t30 = publish.isPending || waiting ? /* @__PURE__ */ jsx(Spinner, {}) : null;
1337
+ $[73] = publish.isPending;
1338
+ $[74] = waiting;
1339
+ $[75] = t30;
1340
+ } else t30 = $[75];
1259
1341
  let t31;
1260
- if ($[72] !== t30) {
1261
- t31 = cn(t30);
1262
- $[72] = t30;
1263
- $[73] = t31;
1264
- } else t31 = $[73];
1265
- const t32 = !ready || !!waiting;
1266
- let t33;
1267
- if ($[74] !== publish.isPending || $[75] !== waiting) {
1268
- t33 = publish.isPending || waiting ? /* @__PURE__ */ jsx(Spinner, {}) : null;
1269
- $[74] = publish.isPending;
1270
- $[75] = waiting;
1271
- $[76] = t33;
1272
- } else t33 = $[76];
1273
- let t34;
1274
- if ($[77] !== publishAll || $[78] !== t31 || $[79] !== t32 || $[80] !== t33) {
1275
- t34 = /* @__PURE__ */ jsxs(Button, {
1276
- className: t31,
1277
- disabled: t32,
1278
- onClick: publishAll,
1279
- children: [t33, "Publish all"]
1280
- });
1281
- $[77] = publishAll;
1282
- $[78] = t31;
1283
- $[79] = t32;
1284
- $[80] = t33;
1285
- $[81] = t34;
1286
- } else t34 = $[81];
1287
- let t35;
1288
- if ($[82] !== t28 || $[83] !== t29 || $[84] !== t34) {
1289
- t35 = /* @__PURE__ */ jsxs("div", {
1290
- className: "flex items-center gap-2",
1291
- children: [
1292
- t28,
1293
- t29,
1294
- t34
1295
- ]
1342
+ if ($[76] !== publishWhole || $[77] !== t28 || $[78] !== t29 || $[79] !== t30) {
1343
+ t31 = /* @__PURE__ */ jsxs(Button, {
1344
+ className: t28,
1345
+ disabled: t29,
1346
+ onClick: publishWhole,
1347
+ children: [t30, "Publish"]
1296
1348
  });
1297
- $[82] = t28;
1298
- $[83] = t29;
1299
- $[84] = t34;
1300
- $[85] = t35;
1301
- } else t35 = $[85];
1302
- let t36;
1303
- if ($[86] !== t24 || $[87] !== t25 || $[88] !== t35) {
1304
- t36 = /* @__PURE__ */ jsxs("div", {
1349
+ $[76] = publishWhole;
1350
+ $[77] = t28;
1351
+ $[78] = t29;
1352
+ $[79] = t30;
1353
+ $[80] = t31;
1354
+ } else t31 = $[80];
1355
+ let t32;
1356
+ if ($[81] !== t25 || $[82] !== t26 || $[83] !== t31) {
1357
+ t32 = /* @__PURE__ */ jsx("div", {
1305
1358
  className: "flex flex-col gap-3 border-t p-4",
1306
- children: [
1307
- t24,
1308
- t25,
1309
- t35
1310
- ]
1359
+ children: /* @__PURE__ */ jsxs("div", {
1360
+ className: "flex items-center gap-2",
1361
+ children: [
1362
+ t25,
1363
+ t26,
1364
+ t31
1365
+ ]
1366
+ })
1311
1367
  });
1312
- $[86] = t24;
1313
- $[87] = t25;
1314
- $[88] = t35;
1315
- $[89] = t36;
1316
- } else t36 = $[89];
1317
- let t37;
1318
- if ($[90] !== initialFocus || $[91] !== t22 || $[92] !== t23 || $[93] !== t36) {
1319
- t37 = /* @__PURE__ */ jsxs(SheetContent, {
1368
+ $[81] = t25;
1369
+ $[82] = t26;
1370
+ $[83] = t31;
1371
+ $[84] = t32;
1372
+ } else t32 = $[84];
1373
+ let t33;
1374
+ if ($[85] !== initialFocus || $[86] !== t21 || $[87] !== t22 || $[88] !== t32) {
1375
+ t33 = /* @__PURE__ */ jsxs(SheetContent, {
1320
1376
  ref: popup,
1321
1377
  initialFocus,
1322
1378
  side: "right",
1323
1379
  className: "w-full gap-0 data-[side=right]:sm:max-w-lg",
1324
1380
  children: [
1381
+ t21,
1325
1382
  t22,
1326
- t23,
1327
- t36
1383
+ t32
1328
1384
  ]
1329
1385
  });
1330
- $[90] = initialFocus;
1331
- $[91] = t22;
1332
- $[92] = t23;
1333
- $[93] = t36;
1334
- $[94] = t37;
1335
- } else t37 = $[94];
1336
- let t38;
1337
- if ($[95] !== onOpenChange || $[96] !== open || $[97] !== t37) {
1338
- t38 = /* @__PURE__ */ jsx(Sheet, {
1386
+ $[85] = initialFocus;
1387
+ $[86] = t21;
1388
+ $[87] = t22;
1389
+ $[88] = t32;
1390
+ $[89] = t33;
1391
+ } else t33 = $[89];
1392
+ let t34;
1393
+ if ($[90] !== onOpenChange || $[91] !== open || $[92] !== t33) {
1394
+ t34 = /* @__PURE__ */ jsx(Sheet, {
1339
1395
  open,
1340
1396
  onOpenChange,
1341
- children: t37
1397
+ children: t33
1342
1398
  });
1343
- $[95] = onOpenChange;
1344
- $[96] = open;
1345
- $[97] = t37;
1346
- $[98] = t38;
1347
- } else t38 = $[98];
1348
- let t39;
1349
- if ($[99] !== confirmingDiscard || $[100] !== leave || $[101] !== projectId) {
1350
- t39 = /* @__PURE__ */ jsx(DiscardDraftDialog, {
1399
+ $[90] = onOpenChange;
1400
+ $[91] = open;
1401
+ $[92] = t33;
1402
+ $[93] = t34;
1403
+ } else t34 = $[93];
1404
+ let t35;
1405
+ if ($[94] !== confirmingDiscard || $[95] !== leave || $[96] !== projectId) {
1406
+ t35 = /* @__PURE__ */ jsx(DiscardDraftDialog, {
1351
1407
  projectId,
1352
1408
  open: confirmingDiscard,
1353
1409
  onOpenChange: setConfirmingDiscard,
1354
1410
  onDiscarded: leave
1355
1411
  });
1356
- $[99] = confirmingDiscard;
1357
- $[100] = leave;
1358
- $[101] = projectId;
1359
- $[102] = t39;
1360
- } else t39 = $[102];
1361
- let t40;
1362
- if ($[103] !== t38 || $[104] !== t39) {
1363
- t40 = /* @__PURE__ */ jsxs(Fragment, { children: [t38, t39] });
1364
- $[103] = t38;
1365
- $[104] = t39;
1366
- $[105] = t40;
1367
- } else t40 = $[105];
1368
- return t40;
1412
+ $[94] = confirmingDiscard;
1413
+ $[95] = leave;
1414
+ $[96] = projectId;
1415
+ $[97] = t35;
1416
+ } else t35 = $[97];
1417
+ let t36;
1418
+ if ($[98] !== t34 || $[99] !== t35) {
1419
+ t36 = /* @__PURE__ */ jsxs(Fragment, { children: [t34, t35] });
1420
+ $[98] = t34;
1421
+ $[99] = t35;
1422
+ $[100] = t36;
1423
+ } else t36 = $[100];
1424
+ return t36;
1369
1425
  }
1370
1426
  /** Asks before discarding the draft the studio is in, then discards it. */
1371
1427
  function DiscardDraftDialog(t0) {
@@ -1385,7 +1441,7 @@ function DiscardDraftDialog(t0) {
1385
1441
  onOpenChange(false);
1386
1442
  onDiscarded(ended);
1387
1443
  },
1388
- onError: _temp8
1444
+ onError: _temp10
1389
1445
  };
1390
1446
  $[1] = onDiscarded;
1391
1447
  $[2] = onOpenChange;
@@ -1464,7 +1520,7 @@ function DiscardDraftDialog(t0) {
1464
1520
  } else t10 = $[25];
1465
1521
  return t10;
1466
1522
  }
1467
- function _temp8(error) {
1523
+ function _temp10(error) {
1468
1524
  return toast.error(error.message || "Could not discard the draft");
1469
1525
  }
1470
1526