camox 0.59.0 → 0.61.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 (55) hide show
  1. package/dist/core/createApp.d.ts +8 -8
  2. package/dist/core/createBlock.d.ts +1 -2
  3. package/dist/core/createLayout.d.ts +10 -2
  4. package/dist/core/createLayout.js +1 -3
  5. package/dist/core/editing/BlockEditingRuntime.d.ts +1 -0
  6. package/dist/core/editing/CompleteBlockEditingRuntime.js +12 -9
  7. package/dist/core/editing/createEditableBlock.d.ts +4 -4
  8. package/dist/core/editing/createEditableBlock.js +20 -26
  9. package/dist/core/lib/artifactData.js +2 -2
  10. package/dist/core/lib/contentType.js +5 -4
  11. package/dist/features/preview/components/SelectionEditor.js +1 -1
  12. package/dist/features/renderer/RendererApp.js +187 -103
  13. package/dist/features/renderer/rendererHost.js +23 -16
  14. package/dist/features/renderer/studioConnection.js +8 -4
  15. package/dist/features/runtime/loopbackFetch.d.ts +8 -0
  16. package/dist/features/runtime/publicCache.d.ts +21 -0
  17. package/dist/features/runtime/publishingDraft.d.ts +4 -0
  18. package/dist/features/runtime/runtime.js +54 -3
  19. package/dist/features/runtime/worker.js +1 -4
  20. package/dist/features/runtime/workerRequest.d.ts +8 -0
  21. package/dist/features/runtime/workerRuntime.d.ts +5 -0
  22. package/dist/features/runtime/workerRuntime.js +6 -0
  23. package/dist/features/sdkBundle/buildSdkBundle.d.ts +40 -0
  24. package/dist/features/sdkBundle/buildSdkBundle.js +323 -0
  25. package/dist/features/sdkBundle/localSdkBundle.d.ts +44 -0
  26. package/dist/features/sdkBundle/localSdkBundle.js +162 -0
  27. package/dist/features/sdkBundle/sdkBundle.d.ts +3 -0
  28. package/dist/features/sdkBundle/sdkBundle.js +4 -0
  29. package/dist/features/sdkBundle/sdkBundleName.d.ts +59 -0
  30. package/dist/features/sdkBundle/sdkBundleName.js +164 -0
  31. package/dist/features/sdkBundle/specifiers.d.ts +34 -0
  32. package/dist/features/sdkBundle/specifiers.js +146 -0
  33. package/dist/features/settings/SocialProfilesSettings.js +284 -151
  34. package/dist/features/settings/useProjectMutation.js +6 -5
  35. package/dist/features/studio/FollowAgentProvider.js +71 -12
  36. package/dist/features/studio/components/ChatWidget.js +85 -43
  37. package/dist/features/studio/components/Patrol.js +311 -208
  38. package/dist/features/studio/components/Squareling.js +164 -66
  39. package/dist/features/studio/components/ThreadComposer.js +139 -69
  40. package/dist/features/studio/components/ThreadMessages.js +115 -45
  41. package/dist/features/studio/editorWhereContext.js +11 -0
  42. package/dist/features/studio/useEditorSelection.js +135 -0
  43. package/dist/features/vite/hostedChecks.js +1 -1
  44. package/dist/features/vite/runtimeDev.js +2 -1
  45. package/dist/features/vite/sdkBundleBuild.js +74 -0
  46. package/dist/features/vite/staticAssetHeaders.js +7 -4
  47. package/dist/features/vite/vite.d.ts +0 -2
  48. package/dist/features/vite/vite.js +33 -3
  49. package/dist/lib/auth.js +24 -58
  50. package/dist/lib/server-auth-cookie.js +12 -2
  51. package/dist/lib/stored-auth-cookies.js +76 -0
  52. package/dist/lib/use-thread.js +9 -5
  53. package/dist/package.js +1 -1
  54. package/dist/studio.css +1 -1
  55. package/package.json +17 -4
@@ -4,9 +4,13 @@ import { c } from "react/compiler-runtime";
4
4
  import * as React from "react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  import { Button } from "@camox/ui/button";
