camox 0.67.0 → 0.69.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 (33) hide show
  1. package/dist/core/editing/createEditableBlock.js +2 -1
  2. package/dist/features/canvas/canvasFrameDocument.js +25 -2
  3. package/dist/features/canvas/useCanvasFrame.js +6 -2
  4. package/dist/features/preview/components/PreviewToolbar.js +77 -68
  5. package/dist/features/preview/components/previewStyles.js +11 -2
  6. package/dist/features/preview/repeatableItemTargets.js +13 -7
  7. package/dist/features/provider/AuthenticatedCamoxProvider.js +33 -28
  8. package/dist/features/renderer/RendererApp.js +202 -154
  9. package/dist/features/renderer/RendererFrames.js +87 -55
  10. package/dist/features/renderer/definitionAnswers.js +1 -0
  11. package/dist/features/renderer/rendererHost.js +4 -0
  12. package/dist/features/renderer/studioConnection.js +9 -1
  13. package/dist/features/runtime/RuntimeChrome.js +47 -61
  14. package/dist/features/runtime/pageNavigation.js +93 -17
  15. package/dist/features/runtime/rendererClient.js +13 -6
  16. package/dist/features/studio/components/ChatWidget.js +3 -4
  17. package/dist/features/studio/components/ConnectAgent.js +33 -59
  18. package/dist/features/studio/components/DraftBar.js +139 -0
  19. package/dist/features/studio/components/DraftsControl.js +129 -164
  20. package/dist/features/studio/components/LocalePicker.js +22 -4
  21. package/dist/features/studio/components/Navbar.js +3 -2
  22. package/dist/features/studio/components/ReviewDraftSheet.js +2 -21
  23. package/dist/features/studio/components/UserButton.js +7 -11
  24. package/dist/features/studio/studioStore.js +0 -13
  25. package/dist/features/studio/viewSwitch.js +64 -0
  26. package/dist/lib/auth.js +5 -1
  27. package/dist/lib/draft-scope.js +28 -15
  28. package/dist/lib/studio-reads.js +46 -13
  29. package/dist/lib/view-switch.js +64 -0
  30. package/dist/package.js +1 -1
  31. package/dist/studio.css +1 -1
  32. package/package.json +4 -4
  33. package/dist/features/studio/components/UnnamedDraftBar.js +0 -349
