camox 0.52.3 → 0.54.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 (59) hide show
  1. package/dist/core/editing/createEditableBlock.js +1 -1
  2. package/dist/features/canvas/CamoxCanvas.js +103 -83
  3. package/dist/features/canvas/CanvasPageFrame.js +1 -1
  4. package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -1
  5. package/dist/features/canvas/canvasCamera.js +3 -3
  6. package/dist/features/canvas/sidebar/CanvasInspector.js +4 -159
  7. package/dist/features/canvas/sidebar/CanvasNavigator.js +41 -85
  8. package/dist/features/canvas/sidebar/CanvasSidebar.js +54 -32
  9. package/dist/features/canvas/sidebar/CanvasSidebarFrame.js +4 -3
  10. package/dist/features/canvas/sidebar/CanvasSidebarSkeleton.js +14 -6
  11. package/dist/features/canvas/sidebar/CanvasViewHeader.js +50 -0
  12. package/dist/features/canvas/sidebar/DerivedPageInspector.js +30 -18
  13. package/dist/features/canvas/sidebar/LayoutPageOverview.js +28 -11
  14. package/dist/features/canvas/sidebar/LayoutPageSeo.js +356 -0
  15. package/dist/features/canvas/sidebar/PageInspector.js +118 -80
  16. package/dist/features/canvas/sidebar/PageOverview.js +6 -1
  17. package/dist/features/canvas/sidebar/SingletonPageInspector.js +22 -14
  18. package/dist/features/canvas/useCanvasCamera.js +36 -39
  19. package/dist/features/og/documentFonts.js +49 -0
  20. package/dist/features/og/imageResponse.d.ts +14 -5
  21. package/dist/features/og/imageResponse.js +20 -21
  22. package/dist/features/og/pageImage.js +7 -4
  23. package/dist/features/preview/CamoxPreview.js +1 -1
  24. package/dist/features/preview/components/BlockActionsPopover.js +2 -2
  25. package/dist/features/preview/components/BlockThumbnail.js +1 -1
  26. package/dist/features/preview/components/CanvasPreview.js +1 -1
  27. package/dist/features/preview/components/CreatePageModal.js +1 -1
  28. package/dist/features/preview/components/IconFieldEditor.js +1 -1
  29. package/dist/features/preview/components/ItemFieldsEditor.js +1 -1
  30. package/dist/features/preview/components/LinkFieldEditor.js +1 -1
  31. package/dist/features/preview/components/OverlayTracker.js +1 -1
  32. package/dist/features/preview/components/PageInfo.js +345 -228
  33. package/dist/features/preview/components/PagePicker.js +1 -1
  34. package/dist/features/preview/components/PageTree.js +1 -1
  35. package/dist/features/preview/components/PreviewPanel.js +1 -1
  36. package/dist/features/preview/components/PreviewToolbar.js +2 -2
  37. package/dist/features/preview/components/RepeatableItemsList.js +1 -1
  38. package/dist/features/preview/components/SelectionEditor.js +668 -652
  39. package/dist/features/preview/components/SidebarStack.js +582 -0
  40. package/dist/features/preview/components/StudioEditingFallback.js +2 -2
  41. package/dist/features/renderer/RendererFrames.js +34 -27
  42. package/dist/features/runtime/RuntimeChrome.js +1 -1
  43. package/dist/features/runtime/runtime.d.ts +5 -0
  44. package/dist/features/runtime/runtime.js +99 -30
  45. package/dist/features/studio/components/ChatSidebar.js +76 -86
  46. package/dist/features/studio/components/Navbar.js +1 -1
  47. package/dist/features/studio/components/Squareling.js +114 -0
  48. package/dist/features/studio/components/ThreadMessages.js +128 -126
  49. package/dist/features/studio/components/UserButton.js +1 -1
  50. package/dist/features/vite/bundlerLogs.js +1 -0
  51. package/dist/features/vite/runtimeDev.js +11 -0
  52. package/dist/features/vite/vite.js +3 -1
  53. package/dist/lib/studio-reads.js +18 -0
  54. package/dist/package.js +1 -1
  55. package/dist/studio.css +1 -1
  56. package/package.json +5 -5
  57. package/skills/camox/references/layout-definitions.md +11 -16
  58. package/dist/features/og/defaultFonts.js +0 -31
  59. package/dist/features/og/geist-variable-ttf-base64.js +0 -21
