camox 0.72.0 → 0.75.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 (38) hide show
  1. package/dist/core/lib/artifactRuntime.js +4 -2
  2. package/dist/features/preview/components/PageInfo.js +121 -98
  3. package/dist/features/preview/components/SelectionEditor.js +1 -1
  4. package/dist/features/renderer/RendererFrames.js +47 -41
  5. package/dist/features/routes/pageRuntime.js +15 -4
  6. package/dist/features/runtime/ClaimCard.js +192 -0
  7. package/dist/features/runtime/pageApp.js +4 -3
  8. package/dist/features/runtime/runtime.js +26 -5
  9. package/dist/features/runtime/worker.js +2 -2
  10. package/dist/features/runtime/workerRequest.d.ts +6 -0
  11. package/dist/features/runtime/workerRequest.js +13 -1
  12. package/dist/features/runtime/workerRuntime.d.ts +2 -2
  13. package/dist/features/runtime/workerRuntime.js +2 -2
  14. package/dist/features/studio/components/AgentSidebar.js +7 -7
  15. package/dist/features/studio/components/ChatWidget.js +142 -106
  16. package/dist/features/studio/components/ContentFindings.js +127 -230
  17. package/dist/features/studio/components/DeleteDraftDialog.js +112 -0
  18. package/dist/features/studio/components/DraftBar.js +98 -53
  19. package/dist/features/studio/components/DraftsControl.js +203 -190
  20. package/dist/features/studio/components/ReviewDraftDialog.js +670 -0
  21. package/dist/features/studio/components/{Patrol.js → Specialists.js} +291 -330
  22. package/dist/features/studio/components/Squareling.js +5 -5
  23. package/dist/features/studio/components/ThreadComposer.js +106 -127
  24. package/dist/features/studio/components/ThreadMessages.js +246 -71
  25. package/dist/features/studio/findingSentence.js +14 -12
  26. package/dist/features/studio/fixMessage.js +23 -0
  27. package/dist/features/studio/reportSentence.js +1 -1
  28. package/dist/features/studio/{patrollerBio.js → specialistBio.js} +8 -5
  29. package/dist/features/studio/studioStore.js +29 -15
  30. package/dist/features/studio/workingSentence.js +1 -1
  31. package/dist/lib/api-client.js +5 -1
  32. package/dist/lib/queries.js +5 -5
  33. package/dist/lib/studio-reads.d.ts +1 -1
  34. package/dist/lib/studio-reads.js +5 -5
  35. package/dist/package.js +1 -1
  36. package/dist/studio.css +1 -1
  37. package/package.json +4 -4
  38. package/dist/features/studio/components/ReviewDraftSheet.js +0 -1587