@@ -0,0 +1,139 @@
1
+ import { cn } from "../../../lib/utils.js";
2
+ import { studioStore } from "../studioStore.js";
3
+ import { plural } from "../draftLabel.js";
4
+ import { useDrafts } from "./DraftsControl.js";
5
+ import { c } from "react/compiler-runtime";
6
+ import * as React from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { Button } from "@camox/ui/button";
9
+ import { FloatingToolbar } from "@camox/ui/floating-toolbar";
10
+
11
+ //#region src/features/studio/components/DraftBar.tsx
12
+ /**
13
+ * How long a draft goes without a change before its bar shows, so it doesn't pop up mid-edit.
14
+ */
15
+ const SETTLE_MS = 1500;
16
+ /**
17
+ * Asks what to do with the draft being viewed, once its edits settle: discard its changes or
18
+ * publish them. `stacked` places it in the Preview toolbar's column, just above the toolbar;
19
+ * otherwise it floats at the bottom of the screen on its own.
20
+ */
21
+ function DraftBar(t0) {
22
+ const $ = c(15);
23
+ const { stacked: t1 } = t0;
24
+ const stacked = t1 === void 0 ? false : t1;
25
+ const { projectId, current } = useDrafts();
26
+ const settled = useSettled(current?.id ?? null, current?.lastChangedAt ?? null);
27
+ if (!projectId || !current || !settled) return null;
28
+ const empty = current.changeCount === 0;
29
+ const t2 = stacked ? "pointer-events-auto relative left-auto translate-x-0" : "fixed bottom-2";
30
+ let t3;
31
+ if ($[0] !== t2) {
32
+ t3 = cn("w-max gap-4", t2);
33
+ $[0] = t2;
34
+ $[1] = t3;
35
+ } else t3 = $[1];
36
+ let t4;
37
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
38
+ t4 = /* @__PURE__ */ jsx("span", {
39
+ "aria-hidden": true,
40
+ className: "size-2 shrink-0 rounded-full bg-blue-500"
41
+ });
42
+ $[2] = t4;
43
+ } else t4 = $[2];
44
+ let t5;
45
+ if ($[3] !== current.changeCount || $[4] !== empty) {
46
+ t5 = empty ? "No changes yet" : plural(current.changeCount, "pending change");
47
+ $[3] = current.changeCount;
48
+ $[4] = empty;
49
+ $[5] = t5;
50
+ } else t5 = $[5];
51
+ let t6;
52
+ if ($[6] !== t5) {
53
+ t6 = /* @__PURE__ */ jsxs("span", {
54
+ className: "flex items-center gap-2 px-2 text-sm",
55
+ children: [t4, t5]
56
+ });
57
+ $[6] = t5;
58
+ $[7] = t6;
59
+ } else t6 = $[7];
60
+ let t7;
61
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
62
+ t7 = /* @__PURE__ */ jsx(Button, {
63
+ type: "button",
64
+ variant: "outline",
65
+ onClick: _temp,
66
+ children: "Discard"
67
+ });
68
+ $[8] = t7;
69
+ } else t7 = $[8];
70
+ let t8;
71
+ if ($[9] !== empty) {
72
+ t8 = /* @__PURE__ */ jsxs("div", {
73
+ className: "flex items-center gap-2",
74
+ children: [t7, /* @__PURE__ */ jsx(Button, {
75
+ type: "button",
76
+ disabled: empty,
77
+ onClick: _temp2,
78
+ children: "Publish…"
79
+ })]
80
+ });
81
+ $[9] = empty;
82
+ $[10] = t8;
83
+ } else t8 = $[10];
84
+ let t9;
85
+ if ($[11] !== t3 || $[12] !== t6 || $[13] !== t8) {
86
+ t9 = /* @__PURE__ */ jsxs(FloatingToolbar, {
87
+ "aria-label": "Draft",
88
+ className: t3,
89
+ children: [t6, t8]
90
+ });
91
+ $[11] = t3;
92
+ $[12] = t6;
93
+ $[13] = t8;
94
+ $[14] = t9;
95
+ } else t9 = $[14];
96
+ return t9;
97
+ }
98
+ function _temp2() {
99
+ return studioStore.send({ type: "openReviewDraftSheet" });
100
+ }
101
+ function _temp() {
102
+ return studioStore.send({ type: "openDeleteDraftDialog" });
103
+ }
104
+ /**
105
+ * Whether the draft went without a change for `SETTLE_MS`. Once settled it stays so for that
106
+ * draft, so the bar doesn't hide again on the next edit.
107
+ */
108
+ function useSettled(draftId, lastChangedAt) {
109
+ const $ = c(5);
110
+ const [settledDraft, setSettledDraft] = React.useState(null);
111
+ let t0;
112
+ let t1;
113
+ if ($[0] !== draftId || $[1] !== lastChangedAt || $[2] !== settledDraft) {
114
+ t0 = () => {
115
+ if (!draftId || settledDraft === draftId) return;
116
+ const wait = Math.max(0, (lastChangedAt ?? 0) + SETTLE_MS - Date.now());
117
+ const timer = setTimeout(() => setSettledDraft(draftId), wait);
118
+ return () => clearTimeout(timer);
119
+ };
120
+ t1 = [
121
+ draftId,
122
+ lastChangedAt,
123
+ settledDraft
124
+ ];
125
+ $[0] = draftId;
126
+ $[1] = lastChangedAt;
127
+ $[2] = settledDraft;
128
+ $[3] = t0;
129
+ $[4] = t1;
130
+ } else {
131
+ t0 = $[3];
132
+ t1 = $[4];
133
+ }
134
+ React.useEffect(t0, t1);
135
+ return !!draftId && settledDraft === draftId;
136
+ }
137
+
138
+ //#endregion
139
+ export { DraftBar, SETTLE_MS };
@@ -6,7 +6,8 @@ import { reads, useReadQuery } from "../../../lib/studio-reads.js";
6
6
  import { cn } from "../../../lib/utils.js";
