camox 0.62.0 → 0.65.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/core/createApp.d.ts +28 -28
  2. package/dist/core/createLayout.d.ts +1 -1
  3. package/dist/core/derivedRoutes.js +3 -30
  4. package/dist/core/editing/createEditableBlock.d.ts +604 -604
  5. package/dist/features/canvas/canvasCamera.js +11 -2
  6. package/dist/features/canvas/useCanvasCamera.js +14 -10
  7. package/dist/features/page/CuratedPageContent.js +2 -1
  8. package/dist/features/page/UnplacedBlockContent.js +52 -0
  9. package/dist/features/preview/components/PreviewPanel.js +40 -12
  10. package/dist/features/preview/components/SidebarStack.js +78 -9
  11. package/dist/features/preview/strayCaretGuard.js +34 -0
  12. package/dist/features/provider/CoreCamoxProvider.js +5 -3
  13. package/dist/features/routes/pageRuntime.d.ts +2 -0
  14. package/dist/features/routes/pageRuntime.js +8 -5
  15. package/dist/features/runtime/pageApp.js +111 -74
  16. package/dist/features/runtime/pageClient.js +22 -2
  17. package/dist/features/runtime/runtime.d.ts +10 -0
  18. package/dist/features/runtime/runtime.js +314 -4
  19. package/dist/features/runtime/runtimeRoutes.d.ts +5 -0
  20. package/dist/features/runtime/runtimeRoutes.js +5 -0
  21. package/dist/features/studio/components/ChatWidget.js +88 -62
  22. package/dist/features/studio/components/ConnectAgent.js +313 -0
  23. package/dist/features/studio/components/Patrol.js +455 -205
  24. package/dist/features/studio/components/ReviewDraftSheet.js +431 -334
  25. package/dist/features/studio/components/Squareling.js +74 -41
  26. package/dist/features/studio/components/ThreadComposer.js +130 -107
  27. package/dist/features/studio/components/ThreadMessages.js +136 -30
  28. package/dist/features/studio/components/clientLogoPaths.js +10 -0
  29. package/dist/features/studio/findingSentence.js +37 -0
  30. package/dist/features/studio/reportSentence.js +15 -0
  31. package/dist/features/studio/studioStore.js +23 -1
  32. package/dist/features/studio/workingSentence.js +8 -0
  33. package/dist/lib/api-client.d.ts +1 -0
  34. package/dist/lib/auth.js +34 -32
  35. package/dist/lib/locale-path.js +1 -7
  36. package/dist/lib/queries.js +9 -1
  37. package/dist/lib/server-auth-cookie.js +17 -4
  38. package/dist/lib/studio-reads.d.ts +1 -1
  39. package/dist/lib/studio-reads.js +5 -1
  40. package/dist/package.js +1 -1
  41. package/dist/studio.css +1 -1
  42. package/package.json +16 -5
@@ -14,6 +14,8 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
14
  * while it works; the SEO manager is a tall block with the small shape's soft corner, in amber,
15
15
  * scanning down while it works.
16
16
  *
17
+ * A patroller off duty where the editor is sleeps, eyes closed, breathing slowly.
18
+ *
17
19
  * One face flows into the next: its eyes glide to where the next face holds them, opening or
18
20
  * narrowing, and a looping motion settles before the next one starts (`useFaceChange`).
19
21
  */
@@ -67,7 +69,8 @@ function Squareling(props) {
67
69
  status: props.status
68
70
  }) : /* @__PURE__ */ jsx(PatrollerEyes, {
69
71
  eyes: look.eyes,
70
- working: props.status === "working"
72
+ working: props.status === "working",
73
+ asleep: props.status === "asleep"
71
74
  })
72
75
  })
73
76
  });
@@ -183,6 +186,24 @@ const LOOKS = {
183
186
  x: [44, 63],
184
187
  y: 28
185
188
  }
189
+ },
190
+ linkChecker: {
191
+ body: "M32 14H68Q86 14 86 32V68Q86 86 68 86H32Q14 86 14 68V32Q14 14 32 14Z",
192
+ middle: 50,
193
+ fill: "fill-sky-500",
194
+ eyes: {
195
+ x: [40, 59],
196
+ y: 32
197
+ }
198
+ },
199
+ proofreader: {
200
+ body: "M20 10H64L88 34V82Q88 90 80 90H20Q12 90 12 82V18Q12 10 20 10Z",
201
+ middle: 50,
202
+ fill: "fill-rose-500",
203
+ eyes: {
204
+ x: [34, 53],
205
+ y: 38
206
+ }
186
207
  }