@@ -0,0 +1,192 @@
1
+ import { useOptionalDraftScope } from "../../lib/draft-scope.js";
2
+ import { useAuthContext, useSignInRedirect } from "../../lib/auth.js";
3
+ import { getApiClient } from "../../lib/api-client.js";
4
+ import { c } from "react/compiler-runtime";
5
+ import * as React from "react";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { CLAIM_LINK_SEARCH_PARAM } from "@camox/api-contract/claim-links";
8
+
9
+ //#region src/features/runtime/ClaimCard.tsx
10
+ /** The page's URL without the Claim Link's token, which would reopen the card. */
11
+ function pageWithoutToken() {
12
+ const url = new URL(window.location.href);
13
+ url.searchParams.delete(CLAIM_LINK_SEARCH_PARAM);
14
+ return url.href;
15
+ }
16
+ /**
17
+ * The claim card, on a page opened from a Claim Link: who built the website for whom, with a
18
+ * button to claim it, or why it can't be claimed. A member of the website's organization sees it
19
+ * as a preview. Nothing shows without a token, or in a draft.
20
+ */
21
+ function ClaimCard() {
22
+ const $ = c(15);
23
+ const [token, setToken] = React.useState(null);
24
+ const [opening, setOpening] = React.useState(null);
25
+ const [closed, setClosed] = React.useState(false);
26
+ const { authenticationUrl } = useAuthContext();
27
+ const signIn = useSignInRedirect(pageWithoutToken);
28
+ const inDraft = useOptionalDraftScope().draftId !== null;
29
+ let t0;
30
+ let t1;
31
+ if ($[0] !== inDraft) {
32
+ t0 = () => {
33
+ if (inDraft) return;
34
+ const found = new URL(window.location.href).searchParams.get(CLAIM_LINK_SEARCH_PARAM);
35
+ if (!found) return;
36
+ setToken(found);
37
+ let current = true;
38
+ getApiClient().claimLinks.open({ token: found }).then((opened) => current && setOpening(opened), _temp);
39
+ return () => {
40
+ current = false;
41
+ };
42
+ };
43
+ t1 = [inDraft];
44
+ $[0] = inDraft;
45
+ $[1] = t0;
46
+ $[2] = t1;
47
+ } else {
48
+ t0 = $[1];
49
+ t1 = $[2];
50
+ }
51
+ React.useEffect(t0, t1);
52
+ if (inDraft || !token || !opening || closed) return null;
53
+ let t2;
54
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
55
+ t2 = () => {
56
+ window.history.replaceState(window.history.state, "", pageWithoutToken());
57
+ setClosed(true);
58
+ };
59
+ $[3] = t2;
60
+ } else t2 = $[3];
61
+ const close = t2;
62
+ let t3;
63
+ if ($[4] !== authenticationUrl || $[5] !== token) {
64
+ t3 = () => {
65
+ const destination = new URL("/claim", authenticationUrl);
66
+ destination.searchParams.set("token", token);
67
+ destination.searchParams.set("callback", pageWithoutToken());
68
+ window.location.href = destination.href;
69
+ };
70
+ $[4] = authenticationUrl;
71
+ $[5] = token;
72
+ $[6] = t3;
73
+ } else t3 = $[6];
74
+ const claim = t3;
75
+ let t4;
76
+ let t5;
77
+ if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
78
+ t4 = /* @__PURE__ */ jsx("style", { children: claimCardStyles });
79
+ t5 = /* @__PURE__ */ jsx("button", {
80
+ type: "button",
81
+ className: "camox-claim-close",
82
+ "aria-label": "Close",
83
+ onClick: close,
84
+ children: "×"
85
+ });
86
+ $[7] = t4;
87
+ $[8] = t5;
88
+ } else {
89
+ t4 = $[7];
90
+ t5 = $[8];
91
+ }
92
+ let t6;
93
+ if ($[9] !== claim || $[10] !== opening.operatorName || $[11] !== opening.organizationName || $[12] !== opening.state || $[13] !== signIn) {
94
+ t6 = /* @__PURE__ */ jsxs("aside", {
95
+ className: "camox-claim-card",
96
+ "aria-label": "Claim this website",
97
+ children: [
98
+ t4,
99
+ t5,
100
+ opening.state === "open" || opening.state === "preview" ? /* @__PURE__ */ jsxs(Fragment, { children: [
101
+ opening.state === "preview" && /* @__PURE__ */ jsx("span", {
102
+ className: "camox-claim-preview",
103
+ children: "Preview: this is the card whoever you send the link to sees"
104
+ }),
105
+ /* @__PURE__ */ jsxs("p", { children: [
106
+ opening.operatorName,
107
+ " from Camox built this website for ",
108
+ opening.organizationName,
109
+ ". Claim it to start editing."
110
+ ] }),
111
+ opening.state === "open" && /* @__PURE__ */ jsx("button", {
112
+ type: "button",
113
+ className: "camox-claim-action",
114
+ onClick: claim,
115
+ children: "Claim website"
116
+ })
117
+ ] }) : opening.state === "claimed" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", { children: "This website has been claimed." }), /* @__PURE__ */ jsx("button", {
118
+ type: "button",
119
+ className: "camox-claim-action",
120
+ onClick: signIn,
121
+ children: "Sign in"
122
+ })] }) : /* @__PURE__ */ jsx("p", { children: "This link no longer works. Ask whoever sent it for a new one." })
123
+ ]
124
+ });
125
+ $[9] = claim;
126
+ $[10] = opening.operatorName;
127
+ $[11] = opening.organizationName;
128
+ $[12] = opening.state;
129
+ $[13] = signIn;
130
+ $[14] = t6;
131
+ } else t6 = $[14];
132
+ return t6;
133
+ }
134
+ function _temp(error) {
135
+ return console.error("The Claim Link couldn't be opened", error);
136
+ }
137
+ const claimCardStyles = `
138
+ .camox-claim-card {
139
+ background: #09090b;
140
+ border: 1px solid #27272a;
141
+ border-radius: 12px;
142
+ bottom: 24px;
143
+ box-shadow: 0 10px 30px rgb(0 0 0 / 0.35);
144
+ box-sizing: border-box;
145
+ color: #fafafa;
146
+ color-scheme: dark;
147
+ display: flex;
148
+ flex-direction: column;
149
+ font: 15px/1.5 Inter, ui-sans-serif, system-ui, sans-serif;
150
+ gap: 12px;
151
+ max-width: min(24rem, calc(100vw - 32px));
152
+ padding: 20px 44px 20px 20px;
153
+ position: fixed;
154
+ right: 16px;
155
+ text-align: left;
156
+ z-index: 2147483647;
157
+ }
158
+ .camox-claim-card p { margin: 0; }
159
+ .camox-claim-card button { cursor: pointer; font: inherit; }
160
+ .camox-claim-card .camox-claim-close {
161
+ background: none;
162
+ border: 0;
163
+ color: #a1a1aa;
164
+ font-size: 20px;
165
+ line-height: 1;
166
+ padding: 4px 8px;
167
+ position: absolute;
168
+ right: 8px;
169
+ top: 8px;
170
+ }
171
+ .camox-claim-card .camox-claim-close:hover { color: #fafafa; }
172
+ .camox-claim-card .camox-claim-preview {
173
+ align-self: flex-start;
174
+ background: #27272a;
175
+ border-radius: 999px;
176
+ color: #d4d4d8;
177
+ font-size: 12px;
178
+ padding: 2px 10px;
179
+ }
180
+ .camox-claim-card .camox-claim-action {
181
+ align-self: flex-start;
182
+ background: #fafafa;
183
+ border: 0;
184
+ border-radius: 8px;
185
+ color: #09090b;
186
+ font-weight: 600;
187
+ padding: 8px 14px;
188
+ }
189
+ `;
190
+
191
+ //#endregion
192
+ export { ClaimCard };
@@ -11,12 +11,13 @@ import { CuratedPageContent } from "../page/CuratedPageContent.js";
11
11
  import { DerivedPageContent } from "../page/DerivedPageContent.js";