7
7
  import { studioStore } from "../studioStore.js";
8
8
  import { draftLabel, plural, timeAgo } from "../draftLabel.js";
9
- import { DeleteDraftDialog, ReviewDraftSheet, useLeaveDraft } from "./ReviewDraftSheet.js";
9
+ import { useLeaveDraft, useSwitchView } from "../viewSwitch.js";
10
+ import { DeleteDraftDialog, ReviewDraftSheet } from "./ReviewDraftSheet.js";
10
11
  import { c } from "react/compiler-runtime";
11
12
  import * as React from "react";
12
13
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -14,7 +15,6 @@ import { useSelector } from "@xstate/store-react";
14
15
  import { Button } from "@camox/ui/button";
15
16
  import { ChevronsUpDown } from "lucide-react";
16
17
  import { toast } from "@camox/ui/toaster";
17
- import { Badge } from "@camox/ui/badge";
18
18
  import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@camox/ui/dropdown-menu";
19
19
 
20
20
  //#region src/features/studio/components/DraftsControl.tsx
@@ -98,12 +98,13 @@ function useDrafts() {
98
98
  * still names what the studio is viewing.
99
99
  */
100
100
  function DraftPicker(t0) {
101
- const $ = c(66);
101
+ const $ = c(68);
102
102
  const { disabled: t1 } = t0;
103
103
  const disabled = t1 === void 0 ? false : t1;
104
104
  const { draftScope, draftId, projectId, list, current } = useDrafts();
105
105
  const navigate = useNavigate();
106
106
  const leaveDraft = useLeaveDraft();
107
+ const switchView = useSwitchView();
107
108
  const review = useSelector(studioStore, _temp);
108
109
  const deleting = useSelector(studioStore, _temp2);
109
110
  let t2;
@@ -135,23 +136,30 @@ function DraftPicker(t0) {
135
136
  } else t5 = $[6];
136
137
  const drafts = t5;
137
138
  let t6;
138
- if ($[7] !== draftId || $[8] !== navigate) {
139
+ if ($[7] !== draftId || $[8] !== drafts || $[9] !== navigate || $[10] !== switchView) {
139
140
  t6 = (next) => {
140
141
  if (next === draftId) return;
141
- navigate({
142
+ const target = next ? drafts.find((draft) => draft.id === next) : void 0;
143
+ const label = next ? target ? draftLabel(target) : "the draft" : "Live";
144
+ switchView(() => navigate({
142
145
  to: window.location.href,
143
146
  draft: next
147
+ }), {
148
+ loading: `Switching to ${label}…`,
149
+ success: `You're now viewing ${label}.`
144
150
  });
145
151
  };
146
152
  $[7] = draftId;
147
- $[8] = navigate;
148
- $[9] = t6;
149
- } else t6 = $[9];
153
+ $[8] = drafts;
154
+ $[9] = navigate;
155
+ $[10] = switchView;
156
+ $[11] = t6;
157
+ } else t6 = $[11];
150
158
  const switchTo = t6;
151
159
  const t7 = !!projectId;
152
160
  const t8 = current?.name === null;
153
161
  let t9;
154
- if ($[10] !== draftId || $[11] !== drafts || $[12] !== switchTo || $[13] !== t7 || $[14] !== t8) {
162
+ if ($[12] !== draftId || $[13] !== drafts || $[14] !== switchTo || $[15] !== t7 || $[16] !== t8) {
155
163
  t9 = {
156
164
  enabled: t7,
157
165
  draftId,
@@ -159,65 +167,65 @@ function DraftPicker(t0) {
159
167
  drafts,
160
168
  switchTo
161
169
  };
162
- $[10] = draftId;
163
- $[11] = drafts;
164
- $[12] = switchTo;
165
- $[13] = t7;
166
- $[14] = t8;
167
- $[15] = t9;
168
- } else t9 = $[15];
170
+ $[12] = draftId;
171
+ $[13] = drafts;
172
+ $[14] = switchTo;
173
+ $[15] = t7;
174
+ $[16] = t8;
175
+ $[17] = t9;
176
+ } else t9 = $[17];
169
177
  useDraftsActions(t9);
170
178
  if (draftId && !current) return null;
171
179
  let t10;
172
- if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
180
+ if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
173
181
  t10 = /* @__PURE__ */ jsx(Button, {
174
182
  type: "button",
175
183
  variant: "ghost"
176
184
  });
177
- $[16] = t10;
178
- } else t10 = $[16];
185
+ $[18] = t10;
186
+ } else t10 = $[18];
179
187
  const t11 = draftId ? "bg-blue-500" : "bg-emerald-500";
180
188
  let t12;
181
- if ($[17] !== t11) {
189
+ if ($[19] !== t11) {
182
190
  t12 = cn("size-2 shrink-0 rounded-full", t11);
183
- $[17] = t11;
184
- $[18] = t12;
185
- } else t12 = $[18];
191
+ $[19] = t11;
192
+ $[20] = t12;
193
+ } else t12 = $[20];
186
194
  let t13;
187
- if ($[19] !== t12) {
195
+ if ($[21] !== t12) {
188
196
  t13 = /* @__PURE__ */ jsx("span", {
189
197
  "aria-hidden": true,
190
198
  className: t12
191
199
  });
192
- $[19] = t12;
193
- $[20] = t13;
194
- } else t13 = $[20];
200
+ $[21] = t12;
201
+ $[22] = t13;
202
+ } else t13 = $[22];
195
203
  let t14;
196
- if ($[21] !== current || $[22] !== draftId) {
204
+ if ($[23] !== current || $[24] !== draftId) {
197
205
  t14 = draftId ? draftLabel(current) : "Live";
198
- $[21] = current;
199
- $[22] = draftId;
200
- $[23] = t14;
201
- } else t14 = $[23];
206
+ $[23] = current;
207
+ $[24] = draftId;
208
+ $[25] = t14;
209
+ } else t14 = $[25];
202
210
  let t15;
203
- if ($[24] !== t14) {
211
+ if ($[26] !== t14) {
204
212
  t15 = /* @__PURE__ */ jsx("span", {
205
213
  className: "max-w-48 truncate",
206
214
  children: t14
207
215
  });
208
- $[24] = t14;
209
- $[25] = t15;
210
- } else t15 = $[25];
216
+ $[26] = t14;
217
+ $[27] = t15;
218
+ } else t15 = $[27];
211
219
  let t16;
212
- if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
220
+ if ($[28] === Symbol.for("react.memo_cache_sentinel")) {
213
221
  t16 = /* @__PURE__ */ jsx(ChevronsUpDown, {
214
222
  "aria-hidden": true,
215
223
  className: "size-4 opacity-50"
216
224
  });
217
- $[26] = t16;
218
- } else t16 = $[26];
225
+ $[28] = t16;
226
+ } else t16 = $[28];
219
227
  let t17;
220
- if ($[27] !== disabled || $[28] !== t13 || $[29] !== t15) {
228
+ if ($[29] !== disabled || $[30] !== t13 || $[31] !== t15) {
221
229
  t17 = /* @__PURE__ */ jsxs(DropdownMenuTrigger, {
222
230
  disabled,
223
231
  render: t10,
@@ -227,48 +235,48 @@ function DraftPicker(t0) {
227
235
  t16
228
236
  ]
229
237
  });
230
- $[27] = disabled;
231
- $[28] = t13;
232
- $[29] = t15;
233
- $[30] = t17;
234
- } else t17 = $[30];
238
+ $[29] = disabled;
239
+ $[30] = t13;
240
+ $[31] = t15;
241
+ $[32] = t17;
242
+ } else t17 = $[32];
235
243
  let t18;
236
- if ($[31] !== draftId) {
244
+ if ($[33] !== draftId) {
237
245
  t18 = !draftId && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsx(DropdownMenuLabel, {
238
246
  className: "text-muted-foreground font-normal",
239
247
  children: "Live is read-only. Your first edit starts a new draft."
240
248
  }) }), /* @__PURE__ */ jsx(DropdownMenuSeparator, {})] });
