camox 0.65.1 → 0.66.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 (30) hide show
  1. package/dist/features/canvas/CamoxCanvas.js +195 -173
  2. package/dist/features/canvas/canvasFrameCapture.js +5 -12
  3. package/dist/features/canvas/canvasFrameDocument.js +90 -29
  4. package/dist/features/canvas/canvasItems.js +22 -6
  5. package/dist/features/canvas/sidebar/ContentSidebar.js +19 -21
  6. package/dist/features/canvas/sidebar/LayoutPageOverview.js +22 -49
  7. package/dist/features/canvas/sidebar/LayoutPageSeo.js +73 -76
  8. package/dist/features/canvas/sidebar/PageInspector.js +61 -50
  9. package/dist/features/canvas/sidebar/PageInspectorSkeleton.js +4 -4
  10. package/dist/features/canvas/useCanvasCamera.js +22 -5
  11. package/dist/features/preview/components/PageInfo.js +103 -100
  12. package/dist/features/runtime/RuntimeChrome.js +66 -40
  13. package/dist/features/studio/components/AgentSidebar.js +3 -3
  14. package/dist/features/studio/components/ChatWidget.js +34 -29
  15. package/dist/features/studio/components/DraftsControl.js +172 -159
  16. package/dist/features/studio/components/Patrol.js +423 -418
  17. package/dist/features/studio/components/ReviewDraftSheet.js +227 -188
  18. package/dist/features/studio/components/ThreadComposer.js +183 -121
  19. package/dist/features/studio/components/ThreadMessages.js +19 -11
  20. package/dist/features/studio/components/UnnamedDraftBar.js +349 -0
  21. package/dist/features/studio/patrollerBio.js +40 -0
  22. package/dist/features/studio/studioStore.js +13 -0
  23. package/dist/features/studio/workingSentence.js +2 -7
  24. package/dist/lib/revisions.js +25 -3
  25. package/dist/lib/use-thread.js +1 -1
  26. package/dist/package.js +1 -1
  27. package/dist/studio.css +1 -1
  28. package/package.json +4 -4
  29. package/dist/features/canvas/sidebar/DerivedPageInspector.js +0 -49
  30. package/dist/features/canvas/sidebar/SingletonPageInspector.js +0 -39
@@ -10,12 +10,12 @@ import { AssetLightbox } from "../../preview/components/AssetLightbox.js";
10
10
  import { BOTTOM_CARD_EDGES, CARD_BODY_EDGES } from "../../preview/components/SidebarStack.js";
11
11
  import { editCollectionItemPath } from "../routes.js";
12
12
  import { studioStore } from "../studioStore.js";
13
- import { timeAgo } from "../draftLabel.js";
14
13
  import { askAgentMessage, dismissLabel, dismissedSentence, findingSentence, fixLabel } from "../findingSentence.js";
15
14
  import { useShowInCanvas } from "../showInCanvas.js";
16
15
  import { Squareling } from "./Squareling.js";
16
+ import { aboutSentence, whenTag } from "../patrollerBio.js";
17
17
  import { moreSentence, reportSentence, shortTimeAgo, whereReportLeads } from "../reportSentence.js";
18
- import { singleLocaleSentence, workingSentence } from "../workingSentence.js";
18
+ import { workingSentence } from "../workingSentence.js";
19
19
  import { c } from "react/compiler-runtime";
20
20
  import * as React from "react";
21
21
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -59,7 +59,7 @@ function Patrol(t0) {
59
59
  children: "Patrol"
60
60
  })
61
61
  });
62
- t4 = cn("bg-background min-h-0 flex-1 overflow-y-auto", CARD_BODY_EDGES);
62
+ t4 = cn("bg-background flex min-h-0 flex-1 flex-col overflow-y-auto", CARD_BODY_EDGES);
63
63
  $[4] = t3;
64
64
  $[5] = t4;