7
- import { Input } from "@camox/ui/input";
8
- import { ArrowDown, ArrowUp, Plus, Trash2 } from "lucide-react";
7
+ import { GripVertical, Plus, Trash2 } from "lucide-react";
8
+ import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
9
+ import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
10
+ import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
11
+ import { CSS } from "@dnd-kit/utilities";
9
12
  import { Spinner } from "@camox/ui/spinner";
13
+ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "@camox/ui/input-group";
10
14
  import { socialProfileUrlSchema } from "@camox/api-contract/projects";
11
15
 
12
16
  //#region src/features/settings/SocialProfilesSettings.tsx
@@ -16,69 +20,67 @@ const row = (url) => ({
16
20
  url
17
21
  });
18
22
  function SocialProfilesSettings(t0) {
19
- const $ = c(33);
23
+ const $ = c(36);
20
24
  const { project } = t0;
21
25
  let t1;
22
- if ($[0] !== project) {
26
+ if ($[0] !== project.socialProfiles) {
23
27
  t1 = () => project.socialProfiles.map(row);
24
- $[0] = project;
28
+ $[0] = project.socialProfiles;
25
29
  $[1] = t1;
26
30
  } else t1 = $[1];
27
31
  const [rows, setRows] = React.useState(t1);
28
32
  const [showErrors, setShowErrors] = React.useState(false);
29
- let t2;
30
- if ($[2] !== rows) {
31
- t2 = rows.map(_temp).filter(_temp2);
32
- $[2] = rows;
33
- $[3] = t2;
34
- } else t2 = $[3];
35
- const filled = t2;
36
- let t3;
37
- if ($[4] !== filled) {
38
- t3 = {
39
- success: "Social profiles updated",
40
- failure: "Could not save the social profiles",
41
- onSuccess: () => {
42
- setRows(filled);
43
- setShowErrors(false);
44
- }
45
- };
46
- $[4] = filled;
47
- $[5] = t3;
48
- } else t3 = $[5];
49
- const save = useProjectMutation(project, "updateSocialProfiles", t3);
33
+ const filled = rows.map(_temp).filter(_temp2);
34
+ const save = useProjectMutation(project, "updateSocialProfiles", {
35
+ success: "Social profiles updated",
36
+ failure: "Could not save the social profiles",
37
+ onSuccess: () => {
38
+ setRows(filled);
39
+ setShowErrors(false);
40
+ }
41
+ });
50
42
  const errorOf = _temp3;
51
- let t4;
52
- if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
53
- t4 = (key, url_0) => setRows((current) => current.map((entry_0) => entry_0.key === key ? {
43
+ let t2;
44
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
45
+ t2 = (key, url_0) => setRows((current) => current.map((entry_0) => entry_0.key === key ? {
54
46
  ...entry_0,
55
47
  url: url_0
56
48
  } : entry_0));
57
- $[6] = t4;
58
- } else t4 = $[6];
59
- const update = t4;
49
+ $[2] = t2;
50
+ } else t2 = $[2];
51
+ const update = t2;
52
+ let t3;
53
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
54
+ t3 = (key_0) => setRows((current_0) => current_0.filter((entry_1) => entry_1.key !== key_0));
55
+ $[3] = t3;
56
+ } else t3 = $[3];
57
+ const remove = t3;
58
+ let t4;
59
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
60
+ t4 = { coordinateGetter: sortableKeyboardCoordinates };
61
+ $[4] = t4;
62
+ } else t4 = $[4];
63
+ const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, t4));
60
64
  let t5;
61
- if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
62
- t5 = (key_0) => setRows((current_0) => current_0.filter((entry_1) => entry_1.key !== key_0));
63
- $[7] = t5;
64
- } else t5 = $[7];
65
- const remove = t5;
65
+ if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
66
+ t5 = (t6) => {
67
+ const { active, over } = t6;
68
+ if (!over || active.id === over.id) return;
69
+ setRows((current_1) => {
70
+ const from = current_1.findIndex((entry_2) => entry_2.key === active.id);
71
+ const to = current_1.findIndex((entry_3) => entry_3.key === over.id);
72
+ return from === -1 || to === -1 ? current_1 : arrayMove(current_1, from, to);
73
+ });
74
+ };
75
+ $[5] = t5;
76
+ } else t5 = $[5];
77
+ const handleDragEnd = t5;
78
+ const hasChanges = filled.length !== project.socialProfiles.length || filled.some((entry_4, index) => entry_4.url !== project.socialProfiles[index]);
66
79
  let t6;