241
- $[31] = draftId;
242
- $[32] = t18;
243
- } else t18 = $[32];
249
+ $[33] = draftId;
250
+ $[34] = t18;
251
+ } else t18 = $[34];
244
252
  const t19 = draftId ?? LIVE;
245
253
  let t20;
246
- if ($[33] !== switchTo) {
254
+ if ($[35] !== switchTo) {
247
255
  t20 = (value) => switchTo(value === LIVE ? null : String(value));
248
- $[33] = switchTo;
249
- $[34] = t20;
250
- } else t20 = $[34];
256
+ $[35] = switchTo;
257
+ $[36] = t20;
258
+ } else t20 = $[36];
251
259
  let t21;
252
- if ($[35] === Symbol.for("react.memo_cache_sentinel")) {
260
+ if ($[37] === Symbol.for("react.memo_cache_sentinel")) {
253
261
  t21 = /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Switch to" });
254
- $[35] = t21;
255
- } else t21 = $[35];
262
+ $[37] = t21;
263
+ } else t21 = $[37];
256
264
  let t22;
257
- if ($[36] === Symbol.for("react.memo_cache_sentinel")) {
265
+ if ($[38] === Symbol.for("react.memo_cache_sentinel")) {
258
266
  t22 = /* @__PURE__ */ jsx("span", { children: "Live" });
259
- $[36] = t22;
260
- } else t22 = $[36];
267
+ $[38] = t22;
268
+ } else t22 = $[38];
261
269
  let t23;