12
12
  import { UnplacedBlockContent } from "../page/UnplacedBlockContent.js";
13
13
  import { UnplacedLayoutContent } from "../page/UnplacedLayoutContent.js";
14
+ import { ClaimCard } from "./ClaimCard.js";
14
15
  import { EditingFallbackSlot } from "./editingFallback.js";
15
16
  import { PageNavigationProvider } from "./pageNavigation.js";
16
17
  import { RuntimeChromeSlot } from "./runtimeChromeLoader.js";
17
18
  import { c } from "react/compiler-runtime";
18
19
  import * as React from "react";
19
- import { jsx, jsxs } from "react/jsx-runtime";
20
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
20
21
  import { HydrationBoundary, QueryClientProvider } from "@tanstack/react-query";
21
22
 
22
23
  //#region src/features/runtime/pageApp.tsx
@@ -43,12 +44,12 @@ function PageApp(t0) {
43
44
  camoxApp,
44
45
  input: currentInput
45
46
  })
46
- }) : /* @__PURE__ */ jsx(PageExperience, {
47
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(PageExperience, {
47
48
  camoxApp,
48
49
  input: currentInput,
49
50
  queryClient,
50
51
  studioDocument: input.presentation === "studio"
51
- })
52
+ }), /* @__PURE__ */ jsx(ClaimCard, {})] })
52
53
  })
53
54
  });
54
55
  $[0] = camoxApp;
@@ -918,6 +918,25 @@ function visitorAnalytics(render, project) {
918
918
  if (render.studio || render.draftId) return void 0;
919
919
  return configuredProviders(project.analytics);
920
920
  }