187
208
  };
188
209
  const EYE_WIDTH = 11;
@@ -192,60 +213,68 @@ const OPEN = 17;
192
213
  const NARROWED = 6;
193
214
  /** How far down a narrowed eye's middle sits, from the open one's. */
194
215
  const NARROWED_SHIFT = 2.5;
216
+ const CLOSED = 2;
217
+ /** How far down a closed eye's middle sits, from the open one's: near its lower lid. */
218
+ const CLOSED_SHIFT = 5;
195
219
  /**
196
- * One eye, its left edge at `x` and its top at `y`: open, or narrowed on the work, lower down.
197
- * It narrows by scaling, which `studio.css` eases. Only an eye that blinks carries the class
198
- * `studio.css` blinks.
220
+ * One eye, its left edge at `x` and its top at `y`: open, narrowed on the work, or closed, each
221
+ * lower down. It narrows and closes by scaling, which `studio.css` eases. Only an eye that blinks
222
+ * carries the class `studio.css` blinks.
199
223
  */
200
224
  function Eye(t0) {
201
- const $ = c(9);
202
- const { x, y, narrowed, blinks } = t0;
203
- const t1 = blinks && "squareling-blinks";
204
- let t2;
205
- if ($[0] !== t1) {
206
- t2 = cn("squareling-eye", t1);
207
- $[0] = t1;
208
- $[1] = t2;
209
- } else t2 = $[1];
225
+ const $ = c(7);
226
+ const { x, y, narrowed, closed: t1, blinks } = t0;
227
+ const openness = (t1 === void 0 ? false : t1) ? "closed" : narrowed ? "narrowed" : "open";
228
+ const t2 = blinks && "squareling-blinks";
210
229
  let t3;
211
- if ($[2] !== narrowed) {
212
- t3 = narrowed ? {
213
- scale: `1 ${NARROWED / OPEN}`,
214
- translate: `0 ${NARROWED_SHIFT}px`
215
- } : {
216
- scale: "1",
217
- translate: "0"
218
- };
219
- $[2] = narrowed;
220
- $[3] = t3;
221
- } else t3 = $[3];
222
- let t4;
223
- if ($[4] !== t2 || $[5] !== t3 || $[6] !== x || $[7] !== y) {
224
- t4 = /* @__PURE__ */ jsx("rect", {
225
- className: t2,
230
+ if ($[0] !== t2) {
231
+ t3 = cn("squareling-eye", t2);
232
+ $[0] = t2;
233
+ $[1] = t3;
234
+ } else t3 = $[1];
235
+ const t4 = EYE_STYLES[openness];
236
+ let t5;
237
+ if ($[2] !== t3 || $[3] !== t4 || $[4] !== x || $[5] !== y) {
238
+ t5 = /* @__PURE__ */ jsx("rect", {
239
+ className: t3,
226
240
  x,
227
241
  y,
228
242
  width: EYE_WIDTH,
229
243
  height: OPEN,
230
- style: t3
244
+ style: t4
231
245
  });
232
- $[4] = t2;
233
- $[5] = t3;
234
- $[6] = x;
235
- $[7] = y;
236
- $[8] = t4;
237
- } else t4 = $[8];
238
- return t4;
246
+ $[2] = t3;
247
+ $[3] = t4;
248
+ $[4] = x;
249
+ $[5] = y;
250
+ $[6] = t5;
251
+ } else t5 = $[6];
252
+ return t5;
239
253
  }
254
+ const EYE_STYLES = {
255
+ open: {
256
+ scale: "1",
257
+ translate: "0"
258
+ },
259
+ narrowed: {
260
+ scale: `1 ${NARROWED / OPEN}`,
261
+ translate: `0 ${NARROWED_SHIFT}px`
262
+ },
263
+ closed: {
264
+ scale: `1 ${CLOSED / OPEN}`,
265
+ translate: `0 ${CLOSED_SHIFT}px`
266
+ }
267
+ };
240
268
  /**
241
269
  * The agent's eyes: both narrowed on the work while making changes, the right one while fixing,
242
- * open otherwise, blinking unless it looks around.
270
+ * open otherwise, blinking unless it looks around, makes changes, or checks the design, its eyes
271
+ * fixed on it.
243
272
  */
244
273
  function AgentEyes(t0) {
245
274
  const $ = c(13);
246
275
  const { eyes, status } = t0;
247
276
  const [left, right] = eyes.x;
248
- const blinks = status !== "exploring" && status !== "changing";
277
+ const blinks = status !== "exploring" && status !== "changing" && status !== "checking";
249
278
  const t1 = status === "changing";
250
279
  let t2;
251
280
  if ($[0] !== blinks || $[1] !== eyes.y || $[2] !== left || $[3] !== t1) {
@@ -285,13 +314,17 @@ function AgentEyes(t0) {
285
314
  } else t5 = $[12];
286
315
  return t5;
287
316
  }
288
- /** A patroller's eyes: open while idle, narrowed on the work while working. */
289
- function PatrollerEyes({ eyes, working }) {
317
+ /**
318
+ * A patroller's eyes: open while idle, narrowed on the work while working, closed while asleep,
319
+ * when they don't blink.
320
+ */
321
+ function PatrollerEyes({ eyes, working, asleep }) {
290
322
  return eyes.x.map((x) => /* @__PURE__ */ jsx(Eye, {
291
323
  x,
292
324
  y: eyes.y,
293
325
  narrowed: working,
294
- blinks: true
326
+ closed: asleep,
327
+ blinks: !asleep
295
328
  }, x));
296
329
  }
297
330
 
@@ -1,5 +1,5 @@
1
1
  import { c } from "react/compiler-runtime";
2
- import { useState } from "react";
2
+ import { useEffect, useRef, useState } from "react";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  import { ArrowUp, Square, SquareDashedMousePointer, X } from "lucide-react";
5
5
  import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupTextarea } from "@camox/ui/input-group";
@@ -8,47 +8,69 @@ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupTextarea } fro
8
8
  /**
9
9
  * Where an editor writes to the agent: Enter sends, Shift+Enter adds a line. While a run is
10
10
  * going, sending steers it, and a Stop button sits beside Send. Over the message, what the
11
- * editor has selected, which their messages carry to the agent until they clear it.
11
+ * editor has selected, which their messages carry to the agent until they clear it. A message
12
+ * filled in from elsewhere in the studio replaces what the editor wrote, for them to send.
12
13
  */
13
14
  function ThreadComposer(t0) {
14
- const $ = c(36);
15
- const { onSend, onStop, selection, onClearSelection, running: t1, disabled: t2 } = t0;
15
+ const $ = c(39);
16
+ const { onSend, onStop, selection, onClearSelection, running: t1, disabled: t2, filled } = t0;
16
17
  const running = t1 === void 0 ? false : t1;
17
18
  const disabled = t2 === void 0 ? false : t2;
18
19
  const [text, setText] = useState("");
20
+ const [filledId, setFilledId] = useState();
21
+ if (filled && filled.id !== filledId) {
22
+ setFilledId(filled.id);
23
+ setText(filled.text);
24
+ }
25
+ const box = useRef(null);
19
26
  let t3;
20
- if ($[0] !== text) {
21
- t3 = text.trim();
22
- $[0] = text;
27
+ let t4;
28
+ if ($[0] !== filledId) {
29
+ t3 = () => {
30
+ if (filledId !== void 0) box.current?.focus();
31
+ };
32
+ t4 = [filledId];
33
+ $[0] = filledId;
23
34
  $[1] = t3;
24
- } else t3 = $[1];
25
- const message = t3;
35
+ $[2] = t4;
36
+ } else {
37
+ t3 = $[1];
38
+ t4 = $[2];
39
+ }
40
+ useEffect(t3, t4);
41
+ let t5;
42
+ if ($[3] !== text) {
43
+ t5 = text.trim();
44
+ $[3] = text;
45
+ $[4] = t5;
46
+ } else t5 = $[4];
47
+ const message = t5;
26
48
  const canSend = !disabled && message !== "" && onSend !== void 0;
27
- let t4;
28
- if ($[2] !== canSend || $[3] !== message || $[4] !== onSend) {
29
- t4 = () => {
49
+ let t6;
50
+ if ($[5] !== canSend || $[6] !== message || $[7] !== onSend) {
51
+ t6 = () => {
30
52
  if (!canSend) return;
31
53
  onSend(message);
32
54
  setText("");
33
55
  };
34
- $[2] = canSend;
35
- $[3] = message;
36
- $[4] = onSend;
37
- $[5] = t4;
38
- } else t4 = $[5];
39
- const submit = t4;
40
- let t5;
41
- if ($[6] !== submit) {
42
- t5 = (event) => {
56
+ $[5] = canSend;
57
+ $[6] = message;
58
+ $[7] = onSend;
59
+ $[8] = t6;
60
+ } else t6 = $[8];
61
+ const submit = t6;
62
+ let t7;
63
+ if ($[9] !== submit) {
64
+ t7 = (event) => {
43
65
  event.preventDefault();
44
66
  submit();
45
67
  };
46
- $[6] = submit;
47
- $[7] = t5;
48
- } else t5 = $[7];
49
- let t6;
50
- if ($[8] !== onClearSelection || $[9] !== selection) {
51
- t6 = selection && /* @__PURE__ */ jsx(InputGroupAddon, {
68
+ $[9] = submit;
69
+ $[10] = t7;
70
+ } else t7 = $[10];
71
+ let t8;
72
+ if ($[11] !== onClearSelection || $[12] !== selection) {
73
+ t8 = selection && /* @__PURE__ */ jsx(InputGroupAddon, {
52
74
  align: "block-start",
53
75
  className: "border-input border-b",
54
76
  children: /* @__PURE__ */ jsx(SelectionChip, {
@@ -56,44 +78,45 @@ function ThreadComposer(t0) {
56
78
  onClear: onClearSelection
57
79
  })
58
80
  });
59
- $[8] = onClearSelection;
60
- $[9] = selection;
61
- $[10] = t6;
62
- } else t6 = $[10];
63
- let t7;
64
- if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
65
- t7 = (event_0) => setText(event_0.target.value);
66
- $[11] = t7;
67
- } else t7 = $[11];
68
- let t8;
69
- if ($[12] !== submit) {
70
- t8 = (event_1) => {
81
+ $[11] = onClearSelection;
82
+ $[12] = selection;
83
+ $[13] = t8;
84
+ } else t8 = $[13];
85
+ let t9;
86
+ if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
87
+ t9 = (event_0) => setText(event_0.target.value);
88
+ $[14] = t9;
89
+ } else t9 = $[14];
90
+ let t10;
91
+ if ($[15] !== submit) {
92
+ t10 = (event_1) => {
71
93
  if (event_1.key !== "Enter" || event_1.shiftKey || event_1.nativeEvent.isComposing) return;
72
94
  event_1.preventDefault();
73
95
  submit();
74
96
  };
75
- $[12] = submit;
76
- $[13] = t8;
77
- } else t8 = $[13];
78
- let t9;
79
- if ($[14] !== disabled || $[15] !== t8 || $[16] !== text) {
80
- t9 = /* @__PURE__ */ jsx(InputGroupTextarea, {
97
+ $[15] = submit;
98
+ $[16] = t10;
99
+ } else t10 = $[16];
100
+ let t11;
101
+ if ($[17] !== disabled || $[18] !== t10 || $[19] !== text) {
102
+ t11 = /* @__PURE__ */ jsx(InputGroupTextarea, {
103
+ ref: box,
81
104
  "aria-label": "Message",
82
105
  placeholder: "Message Camox…",
83
106
  value: text,
84
107
  disabled,
85
- onChange: t7,
86
- onKeyDown: t8,
108
+ onChange: t9,
109
+ onKeyDown: t10,
87
110
  className: "max-h-48 min-h-14"
88
111
  });
89
- $[14] = disabled;
90
- $[15] = t8;
91
- $[16] = text;
92
- $[17] = t9;
93
- } else t9 = $[17];
94
- let t10;
95
- if ($[18] !== disabled || $[19] !== onStop || $[20] !== running) {
96
- t10 = running && onStop && /* @__PURE__ */ jsxs(InputGroupButton, {
112
+ $[17] = disabled;
113
+ $[18] = t10;
114
+ $[19] = text;
115
+ $[20] = t11;
116
+ } else t11 = $[20];
117
+ let t12;
118
+ if ($[21] !== disabled || $[22] !== onStop || $[23] !== running) {
119
+ t12 = running && onStop && /* @__PURE__ */ jsxs(InputGroupButton, {
97
120
  type: "button",
98
121
  variant: "outline",
99
122
  size: "icon-sm",
@@ -104,73 +127,73 @@ function ThreadComposer(t0) {
104
127
  children: "Stop"
105
128
  })]
106
129
  });
107
- $[18] = disabled;
108
- $[19] = onStop;
109
- $[20] = running;
110
- $[21] = t10;
111
- } else t10 = $[21];
112
- const t11 = !canSend;
113
- let t12;
114
- let t13;
115
- if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
116
- t12 = /* @__PURE__ */ jsx(ArrowUp, {});
117
- t13 = /* @__PURE__ */ jsx("span", {
130
+ $[21] = disabled;
131
+ $[22] = onStop;
132
+ $[23] = running;
133
+ $[24] = t12;
134
+ } else t12 = $[24];
135
+ const t13 = !canSend;
136
+ let t14;
137
+ let t15;
138
+ if ($[25] === Symbol.for("react.memo_cache_sentinel")) {
139
+ t14 = /* @__PURE__ */ jsx(ArrowUp, {});
140
+ t15 = /* @__PURE__ */ jsx("span", {
118
141
  className: "sr-only",
119
142
  children: "Send"
120
143
  });
121
- $[22] = t12;
122
- $[23] = t13;
144
+ $[25] = t14;
145
+ $[26] = t15;
123
146
  } else {
124
- t12 = $[22];
125
- t13 = $[23];
147
+ t14 = $[25];
148
+ t15 = $[26];
126
149
  }
127
- let t14;
128
- if ($[24] !== t11) {
129
- t14 = /* @__PURE__ */ jsxs(InputGroupButton, {
150
+ let t16;
151
+ if ($[27] !== t13) {
152
+ t16 = /* @__PURE__ */ jsxs(InputGroupButton, {
130
153
  type: "submit",
131
154
  variant: "default",
132
155
  size: "icon-sm",
133
- disabled: t11,
134
- children: [t12, t13]
156
+ disabled: t13,
157
+ children: [t14, t15]
135
158
  });
136
- $[24] = t11;
137
- $[25] = t14;
138
- } else t14 = $[25];
139
- let t15;
140
- if ($[26] !== t10 || $[27] !== t14) {
141
- t15 = /* @__PURE__ */ jsxs(InputGroupAddon, {
159
+ $[27] = t13;
160
+ $[28] = t16;
161
+ } else t16 = $[28];
162
+ let t17;
163
+ if ($[29] !== t12 || $[30] !== t16) {
164
+ t17 = /* @__PURE__ */ jsxs(InputGroupAddon, {
142
165
  align: "block-end",
143
166
  className: "justify-end",
144
- children: [t10, t14]
167
+ children: [t12, t16]
145
168
  });
146
- $[26] = t10;
147
- $[27] = t14;
148
- $[28] = t15;
149
- } else t15 = $[28];
150
- let t16;
151
- if ($[29] !== t15 || $[30] !== t6 || $[31] !== t9) {
152
- t16 = /* @__PURE__ */ jsxs(InputGroup, { children: [
153
- t6,
154
- t9,
155
- t15
169
+ $[29] = t12;
170
+ $[30] = t16;
171
+ $[31] = t17;
172
+ } else t17 = $[31];
173
+ let t18;
174
+ if ($[32] !== t11 || $[33] !== t17 || $[34] !== t8) {
175
+ t18 = /* @__PURE__ */ jsxs(InputGroup, { children: [
176
+ t8,
177
+ t11,
178
+ t17
156
179
  ] });
157
- $[29] = t15;
158
- $[30] = t6;
159
- $[31] = t9;
160
- $[32] = t16;
161
- } else t16 = $[32];
162
- let t17;
163
- if ($[33] !== t16 || $[34] !== t5) {
164
- t17 = /* @__PURE__ */ jsx("form", {
180
+ $[32] = t11;
181
+ $[33] = t17;
182
+ $[34] = t8;
183
+ $[35] = t18;
184
+ } else t18 = $[35];
185
+ let t19;
186
+ if ($[36] !== t18 || $[37] !== t7) {
187
+ t19 = /* @__PURE__ */ jsx("form", {
165
188
  className: "p-2",
166
- onSubmit: t5,
167
- children: t16
189
+ onSubmit: t7,
190
+ children: t18
168
191
  });
169
- $[33] = t16;
170
- $[34] = t5;
171
- $[35] = t17;
172
- } else t17 = $[35];
173
- return t17;
192
+ $[36] = t18;
193
+ $[37] = t7;
194
+ $[38] = t19;
195
+ } else t19 = $[38];
196
+ return t19;
174
197
  }
175
198
  /** The selection the editor's messages carry, by its name. */
176
199
  function SelectionChip(t0) {