262
- if ($[37] !== list) {
270
+ if ($[39] !== list) {
263
271
  t23 = list && /* @__PURE__ */ jsx("span", {
264
272
  className: "text-muted-foreground text-xs",
265
273
  children: liveLine(list.live)
266
274
  });
267
- $[37] = list;
268
- $[38] = t23;
269
- } else t23 = $[38];
275
+ $[39] = list;
276
+ $[40] = t23;
277
+ } else t23 = $[40];
270
278
  let t24;
271
- if ($[39] !== t23) {
279
+ if ($[41] !== t23) {
272
280
  t24 = /* @__PURE__ */ jsx(DropdownMenuRadioItem, {
273
281
  value: LIVE,
274
282
  closeOnClick: true,
@@ -277,58 +285,58 @@ function DraftPicker(t0) {
277
285
  children: [t22, t23]
278
286
  })
279
287
  });
280
- $[39] = t23;
281
- $[40] = t24;
282
- } else t24 = $[40];
288
+ $[41] = t23;
289
+ $[42] = t24;
290
+ } else t24 = $[42];
283
291
  let t25;
284
- if ($[41] !== drafts) {
292
+ if ($[43] !== drafts) {
285
293
  t25 = drafts.map(_temp6);
286
- $[41] = drafts;
287
- $[42] = t25;
288
- } else t25 = $[42];
294
+ $[43] = drafts;
295
+ $[44] = t25;
296
+ } else t25 = $[44];
289
297
  let t26;
290
- if ($[43] !== t24 || $[44] !== t25) {
298
+ if ($[45] !== t24 || $[46] !== t25) {
291
299
  t26 = /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
292
300
  t21,
293
301
  t24,
294
302
  t25
295
303
  ] });
296
- $[43] = t24;
297
- $[44] = t25;
298
- $[45] = t26;
299
- } else t26 = $[45];
304
+ $[45] = t24;
305
+ $[46] = t25;
306
+ $[47] = t26;
307
+ } else t26 = $[47];
300
308
  let t27;