65
65
  } else {
@@ -100,7 +100,7 @@ function Patrol(t0) {
100
100
  return t7;
101
101
  }
102
102
  function ProjectPatrol(t0) {
103
- const $ = c(53);
103
+ const $ = c(32);
104
104
  const { projectId, inDraft } = t0;
105
105
  let t1;
106
106
  if ($[0] !== projectId) {
@@ -118,193 +118,118 @@ function ProjectPatrol(t0) {
118
118
  const { data: locales } = useReadQuery(t2);
119
119
  const [open, setOpen] = React.useState(null);
120
120
  const now = useNow(3e4);
121
- const [heldOrder, setHeldOrder] = React.useState(null);
122
- const pointerIn = React.useRef(false);
123
- let t3;
124
- if ($[4] !== heldOrder || $[5] !== view) {
125
- t3 = view && inHeldOrder(view, heldOrder);
126
- $[4] = heldOrder;
127
- $[5] = view;
128
- $[6] = t3;
129
- } else t3 = $[6];
130
- const shown = t3;
131
- let t4;
132
- if ($[7] !== shown?.patrollers) {
133
- t4 = shown?.patrollers.map(_temp).join(" ");
134
- $[7] = shown?.patrollers;
135
- $[8] = t4;
136
- } else t4 = $[8];
137
- const roster = useMovingRows(t4);
138
121
  const [openFileId, setOpenFileId] = React.useState(null);
139
122
  const showReport = useShowReport(inDraft, setOpenFileId);
140
123
  const navigate = useNavigate();
141
- let t5;
142
- if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
143
- t5 = patrolMutations.applyFix();
144
- $[9] = t5;
145
- } else t5 = $[9];
146
- const applyFix = useMutation(t5);
124
+ let t3;
125
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
126
+ t3 = patrolMutations.applyFix();
127
+ $[4] = t3;
128
+ } else t3 = $[4];
129
+ const applyFix = useMutation(t3);
130
+ let t4;
131
+ if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
132
+ t4 = patrolMutations.dismissFinding();
133
+ $[5] = t4;
134
+ } else t4 = $[5];
135
+ const dismissFinding = useMutation(t4);
136
+ if (!view) return null;
137
+ const t5 = locales?.length === 1;
147
138
  let t6;
148
- if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
149
- t6 = patrolMutations.dismissFinding();
150
- $[10] = t6;
151
- } else t6 = $[10];
152
- const dismissFinding = useMutation(t6);
153
- if (!shown) return null;
154
- let t7;
155
- if ($[11] !== shown) {
156
- t7 = () => setHeldOrder((held) => held ?? shown.patrollers.map(_temp2));
157
- $[11] = shown;
158
- $[12] = t7;
159
- } else t7 = $[12];
160
- const hold = t7;
161
- let t8;
162
- if ($[13] !== hold) {
163
- t8 = (id_1) => {
164
- setOpen(id_1);
165
- if (id_1) hold();
166
- else if (!pointerIn.current) setHeldOrder(null);
167
- };
168
- $[13] = hold;
169
- $[14] = t8;
170
- } else t8 = $[14];
171
- const openReports = t8;
172
- let t9;
173
- if ($[15] !== hold) {
174
- t9 = () => {
175
- pointerIn.current = true;
176
- hold();
139
+ if ($[6] !== showReport) {
140
+ t6 = (shown) => {
141
+ setOpen(null);
142
+ showReport(shown);
177
143
  };
178
- $[15] = hold;
179
- $[16] = t9;
180
- } else t9 = $[16];
181
- let t10;
182
- if ($[17] !== open) {
183
- t10 = () => {
184
- pointerIn.current = false;
185
- if (!open) setHeldOrder(null);
186
- };
187
- $[17] = open;
188
- $[18] = t10;
189
- } else t10 = $[18];
190
- const t11 = locales?.length === 1;
191
- let t12;
192
- if ($[19] !== openReports || $[20] !== showReport) {
193
- t12 = (shown_0) => {
194
- openReports(null);
195
- showReport(shown_0);
196
- };
197
- $[19] = openReports;
198
- $[20] = showReport;
199
- $[21] = t12;
200
- } else t12 = $[21];
201
- let t13;
202
- if ($[22] !== applyFix || $[23] !== projectId) {
203
- t13 = (finding) => applyFix.mutate({
144
+ $[6] = showReport;
145
+ $[7] = t6;
146
+ } else t6 = $[7];
147
+ let t7;
148
+ if ($[8] !== applyFix || $[9] !== projectId) {
149
+ t7 = (finding) => applyFix.mutate({
204
150
  projectId,
205
151
  findingId: finding.id
206
152
  });
207
- $[22] = applyFix;
208
- $[23] = projectId;
209
- $[24] = t13;
210
- } else t13 = $[24];
211
- let t14;
212
- if ($[25] !== openReports) {
213
- t14 = (patroller, finding_0) => {
214
- openReports(null);
153
+ $[8] = applyFix;
154
+ $[9] = projectId;
155
+ $[10] = t7;
156
+ } else t7 = $[10];
157
+ let t8;
158
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
159
+ t8 = (patroller, finding_0) => {
160
+ setOpen(null);
215
161
  studioStore.trigger.askAgent({ text: askAgentMessage(finding_0, patroller.role) });
216
162
  };
217
- $[25] = openReports;
218
- $[26] = t14;
219
- } else t14 = $[26];
220
- let t15;
221
- if ($[27] !== dismissFinding || $[28] !== projectId) {
222
- t15 = (finding_1) => dismissFinding.mutate({
163
+ $[11] = t8;
164
+ } else t8 = $[11];
165
+ let t9;
166
+ if ($[12] !== dismissFinding || $[13] !== projectId) {
167
+ t9 = (finding_1) => dismissFinding.mutate({
223
168
  projectId,
224
169
  findingId: finding_1.id
225
170
  });
226
- $[27] = dismissFinding;
227
- $[28] = projectId;
228
- $[29] = t15;
229
- } else t15 = $[29];
230
- let t16;
231
- if ($[30] !== navigate || $[31] !== openReports) {
232
- t16 = (draft) => {
233
- openReports(null);
171
+ $[12] = dismissFinding;
172
+ $[13] = projectId;
173
+ $[14] = t9;
174
+ } else t9 = $[14];
175
+ let t10;
176
+ if ($[15] !== navigate) {
177
+ t10 = (draft) => {
178
+ setOpen(null);
234
179
  navigate({
235
180
  to: window.location.href,
236
181
  draft: draft.id
237
182
  });
238
183
  };
239
- $[30] = navigate;
240
- $[31] = openReports;
241
- $[32] = t16;
242
- } else t16 = $[32];
243
- let t17;
244
- if ($[33] !== inDraft || $[34] !== now || $[35] !== open || $[36] !== openReports || $[37] !== shown || $[38] !== t11 || $[39] !== t12 || $[40] !== t13 || $[41] !== t14 || $[42] !== t15 || $[43] !== t16) {
245
- t17 = /* @__PURE__ */ jsx(PatrolRoster, {
246
- view: shown,
184
+ $[15] = navigate;
185
+ $[16] = t10;
186
+ } else t10 = $[16];
187
+ let t11;
188
+ if ($[17] !== inDraft || $[18] !== now || $[19] !== open || $[20] !== t10 || $[21] !== t5 || $[22] !== t6 || $[23] !== t7 || $[24] !== t9 || $[25] !== view) {
189
+ t11 = /* @__PURE__ */ jsx(PatrolRoster, {
190
+ view,
247
191
  now,
248
192
  inDraft,
249
- singleLocale: t11,
193
+ singleLocale: t5,
250
194
  open,
251
- onOpenChange: openReports,
252
- onShow: t12,
253
- onApply: t13,
254
- onAsk: t14,
255
- onDismiss: t15,
256
- onOpenPatrolDraft: t16
195
+ onOpenChange: setOpen,
196
+ onShow: t6,
197
+ onApply: t7,
198
+ onAsk: t8,
199
+ onDismiss: t9,
200
+ onOpenPatrolDraft: t10
257
201
  });
258
- $[33] = inDraft;
259
- $[34] = now;
260
- $[35] = open;
261
- $[36] = openReports;
262
- $[37] = shown;
263
- $[38] = t11;
264
- $[39] = t12;
265
- $[40] = t13;
266
- $[41] = t14;
267
- $[42] = t15;
268
- $[43] = t16;
269
- $[44] = t17;
270
- } else t17 = $[44];
271
- let t18;
272
- if ($[45] !== openFileId) {
273
- t18 = openFileId && /* @__PURE__ */ jsx(AssetLightbox, {
202
+ $[17] = inDraft;
203
+ $[18] = now;
204
+ $[19] = open;
205
+ $[20] = t10;
206
+ $[21] = t5;
207
+ $[22] = t6;
208
+ $[23] = t7;
209
+ $[24] = t9;
210
+ $[25] = view;
211
+ $[26] = t11;
212
+ } else t11 = $[26];
213
+ let t12;
214
+ if ($[27] !== openFileId) {
215
+ t12 = openFileId && /* @__PURE__ */ jsx(AssetLightbox, {
274
216
  open: true,
275
217
  onOpenChange: (open_0) => {
276
218
  if (!open_0) setOpenFileId(null);
277
219
  },
278
220
  fileId: openFileId
279
221
  });
280
- $[45] = openFileId;
281
- $[46] = t18;
282
- } else t18 = $[46];
283
- let t19;
284
- if ($[47] !== roster || $[48] !== t10 || $[49] !== t17 || $[50] !== t18 || $[51] !== t9) {
285
- t19 = /* @__PURE__ */ jsxs("div", {
286
- ref: roster,
287
- className: "relative",
288
- onPointerEnter: t9,
289
- onPointerLeave: t10,
290
- children: [t17, t18]
291
- });
292
- $[47] = roster;
293
- $[48] = t10;
294
- $[49] = t17;
295
- $[50] = t18;
296
- $[51] = t9;
297
- $[52] = t19;
298
- } else t19 = $[52];
299
- return t19;
300
- }
301
- function _temp2(t0) {
302
- const { id: id_0 } = t0;
303
- return id_0;
304
- }
305
- function _temp(t0) {
306
- const { id } = t0;
307
- return id;
222
+ $[27] = openFileId;
223
+ $[28] = t12;
224
+ } else t12 = $[28];
225
+ let t13;
226
+ if ($[29] !== t11 || $[30] !== t12) {
227
+ t13 = /* @__PURE__ */ jsxs("div", { children: [t11, t12] });
228
+ $[29] = t11;
229
+ $[30] = t12;
230
+ $[31] = t13;
231
+ } else t13 = $[31];
232
+ return t13;
308
233
  }
309
234
  /** A report, as the Patrol shows its subject. */
310
235
  const shownOf = (report) => ({
@@ -363,70 +288,10 @@ function useShowReport(inDraft, openFile) {
363
288
  } else t0 = $[5];
364
289
  return t0;
365
290
  }
366
- /**
367
- * The view with its patrollers in the order held, if any, and its latest content: patrollers the
368
- * order doesn't hold follow, in the view's order, and those no longer in the view are dropped.
369
- */
370
- function inHeldOrder(view, order) {
371
- if (!order) return view;
372
- const place = (id) => {
373
- const index = order.indexOf(id);
374
- return index === -1 ? order.length : index;
375
- };
376
- return {
377
- ...view,
378
- patrollers: [...view.patrollers].sort((a, b) => place(a.id) - place(b.id))
379
- };
380
- }
381
- /** How long a patroller takes to move to its new place, in ms. */
382
- const MOVE_DURATION = 250;
383
- /** A strong ease-out: the move starts at once and settles gently. */
384
- const MOVE_EASING = "cubic-bezier(0.23, 1, 0.32, 1)";
385
- /**
386
- * Moves each patroller from where it showed to its new place when the order (a key of their ids)
387
- * changes, rather than jumping there. Without motion for editors who reduce it.
388
- */
389
- function useMovingRows(order) {
390
- const $ = c(2);
391
- const node = React.useRef(null);
392
- const last = React.useRef(null);
393
- let t0;
394
- if ($[0] !== order) {
395
- t0 = () => {
396
- const roster = node.current;
397
- if (!roster) return;
398
- const rows = [...roster.querySelectorAll("[data-patroller]")];
399
- const tops = new Map(rows.map(_temp3));
400
- const previous = last.current;
401
- last.current = {
402
- order,
403
- tops
404
- };
405
- if (!previous || previous.order === order) return;
406
- if (matchMedia("(prefers-reduced-motion: reduce)").matches) return;
407
- for (const row_0 of rows) {
408
- const from = previous.tops.get(row_0.dataset.patroller);
409
- const to = tops.get(row_0.dataset.patroller);
410
- if (from === void 0 || from === to) continue;
411
- row_0.animate([{ transform: `translateY(${from - to}px)` }, { transform: "none" }], {
412
- duration: MOVE_DURATION,
413
- easing: MOVE_EASING
414
- });
415
- }
416
- };
417
- $[0] = order;
418
- $[1] = t0;
419
- } else t0 = $[1];
420
- React.useLayoutEffect(t0);
421
- return node;
422
- }
423
- function _temp3(row) {
424
- return [row.dataset.patroller, row.offsetTop];
425
- }
426
291
  /** The time now, updated every `intervalMs`. */
427
292
  function useNow(intervalMs) {
428
293
  const $ = c(3);
429
- const [now, setNow] = React.useState(_temp4);
294
+ const [now, setNow] = React.useState(_temp);
430
295
  let t0;
431
296
  let t1;
432
297
  if ($[0] !== intervalMs) {
@@ -445,13 +310,14 @@ function useNow(intervalMs) {
445
310
  React.useEffect(t0, t1);
446
311
  return now;
447
312
  }
448
- function _temp4() {
313
+ function _temp() {
449
314
  return Date.now();
450
315
  }
451
316
  /**
452
- * A `PatrolView`, in the order it gives: each patroller's avatar, role, and when it last worked,
453
- * opening its reports in a popover to the left. Live's reports carry a tag when a draft is viewed. In a
454
- * project with a single locale, the Translator invites the editor to add a language instead.
317
+ * A `PatrolView`, in the order it gives, as avatars in rows of three, each over its role like a
318
+ * story. Each opens its reports in a popover to the left, under its role and when it last worked,
319
+ * or what it's on. Live's reports carry a tag when a draft is viewed. In a project with a single
320
+ * locale, the Translator invites the editor to add a language instead.
455
321
  */
456
322
  function PatrolRoster(t0) {
457
323
  const $ = c(27);
@@ -464,7 +330,7 @@ function PatrolRoster(t0) {
464
330
  patroller,
465
331
  now,
466
332
  inDraft,
467
- idle: singleLocale ? singleLocaleSentence(patroller.id) : void 0,
333
+ singleLocale,
468
334
  open: open === patroller.id,
469
335
  onOpenChange: (next) => onOpenChange(next ? patroller.id : null),
470
336
  onShow,
@@ -504,9 +370,12 @@ function PatrolRoster(t0) {
504
370
  } else t1 = $[12];
505
371
  let t2;
506
372
  if ($[25] !== t1) {
507
- t2 = /* @__PURE__ */ jsx("ul", {
508
- className: "flex flex-col gap-px p-1",
509
- children: t1
373
+ t2 = /* @__PURE__ */ jsx("div", {
374
+ className: "px-1 py-3",
375
+ children: /* @__PURE__ */ jsx("ul", {
376
+ className: "mx-auto grid w-fit grid-cols-[repeat(3,5rem)] gap-y-3.5",
377
+ children: t1
378
+ })
510
379
  });
511
380
  $[25] = t1;
512
381
  $[26] = t2;
@@ -514,8 +383,8 @@ function PatrolRoster(t0) {
514
383
  return t2;
515
384
  }
516
385
  /**
517
- * A thin, low-contrast arc travelling around a working patroller's avatar circle, or the whole
518
- * circle pulsing slowly under reduced motion. The motion lives in `studio.css`.
386
+ * A thin, low-contrast arc travelling around a working patroller's avatar, where its story ring
387
+ * goes, or the whole ring pulsing slowly under reduced motion. The motion lives in `studio.css`.
519
388
  */
520
389
  function WorkingArc() {
521
390
  const $ = c(1);
@@ -524,12 +393,12 @@ function WorkingArc() {
524
393
  t0 = /* @__PURE__ */ jsx("svg", {
525
394
  "data-working-indicator": true,
526
395
  "aria-hidden": true,
527
- viewBox: "0 0 32 32",
528
- className: "patrol-working text-foreground/30 pointer-events-none absolute inset-0 size-full",
396
+ viewBox: "0 0 36 36",
397
+ className: "patrol-working text-foreground/40 pointer-events-none absolute -inset-[3px] size-[calc(100%+6px)]",
529
398
  children: /* @__PURE__ */ jsx("circle", {
530
- cx: "16",
531
- cy: "16",
532
- r: "15.25",
399
+ cx: "18",
400
+ cy: "18",
401
+ r: "17.25",
533
402
  pathLength: "100",
534
403
  fill: "none",
535
404
  stroke: "currentColor",
@@ -543,8 +412,8 @@ function WorkingArc() {
543
412
  return t0;
544
413
  }
545
414
  function PatrollerRow(t0) {
546
- const $ = c(65);
547
- const { patroller, now, inDraft, idle, open, onOpenChange, onShow, onApply, onAsk, onDismiss, patrolDraft, onOpenPatrolDraft } = t0;
415
+ const $ = c(53);
416
+ const { patroller, now, inDraft, singleLocale, open, onOpenChange, onShow, onApply, onAsk, onDismiss, patrolDraft, onOpenPatrolDraft } = t0;
548
417
  const statusId = React.useId();
549
418
  let t1;
550
419
  if ($[0] !== patroller.id || $[1] !== patroller.working) {
@@ -554,209 +423,345 @@ function PatrollerRow(t0) {
554
423
  $[2] = t1;
555
424
  } else t1 = $[2];
556
425
  const working = t1;
557
- let t2;
558
- if ($[3] !== idle || $[4] !== now || $[5] !== patroller.duty || $[6] !== patroller.lastActivityAt || $[7] !== working) {
559
- t2 = working ?? idle ?? (patroller.duty === "atPublish" ? "Checks when you publish" : void 0) ?? (patroller.lastActivityAt === null ? "" : timeAgo(patroller.lastActivityAt, now));
560
- $[3] = idle;
561
- $[4] = now;
562
- $[5] = patroller.duty;
563
- $[6] = patroller.lastActivityAt;
564
- $[7] = working;
565
- $[8] = t2;
566
- } else t2 = $[8];
567
- const subtitle = t2;
568
426
  const count = patroller.findings.length;
569
- const t3 = open || void 0;
570
- const t4 = working ? statusId : void 0;
571
- const t5 = working ? "working" : patroller.duty === "off" ? "asleep" : "idle";
572
- let t6;
573
- if ($[9] !== patroller.id || $[10] !== t5) {
574
- t6 = /* @__PURE__ */ jsx(Squareling, {
575
- variant: patroller.id,
576
- status: t5,
577
- className: "size-5"
427
+ const t2 = open || void 0;
428
+ const t3 = working ? statusId : void 0;
429
+ let t4;
430
+ if ($[3] !== count || $[4] !== working) {
431
+ t4 = !working && /* @__PURE__ */ jsx("span", {
432
+ "aria-hidden": true,
433
+ className: cn("group-focus-visible/patroller:ring-ring/50 pointer-events-none absolute -inset-[3px] rounded-full border group-focus-visible/patroller:ring-[3px]", count > 0 ? "border-foreground border-[1.5px]" : "border-border")
578
434
  });
579
- $[9] = patroller.id;
580
- $[10] = t5;
581
- $[11] = t6;
582
- } else t6 = $[11];
435
+ $[3] = count;
436
+ $[4] = working;
437
+ $[5] = t4;
438
+ } else t4 = $[5];
439
+ let t5;
440
+ if ($[6] !== working) {
441
+ t5 = working && /* @__PURE__ */ jsx(WorkingArc, {});
442
+ $[6] = working;
443
+ $[7] = t5;
444
+ } else t5 = $[7];
445
+ const t6 = working ? "working" : patroller.duty === "off" ? "asleep" : "idle";
583
446
  let t7;
584
- if ($[12] !== working) {
585
- t7 = working && /* @__PURE__ */ jsx(WorkingArc, {});
586
- $[12] = working;
587
- $[13] = t7;
588
- } else t7 = $[13];
447
+ if ($[8] !== patroller.id || $[9] !== t6) {
448
+ t7 = /* @__PURE__ */ jsx("span", {
449
+ className: "bg-muted group-hover/patroller:bg-muted-foreground/15 group-data-popup-open/patroller:bg-muted-foreground/15 flex size-full items-center justify-center rounded-full transition-colors",
450
+ children: /* @__PURE__ */ jsx(Squareling, {
451
+ variant: patroller.id,
452
+ status: t6,
453
+ className: "size-6"
454
+ })
455
+ });
456
+ $[8] = patroller.id;
457
+ $[9] = t6;
458
+ $[10] = t7;
459
+ } else t7 = $[10];
589
460
  let t8;
590
- if ($[14] !== t6 || $[15] !== t7) {
591
- t8 = /* @__PURE__ */ jsxs("span", {
592
- className: "bg-muted relative flex size-8 shrink-0 items-center justify-center rounded-full",
593
- children: [t6, t7]
461
+ if ($[11] !== count) {
462
+ t8 = count > 0 && /* @__PURE__ */ jsx("span", {
463
+ "data-findings-count": true,
464
+ "aria-label": `${count} open ${count === 1 ? "finding" : "findings"}`,
465
+ className: "bg-foreground text-background ring-background absolute -top-1.5 -right-1.5 flex h-4 min-w-4 items-center justify-center rounded-full px-1 text-[10px] font-medium tabular-nums ring-2",
466
+ children: count
594
467
  });
595
- $[14] = t6;
468
+ $[11] = count;
469
+ $[12] = t8;
470
+ } else t8 = $[12];
471
+ let t9;
472
+ if ($[13] !== t4 || $[14] !== t5 || $[15] !== t7 || $[16] !== t8) {
473
+ t9 = /* @__PURE__ */ jsxs("span", {
474
+ className: "relative flex size-10 shrink-0 transition-[scale] duration-200 ease-out group-hover/patroller:scale-105 group-active/patroller:scale-95 motion-reduce:transition-none",
475
+ children: [
476
+ t4,
477
+ t5,
478
+ t7,
479
+ t8
480
+ ]
481
+ });
482
+ $[13] = t4;
483
+ $[14] = t5;
596
484
  $[15] = t7;
597
485
  $[16] = t8;
598
- } else t8 = $[16];
599
- let t9;
600
- if ($[17] !== patroller.role) {
601
- t9 = /* @__PURE__ */ jsx("span", {
486
+ $[17] = t9;
487
+ } else t9 = $[17];
488
+ let t10;
489
+ if ($[18] !== patroller.role) {
490
+ t10 = /* @__PURE__ */ jsx("span", {
602
491
  "data-patroller-role": true,
603
- className: "truncate text-sm font-medium",
492
+ className: "max-w-full truncate text-[11px] leading-4 font-medium",
604
493
  children: patroller.role
605
494
  });
606
- $[17] = patroller.role;
607
- $[18] = t9;
608
- } else t9 = $[18];
609
- const t10 = working ? true : void 0;
495
+ $[18] = patroller.role;
496
+ $[19] = t10;
497
+ } else t10 = $[19];
610
498
  let t11;
611
- if ($[19] !== subtitle || $[20] !== t10) {
612
- t11 = /* @__PURE__ */ jsx("span", {
613
- "data-patroller-subtitle": true,
614
- "aria-hidden": t10,
615
- className: "text-muted-foreground truncate text-xs",
616
- children: subtitle
499
+ if ($[20] !== t10 || $[21] !== t3 || $[22] !== t9) {
500
+ t11 = /* @__PURE__ */ jsxs(PopoverTrigger, {
501
+ "aria-describedby": t3,
502
+ className: "group/patroller flex max-w-full min-w-0 cursor-pointer flex-col items-center gap-1 pt-[3px] outline-none",
503
+ children: [t9, t10]
617
504
  });
618
- $[19] = subtitle;
619
505
  $[20] = t10;
620
- $[21] = t11;
621
- } else t11 = $[21];
506
+ $[21] = t3;
507
+ $[22] = t9;
508
+ $[23] = t11;
509
+ } else t11 = $[23];
622
510
  let t12;
623
- if ($[22] !== t11 || $[23] !== t9) {
624
- t12 = /* @__PURE__ */ jsxs("span", {
625
- className: "flex min-w-0 flex-col",
626
- children: [t9, t11]
627
- });
628
- $[22] = t11;
629
- $[23] = t9;
630
- $[24] = t12;
631
- } else t12 = $[24];
511
+ if ($[24] !== onAsk || $[25] !== patroller) {
512
+ t12 = (finding) => onAsk(patroller, finding);
513
+ $[24] = onAsk;
514
+ $[25] = patroller;
515
+ $[26] = t12;
516
+ } else t12 = $[26];
632
517
  let t13;
633
- if ($[25] !== count) {
634
- t13 = count > 0 && /* @__PURE__ */ jsx("span", {
635
- "data-findings-count": true,
636
- "aria-label": `${count} open ${count === 1 ? "finding" : "findings"}`,
637
- className: "bg-foreground text-background ml-auto flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 text-xs font-medium tabular-nums",
638
- children: count
518
+ if ($[27] !== inDraft || $[28] !== now || $[29] !== onApply || $[30] !== onDismiss || $[31] !== onOpenPatrolDraft || $[32] !== onShow || $[33] !== patrolDraft || $[34] !== patroller || $[35] !== singleLocale || $[36] !== t12) {
519
+ t13 = /* @__PURE__ */ jsx(PopoverContent, {
520
+ sideOffset: 8,
521
+ className: "w-96 gap-3 p-4",
522
+ children: /* @__PURE__ */ jsx(PatrollerCard, {
523
+ patroller,
524
+ now,
525
+ inDraft,
526
+ singleLocale,
527
+ onShow,
528
+ onApply,
529
+ onAsk: t12,
530
+ onDismiss,
531
+ patrolDraft,
532
+ onOpenPatrolDraft
533
+ })
639
534
  });
640
- $[25] = count;
641
- $[26] = t13;
642
- } else t13 = $[26];
535
+ $[27] = inDraft;
536
+ $[28] = now;
537
+ $[29] = onApply;
538
+ $[30] = onDismiss;
539
+ $[31] = onOpenPatrolDraft;
540
+ $[32] = onShow;
541
+ $[33] = patrolDraft;
542
+ $[34] = patroller;
543
+ $[35] = singleLocale;
544
+ $[36] = t12;
545
+ $[37] = t13;
546
+ } else t13 = $[37];
643
547
  let t14;
644
- if ($[27] !== t12 || $[28] !== t13 || $[29] !== t4 || $[30] !== t8) {
645
- t14 = /* @__PURE__ */ jsxs(PopoverTrigger, {
646
- "aria-describedby": t4,
647
- className: "hover:bg-muted/60 data-popup-open:bg-muted/60 focus-visible:ring-ring/50 flex cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1.5 text-left outline-none focus-visible:ring-[3px]",
648
- children: [
649
- t8,
650
- t12,
651
- t13
652
- ]
653
- });
654
- $[27] = t12;
655
- $[28] = t13;
656
- $[29] = t4;
657
- $[30] = t8;
658
- $[31] = t14;
659
- } else t14 = $[31];
660
- let t15;
661
- if ($[32] !== patroller.role) {
662
- t15 = /* @__PURE__ */ jsx(PopoverTitle, {
663
- className: "text-sm",
664
- children: patroller.role
665
- });
666
- $[32] = patroller.role;
667
- $[33] = t15;
668
- } else t15 = $[33];
669
- let t16;
670
- if ($[34] !== onAsk || $[35] !== patroller) {
671
- t16 = (finding) => onAsk(patroller, finding);
672
- $[34] = onAsk;
673
- $[35] = patroller;
674
- $[36] = t16;
675
- } else t16 = $[36];
676
- let t17;
677
- if ($[37] !== inDraft || $[38] !== now || $[39] !== onApply || $[40] !== onDismiss || $[41] !== onOpenPatrolDraft || $[42] !== onShow || $[43] !== patrolDraft || $[44] !== patroller || $[45] !== t16) {
678
- t17 = /* @__PURE__ */ jsx(PatrollerDetails, {
679
- patroller,
680
- now,
681
- inDraft,
682
- onShow,
683
- onApply,
684
- onAsk: t16,
685
- onDismiss,
686
- patrolDraft,
687
- onOpenPatrolDraft
688
- });
689
- $[37] = inDraft;
690
- $[38] = now;
691
- $[39] = onApply;
692
- $[40] = onDismiss;
693
- $[41] = onOpenPatrolDraft;
694
- $[42] = onShow;
695
- $[43] = patrolDraft;
696
- $[44] = patroller;
697
- $[45] = t16;
698
- $[46] = t17;
699
- } else t17 = $[46];
700
- let t18;
701
- if ($[47] !== t15 || $[48] !== t17) {
702
- t18 = /* @__PURE__ */ jsxs(PopoverContent, {
703
- side: "left",
704
- align: "start",
705
- sideOffset: 12,
706
- className: "w-80 gap-2 p-3",
707
- children: [t15, t17]
708
- });
709
- $[47] = t15;
710
- $[48] = t17;
711
- $[49] = t18;
712
- } else t18 = $[49];
713
- let t19;
714
- if ($[50] !== onOpenChange || $[51] !== open || $[52] !== t14 || $[53] !== t18) {
715
- t19 = /* @__PURE__ */ jsxs(Popover, {
548
+ if ($[38] !== onOpenChange || $[39] !== open || $[40] !== t11 || $[41] !== t13) {
549
+ t14 = /* @__PURE__ */ jsxs(Popover, {
716
550
  open,
717
551
  onOpenChange,
718
- children: [t14, t18]
552
+ children: [t11, t13]
719
553
  });
720
- $[50] = onOpenChange;
721
- $[51] = open;
722
- $[52] = t14;
723
- $[53] = t18;
724
- $[54] = t19;
725
- } else t19 = $[54];
726
- let t20;
727
- if ($[55] !== working) {
728
- t20 = working && `Working: ${working.charAt(0).toLowerCase()}${working.slice(1)}`;
729
- $[55] = working;
730
- $[56] = t20;
731
- } else t20 = $[56];
732
- let t21;
733
- if ($[57] !== statusId || $[58] !== t20) {
734
- t21 = /* @__PURE__ */ jsx("span", {
554
+ $[38] = onOpenChange;
555
+ $[39] = open;
556
+ $[40] = t11;
557
+ $[41] = t13;
558
+ $[42] = t14;
559
+ } else t14 = $[42];
560
+ let t15;
561
+ if ($[43] !== working) {
562
+ t15 = working && `Working: ${working.charAt(0).toLowerCase()}${working.slice(1)}`;
563
+ $[43] = working;
564
+ $[44] = t15;
565
+ } else t15 = $[44];
566
+ let t16;
567
+ if ($[45] !== statusId || $[46] !== t15) {
568
+ t16 = /* @__PURE__ */ jsx("span", {
735
569
  id: statusId,
736
570
  "data-working-status": true,
737
571
  role: "status",
738
572
  className: "sr-only",
739
- children: t20
573
+ children: t15
740
574
  });
741
- $[57] = statusId;
742
- $[58] = t20;
743
- $[59] = t21;
744
- } else t21 = $[59];
745
- let t22;
746
- if ($[60] !== patroller.id || $[61] !== t19 || $[62] !== t21 || $[63] !== t3) {
747
- t22 = /* @__PURE__ */ jsxs("li", {
575
+ $[45] = statusId;
576
+ $[46] = t15;
577
+ $[47] = t16;
578
+ } else t16 = $[47];
579
+ let t17;
580
+ if ($[48] !== patroller.id || $[49] !== t14 || $[50] !== t16 || $[51] !== t2) {
581
+ t17 = /* @__PURE__ */ jsxs("li", {
748
582
  "data-patroller": patroller.id,
749
- "data-open": t3,
750
- className: "flex flex-col",
751
- children: [t19, t21]
583
+ "data-open": t2,
584
+ className: "flex justify-center",
585
+ children: [t14, t16]
586
+ });
587
+ $[48] = patroller.id;
588
+ $[49] = t14;
589
+ $[50] = t16;
590
+ $[51] = t2;
591
+ $[52] = t17;
592
+ } else t17 = $[52];
593
+ return t17;
594
+ }
595
+ /**
596
+ * A patroller's popover, a profile card: its avatar and role, a tag of when it works where the
597
+ * editor is over what it does, what it's on while it works, then what it did.
598
+ */
599
+ function PatrollerCard(t0) {
600
+ const $ = c(47);
601
+ let props;
602
+ let singleLocale;
603
+ if ($[0] !== t0) {
604
+ ({singleLocale, ...props} = t0);
605
+ $[0] = t0;
606
+ $[1] = props;
607
+ $[2] = singleLocale;
608
+ } else {
609
+ props = $[1];
610
+ singleLocale = $[2];
611
+ }
612
+ const { patroller, inDraft } = props;
613
+ let t1;
614
+ if ($[3] !== patroller.id || $[4] !== patroller.working) {
615
+ t1 = patroller.working && workingSentence(patroller.id, patroller.working);
616
+ $[3] = patroller.id;
617
+ $[4] = patroller.working;
618
+ $[5] = t1;
619
+ } else t1 = $[5];
620
+ const working = t1;
621
+ let t2;
622
+ if ($[6] !== inDraft || $[7] !== patroller.duty || $[8] !== patroller.id || $[9] !== singleLocale) {
623
+ t2 = whenTag(patroller.id, patroller.duty, inDraft, singleLocale);
624
+ $[6] = inDraft;
625
+ $[7] = patroller.duty;
626
+ $[8] = patroller.id;
627
+ $[9] = singleLocale;
628
+ $[10] = t2;
629
+ } else t2 = $[10];
630
+ const when = t2;
631
+ const t3 = working ? "working" : patroller.duty === "off" ? "asleep" : "idle";
632
+ let t4;
633
+ if ($[11] !== patroller.id || $[12] !== t3) {
634
+ t4 = /* @__PURE__ */ jsx(Squareling, {
635
+ variant: patroller.id,
636
+ status: t3,
637
+ className: "size-7"
638
+ });
639
+ $[11] = patroller.id;
640
+ $[12] = t3;
641
+ $[13] = t4;
642
+ } else t4 = $[13];
643
+ let t5;
644
+ if ($[14] !== working) {
645
+ t5 = working && /* @__PURE__ */ jsx(WorkingArc, {});
646
+ $[14] = working;
647
+ $[15] = t5;
648
+ } else t5 = $[15];
649
+ let t6;
650
+ if ($[16] !== t4 || $[17] !== t5) {
651
+ t6 = /* @__PURE__ */ jsxs("span", {
652
+ className: "bg-muted relative flex size-12 shrink-0 items-center justify-center rounded-full",
653
+ children: [t4, t5]
654
+ });
655
+ $[16] = t4;
656
+ $[17] = t5;
657
+ $[18] = t6;
658
+ } else t6 = $[18];
659
+ let t7;
660
+ if ($[19] !== patroller.role) {
661
+ t7 = /* @__PURE__ */ jsx(PopoverTitle, {
662
+ className: "min-w-0 text-base",
663
+ children: patroller.role
664
+ });
665
+ $[19] = patroller.role;
666
+ $[20] = t7;
667
+ } else t7 = $[20];
668
+ let t8;
669
+ if ($[21] !== t6 || $[22] !== t7) {
670
+ t8 = /* @__PURE__ */ jsxs("header", {
671
+ className: "flex items-center gap-3",
672
+ children: [t6, t7]
673
+ });
674
+ $[21] = t6;
675
+ $[22] = t7;
676
+ $[23] = t8;
677
+ } else t8 = $[23];
678
+ const t9 = when.runs ? "bg-emerald-500" : "bg-muted-foreground/40";
679
+ let t10;
680
+ if ($[24] !== t9) {
681
+ t10 = cn("size-1.5 rounded-full", t9);
682
+ $[24] = t9;
683
+ $[25] = t10;
684
+ } else t10 = $[25];
685
+ let t11;
686
+ if ($[26] !== t10) {
687
+ t11 = /* @__PURE__ */ jsx("span", {
688
+ "aria-hidden": true,
689
+ className: t10
752
690
  });
753
- $[60] = patroller.id;
754
- $[61] = t19;
755
- $[62] = t21;
756
- $[63] = t3;
757
- $[64] = t22;
758
- } else t22 = $[64];
759
- return t22;
691
+ $[26] = t10;
692
+ $[27] = t11;
693
+ } else t11 = $[27];
694
+ let t12;
695
+ if ($[28] !== t11 || $[29] !== when.label) {
696
+ t12 = /* @__PURE__ */ jsxs("span", {
697
+ "data-patroller-when": true,
698
+ className: "bg-muted text-muted-foreground inline-flex items-center gap-1.5 rounded-full py-0.5 pr-2.5 pl-2 text-xs font-medium",
699
+ children: [t11, when.label]
700
+ });
701
+ $[28] = t11;
702
+ $[29] = when.label;
703
+ $[30] = t12;
704
+ } else t12 = $[30];
705
+ let t13;
706
+ if ($[31] !== patroller.id) {
707
+ t13 = aboutSentence(patroller.id);
708
+ $[31] = patroller.id;
709
+ $[32] = t13;
710
+ } else t13 = $[32];
711
+ let t14;
712
+ if ($[33] !== t13) {
713
+ t14 = /* @__PURE__ */ jsx("p", {
714
+ "data-patroller-about": true,
715
+ className: "text-sm",
716
+ children: t13
717
+ });
718
+ $[33] = t13;
719
+ $[34] = t14;
720
+ } else t14 = $[34];
721
+ let t15;
722
+ if ($[35] !== t12 || $[36] !== t14) {
723
+ t15 = /* @__PURE__ */ jsxs("div", {
724
+ className: "flex flex-col items-start gap-1.5",
725
+ children: [t12, t14]
726
+ });
727
+ $[35] = t12;
728
+ $[36] = t14;
729
+ $[37] = t15;
730
+ } else t15 = $[37];
731
+ let t16;
732
+ if ($[38] !== working) {
733
+ t16 = working && /* @__PURE__ */ jsx("p", {
734
+ "data-patroller-working": true,
735
+ className: "bg-muted rounded-md px-2.5 py-1.5 text-xs",
736
+ children: working
737
+ });
738
+ $[38] = working;
739
+ $[39] = t16;
740
+ } else t16 = $[39];
741
+ let t17;
742
+ if ($[40] !== props) {
743
+ t17 = /* @__PURE__ */ jsx("div", {
744
+ className: "flex flex-col gap-2 border-t pt-3",
745
+ children: /* @__PURE__ */ jsx(PatrollerDetails, { ...props })
746
+ });
747
+ $[40] = props;
748
+ $[41] = t17;
749
+ } else t17 = $[41];
750
+ let t18;
751
+ if ($[42] !== t15 || $[43] !== t16 || $[44] !== t17 || $[45] !== t8) {
752
+ t18 = /* @__PURE__ */ jsxs(Fragment, { children: [
753
+ t8,
754
+ t15,
755
+ t16,
756
+ t17
757
+ ] });
758
+ $[42] = t15;
759
+ $[43] = t16;
760
+ $[44] = t17;
761
+ $[45] = t8;
762
+ $[46] = t18;
763
+ } else t18 = $[46];
764
+ return t18;
760
765
  }
761
766
  /**
762
767
  * What a patroller's popover shows: its open findings with their actions, then its reports, then
@@ -1026,4 +1031,4 @@ function ReportSentence(t0) {
1026
1031
  }
1027
1032
 
1028
1033
  //#endregion
1029
- export { Patrol, PatrolRoster, PatrollerDetails, PatrollerReports, inHeldOrder };
1034
+ export { Patrol, PatrolRoster, PatrollerCard, PatrollerDetails, PatrollerReports };