921
+ /**
922
+ * A project waiting to be claimed keeps search engines away from its pages, so the copy an
923
+ * operator built doesn't compete with the customer's current website. APIs older than Claim Links
924
+ * don't say, and their projects are indexed.
925
+ */
926
+ function isHiddenFromSearchEngines(project) {
927
+ return project.hiddenFromSearchEngines === true;
928
+ }
929
+ /** A page's head, with the robots `noindex` meta tag when its project is hidden. */
930
+ function withSearchEngineMark(head, project) {
931
+ if (!head || !isHiddenFromSearchEngines(project)) return head;
932
+ return {
933
+ ...head,
934
+ meta: [...head.meta ?? [], {
935
+ name: "robots",
936
+ content: "noindex"
937
+ }]
938
+ };
939
+ }
921
940
  /** Whether a request is a preview link's token handoff, which signs in before reading anything. */
922
941
  function isPreviewHandoff(request, options) {
923
942
  const { searchParams } = new URL(request.url);
@@ -1247,13 +1266,14 @@ async function createPageHtmlResponse({ options, pathname, located, request, pag
1247
1266
  if (result.shouldClearAuthCookie) headers.append("Set-Cookie", buildClearServerAuthCookieHeader());
1248
1267
  const camoxApp = await options.getCamoxApp?.();
1249
1268
  const document = await options.getDocument?.() ?? {};
1269
+ if (isHiddenFromSearchEngines(result.data.page.project)) headers.set("X-Robots-Tag", "noindex");
1250
1270
  const { alternates, head } = await readAlternates(request, options, {
1251
1271
  located,
1252
1272
  identity: {
1253
1273
  kind: "curated",
1254
1274
  pageId: result.data.page.page.id
1255
1275
  },
1256
- head: camoxApp ? buildCamoxPageHead(camoxApp, result.data, located.locale) : {},
1276
+ head: withSearchEngineMark(camoxApp ? buildCamoxPageHead(camoxApp, result.data, located.locale) : {}, result.data.page.project),
1257
1277
  described: curatedPageDescription(camoxApp, result.data.page, located.locale),
1258
1278
  localeReads: localeReads(result.draftId)
1259
1279
  });
@@ -1559,14 +1579,14 @@ async function createDerivedResponse(options, pathname, located, request, { data
1559
1579
  layout: match.layout,
1560
1580
  recordId: record.data.id
1561
1581
  } : { kind: "code-owned" },
1562
- head: buildPageHead({
1582
+ head: withSearchEngineMark(buildPageHead({
1563
1583
  layout: match.layout._internal,
1564
1584
  context,
1565
1585
  origin: new URL(request.url).origin,
1566
1586
  faviconUrl: buildFaviconUrl(options.apiUrl, shared.project),
1567
1587
  hasMarkdown: match.layout._internal.toMarkdown !== void 0,
1568
1588
  recordType: record?.structuredData?.node?.["@type"]
1569
- }),
1589
+ }), shared.project),
1570
1590
  described: {
1571
1591
  project: {
1572
1592
  ...shared.project,
@@ -1638,7 +1658,8 @@ async function createDerivedResponse(options, pathname, located, request, { data
1638
1658
  Vary: "Cookie",
1639
1659
  Link: llmsTxtLinkHeader(options),
1640
1660
  ...isPrivateRender(request) ? { "Cache-Control": "private, no-store" } : {},
1641
- ...clearAuthCookie ? { "Set-Cookie": buildClearServerAuthCookieHeader() } : {}
1661
+ ...clearAuthCookie ? { "Set-Cookie": buildClearServerAuthCookieHeader() } : {},
1662
+ ...isHiddenFromSearchEngines(shared.project) && { "X-Robots-Tag": "noindex" }
1642
1663
  } });
1643
1664
  } catch (error) {
1644
1665
  if (isNotFoundError(error)) return new Response("Page not found", { status: 404 });
@@ -1770,7 +1791,7 @@ async function createPageDataResponse({ options, pathname, located, request, pag
1770
1791
  kind: "curated",
1771
1792
  pageId: result.data.page.page.id
1772
1793
  },
1773
- head: camoxApp ? buildCamoxPageHead(camoxApp, result.data, located.locale) : null,
1794
+ head: withSearchEngineMark(camoxApp ? buildCamoxPageHead(camoxApp, result.data, located.locale) : null, result.data.page.project),
1774
1795
  described: curatedPageDescription(camoxApp, result.data.page, located.locale),
1775
1796
  localeReads: localeReads(result.draftId)
1776
1797
  });
@@ -1,4 +1,4 @@
1
- import { PUBLIC_CACHE_NAME, fetchLocalhostOnLoopback, readLiveCacheKey, rememberPublishingDraft, respondThroughPublicCache, shouldHandleRequest, withDevHtml } from "camox/_internal/workerRuntime";
1
+ import { PUBLIC_CACHE_NAME, fetchLocalhostOnLoopback, readLiveCacheKey, rememberPublishingDraft, respondThroughPublicCache, shouldHandleRequest, withDevHtml, withoutClaimLinkToken } from "camox/_internal/workerRuntime";
2
2
  import { WorkerEntrypoint } from "cloudflare:workers";
3
3
  import { devHtml, handleCamoxRequest, isPublicRequest, publicCacheSource, readDefinitionSet, runtimeBasePath } from "virtual:camox/server";
4
4
 
@@ -41,7 +41,7 @@ var CamoxDefinitionSet = class extends WorkerEntrypoint {
41
41
  var worker_default = { async fetch(request, env, context) {
42
42
  rememberPublishingDraft(env);
43
43
  if (!shouldHandleRequest(request, runtimeBasePath)) return notFound();
44
- const response = await respond(request, context);
44
+ const response = await respond(withoutClaimLinkToken(request), context);
45
45
  if (!response) return notFound();
46
46
  return withDevHtml(response, devHtml);
47
47
  } };
@@ -1,5 +1,11 @@
1
1
  //#region src/features/runtime/workerRequest.d.ts
2
2
  export declare function shouldHandleRequest(request: Request, basePath: string): boolean;
3
+ /**
4
+ * The request without a Claim Link's token, which only the claim card reads, in the browser. The
5
+ * page renders and is kept in the edge cache as if the visitor came without it, so the token
6
+ * never reaches the cache key or the rendered page.
7
+ */
8
+ export declare function withoutClaimLinkToken(request: Request): Request;
3
9
  /** Adds what Vite injects into HTML in dev, such as its client and React Refresh. */
4
10
  export declare function withDevHtml(response: Response, html: {
5
11
  head: string;
@@ -1,4 +1,5 @@
1
1
  import { matchRuntimeOwnedRoute } from "./runtimeRoutes.js";
2
+ import { CLAIM_LINK_SEARCH_PARAM } from "@camox/api-contract/claim-links";
2
3
 
3
4
  //#region src/features/runtime/workerRequest.ts
4
5
  /** How the Camox Worker picks the requests it answers and prepares its responses. */
@@ -26,6 +27,17 @@ function shouldHandleRequest(request, basePath) {
26
27
  if (pathname.startsWith("/node_modules/")) return false;
27
28
  return isDocumentRequest(request);
28
29
  }
30
+ /**
31
+ * The request without a Claim Link's token, which only the claim card reads, in the browser. The
32
+ * page renders and is kept in the edge cache as if the visitor came without it, so the token
33
+ * never reaches the cache key or the rendered page.
34
+ */
35
+ function withoutClaimLinkToken(request) {
36
+ const url = new URL(request.url);
37
+ if (!url.searchParams.has(CLAIM_LINK_SEARCH_PARAM)) return request;
38
+ url.searchParams.delete(CLAIM_LINK_SEARCH_PARAM);
39
+ return new Request(url, request);
40
+ }
29
41
  /** Adds what Vite injects into HTML in dev, such as its client and React Refresh. */
30
42
  async function withDevHtml(response, html) {
31
43
  if (!html) return response;
@@ -41,4 +53,4 @@ async function withDevHtml(response, html) {
41
53
  }
42
54
 
43
55
  //#endregion
44
- export { shouldHandleRequest, withDevHtml };
56
+ export { shouldHandleRequest, withDevHtml, withoutClaimLinkToken };
@@ -1,5 +1,5 @@
1
1
  import { fetchLocalhostOnLoopback } from "./loopbackFetch.js";
2
2
  import { PUBLIC_CACHE_NAME, readLiveCacheKey, respondThroughPublicCache } from "./publicCache.js";
3
3
  import { rememberPublishingDraft } from "./publishingDraft.js";
4
- import { shouldHandleRequest, withDevHtml } from "./workerRequest.js";
5
- export { PUBLIC_CACHE_NAME, fetchLocalhostOnLoopback, readLiveCacheKey, rememberPublishingDraft, respondThroughPublicCache, shouldHandleRequest, withDevHtml };
4
+ import { shouldHandleRequest, withDevHtml, withoutClaimLinkToken } from "./workerRequest.js";
5
+ export { PUBLIC_CACHE_NAME, fetchLocalhostOnLoopback, readLiveCacheKey, rememberPublishingDraft, respondThroughPublicCache, shouldHandleRequest, withDevHtml, withoutClaimLinkToken };
@@ -1,6 +1,6 @@
1
1
  import { rememberPublishingDraft } from "./publishingDraft.js";
2
2
  import { fetchLocalhostOnLoopback } from "./loopbackFetch.js";
3
3
  import { PUBLIC_CACHE_NAME, readLiveCacheKey, respondThroughPublicCache } from "./publicCache.js";
4
- import { shouldHandleRequest, withDevHtml } from "./workerRequest.js";
4
+ import { shouldHandleRequest, withDevHtml, withoutClaimLinkToken } from "./workerRequest.js";
5
5
 
6
- export { PUBLIC_CACHE_NAME, fetchLocalhostOnLoopback, readLiveCacheKey, rememberPublishingDraft, respondThroughPublicCache, shouldHandleRequest, withDevHtml };
6
+ export { PUBLIC_CACHE_NAME, fetchLocalhostOnLoopback, readLiveCacheKey, rememberPublishingDraft, respondThroughPublicCache, shouldHandleRequest, withDevHtml, withoutClaimLinkToken };
@@ -1,17 +1,17 @@
1
1
  import { cn } from "../../../lib/utils.js";
2
2
  import { SIDEBAR_GUTTER } from "../../preview/components/SidebarStack.js";
3
3
  import { ChatWidget } from "./ChatWidget.js";
4
- import { Patrol } from "./Patrol.js";
4
+ import { Specialists } from "./Specialists.js";
5
5
  import { c } from "react/compiler-runtime";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
 
8
8
  //#region src/features/studio/components/AgentSidebar.tsx
9
9
  /**
10
- * The sidebar on the Canvas's right side, where editors work with Camox's agent: the Patrol, as
11
- * tall as its patrollers, over the Chat widget, which gets the rest of the height. Laid over the Canvas,
12
- * as the Content Sidebar is over its left: only the cards have a background, and the Canvas shows
13
- * around them. Elsewhere in the studio it is only hidden, so the chat keeps its thread and the
14
- * Preview and Studio pages follow the editor's runs too.
10
+ * The sidebar on the Canvas's right side, where editors work with Camox's agent: the Specialists,
11
+ * as tall as its specialists, over the Chat widget, which gets the rest of the height. Laid over
12
+ * the Canvas, as the Content Sidebar is over its left: only the cards have a background, and the
13
+ * Canvas shows around them. Elsewhere in the studio it is only hidden, so the chat keeps its thread
14
+ * and the Preview and Studio pages follow the editor's runs too.
15
15
  */
16
16
  function AgentSidebar(t0) {
17
17
  const $ = c(6);
@@ -24,7 +24,7 @@ function AgentSidebar(t0) {
24
24
  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25
25
  t2 = cn("absolute inset-y-0 right-0 z-10 flex flex-col gap-2 py-2 max-md:hidden", SIDEBAR_GUTTER);
26
26
  t3 = { width: 265 };
27
- t4 = /* @__PURE__ */ jsx(Patrol, { className: "min-h-0 flex-[0_1_auto]" });
27
+ t4 = /* @__PURE__ */ jsx(Specialists, { className: "min-h-0 flex-[0_1_auto]" });
28
28
  t5 = /* @__PURE__ */ jsx(ChatWidget, { className: "min-h-0 flex-[7_1_0]" });
29
29
  $[0] = t2;
30
30
  $[1] = t3;