301
- if ($[46] !== t19 || $[47] !== t20 || $[48] !== t26) {
309
+ if ($[48] !== t19 || $[49] !== t20 || $[50] !== t26) {
302
310
  t27 = /* @__PURE__ */ jsx(DropdownMenuRadioGroup, {
303
311
  value: t19,
304
312
  onValueChange: t20,
305
313
  children: t26
306
314
  });
307
- $[46] = t19;
308
- $[47] = t20;
309
- $[48] = t26;
310
- $[49] = t27;
311
- } else t27 = $[49];
315
+ $[48] = t19;
316
+ $[49] = t20;
317
+ $[50] = t26;
318
+ $[51] = t27;
319
+ } else t27 = $[51];
312
320
  let t28;
313
- if ($[50] !== t18 || $[51] !== t27) {
321
+ if ($[52] !== t18 || $[53] !== t27) {
314
322
  t28 = /* @__PURE__ */ jsx(DropdownMenuContent, {
315
323
  className: "w-80",
316
324
  align: "start",
317
325
  children: /* @__PURE__ */ jsxs(Fragment, { children: [t18, t27] })
318
326
  });
319
- $[50] = t18;
320
- $[51] = t27;
321
- $[52] = t28;
322
- } else t28 = $[52];
327
+ $[52] = t18;
328
+ $[53] = t27;
329
+ $[54] = t28;
330
+ } else t28 = $[54];
323
331
  let t29;
324
- if ($[53] !== t17 || $[54] !== t28) {
332
+ if ($[55] !== t17 || $[56] !== t28) {
325
333
  t29 = /* @__PURE__ */ jsxs(DropdownMenu, { children: [t17, t28] });
326
- $[53] = t17;
327
- $[54] = t28;
328
- $[55] = t29;
329
- } else t29 = $[55];
334
+ $[55] = t17;
335
+ $[56] = t28;
336
+ $[57] = t29;
337
+ } else t29 = $[57];
330
338
  let t30;
331
- if ($[56] !== current?.name || $[57] !== deleting || $[58] !== draftId || $[59] !== leaveDraft || $[60] !== projectId || $[61] !== review) {
339
+ if ($[58] !== current?.name || $[59] !== deleting || $[60] !== draftId || $[61] !== leaveDraft || $[62] !== projectId || $[63] !== review) {
332
340
  t30 = draftId && projectId && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ReviewDraftSheet, {
333
341
  projectId,
334
342
  draftId,
@@ -342,21 +350,21 @@ function DraftPicker(t0) {
342
350
  onOpenChange: _temp8,
343
351
  onDeleted: (ended) => leaveDraft(ended, { discarded: current?.name === null })
344
352
  })] });
345
- $[56] = current?.name;
346
- $[57] = deleting;
347
- $[58] = draftId;
348
- $[59] = leaveDraft;
349
- $[60] = projectId;
350
- $[61] = review;
351
- $[62] = t30;
352
- } else t30 = $[62];
353
+ $[58] = current?.name;
354
+ $[59] = deleting;
355
+ $[60] = draftId;
356
+ $[61] = leaveDraft;
357
+ $[62] = projectId;
358
+ $[63] = review;
359
+ $[64] = t30;
360
+ } else t30 = $[64];
353
361
  let t31;
354
- if ($[63] !== t29 || $[64] !== t30) {
362
+ if ($[65] !== t29 || $[66] !== t30) {
355
363
  t31 = /* @__PURE__ */ jsxs(Fragment, { children: [t29, t30] });
356
- $[63] = t29;
357
- $[64] = t30;
358
- $[65] = t31;
359
- } else t31 = $[65];
364
+ $[65] = t29;
365
+ $[66] = t30;
366
+ $[67] = t31;
367
+ } else t31 = $[67];
360
368
  return t31;
361
369
  }