67
- if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
68
- t6 = (index, by) => setRows((current_1) => {
69
- const next = [...current_1];
70
- const [moved] = next.splice(index, 1);
71
- next.splice(index + by, 0, moved);
72
- return next;
73
- });
74
- $[8] = t6;
75
- } else t6 = $[8];
76
- const move = t6;
77
- let t7;
78
- if ($[9] !== filled || $[10] !== project || $[11] !== save) {
79
- t7 = (event) => {
80
+ if ($[6] !== errorOf || $[7] !== filled || $[8] !== project.id || $[9] !== save) {
81
+ t6 = (event) => {
80
82
  event.preventDefault();
81
- if (filled.some((entry_2) => errorOf(entry_2.url))) {
83
+ if (filled.some((entry_5) => errorOf(entry_5.url))) {
82
84
  setShowErrors(true);
83
85
  return;
84
86
  }
@@ -87,145 +89,123 @@ function SocialProfilesSettings(t0) {
87
89
  socialProfiles: filled.map(_temp4)
88
90
  });
89
91
  };
90
- $[9] = filled;
91
- $[10] = project;
92
- $[11] = save;
93
- $[12] = t7;
94
- } else t7 = $[12];
95
- const submit = t7;
96
- let t8;
97
- if ($[13] !== rows || $[14] !== save.isPending || $[15] !== showErrors) {
98
- t8 = rows.length > 0 && /* @__PURE__ */ jsx("ol", {
99
- className: "flex flex-col gap-2",
100
- children: rows.map((entry_4, index_0) => {
101
- const error = showErrors && entry_4.url.trim() ? errorOf(entry_4.url) : void 0;
102
- return /* @__PURE__ */ jsxs("li", {
103
- className: "flex flex-col gap-1",
104
- children: [/* @__PURE__ */ jsxs("div", {
105
- className: "flex items-center gap-1",
106
- children: [
107
- /* @__PURE__ */ jsx(Input, {
108
- type: "url",
109
- value: entry_4.url,
110
- placeholder: "https://www.linkedin.com/company/…",
111
- "aria-label": `Profile ${index_0 + 1}`,
112
- "aria-invalid": error ? true : void 0,
113
- disabled: save.isPending,
114
- onChange: (event_0) => update(entry_4.key, event_0.target.value)
115
- }),
116
- /* @__PURE__ */ jsx(Button, {
117
- type: "button",
118
- variant: "ghost",
119
- size: "icon",
120
- "aria-label": "Move up",
121
- disabled: index_0 === 0 || save.isPending,
122
- onClick: () => move(index_0, -1),
123
- children: /* @__PURE__ */ jsx(ArrowUp, {})
124
- }),
125
- /* @__PURE__ */ jsx(Button, {
126
- type: "button",
127
- variant: "ghost",
128
- size: "icon",
129
- "aria-label": "Move down",
130
- disabled: index_0 === rows.length - 1 || save.isPending,
131
- onClick: () => move(index_0, 1),
132
- children: /* @__PURE__ */ jsx(ArrowDown, {})
133
- }),
134
- /* @__PURE__ */ jsx(Button, {
135
- type: "button",
136
- variant: "ghost",
137
- size: "icon",
138
- "aria-label": "Remove",
139
- disabled: save.isPending,
140
- onClick: () => remove(entry_4.key),
141
- children: /* @__PURE__ */ jsx(Trash2, {})
142
- })
143
- ]
144
- }), error && /* @__PURE__ */ jsx("p", {
145
- className: "text-destructive text-xs",
146
- children: error
147
- })]
148
- }, entry_4.key);
92
+ $[6] = errorOf;
93
+ $[7] = filled;
94
+ $[8] = project.id;
95
+ $[9] = save;
96
+ $[10] = t6;
97
+ } else t6 = $[10];
98
+ const submit = t6;
99
+ let t7;
100
+ if ($[11] !== errorOf || $[12] !== handleDragEnd || $[13] !== remove || $[14] !== rows || $[15] !== save.isPending || $[16] !== sensors || $[17] !== showErrors || $[18] !== update) {
101
+ t7 = rows.length > 0 && /* @__PURE__ */ jsx(DndContext, {
102
+ sensors,
103
+ collisionDetection: closestCenter,
104
+ onDragEnd: handleDragEnd,
105
+ modifiers: [restrictToVerticalAxis],
106
+ children: /* @__PURE__ */ jsx(SortableContext, {
107
+ items: rows.map(_temp5),
108
+ strategy: verticalListSortingStrategy,
109
+ children: /* @__PURE__ */ jsx("ol", {
110
+ className: "flex flex-col gap-2",
111
+ children: rows.map((entry_8, index_0) => /* @__PURE__ */ jsx(SortableProfileRow, {
112
+ entry: entry_8,
113
+ index: index_0,
114
+ error: showErrors && entry_8.url.trim() ? errorOf(entry_8.url) : void 0,
115
+ disabled: save.isPending,
116
+ onChange: (url_1) => update(entry_8.key, url_1),
117
+ onRemove: () => remove(entry_8.key)
118
+ }, entry_8.key))
119
+ })
149
120
  })
150
121
  });
151
- $[13] = rows;
152
- $[14] = save.isPending;
153
- $[15] = showErrors;
154
- $[16] = t8;
155
- } else t8 = $[16];
122
+ $[11] = errorOf;
123
+ $[12] = handleDragEnd;
124
+ $[13] = remove;
125
+ $[14] = rows;
126
+ $[15] = save.isPending;
127
+ $[16] = sensors;
128
+ $[17] = showErrors;
129
+ $[18] = update;
130
+ $[19] = t7;
131
+ } else t7 = $[19];
132
+ const t8 = !hasChanges || save.isPending;
156
133
  let t9;
157
- if ($[17] !== save.isPending) {
134
+ if ($[20] !== save.isPending) {
158
135
  t9 = save.isPending && /* @__PURE__ */ jsx(Spinner, {});
159
- $[17] = save.isPending;
160
- $[18] = t9;
161
- } else t9 = $[18];
136
+ $[20] = save.isPending;
137
+ $[21] = t9;
138
+ } else t9 = $[21];
162
139
  let t10;
163
- if ($[19] !== save.isPending || $[20] !== t9) {
140
+ if ($[22] !== t8 || $[23] !== t9) {
164
141
  t10 = /* @__PURE__ */ jsxs(Button, {
165
142
  type: "submit",
166
- disabled: save.isPending,
143
+ disabled: t8,
167
144
  children: [t9, "Save"]
168
145
  });
169
- $[19] = save.isPending;
170
- $[20] = t9;
171
- $[21] = t10;
172
- } else t10 = $[21];
146
+ $[22] = t8;
147
+ $[23] = t9;
148
+ $[24] = t10;
149
+ } else t10 = $[24];
173
150
  let t11;
174
151
  let t12;
175
- if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
176
- t11 = () => setRows(_temp5);
152
+ if ($[25] === Symbol.for("react.memo_cache_sentinel")) {
153
+ t11 = () => setRows(_temp6);
177
154
  t12 = /* @__PURE__ */ jsx(Plus, {});
178
- $[22] = t11;
179
- $[23] = t12;
155
+ $[25] = t11;
156
+ $[26] = t12;
180
157
  } else {
181
- t11 = $[22];
182
- t12 = $[23];
158
+ t11 = $[25];
159
+ t12 = $[26];
183
160
  }
184
161
  let t13;
185
- if ($[24] !== save.isPending) {
162
+ if ($[27] !== save.isPending) {
186
163
  t13 = /* @__PURE__ */ jsxs(Button, {
187
164
  type: "button",
188
- variant: "ghost",
165
+ variant: "outline",
189
166
  disabled: save.isPending,
190
167
  onClick: t11,
191
168
  children: [t12, "Add profile"]
192
169
  });
193
- $[24] = save.isPending;
194
- $[25] = t13;
195
- } else t13 = $[25];
170
+ $[27] = save.isPending;
171
+ $[28] = t13;
172
+ } else t13 = $[28];
196
173
  let t14;
197
- if ($[26] !== t10 || $[27] !== t13) {
174
+ if ($[29] !== t10 || $[30] !== t13) {
198
175
  t14 = /* @__PURE__ */ jsxs("div", {
199
176
  className: "flex flex-wrap gap-2",
200
177
  children: [t10, t13]
201
178
  });
202
- $[26] = t10;
203
- $[27] = t13;
204
- $[28] = t14;
205
- } else t14 = $[28];
179
+ $[29] = t10;
180
+ $[30] = t13;
181
+ $[31] = t14;
182
+ } else t14 = $[31];
206
183
  let t15;
207
- if ($[29] !== submit || $[30] !== t14 || $[31] !== t8) {
184
+ if ($[32] !== submit || $[33] !== t14 || $[34] !== t7) {
208
185
  t15 = /* @__PURE__ */ jsx(SettingsPart, {
209
186
  title: "Social profiles",
210
187
  description: "The project's accounts elsewhere, such as on LinkedIn, X or GitHub. Search engines and AI answer engines use them to tie the website to your organization.",
211
188
  children: /* @__PURE__ */ jsxs("form", {
212
189
  onSubmit: submit,
213
190
  className: "flex flex-col gap-4",
214
- children: [t8, t14]
191
+ children: [t7, t14]
215
192
  })
216
193
  });
217
- $[29] = submit;
218
- $[30] = t14;
219
- $[31] = t8;
220
- $[32] = t15;
221
- } else t15 = $[32];
194
+ $[32] = submit;
195
+ $[33] = t14;
196
+ $[34] = t7;
197
+ $[35] = t15;
198
+ } else t15 = $[35];
222
199
  return t15;
223
200
  }
224
- function _temp5(current_2) {
201
+ function _temp6(current_2) {
225
202
  return [...current_2, row("")];
226
203
  }
227
- function _temp4(entry_3) {
228
- return entry_3.url;
204
+ function _temp5(entry_7) {
205
+ return entry_7.key;
206
+ }
207
+ function _temp4(entry_6) {
208
+ return entry_6.url;
229
209
  }
230
210
  function _temp3(url) {
231
211
  const result = socialProfileUrlSchema.safeParse(url.trim());
@@ -240,6 +220,159 @@ function _temp(entry) {
240
220
  url: entry.url.trim()
241
221
  };
242
222
  }
223
+ function SortableProfileRow(t0) {
224
+ const $ = c(41);
225
+ const { entry, index, error, disabled, onChange, onRemove } = t0;
226
+ let t1;
227
+ if ($[0] !== disabled || $[1] !== entry.key) {
228
+ t1 = {
229
+ id: entry.key,
230
+ disabled
231
+ };
232
+ $[0] = disabled;
233
+ $[1] = entry.key;
234
+ $[2] = t1;
235
+ } else t1 = $[2];
236
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable(t1);
237
+ let t2;
238
+ if ($[3] !== transform) {
239
+ t2 = CSS.Transform.toString(transform);
240
+ $[3] = transform;
241
+ $[4] = t2;
242
+ } else t2 = $[4];
243
+ const t3 = isDragging ? .5 : 1;
244
+ let t4;
245
+ if ($[5] !== t2 || $[6] !== t3 || $[7] !== transition) {
246
+ t4 = {
247
+ transform: t2,
248
+ transition,
249
+ opacity: t3
250
+ };
251
+ $[5] = t2;
252
+ $[6] = t3;
253
+ $[7] = transition;
254
+ $[8] = t4;
255
+ } else t4 = $[8];
256
+ const t5 = `Reorder profile ${index + 1}`;
257
+ let t6;
258
+ if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
259
+ t6 = /* @__PURE__ */ jsx(GripVertical, {});
260
+ $[9] = t6;
261
+ } else t6 = $[9];
262
+ let t7;
263
+ if ($[10] !== attributes || $[11] !== disabled || $[12] !== listeners || $[13] !== t5) {
264
+ t7 = /* @__PURE__ */ jsx(Button, {
265
+ type: "button",
266
+ variant: "ghost",
267
+ size: "icon-sm",
268
+ "aria-label": t5,
269
+ className: "text-muted-foreground hover:text-foreground cursor-grab active:cursor-grabbing",
270
+ disabled,
271
+ ...attributes,
272
+ ...listeners,
273
+ children: t6
274
+ });
275
+ $[10] = attributes;
276
+ $[11] = disabled;
277
+ $[12] = listeners;
278
+ $[13] = t5;
279
+ $[14] = t7;
280
+ } else t7 = $[14];
281
+ const t8 = disabled || void 0;
282
+ const t9 = `Profile ${index + 1}`;
283
+ const t10 = error ? true : void 0;
284
+ let t11;
285
+ if ($[15] !== onChange) {
286
+ t11 = (event) => onChange(event.target.value);
287
+ $[15] = onChange;
288
+ $[16] = t11;
289
+ } else t11 = $[16];
290
+ let t12;
291
+ if ($[17] !== disabled || $[18] !== entry.url || $[19] !== t10 || $[20] !== t11 || $[21] !== t9) {
292
+ t12 = /* @__PURE__ */ jsx(InputGroupInput, {
293
+ type: "url",
294
+ value: entry.url,
295
+ placeholder: "https://www.linkedin.com/company/…",
296
+ "aria-label": t9,
297
+ "aria-invalid": t10,
298
+ disabled,
299
+ onChange: t11
300
+ });
301
+ $[17] = disabled;
302
+ $[18] = entry.url;
303
+ $[19] = t10;
304
+ $[20] = t11;
305
+ $[21] = t9;
306
+ $[22] = t12;
307
+ } else t12 = $[22];
308
+ let t13;
309
+ if ($[23] === Symbol.for("react.memo_cache_sentinel")) {
310
+ t13 = /* @__PURE__ */ jsx(Trash2, {});
311
+ $[23] = t13;
312
+ } else t13 = $[23];
313
+ let t14;
314
+ if ($[24] !== disabled || $[25] !== onRemove) {
315
+ t14 = /* @__PURE__ */ jsx(InputGroupAddon, {
316
+ align: "inline-end",
317
+ className: "opacity-0 group-focus-within/input-group:opacity-100 group-hover/input-group:opacity-100",
318
+ children: /* @__PURE__ */ jsx(InputGroupButton, {
319
+ size: "icon-xs",
320
+ "aria-label": "Remove",
321
+ disabled,
322
+ onClick: onRemove,
323
+ children: t13
324
+ })
325
+ });
326
+ $[24] = disabled;
327
+ $[25] = onRemove;
328
+ $[26] = t14;
329
+ } else t14 = $[26];
330
+ let t15;
331
+ if ($[27] !== t12 || $[28] !== t14 || $[29] !== t8) {
332
+ t15 = /* @__PURE__ */ jsxs(InputGroup, {
333
+ "data-disabled": t8,
334
+ children: [t12, t14]
335
+ });
336
+ $[27] = t12;
337
+ $[28] = t14;
338
+ $[29] = t8;
339
+ $[30] = t15;
340
+ } else t15 = $[30];
341
+ let t16;
342
+ if ($[31] !== t15 || $[32] !== t7) {
343
+ t16 = /* @__PURE__ */ jsxs("div", {
344
+ className: "flex items-center gap-1",
345
+ children: [t7, t15]
346
+ });
347
+ $[31] = t15;
348
+ $[32] = t7;
349
+ $[33] = t16;
350
+ } else t16 = $[33];
351
+ let t17;
352
+ if ($[34] !== error) {
353
+ t17 = error && /* @__PURE__ */ jsx("p", {
354
+ className: "text-destructive pl-9 text-xs",
355
+ children: error
356
+ });
357
+ $[34] = error;
358
+ $[35] = t17;
359
+ } else t17 = $[35];
360
+ let t18;
361
+ if ($[36] !== setNodeRef || $[37] !== t16 || $[38] !== t17 || $[39] !== t4) {
362
+ t18 = /* @__PURE__ */ jsxs("li", {
363
+ ref: setNodeRef,
364
+ style: t4,
365
+ className: "flex flex-col gap-1",
366
+ children: [t16, t17]
367
+ });
368
+ $[36] = setNodeRef;
369
+ $[37] = t16;
370
+ $[38] = t17;
371
+ $[39] = t4;
372
+ $[40] = t18;
373
+ } else t18 = $[40];
374
+ return t18;
375
+ }
243
376
 
244
377
  //#endregion
245
378
  export { SocialProfilesSettings };
@@ -5,6 +5,8 @@ import { useMutation } from "@tanstack/react-query";
5
5
  import { toast } from "@camox/ui/toaster";
6
6
 
7
7
  //#region src/features/settings/useProjectMutation.ts
8
+ /** Each project mutation's options, as far as saving with it needs them. */
9
+ const projectMutationOptions = projectMutations;
8
10
  /**
9
11
  * One of the project's mutations, as a Settings part saves with it: once it succeeds the studio
10
12
  * reads the project afresh, then `onSuccess` runs and a toast says `success`; a failure toasts the
@@ -16,11 +18,10 @@ function useProjectMutation(project, mutation, t0) {
16
18
  const studioCache = useStudioCache();
17
19
  let t1;
18
20
  if ($[0] !== mutation) {
19
- t1 = projectMutations[mutation]();
21
+ t1 = projectMutationOptions[mutation]();
20
22
  $[0] = mutation;
21
23
  $[1] = t1;
22
24
  } else t1 = $[1];
23
- const options = t1;
24
25
  let t2;
25
26
  if ($[2] !== onSuccess || $[3] !== project || $[4] !== studioCache || $[5] !== success) {
26
27
  t2 = async (_, variables) => {
@@ -43,13 +44,13 @@ function useProjectMutation(project, mutation, t0) {
43
44
  $[8] = t3;
44
45
  } else t3 = $[8];
45
46
  let t4;
46
- if ($[9] !== options || $[10] !== t2 || $[11] !== t3) {
47
+ if ($[9] !== t1 || $[10] !== t2 || $[11] !== t3) {
47
48
  t4 = {
48
- ...options,
49
+ ...t1,
49
50
  onSuccess: t2,
50
51
  onError: t3
51
52
  };
52
- $[9] = options;
53
+ $[9] = t1;
53
54
  $[10] = t2;
54
55
  $[11] = t3;
55
56
  $[12] = t4;
@@ -4,10 +4,12 @@ import { useLocation, useNavigate } from "../navigation/navigation.js";
4
4
  import { useProjectUuid } from "../../lib/auth.js";
5
5
  import { reads, useReadQueries, useReadQuery } from "../../lib/studio-reads.js";
6
6
  import { useRoutableLayouts } from "../../lib/studio-definitions.js";
7
+ import { STUDIO_CANVAS_PATH } from "./routes.js";
7
8
  import { FollowAgentContext } from "./followAgentContext.js";
8
9
  import { canvasPageId, getCanvasPages } from "../canvas/canvasPages.js";
9
10
  import { selectedCanvasPage } from "../canvas/canvasSelection.js";
10
11
  import { useDiscoveredPreviewPaths } from "../canvas/useDiscoveredPreviewPaths.js";
12
+ import { EditorWhereContext } from "./editorWhereContext.js";
11
13
  import { createFollowAgent } from "./followAgent.js";
12
14
  import { c } from "react/compiler-runtime";
13
15
  import * as React from "react";
@@ -99,9 +101,27 @@ function useCurrentPageBlocks(page, path) {
99
101
  function _temp(id) {
100
102
  return reads.blockBundle(id);
101
103
  }
102
- /** Where the editor is, and the Studio content following locates the agent's touches with. */
104
+ /** Where the editor is, for the agent to read, from the Page they look at, if any. */
105
+ function editorWhereOf(current, path, locale) {
106
+ if (path === "/camox/canvas") return {
107
+ on: "canvas",
108
+ locale
109
+ };
110
+ if (!current) return void 0;
111
+ return {
112
+ on: "page",
113
+ locale,
114
+ path,
115
+ title: current.title,
116
+ ...current.kind === "curated" ? { pageId: current.pageId } : { layoutId: current.layoutId }
117
+ };
118
+ }
119
+ /**
120
+ * Where the editor is, with the Studio content following locates the agent's touches with, and
121
+ * as the agent reads it.
122
+ */
103
123
  function useFollowWhere(runtimeBasePath) {
104
- const $ = c(35);
124
+ const $ = c(44);
105
125
  const layouts = useRoutableLayouts();
106
126
  const projectUuid = useProjectUuid();
107
127
  const location = useLocation();
@@ -155,7 +175,8 @@ function useFollowWhere(runtimeBasePath) {
155
175
  $[17] = location.pathname;
156
176
  $[18] = t6;
157
177
  } else t6 = $[18];
158
- const blocks = useCurrentPageBlocks(current, t6.path);
178
+ const path = t6.path;
179
+ const blocks = useCurrentPageBlocks(current, path);
159
180
  let t7;
160
181
  if ($[19] !== blocks || $[20] !== canvasPages || $[21] !== current?.key || $[22] !== pageList) {
161
182
  t7 = () => {
@@ -221,7 +242,34 @@ function useFollowWhere(runtimeBasePath) {
221
242
  $[33] = t9;
222
243
  $[34] = t11;
223
244
  } else t11 = $[34];
224
- return t11;
245
+ const where = t11;
246
+ let t12;
247
+ if ($[35] !== current || $[36] !== locale.tag || $[37] !== path) {
248
+ t12 = JSON.stringify(editorWhereOf(current, path, locale.tag) ?? null);
249
+ $[35] = current;
250
+ $[36] = locale.tag;
251
+ $[37] = path;
252
+ $[38] = t12;
253
+ } else t12 = $[38];
254
+ const json = t12;
255
+ let t13;
256
+ if ($[39] !== json) {
257
+ t13 = JSON.parse(json) ?? void 0;
258
+ $[39] = json;
259
+ $[40] = t13;
260
+ } else t13 = $[40];
261
+ const editorWhere = t13;
262
+ let t14;
263
+ if ($[41] !== editorWhere || $[42] !== where) {
264
+ t14 = {
265
+ where,
266
+ editorWhere
267
+ };
268
+ $[41] = editorWhere;
269
+ $[42] = where;
270
+ $[43] = t14;
271
+ } else t14 = $[43];
272
+ return t14;
225
273
  }
226
274
  function _temp2(page) {
227
275
  return [page.id, page.layoutId];
@@ -229,12 +277,13 @@ function _temp2(page) {
229
277
  /**
230
278
  * Follows the agent for the Studio session, across its pages and into the draft its Live thread
231
279
  * starts: the Canvas or the Preview goes where the editor's runs write. Only the Website Section
232
- * follows; elsewhere in the Studio, the editor stays where they are.
280
+ * follows; elsewhere in the Studio, the editor stays where they are. It tells the thread where
281
+ * the editor is too, which their messages carry to the agent.
233
282
  */
234
283
  function FollowAgentProvider(t0) {
235
- const $ = c(18);
284
+ const $ = c(21);
236
285
  const { runtimeBasePath, website, children } = t0;
237
- const where = useFollowWhere(runtimeBasePath);
286
+ const { where, editorWhere } = useFollowWhere(runtimeBasePath);
238
287
  const navigate = useNavigate();
239
288
  let t1;
240
289
  if ($[0] !== navigate || $[1] !== where) {
@@ -311,16 +360,26 @@ function FollowAgentProvider(t0) {
311
360
  } else t7 = $[14];
312
361
  const value = t7;
313
362
  let t8;
314
- if ($[15] !== children || $[16] !== value) {
315
- t8 = /* @__PURE__ */ jsx(FollowAgentContext, {
316
- value,
363
+ if ($[15] !== children || $[16] !== editorWhere) {
364
+ t8 = /* @__PURE__ */ jsx(EditorWhereContext, {
365
+ value: editorWhere,
317
366
  children
318
367
  });
319
368
  $[15] = children;
320
- $[16] = value;
369
+ $[16] = editorWhere;
321
370
  $[17] = t8;
322
371
  } else t8 = $[17];
323
- return t8;
372
+ let t9;
373
+ if ($[18] !== t8 || $[19] !== value) {
374
+ t9 = /* @__PURE__ */ jsx(FollowAgentContext, {
375
+ value,
376
+ children: t8
377
+ });
378
+ $[18] = t8;
379
+ $[19] = value;
380
+ $[20] = t9;
381
+ } else t9 = $[20];
382
+ return t9;
324
383
  }
325
384
 
326
385
  //#endregion