@@ -93,6 +93,11 @@ export interface RuntimeOptions {
93
93
  rendererClientEntryUrl?: string;
94
94
  getCamoxApp?: () => Promise<CamoxApp>;
95
95
  getDocument?: () => Promise<CamoxDocument>;
96
+ /**
97
+ * The app's stylesheet, compiled, which page images render with: a `toImage` styles its
98
+ * elements with the same classes as the site.
99
+ */
100
+ getImageStylesheet?: () => Promise<string>;
96
101
  projectUuid?: string;
97
102
  renderPage?: (input: PageRenderInput) => Promise<string>;
98
103
  renderStudio?: (input: StudioRenderInput) => Promise<string>;
@@ -14,6 +14,7 @@ import { discoverLayoutPages, matchDerivedLayout } from "../../core/derivedRoute
14
14
  import { buildLayoutContext, curatedLayoutContext } from "../../core/layoutContext.js";
15
15
  import { buildCamoxPageHead, buildFaviconUrl, buildPageHead, buildPageMeta, createServerApiClient, createServerStudioCache, curatedMarkdownResponse, declarePage, isNotFoundError, loadCamoxPageForRequest, parseMarkdownPath, prefersMarkdown, readDraftOrLive, readPageMarkdown, readScopeLocales, renderedHref, resolveMemberProject, withFrontMatter } from "../routes/pageRuntime.js";
16
16
  import { assetPrefix } from "./assetPrefix.js";
17
+ import { documentGoogleFonts } from "../og/documentFonts.js";
17
18
  import { alternatesByPage, findAlternates, hreflangLinks } from "./alternates.js";
18
19
  import { configuredProviders, renderAnalyticsScripts } from "./analytics.js";
19
20
  import { omitArtifactSources } from "./artifactSources.js";
@@ -294,16 +295,26 @@ async function createRoutesResponse(request, options) {
294
295
  }
295
296
  /**
296
297
  * The image of the page `/og?path=` names, by its path with its locale's prefix: its layout's
297
- * `toImage`, or Camox's default image, rendered with the page's context. Only real pages have
298
- * one, read as the page itself would be, in the draft the URL names for a member.
298
+ * `toImage`, or Camox's default image, rendered with the page's context and the site's
299
+ * stylesheet and fonts. Only real pages have one, read as the page itself would be, in the draft
300
+ * the URL names for a member.
299
301
  */
300
302
  async function createOgResponse(request, options) {
301
303
  const camoxApp = await options.getCamoxApp?.();
302
304
  if (!camoxApp) return Response.json({ message: "Camox app registry is not available." }, { status: 500 });
303
305
  const source = await readPageImageSource(request, options, camoxApp);
304
306
  if (!source) return new Response("Not found", { status: 404 });
307
+ const [css, document] = await Promise.all([options.getImageStylesheet?.(), options.getDocument?.()]);
308
+ const style = {
309
+ css,
310
+ fonts: documentGoogleFonts(document ?? {})
311
+ };
305
312
  const headers = {
306
- ETag: await etagOf(JSON.stringify([source.layout?.id ?? null, source.context])),
313
+ ETag: await etagOf(JSON.stringify([
314
+ source.layout?.id ?? null,
315
+ source.context,
316
+ style
317
+ ])),
307
318
  "Cache-Control": isPrivateRender(request, options) ? "private, no-store" : "public, no-cache"
308
319
  };
309
320
  if (namesEtag(request, headers.ETag)) return new Response(null, {
@@ -311,7 +322,7 @@ async function createOgResponse(request, options) {
311
322
  headers
312
323
  });
313
324
  const toImage = source.layout?.toImage ?? DefaultPageImage;
314
- const image = await renderPageImage(toImage(source.context));
325
+ const image = await renderPageImage(toImage(source.context), style);
315
326
  for (const [name, value] of Object.entries(headers)) image.headers.set(name, value);
316
327
  return image;
317
328
  }
@@ -933,17 +944,41 @@ async function loadLayoutResult(app, match, context, locale) {
933
944
  }
934
945
  /**
935
946
  * The Markdown of a singleton or derived page: front matter, its before blocks, the layout's
936
- * toMarkdown output, then its after blocks. Without toMarkdown, the page is HTML only.
947
+ * toMarkdown output, then its after blocks. Null without toMarkdown: the page is then HTML only.
948
+ * The layout's blocks settle which draft it reads, as they do for the page's HTML.
937
949
  */
938
- async function createLayoutMarkdownResponse(options, match, locale, page) {
950
+ async function buildLayoutMarkdown(options, match, locale, page, reader = { member: false }) {
939
951
  const { toMarkdown, id } = match.layout._internal;
940
952
  const { apiUrl, projectUuid } = options;
941
953
  if (!toMarkdown || !apiUrl || !projectUuid) return null;
942
- const api = createServerApiClient(apiUrl, { locale });
954
+ const authCookieHeader = reader.member ? reader.authCookieHeader : void 0;
955
+ const api = (draftId) => createServerApiClient(apiUrl, {
956
+ authCookieHeader,
957
+ draftId,
958
+ locale
959
+ });
960
+ const { value: slots, draftId } = await readDraftOrLive(reader.requestedDraft, reader.member, (draftId) => api(draftId).blocks.getLayoutMarkdown({
961
+ projectUuid,
962
+ layoutId: id
963
+ })).catch((error) => {
964
+ if (!isNotFoundError(error)) throw error;
965
+ return {
966
+ value: {
967
+ before: "",
968
+ after: "",
969
+ projectName: ""
970
+ },
971
+ draftId: reader.member ? reader.requestedDraft : void 0
972
+ };
973
+ });
943
974
  const app = await options.getCamoxApp?.();
944
975
  /** The layout's own Markdown, between its before and after blocks, and what built it. */
945
976
  const layoutMarkdown = async () => {
946
- const result = await loadLayoutResult(app, match, createLayoutRequestContext(options, "live", { locale }), locale);
977
+ const result = await loadLayoutResult(app, match, createLayoutRequestContext(options, reader.member ? "draft" : "live", {
978
+ authCookieHeader,
979
+ draftId,
980
+ locale
981
+ }), locale);
947
982
  const record = asCollectionItem(result);
948
983
  const collection = record && app?.getCollectionById(record.collectionId);
949
984
  if (!record || !collection) return {
@@ -960,7 +995,7 @@ async function createLayoutMarkdownResponse(options, match, locale, page) {
960
995
  item
961
996
  }));
962
997
  return {
963
- body: [await api.collectionDefinitions.recordMarkdown({
998
+ body: [await api(draftId).collectionDefinitions.recordMarkdown({
964
999
  projectUuid,
965
1000
  collectionId: record.collectionId,
966
1001
  id: data.id,
@@ -970,24 +1005,7 @@ async function createLayoutMarkdownResponse(options, match, locale, page) {
970
1005
  record: recordPageValues(collection, record)
971
1006
  };
972
1007
  };
973
- let rendered;
974
- try {
975
- rendered = await layoutMarkdown();
976
- } catch (error) {
977
- if (isNotFoundError(error)) return new Response("Page not found", { status: 404 });
978
- throw error;
979
- }
980
- const slots = await api.blocks.getLayoutMarkdown({
981
- projectUuid,
982
- layoutId: id
983
- }).catch((error) => {
984
- if (isNotFoundError(error)) return {
985
- before: "",
986
- after: "",
987
- projectName: ""
988
- };
989
- throw error;
990
- });
1008
+ const rendered = await layoutMarkdown();
991
1009
  const meta = buildPageMeta({
992
1010
  layout: match.layout._internal,
993
1011
  context: buildLayoutContext(match.layout._internal, {
@@ -1004,10 +1022,59 @@ async function createLayoutMarkdownResponse(options, match, locale, page) {
1004
1022
  ...rendered.body,
1005
1023
  slots.after
1006
1024
  ].filter(Boolean).join("\n\n");
1007
- return new Response(withFrontMatter(markdown, {
1025
+ return withFrontMatter(markdown, {
1008
1026
  ...meta,
1009
1027
  url: page.url
1010
- }), { headers: { "Content-Type": "text/markdown; charset=utf-8" } });
1028
+ });
1029
+ }
1030
+ /**
1031
+ * A singleton or derived page's public Markdown Representation. Markdown is a public output: it
1032
+ * reads published records and blocks whoever asks.
1033
+ */
1034
+ async function createLayoutMarkdownResponse(options, match, locale, page) {
1035
+ let markdown;
1036
+ try {
1037
+ markdown = await buildLayoutMarkdown(options, match, locale, page);
1038
+ } catch (error) {
1039
+ if (isNotFoundError(error)) return new Response("Page not found", { status: 404 });
1040
+ throw error;
1041
+ }
1042
+ if (markdown === null) return null;
1043
+ return new Response(markdown, { headers: { "Content-Type": "text/markdown; charset=utf-8" } });
1044
+ }
1045
+ /**
1046
+ * A singleton or derived page's Markdown Representation as JSON (`/_camox/data?markdown`), read
1047
+ * like the page's data: in the draft the URL names, for a member. The studio shows it, while the
1048
+ * page's `.md` URL always reads Live. `markdown` is null when the layout declares none.
1049
+ */
1050
+ async function createLayoutMarkdownDataResponse(options, request, pathname) {
1051
+ const located = await locateRequest(request, options, pathname);
1052
+ const app = await options.getCamoxApp?.();
1053
+ const match = app && matchDerivedLayout(app.getLayouts(), located.path);
1054
+ if (!match || matchLocalizedRoute(located.path)?.kind !== "page") return new Response("Not found", { status: 404 });
1055
+ const { project, clearAuthCookie } = await resolveRequestMember(request, options);
1056
+ const headers = {
1057
+ ...isPrivateRender(request, options) ? { "Cache-Control": "private, no-store" } : {},
1058
+ Vary: "Cookie",
1059
+ ...clearAuthCookie ? { "Set-Cookie": buildClearServerAuthCookieHeader() } : {}
1060
+ };
1061
+ try {
1062
+ const markdown = await buildLayoutMarkdown(options, match, located.locale, {
1063
+ pathname,
1064
+ url: absoluteUrl(request, options)(pathname)
1065
+ }, {
1066
+ member: project !== void 0,
1067
+ authCookieHeader: getServerAuthCookieHeader(request.headers),
1068
+ requestedDraft: getRequestDraftId(request, options)
1069
+ });
1070
+ return Response.json({ markdown }, { headers });
1071
+ } catch (error) {
1072
+ if (isNotFoundError(error)) return new Response("Not found", {
1073
+ status: 404,
1074
+ headers
1075
+ });
1076
+ throw error;
1077
+ }
1011
1078
  }
1012
1079
  async function createDerivedResponse(options, pathname, located, request, { dataOnly = false, singletonOnly = false } = {}) {
1013
1080
  const app = await options.getCamoxApp?.();
@@ -1337,8 +1404,10 @@ async function handleCamoxRequest(request, options = {}) {
1337
1404
  if (match.kind === "llms-txt") return createLlmsTxtResponse(request, options);
1338
1405
  if (match.kind === "routes") return createRoutesResponse(request, options);
1339
1406
  if (match.kind === "data") {
1340
- const targetPathname = normalizePagePath(new URL(request.url).searchParams.get("path"));
1407
+ const { searchParams } = new URL(request.url);
1408
+ const targetPathname = normalizePagePath(searchParams.get("path"));
1341
1409
  if (matchRuntimeOwnedRoute(targetPathname)) return new Response("Not found", { status: 404 });
1410
+ if (searchParams.has("markdown")) return createLayoutMarkdownDataResponse(options, request, targetPathname);
1342
1411
  return respondInLocale(options, request, targetPathname, { dataOnly: true });
1343
1412
  }
1344
1413
  if (isPreviewHandoff(request, options) && match.kind === "page") return createPreviewHandoffResponse({
@@ -2,9 +2,12 @@ import { AuthContext } from "../../../lib/auth.js";
2
2
  import { useCurrentDraftId, useDraftScope } from "../../../lib/draft-scope.js";
3
3
  import { useNavigate } from "../../navigation/navigation.js";
4
4
  import { reads, useReadQuery } from "../../../lib/studio-reads.js";
5
+ import { cn } from "../../../lib/utils.js";
6
+ import { BOTTOM_CARD_EDGES, CARD_BODY_EDGES, SIDEBAR_GUTTER } from "../../preview/components/SidebarStack.js";
5
7
  import { draftLabel } from "../draftLabel.js";
6
8
  import { FollowAgentContext } from "../followAgentContext.js";
7
9
  import { useThread } from "../../../lib/use-thread.js";
10
+ import { Squareling } from "./Squareling.js";
8
11
  import { ThreadComposer } from "./ThreadComposer.js";
9
12
  import { ThreadMessages } from "./ThreadMessages.js";
10
13
  import { c } from "react/compiler-runtime";
@@ -20,64 +23,54 @@ import { EMPTY_THREAD_VIEW } from "@camox/api-contract/threads";
20
23
  * When the Live thread starts a draft, the studio enters it with the thread.
21
24
  */
22
25
  function ChatSidebar(t0) {
23
- const $ = c(5);
26
+ const $ = c(6);
24
27
  const { hidden: t1 } = t0;
25
28
  const hidden = t1 === void 0 ? false : t1;
26
29
  let t2;
27
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28
- t2 = { width: 265 };
29
- $[0] = t2;
30
- } else t2 = $[0];
31
30
  let t3;
32
31
  let t4;
33
- if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
34
- t3 = /* @__PURE__ */ jsxs("header", {
35
- className: "border-border box-content flex h-8 min-w-0 items-center gap-2 border-b px-2 py-2",
36
- children: [/* @__PURE__ */ jsx(CamoxMark, {}), /* @__PURE__ */ jsx("h2", {
32
+ let t5;
33
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
34
+ t2 = cn("absolute inset-y-0 right-0 z-10 flex flex-col py-2 max-md:hidden", SIDEBAR_GUTTER);
35
+ t3 = { width: 265 };
36
+ t4 = /* @__PURE__ */ jsxs("header", {
37
+ className: cn("bg-background flex h-11 min-w-0 shrink-0 items-center justify-center gap-2 px-3", BOTTOM_CARD_EDGES),
38
+ children: [/* @__PURE__ */ jsx(Squareling, {
39
+ status: "idle",
40
+ className: "size-5"
41
+ }), /* @__PURE__ */ jsx("h2", {
37
42
  className: "truncate text-sm font-medium",
38
- children: "Chat"
43
+ children: "Agent"
39
44
  })]
40
45
  });
41
- t4 = /* @__PURE__ */ jsx(CurrentThread, {});
46
+ t5 = /* @__PURE__ */ jsx("div", {
47
+ className: cn("bg-background flex min-h-0 flex-1 flex-col", CARD_BODY_EDGES),
48
+ children: /* @__PURE__ */ jsx(CurrentThread, {})
49
+ });
50
+ $[0] = t2;
42
51
  $[1] = t3;
43
52
  $[2] = t4;
53
+ $[3] = t5;
44
54
  } else {
55
+ t2 = $[0];
45
56
  t3 = $[1];
46
57
  t4 = $[2];
58
+ t5 = $[3];
47
59
  }
48
- let t5;
49
- if ($[3] !== hidden) {
50
- t5 = /* @__PURE__ */ jsxs("aside", {
51
- "aria-label": "Chat",
60
+ let t6;
61
+ if ($[4] !== hidden) {
62
+ t6 = /* @__PURE__ */ jsxs("aside", {
63
+ "aria-label": "Agent",
52
64
  "data-chat-sidebar": true,
53
65
  hidden,
54
- className: "bg-background flex shrink-0 flex-col border-l-2 max-md:hidden",
55
- style: t2,
56
- children: [t3, t4]
57
- });
58
- $[3] = hidden;
59
- $[4] = t5;
60
- } else t5 = $[4];
61
- return t5;
62
- }
63
- /** Camox's logo, beside the heading: the agent is Camox. */
64
- function CamoxMark() {
65
- const $ = c(1);
66
- let t0;
67
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
68
- t0 = /* @__PURE__ */ jsx("svg", {
69
- "aria-hidden": true,
70
- viewBox: "0 0 191.03 132",
71
- className: "size-5 shrink-0",
72
- xmlns: "http://www.w3.org/2000/svg",
73
- children: /* @__PURE__ */ jsx("path", {
74
- d: "M0 22.55A22.55 22.55 0 0 1 22.55 0L90.19 0A5.32 5.32 0 0 1 95.52 5.32L95.52 36.48L36.48 36.48L36.48 95.52L5.32 95.52A5.32 5.32 0 0 1 0 90.19ZM95.52 36.48L181.48 36.48A5.32 5.32 0 0 1 186.01 44.61L138.61 121.31A22.55 22.55 0 0 1 119.43 132L41.81 132A5.32 5.32 0 0 1 36.48 126.68L36.48 95.52L95.52 95.52Z",
75
- fill: "#00BC7D"
76
- })
66
+ className: t2,
67
+ style: t3,
68
+ children: [t4, t5]
77
69
  });
78
- $[0] = t0;
79
- } else t0 = $[0];
80
- return t0;
70
+ $[4] = hidden;
71
+ $[5] = t6;
72
+ } else t6 = $[5];
73
+ return t6;
81
74
  }
82
75
  function CurrentThread() {
83
76
  const $ = c(15);
@@ -156,7 +149,7 @@ function CurrentThread() {
156
149
  return t6;
157
150
  }
158
151
  function Thread(t0) {
159
- const $ = c(31);
152
+ const $ = c(30);
160
153
  const { apiUrl, projectId, draftId, carried, onEnterDraft } = t0;
161
154
  let t1;
162
155
  if ($[0] !== carried || $[1] !== onEnterDraft) {
@@ -204,68 +197,65 @@ function Thread(t0) {
204
197
  $[12] = t5;
205
198
  } else t5 = $[12];
206
199
  const sendFollowing = t5;
207
- const t6 = draftId !== null;
208
- let t7;
209
- if ($[13] !== sending || $[14] !== t6 || $[15] !== view) {
210
- t7 = {
200
+ let t6;
201
+ if ($[13] !== sending || $[14] !== view) {
202
+ t6 = {
211
203
  view,
212
- sending,
213
- showSenders: t6
204
+ sending
214
205
  };
215
206
  $[13] = sending;
216
- $[14] = t6;
217
- $[15] = view;
218
- $[16] = t7;
219
- } else t7 = $[16];
220
- const messages = t7;
207
+ $[14] = view;
208
+ $[15] = t6;
209
+ } else t6 = $[15];
210
+ const messages = t6;
221
211
  const continuedIn = draftId === null ? view.continuedIn?.draftId : void 0;
222
- let t8;
223
- if ($[17] !== continuedIn || $[18] !== messages || $[19] !== projectId) {
224
- t8 = continuedIn ? /* @__PURE__ */ jsx(ContinuedInMessages, {
212
+ let t7;
213
+ if ($[16] !== continuedIn || $[17] !== messages || $[18] !== projectId) {
214
+ t7 = continuedIn ? /* @__PURE__ */ jsx(ContinuedInMessages, {
225
215
  ...messages,
226
216
  projectId,
227
217
  draftId: continuedIn
228
218
  }) : /* @__PURE__ */ jsx(ThreadMessages, { ...messages });
229
- $[17] = continuedIn;
230
- $[18] = messages;
231
- $[19] = projectId;
232
- $[20] = t8;
233
- } else t8 = $[20];
234
- let t9;
235
- if ($[21] !== error) {
236
- t9 = error && /* @__PURE__ */ jsx("p", {
219
+ $[16] = continuedIn;
220
+ $[17] = messages;
221
+ $[18] = projectId;
222
+ $[19] = t7;
223
+ } else t7 = $[19];
224
+ let t8;
225
+ if ($[20] !== error) {
226
+ t8 = error && /* @__PURE__ */ jsx("p", {
237
227
  role: "alert",
238
228
  className: "text-destructive px-2 pt-2 text-sm",
239
229
  children: error
240
230
  });
241
- $[21] = error;
242
- $[22] = t9;
243
- } else t9 = $[22];
244
- let t10;
245
- if ($[23] !== sendFollowing || $[24] !== stop || $[25] !== view.running) {
246
- t10 = /* @__PURE__ */ jsx(ThreadComposer, {
231
+ $[20] = error;
232
+ $[21] = t8;
233
+ } else t8 = $[21];
234
+ let t9;
235
+ if ($[22] !== sendFollowing || $[23] !== stop || $[24] !== view.running) {
236
+ t9 = /* @__PURE__ */ jsx(ThreadComposer, {
247
237
  onSend: sendFollowing,
248
238
  onStop: stop,
249
239
  running: view.running
250
240
  });
251
- $[23] = sendFollowing;
252
- $[24] = stop;
253
- $[25] = view.running;
254
- $[26] = t10;
255
- } else t10 = $[26];
256
- let t11;
257
- if ($[27] !== t10 || $[28] !== t8 || $[29] !== t9) {
258
- t11 = /* @__PURE__ */ jsxs(Fragment, { children: [
241
+ $[22] = sendFollowing;
242
+ $[23] = stop;
243
+ $[24] = view.running;
244
+ $[25] = t9;
245
+ } else t9 = $[25];
246
+ let t10;
247
+ if ($[26] !== t7 || $[27] !== t8 || $[28] !== t9) {
248
+ t10 = /* @__PURE__ */ jsxs(Fragment, { children: [
249
+ t7,
259
250
  t8,
260
- t9,
261
- t10
251
+ t9
262
252
  ] });
263
- $[27] = t10;
264
- $[28] = t8;
265
- $[29] = t9;
266
- $[30] = t11;
267
- } else t11 = $[30];
268
- return t11;
253
+ $[26] = t7;
254
+ $[27] = t8;
255
+ $[28] = t9;
256
+ $[29] = t10;
257
+ } else t10 = $[29];
258
+ return t10;
269
259
  }
270
260
  /**
271
261
  * A fresh Live thread's messages, linking to the draft the editor's previous one continued in,
@@ -151,7 +151,7 @@ const Navbar = (t0) => {
151
151
  let t11;
152
152
  if ($[24] !== t9) {
153
153
  t11 = /* @__PURE__ */ jsxs("nav", {
154
- className: "bg-background relative flex items-center justify-between gap-4 border-b-2 px-2 py-2",
154
+ className: "bg-background relative flex items-center justify-between gap-4 border-b px-2 py-2",
155
155
  children: [t9, t10]
156
156
  });
157
157
  $[24] = t9;
@@ -0,0 +1,114 @@
1
+ import { cn } from "../../../lib/utils.js";
2
+ import { c } from "react/compiler-runtime";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+
5
+ //#region src/features/studio/components/Squareling.tsx
6
+ /**
7
+ * Camox's agent, drawn from the logo's shapes: its square, the soft corner, and the knockout as
8
+ * eyes, looking right like the mark. Its face and motion say what the agent is doing. The
9
+ * animations live in `studio.css`.
10
+ */
11
+ function Squareling(t0) {
12
+ const $ = c(17);
13
+ const { status, className } = t0;
14
+ let t1;
15
+ if ($[0] !== className) {
16
+ t1 = cn("squareling shrink-0 overflow-visible", className);
17
+ $[0] = className;
18
+ $[1] = t1;
19
+ } else t1 = $[1];
20
+ let t2;
21
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
22
+ t2 = /* @__PURE__ */ jsx("path", {
23
+ d: "M20 12H80Q88 12 88 20V64Q88 88 64 88H20Q12 88 12 80V20Q12 12 20 12Z",
24
+ className: "fill-emerald-500"
25
+ });
26
+ $[2] = t2;
27
+ } else t2 = $[2];
28
+ let t3;
29
+ if ($[3] !== status) {
30
+ t3 = (status === "idle" || status === "thinking") && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("rect", {
31
+ className: "squareling-eye",
32
+ x: "50",
33
+ y: "36",
34
+ width: "11",
35
+ height: "17"
36
+ }), /* @__PURE__ */ jsx("rect", {
37
+ className: "squareling-eye",
38
+ x: "69",
39
+ y: "36",
40
+ width: "11",
41
+ height: "17"
42
+ })] });
43
+ $[3] = status;
44
+ $[4] = t3;
45
+ } else t3 = $[4];
46
+ let t4;
47
+ if ($[5] !== status) {
48
+ t4 = status === "acting" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("rect", {
49
+ x: "50",
50
+ y: "44",
51
+ width: "11",
52
+ height: "6"
53
+ }), /* @__PURE__ */ jsx("rect", {
54
+ x: "69",
55
+ y: "44",
56
+ width: "11",
57
+ height: "6"
58
+ })] });
59
+ $[5] = status;
60
+ $[6] = t4;
61
+ } else t4 = $[6];
62
+ let t5;
63
+ if ($[7] !== status) {
64
+ t5 = status === "fixing" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("rect", {
65
+ x: "50",
66
+ y: "36",
67
+ width: "11",
68
+ height: "17"
69
+ }), /* @__PURE__ */ jsx("rect", {
70
+ x: "69",
71
+ y: "44",
72
+ width: "11",
73
+ height: "6"
74
+ })] });
75
+ $[7] = status;
76
+ $[8] = t5;
77
+ } else t5 = $[8];
78
+ let t6;
79
+ if ($[9] !== t3 || $[10] !== t4 || $[11] !== t5) {
80
+ t6 = /* @__PURE__ */ jsxs("g", {
81
+ className: "squareling-body",
82
+ children: [t2, /* @__PURE__ */ jsxs("g", {
83
+ className: "squareling-eyes fill-neutral-950",
84
+ children: [
85
+ t3,
86
+ t4,
87
+ t5
88
+ ]
89
+ })]
90
+ });
91
+ $[9] = t3;
92
+ $[10] = t4;
93
+ $[11] = t5;
94
+ $[12] = t6;
95
+ } else t6 = $[12];
96
+ let t7;
97
+ if ($[13] !== status || $[14] !== t1 || $[15] !== t6) {
98
+ t7 = /* @__PURE__ */ jsx("svg", {
99
+ viewBox: "0 0 100 100",
100
+ "aria-hidden": true,
101
+ "data-squareling": status,
102
+ className: t1,
103
+ children: t6
104
+ });
105
+ $[13] = status;
106
+ $[14] = t1;
107
+ $[15] = t6;
108
+ $[16] = t7;
109
+ } else t7 = $[16];
110
+ return t7;
111
+ }
112
+
113
+ //#endregion
114
+ export { Squareling };