362
370
  function _temp8(open_0) {
@@ -365,8 +373,8 @@ function _temp8(open_0) {
365
373
  function _temp7(open) {
366
374
  if (!open) studioStore.send({ type: "closeReviewDraftSheet" });
367
375
  }
368
- function _temp6(draft) {
369
- return /* @__PURE__ */ jsx(DraftItem, { draft }, draft.id);
376
+ function _temp6(draft_0) {
377
+ return /* @__PURE__ */ jsx(DraftItem, { draft: draft_0 }, draft_0.id);
370
378
  }
371
379
  function _temp5() {
372
380
  return _temp4;
@@ -374,7 +382,6 @@ function _temp5() {
374
382
  function _temp4() {
375
383
  studioStore.send({ type: "closeReviewDraftSheet" });
376
384
  studioStore.send({ type: "closeDeleteDraftDialog" });
377
- studioStore.send({ type: "closeKeepDraft" });
378
385
  }
379
386
  function _temp3(t0) {
380
387
  const { move } = t0;
@@ -387,47 +394,6 @@ function _temp(state) {
387
394
  return state.context.reviewDraftSheet;
388
395
  }
389
396
  /**
390
- * The current draft's pending changes, which open its review to publish or delete them. Live
391
- * has none, so it shows nothing there. An unnamed draft shows the Unnamed Draft Bar instead.
392
- */
393
- function PendingChanges() {
394
- const $ = c(7);
395
- const { current } = useDrafts();
396
- if (!current || current.name === null) return null;
397
- let t0;
398
- if ($[0] !== current.changeCount) {
399
- t0 = plural(current.changeCount, "change");
400
- $[0] = current.changeCount;
401
- $[1] = t0;
402
- } else t0 = $[1];
403
- const t1 = `Review ${t0}`;
404
- let t2;
405
- if ($[2] !== current.changeCount) {
406
- t2 = /* @__PURE__ */ jsx(Badge, {
407
- className: "bg-primary-foreground/20 text-primary-foreground min-w-5 px-1.5 tabular-nums",
408
- children: current.changeCount
409
- });
410
- $[2] = current.changeCount;
411
- $[3] = t2;
412
- } else t2 = $[3];
413
- let t3;
414
- if ($[4] !== t1 || $[5] !== t2) {
415
- t3 = /* @__PURE__ */ jsxs(Button, {
416
- type: "button",
417
- "aria-label": t1,
418
- onClick: _temp9,
419
- children: ["Review changes", t2]
420
- });
421
- $[4] = t1;
422
- $[5] = t2;
423
- $[6] = t3;
424
- } else t3 = $[6];
425
- return t3;
426
- }
427
- function _temp9() {
428
- return studioStore.send({ type: "openReviewDraftSheet" });
429
- }
430
- /**
431
397
  * The drafts controls' actions in the command palette, offered where the controls offer them. The palette only opens the review and the delete confirmation; it never publishes or
432
398
  * deletes by itself.
433
399
  */
@@ -453,7 +419,7 @@ function useDraftsActions(t0) {
453
419
  ],
454
420
  groupLabel: "Drafts",
455
421
  checkIfAvailable: () => inDraft,
456
- execute: _temp10
422
+ execute: _temp9
457
423
  },
458
424
  {
459
425
  id: "delete-draft",
@@ -469,22 +435,15 @@ function useDraftsActions(t0) {
469
435
  ],
470
436
  groupLabel: "Drafts",
471
437
  checkIfAvailable: () => inDraft,
472
- execute: _temp11
438
+ execute: _temp10
473
439
  },
474
440
  {
475
441
  id: "rename-draft",
476
- label: unnamed ? "Keep as draft…" : "Rename draft…",
477
- aliases: unnamed ? [
478
- "Name draft",
479
- "Rename draft",
480
- "Save draft"
481
- ] : ["Name draft"],
442
+ label: unnamed ? "Name draft…" : "Rename draft…",
443
+ aliases: unnamed ? ["Rename draft", "Save draft"] : ["Name draft"],
482
444
  groupLabel: "Drafts",
483
445
  checkIfAvailable: () => inDraft,
484
- execute: () => studioStore.send(unnamed ? { type: "openKeepDraft" } : {
485
- type: "openReviewDraftSheet",
486
- startRenaming: true
487
- })
446
+ execute: _temp11
488
447
  },
489
448
  {
490
449
  id: "switch-to-live",
@@ -561,9 +520,15 @@ function _temp13() {
561
520
  }
562
521
  function _temp12() {}
563
522
  function _temp11() {
564
- return studioStore.send({ type: "openDeleteDraftDialog" });
523
+ return studioStore.send({
524
+ type: "openReviewDraftSheet",
525
+ startRenaming: true
526
+ });
565
527
  }
566
528
  function _temp10() {
529
+ return studioStore.send({ type: "openDeleteDraftDialog" });
530
+ }
531
+ function _temp9() {
567
532
  return studioStore.send({ type: "openReviewDraftSheet" });
568
533
  }
569
534
  /** Who published Live last and when: a member, a release, or nobody yet. */
@@ -648,4 +613,4 @@ function DraftItem(t0) {
648
613
  }
649
614
 
650
615
  //#endregion
651
- export { DraftPicker, PendingChanges, useDrafts };
616
+ export { DraftPicker, useDrafts };
@@ -9,6 +9,7 @@ import { usePageDestinations } from "../../../hooks/use-page-destinations.js";
9
9
  import { useLocalePath } from "../../../lib/view-locale.js";
10
10
  import { studioStore } from "../studioStore.js";
11
11
  import { localeLabel, localeOptions } from "../localeOptions.js";
12
+ import { useSwitchView } from "../viewSwitch.js";
12
13
  import { pathInLocale } from "../localeSwitch.js";
13
14
  import { c } from "react/compiler-runtime";
14
15
  import * as React from "react";
@@ -283,7 +284,7 @@ function LocalePicker(t0) {
283
284
  projectId,
284
285
  locales,
285
286
  open: dialog === "add",
286
- onAdded: (added) => void switchTo(added)
287
+ onAdded: (added) => switchTo(added)
287
288
  }), !viewed.isDefault && /* @__PURE__ */ jsx(RemoveLocaleDialog, {
288
289
  projectId,
289
290
  locale: viewed,
@@ -385,7 +386,7 @@ function TranslatingSpinner(t0) {
385
386
  * its home.
386
387
  */
387
388
  function useSwitchLocale(recordPage) {
388
- const $ = c(10);
389
+ const $ = c(15);
389
390
  const navigate = useNavigate();
390
391
  const cache = useStudioCache();
391
392
  const projectUuid = useProjectUuid();
@@ -401,7 +402,6 @@ function useSwitchLocale(recordPage) {
401
402
  let t1;
402
403
  if ($[1] !== cache || $[2] !== destinations || $[3] !== navigate || $[4] !== path || $[5] !== projectUuid || $[6] !== recordPage || $[7] !== search || $[8] !== view.locale) {
403
404
  t1 = async (target) => {
404
- if (target.tag === view.locale.tag && target.isDefault === view.locale.isDefault) return;
405
405
  const pagesIn = (locale) => cache.ensure(reads.pageList({ projectUuid }), { locale }).catch(_temp8);
406
406
  const recordPath = recordPage ? cache.reload(reads.discoveredPath({
407
407
  projectUuid,
@@ -426,7 +426,25 @@ function useSwitchLocale(recordPage) {
426
426
  $[8] = view.locale;
427
427
  $[9] = t1;
428
428
  } else t1 = $[9];
429
- return t1;
429
+ const switchTo = t1;
430
+ const switchView = useSwitchView();
431
+ let t2;
432
+ if ($[10] !== switchTo || $[11] !== switchView || $[12] !== view.locale.isDefault || $[13] !== view.locale.tag) {
433
+ t2 = (target_0) => {
434
+ if (target_0.tag === view.locale.tag && target_0.isDefault === view.locale.isDefault) return;
435
+ const label = localeLabel(target_0.tag);
436
+ switchView(() => switchTo(target_0), {
437
+ loading: `Switching to ${label}…`,
438
+ success: `You're now viewing ${label}.`
439
+ });
440
+ };
441
+ $[10] = switchTo;
442
+ $[11] = switchView;
443
+ $[12] = view.locale.isDefault;
444
+ $[13] = view.locale.tag;
445
+ $[14] = t2;
446
+ } else t2 = $[14];
447
+ return t2;
430
448
  }
431
449
  function _temp9() {
432
450
  return null;