@fayz-ai/app-builder 2.0.1 → 3.0.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.
- package/dist/admin/AdminAppBuilder.d.ts.map +1 -1
- package/dist/admin/preview.d.ts +46 -0
- package/dist/admin/preview.d.ts.map +1 -0
- package/dist/admin/target.d.ts +7 -0
- package/dist/admin/target.d.ts.map +1 -1
- package/dist/{chunk-45SFS6FV.js → chunk-GTK7MRYT.js} +64 -4
- package/dist/chunk-GTK7MRYT.js.map +1 -0
- package/dist/components/BuilderPending.d.ts +34 -0
- package/dist/components/BuilderPending.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/plugin.js +169 -23
- package/dist/plugin.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -7
- package/dist/chunk-45SFS6FV.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminAppBuilder.d.ts","sourceRoot":"","sources":["../../src/admin/AdminAppBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"AdminAppBuilder.d.ts","sourceRoot":"","sources":["../../src/admin/AdminAppBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAkB9B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AAMxD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,CAAC,EAAE,uBAAuB,CAAA;CAAE,qBA2LjF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The running preview container, as one hook.
|
|
3
|
+
*
|
|
4
|
+
* The canvas is supposed to show THE APP — the container the platform runs for
|
|
5
|
+
* this project — and until now the admin had no way to get one: the console's
|
|
6
|
+
* container routes are session-JWT only, so the surface fell back to the
|
|
7
|
+
* published site, which is the app as it was at the last publish rather than as
|
|
8
|
+
* it is now.
|
|
9
|
+
*
|
|
10
|
+
* Three things happen here, and they are one loop rather than three because
|
|
11
|
+
* they share a single fact: the container's state.
|
|
12
|
+
*
|
|
13
|
+
* 1. START — only after a status read says it is not already up. A blind
|
|
14
|
+
* start on every mount would resync files and could restart a container
|
|
15
|
+
* the merchant is looking at.
|
|
16
|
+
* 2. WAIT — poll until `healthy`, not until `RUNNING`. A container can be
|
|
17
|
+
* running with a dev server that has not bound a port yet (~24s on a cold
|
|
18
|
+
* start), and pointing the iframe at it then shows a connection error the
|
|
19
|
+
* merchant reads as a broken site.
|
|
20
|
+
* 3. KEEP ALIVE — the same poll, slower. Reading the state touches
|
|
21
|
+
* `lastActiveAt` on the platform, which is what its idle reaper checks, so
|
|
22
|
+
* watching the preview is what keeps it. There is deliberately no separate
|
|
23
|
+
* heartbeat to forget to call.
|
|
24
|
+
*
|
|
25
|
+
* It never stops the container on unmount. Navigating away from the Site tab
|
|
26
|
+
* for a minute is not a decision to throw away a warm container and pay the
|
|
27
|
+
* cold start again — the platform's 30-minute idle reaper is the right authority
|
|
28
|
+
* on when it goes.
|
|
29
|
+
*/
|
|
30
|
+
export type PreviewPhase =
|
|
31
|
+
/** No project, or no platform credentials — nothing to do. */
|
|
32
|
+
'idle'
|
|
33
|
+
/** Container is coming up, or its dev server has not answered yet. */
|
|
34
|
+
| 'starting'
|
|
35
|
+
/** Serving: point the canvas at `url`. */
|
|
36
|
+
| 'ready' | 'failed';
|
|
37
|
+
export interface PreviewContainer {
|
|
38
|
+
phase: PreviewPhase;
|
|
39
|
+
/** Only set in 'ready' — a URL that is not serving yet is worse than none. */
|
|
40
|
+
url: string | null;
|
|
41
|
+
error?: string;
|
|
42
|
+
/** Run the whole sequence again. The only exit from 'failed'. */
|
|
43
|
+
retry: () => void;
|
|
44
|
+
}
|
|
45
|
+
export declare function usePreviewContainer(projectId: string | null | undefined): PreviewContainer;
|
|
46
|
+
//# sourceMappingURL=preview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../src/admin/preview.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,MAAM,YAAY;AACtB,8DAA8D;AAC5D,MAAM;AACR,sEAAsE;GACpE,UAAU;AACZ,0CAA0C;GACxC,OAAO,GACP,QAAQ,CAAA;AAEZ,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,YAAY,CAAA;IACnB,8EAA8E;IAC9E,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iEAAiE;IACjE,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAkBD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,gBAAgB,CA6F1F"}
|
package/dist/admin/target.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type PreviewPhase } from './preview';
|
|
1
2
|
import type { BuilderTarget } from '../types';
|
|
2
3
|
export interface AdminTargetOptions {
|
|
3
4
|
/** Address of the running preview container, when the host knows it. */
|
|
@@ -15,6 +16,12 @@ export interface AdminTargetState {
|
|
|
15
16
|
target: BuilderTarget | null;
|
|
16
17
|
/** The tenant's projects have not answered yet — "none" is not the answer. */
|
|
17
18
|
loading: boolean;
|
|
19
|
+
/** How the running container is doing, when there is a project to run one for. */
|
|
20
|
+
preview: {
|
|
21
|
+
phase: PreviewPhase;
|
|
22
|
+
error?: string;
|
|
23
|
+
retry: () => void;
|
|
24
|
+
};
|
|
18
25
|
}
|
|
19
26
|
export declare function useAdminBuilderTarget(options?: AdminTargetOptions): AdminTargetState;
|
|
20
27
|
//# sourceMappingURL=target.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"target.d.ts","sourceRoot":"","sources":["../../src/admin/target.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAE7C,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAOD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;IAC5B,8EAA8E;IAC9E,OAAO,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"target.d.ts","sourceRoot":"","sources":["../../src/admin/target.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,WAAW,CAAA;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAE7C,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAOD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;IAC5B,8EAA8E;IAC9E,OAAO,EAAE,OAAO,CAAA;IAChB,kFAAkF;IAClF,OAAO,EAAE;QAAE,KAAK,EAAE,YAAY,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,CAAA;CACpE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,gBAAgB,CA2CpF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Loader2, Check, ChevronsUpDown, ChevronLeft, Search, Folder, ChevronRight, House, FileText, Eye, Code2, Monitor, Smartphone, ExternalLink, RotateCw, AlertTriangle, Globe } from 'lucide-react';
|
|
1
|
+
import { Loader2, Check, ChevronsUpDown, ChevronLeft, Search, Folder, ChevronRight, House, FileText, Eye, Code2, Monitor, Smartphone, ExternalLink, RotateCw, AlertTriangle, Globe, AlertCircle } from 'lucide-react';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import * as React3 from 'react';
|
|
4
4
|
|
|
@@ -715,7 +715,67 @@ function AppBuilder({
|
|
|
715
715
|
chat ? /* @__PURE__ */ jsx("div", { className: "hidden w-[min(28rem,32%)] shrink-0 border-l border-border md:flex md:flex-col md:overflow-hidden", children: chat }) : null
|
|
716
716
|
] });
|
|
717
717
|
}
|
|
718
|
+
function BuilderPending({
|
|
719
|
+
labels,
|
|
720
|
+
name,
|
|
721
|
+
phase,
|
|
722
|
+
error,
|
|
723
|
+
onRetry,
|
|
724
|
+
onAction
|
|
725
|
+
}) {
|
|
726
|
+
if (phase === "failed") {
|
|
727
|
+
return /* @__PURE__ */ jsx(
|
|
728
|
+
Shell,
|
|
729
|
+
{
|
|
730
|
+
icon: /* @__PURE__ */ jsx(AlertCircle, { className: "h-6 w-6 text-destructive" }),
|
|
731
|
+
title: labels?.previewFailedTitle ?? "O preview n\xE3o subiu",
|
|
732
|
+
body: error ?? labels?.previewFailedBody ?? "Tente de novo em alguns instantes.",
|
|
733
|
+
action: onRetry ? { label: labels?.previewRetry ?? "Tentar de novo", onClick: onRetry } : void 0
|
|
734
|
+
}
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
if (phase === "starting") {
|
|
738
|
+
return /* @__PURE__ */ jsx(
|
|
739
|
+
Shell,
|
|
740
|
+
{
|
|
741
|
+
icon: /* @__PURE__ */ jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }),
|
|
742
|
+
title: labels?.previewStartingTitle ?? (name ? `Abrindo ${name}\u2026` : "Abrindo o site\u2026"),
|
|
743
|
+
body: labels?.previewStartingBody ?? "O ambiente do site est\xE1 subindo. Na primeira vez leva alguns segundos."
|
|
744
|
+
}
|
|
745
|
+
);
|
|
746
|
+
}
|
|
747
|
+
return /* @__PURE__ */ jsx(
|
|
748
|
+
Shell,
|
|
749
|
+
{
|
|
750
|
+
icon: /* @__PURE__ */ jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }),
|
|
751
|
+
title: labels?.pendingTitle ?? (name ? `${name} est\xE1 sendo constru\xEDdo` : "Site em constru\xE7\xE3o"),
|
|
752
|
+
body: labels?.pendingBody ?? "Assim que a primeira publica\xE7\xE3o terminar, o site aparece aqui para voc\xEA editar.",
|
|
753
|
+
action: onAction ? { label: labels?.pendingAction ?? "Acompanhar no fayz", onClick: onAction } : void 0
|
|
754
|
+
}
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
function Shell({
|
|
758
|
+
icon,
|
|
759
|
+
title,
|
|
760
|
+
body,
|
|
761
|
+
action
|
|
762
|
+
}) {
|
|
763
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-3 p-8 text-center", children: [
|
|
764
|
+
/* @__PURE__ */ jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-muted", children: icon }),
|
|
765
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: title }),
|
|
766
|
+
/* @__PURE__ */ jsx("p", { className: "max-w-sm text-xs text-muted-foreground", children: body }),
|
|
767
|
+
action ? /* @__PURE__ */ jsx(
|
|
768
|
+
"button",
|
|
769
|
+
{
|
|
770
|
+
type: "button",
|
|
771
|
+
onClick: action.onClick,
|
|
772
|
+
className: "mt-1 rounded-full border border-border px-3 py-1.5 text-xs font-medium text-foreground hover:bg-muted",
|
|
773
|
+
children: action.label
|
|
774
|
+
}
|
|
775
|
+
) : null
|
|
776
|
+
] });
|
|
777
|
+
}
|
|
718
778
|
|
|
719
|
-
export { AppBuilder, BUILDER_MESSAGES, BuilderCanvas, BuilderChrome, BuilderEmpty, PagePicker, PublishButton, addCacheBuster, buildIframeUrl, connectBuilderBridge, extractRouteFromUrl, getBaseUrl, getQueryString, getUrlOrigin, isHomeRoute, isValidPreviewUrl, labelForRoute, navigateBuilder, normalizeRoute, postToBuilder, toPageGroups, toPages, useBuilderFrame };
|
|
720
|
-
//# sourceMappingURL=chunk-
|
|
721
|
-
//# sourceMappingURL=chunk-
|
|
779
|
+
export { AppBuilder, BUILDER_MESSAGES, BuilderCanvas, BuilderChrome, BuilderEmpty, BuilderPending, PagePicker, PublishButton, addCacheBuster, buildIframeUrl, connectBuilderBridge, extractRouteFromUrl, getBaseUrl, getQueryString, getUrlOrigin, isHomeRoute, isValidPreviewUrl, labelForRoute, navigateBuilder, normalizeRoute, postToBuilder, toPageGroups, toPages, useBuilderFrame };
|
|
780
|
+
//# sourceMappingURL=chunk-GTK7MRYT.js.map
|
|
781
|
+
//# sourceMappingURL=chunk-GTK7MRYT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/PublishButton.tsx","../src/lib/pages.ts","../src/lib/cn.ts","../src/components/PagePicker.tsx","../src/components/BuilderChrome.tsx","../src/components/BuilderCanvas.tsx","../src/components/BuilderEmpty.tsx","../src/lib/bridge.ts","../src/lib/url.ts","../src/hooks/useBuilderFrame.ts","../src/components/AppBuilder.tsx","../src/components/BuilderPending.tsx"],"names":["React","jsxs","jsx","Check","React2","Loader2","React4"],"mappings":";;;;;AAMO,SAAS,aAAA,CAAc;AAAA,EAC5B,OAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,MAAM,KAAA,GAAQ,QAAQ,OAAA,IAAW,UAAA;AACjC,EAAA,MAAM,KAAA,GAAQ,SAAS,KAAA,IAAS,MAAA;AAChC,EAAA,MAAM,OAAO,KAAA,KAAU,YAAA;AACvB,EAAA,MAAM,QAAA,GAAW,CAAC,OAAA,IAAW,IAAA;AAE7B,EAAA,uBACE,IAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,MAAM,OAAA,EAAS,OAAA,EAAQ;AAAA,MAChC,QAAA;AAAA,MACA,OACE,OAAA,GACI,OAAA,CAAQ,KAAA,IAAS,KAAA,GACjB,QAAQ,kBAAA,IAAsB,qDAAA;AAAA,MAEpC,SAAA,EAAU,wMAAA;AAAA,MAET,QAAA,EAAA;AAAA,QAAA,IAAA,mBAAO,GAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAU,0BAAA,EAA2B,CAAA,GAAK,IAAA;AAAA,QAC1D,KAAA,KAAU,eAAe,CAAC,IAAA,uBAAQ,KAAA,EAAA,EAAM,SAAA,EAAU,eAAc,CAAA,GAAK,IAAA;AAAA,QACrE;AAAA;AAAA;AAAA,GACH;AAEJ;;;AC7BA,IAAM,WAAA,GAAsC,EAAE,GAAA,EAAK,WAAA,EAAS;AAIrD,SAAS,eAAe,KAAA,EAAuB;AACpD,EAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA;AAClD,EAAA,OAAO,MAAM,UAAA,CAAW,GAAG,CAAA,GAAI,KAAA,GAAQ,IAAI,KAAK,CAAA,CAAA;AAClD;AAEO,SAAS,YAAY,KAAA,EAAwB;AAClD,EAAA,OAAO,cAAA,CAAe,KAAK,CAAA,KAAM,GAAA;AACnC;AAEA,IAAM,KAAA,GAAgC;AAAA,EACpC,QAAA,EAAU,UAAA;AAAA,EACV,QAAA,EAAU,UAAA;AAAA,EACV,QAAA,EAAU,UAAA;AAAA,EACV,IAAA,EAAM,UAAA;AAAA,EACN,QAAA,EAAU,UAAA;AAAA,EACV,OAAA,EAAS,SAAA;AAAA,EACT,OAAA,EAAS,SAAA;AAAA,EACT,KAAA,EAAO,OAAA;AAAA,EACP,KAAA,EAAO,OAAA;AAAA,EACP,IAAA,EAAM,MAAA;AAAA,EACN,QAAA,EAAU,gBAAA;AAAA,EACV,WAAA,EAAa,gBAAA;AAAA,EACb,QAAA,EAAU,aAAA;AAAA,EACV,KAAA,EAAO,OAAA;AAAA,EACP,OAAA,EAAS,OAAA;AAAA,EACT,OAAA,EAAS,SAAA;AAAA,EACT,OAAA,EAAS,aAAA;AAAA,EACT,QAAA,EAAU,aAAA;AAAA,EACV,OAAA,EAAS,aAAA;AAAA,EACT,KAAA,EAAO,QAAA;AAAA,EACP,OAAA,EAAS,YAAA;AAAA,EACT,QAAA,EAAU,UAAA;AAAA,EACV,OAAA,EAAS,UAAA;AAAA,EACT,UAAA,EAAY;AACd,CAAA;AAMO,SAAS,cAAc,KAAA,EAAuB;AACnD,EAAA,MAAM,KAAA,GAAQ,eAAe,KAAK,CAAA;AAClC,EAAA,IAAI,WAAA,CAAY,KAAK,CAAA,EAAG,OAAO,YAAY,KAAK,CAAA;AAEhD,EAAA,MAAM,WAAW,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA,CAAE,OAAO,OAAO,CAAA;AAChD,EAAA,IAAI,CAAC,QAAA,CAAS,MAAA,EAAQ,OAAO,YAAY,GAAG,CAAA;AAE5C,EAAA,OAAO,QAAA,CACJ,GAAA,CAAI,CAAC,OAAA,KAAY;AAChB,IAAA,MAAM,GAAA,GAAM,QAAQ,WAAA,EAAY;AAChC,IAAA,IAAI,KAAA,CAAM,GAAG,CAAA,EAAG,OAAO,MAAM,GAAG,CAAA;AAChC,IAAA,MAAM,KAAA,GAAQ,QAAQ,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA,CAAE,OAAA,CAAQ,UAAU,GAAG,CAAA;AAC7D,IAAA,OAAO,KAAA,CAAM,OAAO,CAAC,CAAA,CAAE,aAAY,GAAI,KAAA,CAAM,MAAM,CAAC,CAAA;AAAA,EACtD,CAAC,CAAA,CACA,IAAA,CAAK,UAAK,CAAA;AACf;AAUA,IAAM,UAAA,GAAa,CAAA;AAOZ,SAAS,aAAa,MAAA,EAAsC;AACjE,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAA2B;AACjD,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,OAAA,GAAU,cAAA,CAAe,KAAK,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AACvE,IAAA,MAAM,IAAA,GAAO,SAAA,CAAU,GAAA,CAAI,OAAO,KAAK,EAAC;AACxC,IAAA,IAAA,CAAK,KAAK,EAAE,KAAA,EAAO,OAAO,aAAA,CAAc,KAAK,GAAG,CAAA;AAChD,IAAA,SAAA,CAAU,GAAA,CAAI,SAAS,IAAI,CAAA;AAAA,EAC7B;AAEA,EAAA,MAAM,SAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,CAAC,OAAA,EAAS,KAAK,CAAA,IAAK,SAAA,EAAW;AACxC,IAAA,IAAI,KAAA,CAAM,MAAA,GAAS,UAAA,IAAc,CAAC,OAAA,EAAS;AACzC,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU,EAAE,KAAK,IAAA,CAAK,KAAA,EAAO,OAAO,IAAA,CAAK,KAAA,EAAO,OAAO,IAAA,CAAK,KAAA,EAAO,UAAU,EAAC,GAAI,CAAC,CAAA;AAC7G,MAAA;AAAA,IACF;AACA,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,GAAA,EAAK,OAAA;AAAA,MACL,KAAA,EAAO,aAAA,CAAc,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE,CAAA;AAAA,MAClC,QAAA,EAAU,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,QAC7B,OAAO,IAAA,CAAK,KAAA;AAAA;AAAA,QAEZ,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,UAAK,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,CAAE,IAAA,CAAK,UAAK,CAAA,IAAK,IAAA,CAAK;AAAA,OAC9D,CAAE;AAAA,KACH,CAAA;AAAA,EACH;AAGA,EAAA,MAAM,IAAA,GAAO,CAAC,CAAA,KAAyB,CAAA,CAAE,SAAS,WAAA,CAAY,CAAA,CAAE,KAAK,CAAA,GAAI,CAAA,GAAI,CAAA;AAC7E,EAAA,OAAO,OAAO,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,KAAK,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,KAAK,CAAA,CAAE,KAAA,CAAM,aAAA,CAAc,CAAA,CAAE,KAAK,CAAC,CAAA;AAClF;AAEO,SAAS,QAAQ,MAAA,EAAiC;AACvD,EAAA,OAAO,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,MAAW,EAAE,OAAO,KAAA,EAAO,aAAA,CAAc,KAAK,CAAA,EAAE,CAAE,CAAA;AACvE;;;ACjHO,SAAS,MAAM,KAAA,EAAyD;AAC7E,EAAA,OAAO,KAAA,CAAM,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AACvC;ACSO,SAAS,UAAA,CAAW;AAAA,EACzB,MAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA,GAAc,kBAAA;AAAA,EACd,UAAA,GAAa;AACf,CAAA,EASG;AACD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAUA,gBAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAUA,gBAAS,EAAE,CAAA;AAC3C,EAAA,MAAM,MAAA,GAAeA,cAA8B,IAAI,CAAA;AACvD,EAAA,MAAM,QAAA,GAAiBA,cAAgC,IAAI,CAAA;AAE3D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAUA,gBAAwB,IAAI,CAAA;AAEhE,EAAA,MAAM,KAAA,GAAcA,eAAQ,MAAM,OAAA,CAAQ,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAC3D,EAAA,MAAM,MAAA,GAAeA,eAAQ,MAAM,YAAA,CAAa,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACjE,EAAA,MAAM,WAAA,GAAoBA,MAAA,CAAA,OAAA,CAAQ,MAAM,MAAA,CAAO,KAAK,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,KAAQ,OAAO,CAAA,IAAK,IAAA,EAAM,CAAC,MAAA,EAAQ,OAAO,CAAC,CAAA;AAIxG,EAAA,MAAM,OAAA,GAAgBA,eAAQ,MAAM;AAClC,IAAA,MAAM,CAAA,GAAI,KAAA,CAAM,IAAA,EAAK,CAAE,WAAA,EAAY;AACnC,IAAA,IAAI,GAAG,OAAO,KAAA,CAAM,OAAO,CAAC,CAAA,KAAM,EAAE,KAAA,CAAM,WAAA,GAAc,QAAA,CAAS,CAAC,KAAK,CAAA,CAAE,KAAA,CAAM,aAAY,CAAE,QAAA,CAAS,CAAC,CAAC,CAAA;AACxG,IAAA,IAAI,WAAA,SAAoB,WAAA,CAAY,QAAA;AACpC,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,EAAG,CAAC,KAAA,EAAO,KAAA,EAAO,WAAW,CAAC,CAAA;AAE9B,EAAMA,iBAAU,MAAM;AACpB,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,MAAA,GAAS,CAAC,KAAA,KAAsB;AACpC,MAAA,IAAI,CAAC,OAAO,OAAA,EAAS,QAAA,CAAS,MAAM,MAAc,CAAA,UAAW,KAAK,CAAA;AAAA,IACpE,CAAA;AACA,IAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,KAAyB;AACtC,MAAA,IAAI,KAAA,CAAM,GAAA,KAAQ,QAAA,EAAU,OAAA,CAAQ,KAAK,CAAA;AAAA,IAC3C,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,aAAa,MAAM,CAAA;AAC7C,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,KAAK,CAAA;AAC1C,IAAA,QAAA,CAAS,SAAS,KAAA,EAAM;AACxB,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,aAAa,MAAM,CAAA;AAChD,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,KAAK,CAAA;AAAA,IAC/C,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,MAAA,GAAS,aAAA,CAAc,WAAW,CAAA,GAAI,QAAA;AAE1D,EAAA,IAAI,CAAC,MAAM,MAAA,EAAQ;AACjB,IAAA,uBACEC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0EAAA,EACZ,QAAA,EAAA;AAAA,MAAA,OAAA;AAAA,sBACDC,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yDAAyD,QAAA,EAAA,KAAA,EAAM;AAAA,KAAA,EACjF,CAAA;AAAA,EAEJ;AAEA,EAAA,uBACED,IAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,MAAA,EAAQ,WAAU,mFAAA,EACzB,QAAA,EAAA;AAAA,IAAA,OAAA;AAAA,oBACDA,IAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,SAAS,MAAM;AACb,UAAA,QAAA,CAAS,EAAE,CAAA;AACX,UAAA,UAAA,CAAW,IAAI,CAAA;AACf,UAAA,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,QACnB,CAAA;AAAA,QACA,eAAA,EAAe,IAAA;AAAA,QACf,eAAA,EAAc,SAAA;AAAA,QACd,SAAA,EAAU,0GAAA;AAAA,QAEV,QAAA,EAAA;AAAA,0BAAAC,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kBAAA,EAAoB,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,0BAC1CA,GAAAA,CAAC,cAAA,EAAA,EAAe,SAAA,EAAU,4CAAA,EAA6C;AAAA;AAAA;AAAA,KACzE;AAAA,IAEC,uBACCD,IAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,SAAA;AAAA,QACL,SAAA,EAAU,iIAAA;AAAA,QAET,QAAA,EAAA;AAAA,UAAA,WAAA,IAAe,CAAC,wBACfA,IAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,OAAA,EAAS,MAAM,UAAA,CAAW,IAAI,CAAA;AAAA,cAC9B,SAAA,EAAU,uHAAA;AAAA,cAEV,QAAA,EAAA;AAAA,gCAAAC,GAAAA,CAAC,WAAA,EAAA,EAAY,SAAA,EAAU,wCAAA,EAAyC,CAAA;AAAA,gBAC/D,WAAA,CAAY;AAAA;AAAA;AAAA,WACf,GACE,IAAA;AAAA,0BAEJD,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0DAAA,EACb,QAAA,EAAA;AAAA,4BAAAC,GAAAA,CAAC,MAAA,EAAA,EAAO,SAAA,EAAU,wCAAA,EAAyC,CAAA;AAAA,4BAC3DA,GAAAA;AAAA,cAAC,OAAA;AAAA,cAAA;AAAA,gBACC,GAAA,EAAK,QAAA;AAAA,gBACL,KAAA,EAAO,KAAA;AAAA,gBACP,UAAU,CAAC,KAAA,KAAU,QAAA,CAAS,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,gBAChD,WAAA,EAAa,WAAA;AAAA,gBACb,YAAA,EAAY,WAAA;AAAA,gBACZ,SAAA,EAAU;AAAA;AAAA;AACZ,WAAA,EACF,CAAA;AAAA,0BAEAA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8BAAA,EACZ,WAAC,OAAA,GACA,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACpB,YAAA,IAAI,CAAC,MAAM,KAAA,EAAO;AAChB,cAAA,uBACED,IAAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBAEC,IAAA,EAAK,QAAA;AAAA,kBACL,OAAA,EAAS,MAAM,UAAA,CAAW,KAAA,CAAM,GAAG,CAAA;AAAA,kBACnC,SAAA,EAAU,+HAAA;AAAA,kBAEV,QAAA,EAAA;AAAA,oCAAAC,GAAAA,CAAC,MAAA,EAAA,EAAO,SAAA,EAAU,wCAAA,EAAyC,CAAA;AAAA,oCAC3DA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yBAAA,EAA2B,gBAAM,KAAA,EAAM,CAAA;AAAA,oCACvDA,GAAAA,CAAC,MAAA,EAAA,EAAK,WAAU,wCAAA,EAA0C,QAAA,EAAA,KAAA,CAAM,SAAS,MAAA,EAAO,CAAA;AAAA,oCAChFA,GAAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAU,wCAAA,EAAyC;AAAA;AAAA,iBAAA;AAAA,gBAR5D,KAAA,CAAM;AAAA,eASb;AAAA,YAEJ;AACA,YAAA,MAAM,SAAS,cAAA,CAAe,KAAA,CAAM,KAAK,CAAA,KAAM,eAAe,WAAW,CAAA;AACzE,YAAA,MAAM,IAAA,GAAO,WAAA,CAAY,KAAA,CAAM,KAAK,IAAI,KAAA,GAAQ,QAAA;AAChD,YAAA,uBACED,IAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBAEC,IAAA,EAAK,QAAA;AAAA,gBACL,IAAA,EAAK,QAAA;AAAA,gBACL,eAAA,EAAe,MAAA;AAAA,gBACf,SAAS,MAAM;AACb,kBAAA,UAAA,CAAW,MAAM,KAAM,CAAA;AACvB,kBAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,gBACf,CAAA;AAAA,gBACA,SAAA,EAAW,EAAA;AAAA,kBACT,6FAAA;AAAA,kBACA,SAAS,sCAAA,GAAyC;AAAA,iBACpD;AAAA,gBAEA,QAAA,EAAA;AAAA,kCAAAC,GAAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,wCAAA,EAAyC,CAAA;AAAA,kCACzDA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yBAAA,EAA2B,gBAAM,KAAA,EAAM,CAAA;AAAA,kBACtD,yBAASA,GAAAA,CAACC,OAAA,EAAM,SAAA,EAAU,0CAAyC,CAAA,GAAK;AAAA;AAAA,eAAA;AAAA,cAfpE,KAAA,CAAM;AAAA,aAgBb;AAAA,UAEJ,CAAC,CAAA,GACC,OAAA,CAAQ,SACV,OAAA,CAAQ,GAAA,CAAI,CAAC,IAAA,KAAS;AACpB,YAAA,MAAM,SAAS,cAAA,CAAe,IAAA,CAAK,KAAK,CAAA,KAAM,eAAe,WAAW,CAAA;AACxE,YAAA,MAAM,IAAA,GAAO,WAAA,CAAY,IAAA,CAAK,KAAK,IAAI,KAAA,GAAQ,QAAA;AAC/C,YAAA,uBACEF,IAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBAEC,IAAA,EAAK,QAAA;AAAA,gBACL,IAAA,EAAK,QAAA;AAAA,gBACL,eAAA,EAAe,MAAA;AAAA,gBACf,SAAS,MAAM;AACb,kBAAA,UAAA,CAAW,KAAK,KAAK,CAAA;AACrB,kBAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,gBACf,CAAA;AAAA,gBACA,SAAA,EAAW,EAAA;AAAA,kBACT,6FAAA;AAAA,kBACA,SAAS,sCAAA,GAAyC;AAAA,iBACpD;AAAA,gBAEA,QAAA,EAAA;AAAA,kCAAAC,GAAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,wCAAA,EAAyC,CAAA;AAAA,kCACzDA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yBAAA,EAA2B,eAAK,KAAA,EAAM,CAAA;AAAA,kBACrD,yBAASA,GAAAA,CAACC,OAAA,EAAM,SAAA,EAAU,0CAAyC,CAAA,GAAK;AAAA;AAAA,eAAA;AAAA,cAfpE,IAAA,CAAK;AAAA,aAgBZ;AAAA,UAEJ,CAAC,oBAEDD,GAAAA,CAAC,OAAE,SAAA,EAAU,uDAAA,EAAyD,sBAAW,CAAA,EAErF;AAAA;AAAA;AAAA,KACF,GACE;AAAA,GAAA,EACN,CAAA;AAEJ;AC1LA,IAAM,UAAA,GACJ,sMAAA;AAGF,SAAS,SAAA,CAAU,KAAoB,IAAA,EAAsB;AAC3D,EAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AACjB,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA,GAAO,OAAO,QAAA,CAAS,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAC7D,IAAA,OAAO,IAAA,KAAS,GAAA,GAAM,IAAA,GAAO,GAAA,GAAM,IAAA,GAAO,IAAA;AAAA,EAC5C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAMA,SAAS,aAAA,CAAc;AAAA,EACrB,OAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA,EAKG;AACD,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,EAAE,EAAA,EAAI,OAAA,EAAS,KAAA,EAAO,cAAA,EAAgB,OAAO,MAAA,EAAQ,KAAA,IAAS,MAAA,EAAQ,OAAA,EAAS,OAAA,EAAQ;AAAA,IACvF,EAAE,EAAA,EAAI,UAAA,EAAY,KAAA,EAAO,cAAA,EAAgB,OAAO,MAAA,EAAQ,UAAA,IAAc,qBAAA,EAAuB,OAAA,EAAS,YAAA,EAAa;AAAA,IACnH,EAAE,EAAA,EAAI,MAAA,EAAQ,KAAA,EAAO,cAAA,EAAgB,OAAO,MAAA,EAAQ,UAAA,IAAc,wBAAA,EAA0B,OAAA,EAAS,YAAA;AAAa,IAClH,MAAA,CAAO,CAAC,UAAU,CAAC,CAAC,MAAM,OAAO,CAAA;AAEnC,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,EAAQ,OAAO,IAAA;AAE3B,EAAA,uBACEA,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2CACZ,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,qBACXA,GAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MAEC,IAAA,EAAK,QAAA;AAAA,MACL,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,cAAY,KAAA,CAAM,KAAA;AAAA,MAClB,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,SAAA,EAAU,4GAAA;AAAA,MAEV,QAAA,kBAAAA,IAAC,MAAA,EAAA,EAAK,SAAA,EAAW,GAAG,sBAAA,EAAwB,KAAA,CAAM,KAAK,CAAA,EAAG;AAAA,KAAA;AAAA,IAPrD,KAAA,CAAM;AAAA,GASd,CAAA,EACH,CAAA;AAEJ;AAOO,SAAS,aAAA,CAAc;AAAA,EAC5B,MAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,gBAAA;AAAA,EACA,QAAA;AAAA,EACA,IAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAgBG;AACD,EAAA,MAAM,OAAA,GAAU,SAAA,CAAU,MAAA,CAAO,GAAA,EAAK,WAAW,CAAA;AACjD,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,OAAA,IAAW,MAAA,CAAO,GAAA;AAI5C,EAAA,MAAM,MAAA,GAAS,QAAA,KAAa,SAAA,GAAY,OAAA,GAAU,UAAA;AAClD,EAAA,MAAM,WAAA,GAAc,QAAA,KAAa,SAAA,GAAY,gBAAA,GAAmB,mBAAA;AAEhE,EAAA;AAAA;AAAA;AAAA,oBAGED,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mEAAA,EAGZ,QAAA,EAAA;AAAA,MAAA,QAAA,KAAa,4BACZC,GAAAA;AAAA,QAAC,aAAA;AAAA,QAAA;AAAA,UACC,OAAA;AAAA,UACA,YAAA;AAAA,UACA,YAAA;AAAA,UACA;AAAA;AAAA,OACF,GACE,IAAA;AAAA,MAEH,YAAA,mBACCA,GAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,wEAAA,EACX,QAAA,EAAA;AAAA,QACA,EAAE,IAAI,SAAA,EAAoB,IAAA,EAAM,KAAK,KAAA,EAAO,MAAA,EAAQ,WAAW,QAAA,EAAS;AAAA,QACxE,EAAE,IAAI,MAAA,EAAiB,IAAA,EAAM,OAAO,KAAA,EAAO,MAAA,EAAQ,QAAQ,WAAA;AAAS,OACtE,CAAG,IAAI,CAAC,EAAE,IAAI,IAAA,EAAM,IAAA,EAAM,KAAA,EAAM,qBAC9BD,IAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UAEC,IAAA,EAAK,QAAA;AAAA,UACL,KAAA;AAAA,UACA,YAAA,EAAY,KAAA;AAAA,UACZ,gBAAc,IAAA,KAAS,EAAA;AAAA,UACvB,OAAA,EAAS,MAAM,YAAA,CAAa,EAAE,CAAA;AAAA,UAC9B,SAAA,EAAW,EAAA;AAAA,YACT,yFAAA;AAAA,YACA,IAAA,KAAS,KAAK,mCAAA,GAAsC;AAAA,WACtD;AAAA,UAEA,QAAA,EAAA;AAAA,4BAAAC,GAAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,YAC7B;AAAA;AAAA,SAAA;AAAA,QAZI;AAAA,OAcR,GACH,CAAA,GACE,IAAA;AAAA,sBAIJA,GAAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,MAAA;AAAA,UACA,WAAA;AAAA,UACA,UAAA;AAAA,UACA,QAAA,EAAU,OAAA;AAAA,UACV,aAAa,MAAA,EAAQ,UAAA;AAAA,UACrB,YAAY,MAAA,EAAQ,MAAA;AAAA,UACpB,yBACEA,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,KAAA,EAAO,WAAA;AAAA,cACP,YAAA,EAAY,WAAA;AAAA,cACZ,SAAS,MAAM,gBAAA,CAAiB,QAAA,KAAa,SAAA,GAAY,WAAW,SAAS,CAAA;AAAA,cAC7E,SAAA,EAAU,qJAAA;AAAA,cAEV,QAAA,kBAAAA,GAAAA,CAAC,MAAA,EAAA,EAAO,SAAA,EAAU,SAAA,EAAU;AAAA;AAAA;AAC9B;AAAA,OAEJ;AAAA,sBAEAA,GAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,KAAA,EAAO,QAAQ,QAAA,IAAY,kBAAA;AAAA,UAC3B,YAAA,EAAY,QAAQ,QAAA,IAAY,kBAAA;AAAA,UAChC,UAAU,CAAC,UAAA;AAAA,UACX,SAAS,MAAM,UAAA,IAAc,OAAO,IAAA,CAAK,UAAA,EAAY,UAAU,qBAAqB,CAAA;AAAA,UACpF,SAAA,EAAW,UAAA;AAAA,UAEX,QAAA,kBAAAA,GAAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAU,SAAA,EAAU;AAAA;AAAA,OACpC;AAAA,sBACAA,GAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,KAAA,EAAO,QAAQ,MAAA,IAAU,YAAA;AAAA,UACzB,YAAA,EAAY,QAAQ,MAAA,IAAU,YAAA;AAAA,UAC9B,OAAA,EAAS,QAAA;AAAA,UACT,SAAA,EAAW,UAAA;AAAA,UAEX,QAAA,kBAAAA,GAAAA,CAAC,QAAA,EAAA,EAAS,SAAA,EAAU,SAAA,EAAU;AAAA;AAAA,OAChC;AAAA,MAEC,SAAA;AAAA,sBACDA,GAAAA,CAAC,aAAA,EAAA,EAAc,OAAA,EAAkB,MAAA,EAAgB;AAAA,KAAA,EACnD;AAAA;AAEJ;ACjMA,IAAM,KAAA,GAAQ,eAAA;AAEP,SAAS,aAAA,CAAc;AAAA,EAC5B,MAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAIG;AAGD,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAUE,gBAAS,KAAK,CAAA;AACpD,EAAMA,iBAAU,MAAM;AACpB,IAAA,MAAM,IAAA,GAAO,CAAC,KAAA,KAAwB;AACpC,MAAA,MAAM,KAAK,KAAA,CAAM,MAAA;AACjB,MAAA,IAAI,EAAA,EAAI,OAAA,CAAQ,oBAAoB,CAAA,cAAe,IAAI,CAAA;AAAA,IACzD,CAAA;AACA,IAAA,MAAM,EAAA,GAAK,MAAM,WAAA,CAAY,KAAK,CAAA;AAClC,IAAA,MAAA,CAAO,gBAAA,CAAiB,aAAA,EAAe,IAAA,EAAM,IAAI,CAAA;AACjD,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAA,EAAa,EAAA,EAAI,IAAI,CAAA;AAC7C,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,aAAA,EAAe,IAAA,EAAM,IAAI,CAAA;AACpD,MAAA,MAAA,CAAO,mBAAA,CAAoB,WAAA,EAAa,EAAA,EAAI,IAAI,CAAA;AAAA,IAClD,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,IAAI,CAAC,KAAA,CAAM,GAAA,EAAK,OAAO,IAAA;AAEvB,EAAA,uBACEH,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6DAAA,EACb,QAAA,EAAA;AAAA,oBAAAC,GAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QAEC,KAAK,KAAA,CAAM,QAAA;AAAA,QACX,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,OAAO,MAAA,CAAO,IAAA;AAAA,QACd,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,SAAA,EAAW,EAAA,CAAG,mBAAA,EAAqB,KAAA,EAAO,YAAY,qBAAqB,CAAA;AAAA,QAC3E,OAAA,EAAQ;AAAA,OAAA;AAAA,MANH,CAAA,EAAG,KAAA,CAAM,GAAG,CAAA,CAAA,EAAI,MAAM,KAAK,CAAA;AAAA,KAOlC;AAAA,IAEC,MAAM,OAAA,IAAW,CAAC,KAAA,CAAM,MAAA,oBACvBA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uEAAA,EACb,0BAAAA,GAAAA,CAACG,OAAAA,EAAA,EAAQ,SAAA,EAAU,8CAA6C,CAAA,EAClE,CAAA;AAAA,IAGD,MAAM,MAAA,oBACLJ,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,mGAAA,EACb,QAAA,EAAA;AAAA,sBAAAC,GAAAA,CAAC,aAAA,EAAA,EAAc,SAAA,EAAU,+BAAA,EAAgC,CAAA;AAAA,sBACzDA,GAAAA,CAAC,GAAA,EAAA,EAAE,WAAU,qCAAA,EACV,QAAA,EAAA,MAAA,EAAQ,cAAc,oDAAA,EACzB,CAAA;AAAA,sBACAA,GAAAA,CAAC,GAAA,EAAA,EAAE,WAAU,wCAAA,EACV,QAAA,EAAA,MAAA,EAAQ,kBACJ,2GAAA,EACP,CAAA;AAAA,sBACAA,GAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,OAAA,EAAS,MAAM,KAAA,CAAM,GAAA,IAAO,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,EAAK,QAAA,EAAU,qBAAqB,CAAA;AAAA,UAClF,SAAA,EAAU,uGAAA;AAAA,UAET,kBAAQ,SAAA,IAAa;AAAA;AAAA;AACxB,KAAA,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ;ACzEO,SAAS,YAAA,CAAa,EAAE,MAAA,EAAQ,QAAA,EAAS,EAAsD;AACpG,EAAA,uBACED,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wEAAA,EACb,QAAA,EAAA;AAAA,oBAAAC,GAAAA,CAAC,SAAI,SAAA,EAAU,kEAAA,EACb,0BAAAA,GAAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAU,+BAAA,EAAgC,CAAA,EACnD,CAAA;AAAA,oBACAA,GAAAA,CAAC,GAAA,EAAA,EAAE,WAAU,qCAAA,EACV,QAAA,EAAA,MAAA,EAAQ,cAAc,4BAAA,EACzB,CAAA;AAAA,oBACAA,GAAAA,CAAC,GAAA,EAAA,EAAE,WAAU,wCAAA,EACV,QAAA,EAAA,MAAA,EAAQ,aAAa,wEAAA,EACxB,CAAA;AAAA,IACC,2BACCA,GAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,QAAA;AAAA,QACT,SAAA,EAAU,uGAAA;AAAA,QAET,kBAAQ,WAAA,IAAe;AAAA;AAAA,KAC1B,GACE;AAAA,GAAA,EACN,CAAA;AAEJ;;;ACvBO,IAAM,gBAAA,GAAmB;AAAA,EAC9B,QAAA,EAAU,yBAAA;AAAA,EACV,UAAA,EAAY,2BAAA;AAAA,EACZ,KAAA,EAAO,sBAAA;AAAA,EACP,MAAA,EAAQ,gBAAA;AAAA,EACR,SAAA,EAAW,0BAAA;AAAA,EACX,UAAA,EAAY;AACd;AASO,IAAM,aAAA,GAAgB,aAAA;AACtB,IAAM,oBAAA,GAAuB,oBAAA;AAc7B,SAAS,oBAAA,CACd,KAAA,EACA,MAAA,EACA,QAAA,EACY;AACZ,EAAA,MAAM,GAAA,GAAM,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,GAAY,MAAA;AACxD,EAAA,IAAI,CAAC,GAAA,EAAK,OAAO,MAAM;AAAA,EAAC,CAAA;AAExB,EAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KAAwB;AACzC,IAAA,IAAI,KAAA,CAAM,WAAW,MAAA,EAAQ;AAC7B,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,KAAA,CAAM,aAAA,EAAe;AAC1C,IAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AAInB,IAAA,IAAI,IAAA,EAAM,WAAW,aAAA,EAAe;AAClC,MAAA,IAAI,IAAA,CAAK,IAAA,KAAS,mBAAA,IAAuB,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAA,EAAG,QAAA,CAAS,QAAA,GAAW,IAAA,CAAK,MAAM,CAAA;AAAA,WAAA,IAC3F,IAAA,CAAK,IAAA,KAAS,eAAA,IAAmB,OAAO,IAAA,CAAK,UAAU,QAAA,EAAU,QAAA,CAAS,UAAA,GAAa,IAAA,CAAK,KAAK,CAAA;AAC1G,MAAA;AAAA,IACF;AAEA,IAAA,QAAQ,MAAM,IAAA;AAAM,MAClB,KAAK,gBAAA,CAAiB,UAAA;AACpB,QAAA,IAAI,OAAO,IAAA,CAAK,IAAA,KAAS,UAAU,QAAA,CAAS,UAAA,GAAa,KAAK,IAAI,CAAA;AAClE,QAAA;AAAA,MACF,KAAK,gBAAA,CAAiB,KAAA;AACpB,QAAA,QAAA,CAAS,OAAA,IAAU;AACnB,QAAA;AAAA,MACF,KAAK,gBAAA,CAAiB,MAAA;AACpB,QAAA,IAAI,IAAA,CAAK,IAAA,EAAM,QAAA,CAAS,QAAA,GAAW,KAAK,IAAI,CAAA;AAC5C,QAAA;AAAA,MACF,KAAK,gBAAA,CAAiB,SAAA;AACpB,QAAA,QAAA,CAAS,WAAA,IAAc;AACvB,QAAA;AAAA;AACJ,EACF,CAAA;AAEA,EAAA,GAAA,CAAI,gBAAA,CAAiB,WAAW,SAAS,CAAA;AACzC,EAAA,OAAO,MAAM,GAAA,CAAI,mBAAA,CAAoB,SAAA,EAAW,SAAS,CAAA;AAC3D;AAGO,SAAS,eAAA,CACd,KAAA,EACA,MAAA,EACA,KAAA,EACM;AACN,EAAA,aAAA,CAAc,KAAA,EAAO,QAAQ,EAAE,MAAA,EAAQ,sBAAsB,IAAA,EAAM,UAAA,EAAY,OAAO,CAAA;AACxF;AAGO,SAAS,aAAA,CACd,KAAA,EACA,MAAA,EACA,OAAA,EACM;AACN,EAAA,IAAI,CAAC,KAAA,EAAO,aAAA,IAAiB,CAAC,MAAA,EAAQ;AACtC,EAAA,KAAA,CAAM,aAAA,CAAc,WAAA,CAAY,OAAA,EAAS,MAAM,CAAA;AACjD;;;ACzFO,SAAS,WAAW,GAAA,EAAqB;AAC9C,EAAA,OAAO,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC1D;AAEO,SAAS,eAAe,GAAA,EAAqB;AAClD,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AAC3B,EAAA,OAAO,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,KAAA,CAAM,CAAC,EAAE,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA;AACrD;AAGO,SAAS,cAAA,CAAe,SAAiB,KAAA,EAAuB;AACrE,EAAA,MAAM,SAAA,GAAY,WAAW,OAAO,CAAA;AACpC,EAAA,MAAM,WAAA,GAAc,eAAe,OAAO,CAAA;AAG1C,EAAA,IAAI,KAAA,CAAM,UAAA,CAAW,IAAI,CAAA,EAAG;AAC1B,IAAA,OAAO,CAAA,EAAG,SAAS,CAAA,EAAG,WAAA,GAAc,MAAM,WAAA,GAAc,EAAE,GAAG,KAAK,CAAA,CAAA;AAAA,EACpE;AAGA,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AACnC,EAAA,MAAM,YAAY,SAAA,KAAc,EAAA,GAAK,QAAQ,KAAA,CAAM,SAAA,CAAU,GAAG,SAAS,CAAA;AACzE,EAAA,MAAM,eAAe,SAAA,KAAc,EAAA,GAAK,EAAA,GAAK,KAAA,CAAM,UAAU,SAAS,CAAA;AAEtE,EAAA,IAAI,SAAS,CAAA,EAAG,SAAS,GAAG,SAAA,KAAc,GAAA,GAAM,KAAK,SAAS,CAAA,CAAA;AAC9D,EAAA,IAAI,WAAA,EAAa,MAAA,IAAU,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA;AAC1C,EAAA,IAAI,cAAc,MAAA,IAAU,YAAA;AAC5B,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,cAAA,CAAe,GAAA,EAAa,GAAA,GAAc,IAAA,CAAK,KAAI,EAAW;AAC5E,EAAA,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,GAAI,GAAA,GAAM,GAAG,CAAA,IAAA,EAAO,GAAG,CAAA,CAAA;AACzD;AAEO,SAAS,mBAAA,CAAoB,SAAiB,OAAA,EAAyB;AAC5E,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,OAAO,CAAA;AAC5B,IAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,OAAO,CAAA;AAC5B,IAAA,IAAI,IAAA,CAAK,IAAA,KAAS,IAAA,CAAK,IAAA,EAAM,OAAO,GAAA;AAEpC,IAAA,IAAI,WAAW,IAAA,CAAK,QAAA;AACpB,IAAA,IAAI,KAAK,QAAA,KAAa,GAAA,IAAO,SAAS,UAAA,CAAW,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC/D,MAAA,QAAA,GAAW,QAAA,CAAS,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA;AAAA,IAChD;AACA,IAAA,IAAI,CAAC,QAAA,CAAS,UAAA,CAAW,GAAG,CAAA,aAAc,GAAA,GAAM,QAAA;AAChD,IAAA,OAAO,QAAA,IAAY,GAAA;AAAA,EACrB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,GAAA;AAAA,EACT;AACF;AAEO,SAAS,kBAAkB,GAAA,EAAyC;AACzE,EAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AACjB,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,OAAO,MAAA,CAAO,QAAA,KAAa,OAAA,IAAW,MAAA,CAAO,QAAA,KAAa,QAAA;AAAA,EAC5D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,SAAS,aAAa,GAAA,EAA4B;AACvD,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,GAAA,CAAI,GAAG,CAAA,CAAE,MAAA;AAAA,EACtB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;ACjDA,IAAM,eAAA,GAAkB,GAAA;AAEjB,SAAS,eAAA,CACd,KACA,QAAA,EACwB;AACxB,EAAA,MAAM,QAAA,GAAiB,cAAiC,IAAI,CAAA;AAC5D,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAU,gBAAS,CAAC,CAAA;AAC1C,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAU,gBAAS,IAAI,CAAA;AACjD,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAU,gBAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAU,gBAAS,GAAG,CAAA;AACxD,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAU,MAAA,CAAA,QAAA,CAAmB,EAAE,CAAA;AAEvD,EAAA,MAAM,MAAA,GAAe,MAAA,CAAA,OAAA,CAAQ,MAAO,GAAA,GAAM,YAAA,CAAa,GAAG,CAAA,GAAI,IAAA,EAAO,CAAC,GAAG,CAAC,CAAA;AAG1E,EAAA,MAAM,GAAA,GAAY,MAAA,CAAA,OAAA,CAAQ,MAAO,GAAA,GAAM,cAAA,CAAe,GAAA,EAAK,GAAG,CAAA,GAAI,IAAA,EAAO,CAAC,GAAG,CAAC,CAAA;AAE9E,EAAA,MAAM,EAAA,GAAW,cAAO,QAAQ,CAAA;AAChC,EAAA,EAAA,CAAG,OAAA,GAAU,QAAA;AAEb,EAAM,iBAAU,MAAM;AACpB,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,SAAA,CAAU,KAAK,CAAA;AAAA,EACjB,CAAA,EAAG,CAAC,GAAA,EAAK,KAAK,CAAC,CAAA;AAEf,EAAM,iBAAU,MAAM;AACpB,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,SAAA,CAAU,IAAI,GAAG,eAAe,CAAA;AAC/D,IAAA,OAAO,MAAM,aAAa,KAAK,CAAA;AAAA,EACjC,CAAA,EAAG,CAAC,OAAA,EAAS,GAAA,EAAK,KAAK,CAAC,CAAA;AAExB,EAAM,iBAAU,MAAM;AACpB,IAAA,MAAM,QAAQ,QAAA,CAAS,OAAA;AACvB,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,MAAA,EAAQ;AACvB,IAAA,OAAO,oBAAA,CAAqB,OAAO,MAAA,EAAQ;AAAA,MACzC,QAAA,EAAU,SAAA;AAAA,MACV,UAAA,EAAY,CAAC,IAAA,KAAS;AACpB,QAAA,cAAA,CAAe,IAAI,CAAA;AACnB,QAAA,EAAA,CAAG,OAAA,EAAS,aAAa,IAAI,CAAA;AAAA,MAC/B,CAAA;AAAA,MACA,QAAA,EAAU,CAAC,KAAA,KAAU,EAAA,CAAG,OAAA,EAAS,MAAA,GAAS,EAAE,QAAA,EAAU,KAAA,CAAM,IAAA,EAAM,OAAA,EAAS,KAAA,CAAM,MAAM;AAAA,KACxF,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,MAAA,EAAQ,KAAK,CAAC,CAAA;AAElB,EAAA,MAAM,MAAA,GAAe,MAAA,CAAA,WAAA,CAAY,MAAM,QAAA,CAAS,CAAC,MAAM,CAAA,GAAI,CAAC,CAAA,EAAG,EAAE,CAAA;AAIjE,EAAA,MAAM,QAAA,GAAiB,MAAA,CAAA,WAAA;AAAA,IACrB,CAAC,IAAA,KAAiB;AAChB,MAAA,cAAA,CAAe,IAAI,CAAA;AACnB,MAAA,eAAA,CAAgB,QAAA,CAAS,OAAA,EAAS,MAAA,EAAQ,IAAI,CAAA;AAAA,IAChD,CAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,MAAA,GAAe,mBAAY,MAAM;AACrC,IAAA,UAAA,CAAW,KAAK,CAAA;AAChB,IAAA,SAAA,CAAU,KAAK,CAAA;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,GAAA,EAAK,MAAA,EAAQ,OAAA,EAAS,MAAA,EAAQ,WAAA,EAAa,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAS;AACxG;ACrEO,SAAS,UAAA,CAAW;AAAA,EACzB,MAAA;AAAA,EACA,IAAA,GAAO,SAAA;AAAA,EACP,YAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA,EAAU,YAAA;AAAA,EACV,gBAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA,EAAO;AACT,CAAA,EAAoB;AAIlB,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAUI,gBAA0B,SAAS,CAAA;AACzF,EAAA,MAAM,WAAW,YAAA,IAAgB,gBAAA;AACjC,EAAA,MAAM,cAAc,gBAAA,IAAoB,mBAAA;AAMxC,EAAA,MAAM,UAAA,GAAmBA,MAAA,CAAA,WAAA;AAAA,IACvB,CAAC,OAAA,KAAmC,MAAA,GAAS,OAAO,CAAA;AAAA,IACpD,CAAC,MAAM;AAAA,GACT;AAKA,EAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,SAAA,GAAY,IAAA,GAAO,MAAA,CAAO,KAAK,EAAE,UAAA,EAAY,MAAA,EAAQ,UAAA,EAAY,CAAA;AAClG,EAAA,MAAM,QAAQ,SAAA,IAAa,QAAA;AAE3B,EAAA,MAAM,IAAA,GAAO,CAAC,MAAA,CAAO,GAAA,GAClB,KAAA,oBAASJ,GAAAA,CAAC,YAAA,EAAA,EAAa,MAAA,EAAgB,CAAA,GACtC,IAAA,KAAS,MAAA,IAAU,uBACrBA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gCAAA,EAAkC,QAAA,EAAA,IAAA,EAAK,CAAA,mBAEtDA,GAAAA,CAAC,aAAA,EAAA,EAAc,MAAA,EAAgB,KAAA,EAAc,MAAA,EAAgB,CAAA;AAK/D,EAAA,MAAM,MAAA,GAAS,QAAA,KAAa,QAAA,IAAY,CAAC,CAAC,MAAA,CAAO,GAAA;AAEjD,EAAA,uBACED,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAW,EAAA,CAAG,qCAAA,EAAuC,SAAS,CAAA,EACjE,QAAA,EAAA;AAAA,oBAAAA,KAAC,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,8CAAA,EAAgD,MAAA,IAAU,+BAA+B,CAAA,EAC1G,QAAA,EAAA;AAAA,sBAAAA,IAAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,EAAA;AAAA,YACT,qDAAA;AAAA,YACA,MAAA,IAAU;AAAA,WACZ;AAAA,UAEF,QAAA,EAAA;AAAA,4BAAAC,GAAAA;AAAA,cAAC,aAAA;AAAA,cAAA;AAAA,gBACC,MAAA;AAAA,gBACA,aAAa,KAAA,CAAM,WAAA;AAAA,gBACnB,QAAQ,KAAA,CAAM,MAAA;AAAA,gBACd,YAAY,KAAA,CAAM,QAAA;AAAA,gBAClB,QAAA;AAAA,gBACA,gBAAA,EAAkB,WAAA;AAAA,gBAClB,UAAU,KAAA,CAAM,MAAA;AAAA,gBAChB,IAAA;AAAA,gBACA,YAAA,EAAc,OAAO,YAAA,GAAe,MAAA;AAAA,gBACpC,OAAA;AAAA,gBACA,OAAA;AAAA,gBACA,YAAA;AAAA,gBACA,YAAA;AAAA,gBACA,WAAW,KAAA,EAAO,SAAA;AAAA,gBAClB;AAAA;AAAA,aACF;AAAA,YACC;AAAA;AAAA;AAAA,OACD;AAAA,MACC,KAAA,EAAO;AAAA,KAAA,EACV,CAAA;AAAA,IAEC,uBACCA,GAAAA,CAAC,SAAI,SAAA,EAAU,kGAAA,EACZ,gBACH,CAAA,GACE;AAAA,GAAA,EACN,CAAA;AAEJ;ACpFO,SAAS,cAAA,CAAe;AAAA,EAC7B,MAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAUG;AACD,EAAA,IAAI,UAAU,QAAA,EAAU;AACtB,IAAA,uBACEA,GAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAA,kBAAMA,GAAAA,CAAC,WAAA,EAAA,EAAY,WAAU,0BAAA,EAA2B,CAAA;AAAA,QACxD,KAAA,EAAO,QAAQ,kBAAA,IAAsB,wBAAA;AAAA,QAGrC,IAAA,EAAM,KAAA,IAAS,MAAA,EAAQ,iBAAA,IAAqB,oCAAA;AAAA,QAC5C,MAAA,EAAQ,UAAU,EAAE,KAAA,EAAO,QAAQ,YAAA,IAAgB,gBAAA,EAAkB,OAAA,EAAS,OAAA,EAAQ,GAAI;AAAA;AAAA,KAC5F;AAAA,EAEJ;AAEA,EAAA,IAAI,UAAU,UAAA,EAAY;AACxB,IAAA,uBACEA,GAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,sBAAMA,GAAAA,CAACG,OAAAA,EAAA,EAAQ,WAAU,4CAAA,EAA6C,CAAA;AAAA,QACtE,OAAO,MAAA,EAAQ,oBAAA,KAAyB,IAAA,GAAO,CAAA,QAAA,EAAW,IAAI,CAAA,MAAA,CAAA,GAAM,sBAAA,CAAA;AAAA,QACpE,IAAA,EACE,QAAQ,mBAAA,IACL;AAAA;AAAA,KAEP;AAAA,EAEJ;AAEA,EAAA,uBACEH,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,sBAAMA,GAAAA,CAACG,OAAAA,EAAA,EAAQ,WAAU,4CAAA,EAA6C,CAAA;AAAA,MACtE,OAAO,MAAA,EAAQ,YAAA,KAAiB,IAAA,GAAO,CAAA,EAAG,IAAI,CAAA,4BAAA,CAAA,GAA2B,0BAAA,CAAA;AAAA,MACzE,IAAA,EACE,QAAQ,WAAA,IACL,0FAAA;AAAA,MAEL,MAAA,EAAQ,WAAW,EAAE,KAAA,EAAO,QAAQ,aAAA,IAAiB,oBAAA,EAAsB,OAAA,EAAS,QAAA,EAAS,GAAI;AAAA;AAAA,GACnG;AAEJ;AAEA,SAAS,KAAA,CAAM;AAAA,EACb,IAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA;AACF,CAAA,EAKG;AACD,EAAA,uBACEJ,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wEAAA,EACb,QAAA,EAAA;AAAA,oBAAAC,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kEAAA,EAAoE,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,oBACxFA,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uCAAuC,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,oBAC1DA,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,0CAA0C,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,IAC3D,yBACCA,GAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,SAAA,EAAU,uGAAA;AAAA,QAET,QAAA,EAAA,MAAA,CAAO;AAAA;AAAA,KACV,GACE;AAAA,GAAA,EACN,CAAA;AAEJ","file":"chunk-GTK7MRYT.js","sourcesContent":["import * as React from 'react'\nimport { Loader2, Check } from 'lucide-react'\nimport type { BuilderLabels, BuilderPublishContract } from '../types'\n\n/** The same button in both hosts; only the transport behind `publish` differs.\n * No contract means the path is not wired up here, and it says so. */\nexport function PublishButton({\n publish,\n labels,\n}: {\n publish?: BuilderPublishContract\n labels?: BuilderLabels\n}) {\n const label = labels?.publish ?? 'Publicar'\n const state = publish?.state ?? 'idle'\n const busy = state === 'publishing'\n const disabled = !publish || busy\n\n return (\n <button\n type=\"button\"\n onClick={() => publish?.publish()}\n disabled={disabled}\n title={\n publish\n ? publish.error ?? label\n : labels?.publishUnavailable ?? 'Publicar ainda não está ligado neste ambiente'\n }\n className=\"flex h-9 items-center gap-1.5 rounded-full bg-primary px-4 text-sm font-medium text-primary-foreground shadow-sm transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {busy ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" /> : null}\n {state === 'published' && !busy ? <Check className=\"h-3.5 w-3.5\" /> : null}\n {label}\n </button>\n )\n}\n","/** A route the app announced, named the way a person would say it. */\nexport interface BuilderPage {\n route: string\n label: string\n}\n\nconst HOME_LABELS: Record<string, string> = { '/': 'Início' }\n\n/** \"#/produtos\" and \"/produtos\" are the same page said two ways — hash routing\n * is a routing style, not a different address space. */\nexport function normalizeRoute(route: string): string {\n const clean = route.split('?')[0].replace(/^#/, '')\n return clean.startsWith('/') ? clean : `/${clean}`\n}\n\nexport function isHomeRoute(route: string): boolean {\n return normalizeRoute(route) === '/'\n}\n\nconst KNOWN: Record<string, string> = {\n produtos: 'Produtos',\n products: 'Produtos',\n carrinho: 'Carrinho',\n cart: 'Carrinho',\n checkout: 'Checkout',\n contato: 'Contato',\n contact: 'Contato',\n sobre: 'Sobre',\n about: 'Sobre',\n blog: 'Blog',\n colecoes: 'Coleções',\n collections: 'Coleções',\n cardapio: 'Cardápio',\n conta: 'Conta',\n account: 'Conta',\n pedidos: 'Pedidos',\n catalog: 'Catálogo',\n catalogo: 'Catálogo',\n privacy: 'Privacidade',\n terms: 'Termos',\n refunds: 'Reembolsos',\n receitas: 'Receitas',\n product: 'Produtos',\n collection: 'Coleções',\n}\n\n/**\n * \"/produtos/:slug\" → \"Produtos ▸ :slug\". A path is what the app calls the page;\n * this is what the person calls it, which is the whole point of the picker.\n */\nexport function labelForRoute(route: string): string {\n const clean = normalizeRoute(route)\n if (HOME_LABELS[clean]) return HOME_LABELS[clean]\n\n const segments = clean.split('/').filter(Boolean)\n if (!segments.length) return HOME_LABELS['/']\n\n return segments\n .map((segment) => {\n const key = segment.toLowerCase()\n if (KNOWN[key]) return KNOWN[key]\n const words = segment.replace(/^:/, '').replace(/[-_]+/g, ' ')\n return words.charAt(0).toUpperCase() + words.slice(1)\n })\n .join(' › ')\n}\n\n/** A leaf, or a section with the pages under it. */\nexport interface BuilderPageGroup {\n key: string\n label: string\n route?: string\n children: BuilderPage[]\n}\n\nconst GROUP_FROM = 3\n\n/**\n * One level of grouping, and only where it earns its place: eleven product\n * pages listed flat bury the four pages someone actually navigates to. Below\n * {@link GROUP_FROM} siblings the folder costs a click and saves nothing.\n */\nexport function toPageGroups(routes: string[]): BuilderPageGroup[] {\n const bySegment = new Map<string, BuilderPage[]>()\n for (const route of routes) {\n const segment = normalizeRoute(route).split('/').filter(Boolean)[0] ?? ''\n const list = bySegment.get(segment) ?? []\n list.push({ route, label: labelForRoute(route) })\n bySegment.set(segment, list)\n }\n\n const groups: BuilderPageGroup[] = []\n for (const [segment, pages] of bySegment) {\n if (pages.length < GROUP_FROM || !segment) {\n groups.push(...pages.map((page) => ({ key: page.route, label: page.label, route: page.route, children: [] })))\n continue\n }\n groups.push({\n key: segment,\n label: labelForRoute(`/${segment}`),\n children: pages.map((page) => ({\n route: page.route,\n // Inside the folder the section name is the folder's, not each row's.\n label: page.label.split(' › ').slice(1).join(' › ') || page.label,\n })),\n })\n }\n // Home first, then alphabetical. A comparator that only says \"home wins\"\n // when home is one of the two arguments is not an order, and sort showed it.\n const rank = (g: BuilderPageGroup) => (g.route && isHomeRoute(g.route) ? 0 : 1)\n return groups.sort((a, b) => rank(a) - rank(b) || a.label.localeCompare(b.label))\n}\n\nexport function toPages(routes: string[]): BuilderPage[] {\n return routes.map((route) => ({ route, label: labelForRoute(route) }))\n}\n","/** The whole of clsx we need. Keeping it local is what keeps this package free\n * of a design-system dependency, so both hosts can mount the surface. */\nexport function cn(...parts: Array<string | false | null | undefined>): string {\n return parts.filter(Boolean).join(' ')\n}\n","import * as React from 'react'\nimport { ChevronsUpDown, Search, House, FileText, Folder, ChevronRight, ChevronLeft, Check } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { isHomeRoute, labelForRoute, normalizeRoute, toPageGroups, toPages } from '../lib/pages'\n\n/**\n * The address bar as the app's own table of contents: the page you are on, by\n * its name, and the pages you can go to. A raw URL is the app's word for the\n * page; this is the person's.\n *\n * With no routes announced it stays a plain label — a picker that opens on\n * nothing is worse than no picker.\n */\nexport function PagePicker({\n routes,\n currentPath,\n onNavigate,\n fallback,\n leading,\n searchLabel = 'Buscar página',\n emptyLabel = 'Nenhuma página com esse nome',\n}: {\n routes: string[]\n currentPath: string\n onNavigate: (route: string) => void\n /** Shown when the app has not announced any route. */\n fallback: string\n leading?: React.ReactNode\n searchLabel?: string\n emptyLabel?: string\n}) {\n const [open, setOpen] = React.useState(false)\n const [query, setQuery] = React.useState('')\n const boxRef = React.useRef<HTMLDivElement | null>(null)\n const inputRef = React.useRef<HTMLInputElement | null>(null)\n\n const [section, setSection] = React.useState<string | null>(null)\n\n const pages = React.useMemo(() => toPages(routes), [routes])\n const groups = React.useMemo(() => toPageGroups(routes), [routes])\n const openSection = React.useMemo(() => groups.find((g) => g.key === section) ?? null, [groups, section])\n\n // Search reaches every page, folders and all — a name is easier to type than\n // to remember which section it lives in.\n const matches = React.useMemo(() => {\n const q = query.trim().toLowerCase()\n if (q) return pages.filter((p) => p.label.toLowerCase().includes(q) || p.route.toLowerCase().includes(q))\n if (openSection) return openSection.children\n return null\n }, [pages, query, openSection])\n\n React.useEffect(() => {\n if (!open) return\n const onDown = (event: MouseEvent) => {\n if (!boxRef.current?.contains(event.target as Node)) setOpen(false)\n }\n const onKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') setOpen(false)\n }\n document.addEventListener('mousedown', onDown)\n document.addEventListener('keydown', onKey)\n inputRef.current?.focus()\n return () => {\n document.removeEventListener('mousedown', onDown)\n document.removeEventListener('keydown', onKey)\n }\n }, [open])\n\n const label = pages.length ? labelForRoute(currentPath) : fallback\n\n if (!pages.length) {\n return (\n <div className=\"flex h-9 min-w-0 flex-1 items-center gap-2 rounded-full bg-muted/60 px-2\">\n {leading}\n <span className=\"min-w-0 flex-1 truncate text-xs text-muted-foreground\">{label}</span>\n </div>\n )\n }\n\n return (\n <div ref={boxRef} className=\"relative flex h-9 min-w-0 flex-1 items-center gap-2 rounded-full bg-muted/60 px-2\">\n {leading}\n <button\n type=\"button\"\n onClick={() => {\n setQuery('')\n setSection(null)\n setOpen((v) => !v)\n }}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n className=\"flex min-w-0 flex-1 items-center gap-1.5 rounded-full py-1 text-left text-xs font-medium text-foreground\"\n >\n <span className=\"min-w-0 truncate\">{label}</span>\n <ChevronsUpDown className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n </button>\n\n {open ? (\n <div\n role=\"listbox\"\n className=\"absolute left-0 top-[calc(100%+6px)] z-50 w-[min(22rem,100%)] overflow-hidden rounded-xl border border-border bg-card shadow-lg\"\n >\n {openSection && !query ? (\n <button\n type=\"button\"\n onClick={() => setSection(null)}\n className=\"flex w-full items-center gap-2 border-b border-border px-3 py-2 text-sm font-medium text-foreground hover:bg-muted/60\"\n >\n <ChevronLeft className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n {openSection.label}\n </button>\n ) : null}\n\n <div className=\"flex items-center gap-2 border-b border-border px-3 py-2\">\n <Search className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <input\n ref={inputRef}\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n placeholder={searchLabel}\n aria-label={searchLabel}\n className=\"w-full bg-transparent text-sm text-foreground outline-none placeholder:text-muted-foreground\"\n />\n </div>\n\n <div className=\"max-h-72 overflow-y-auto p-1\">\n {!matches ? (\n groups.map((group) => {\n if (!group.route) {\n return (\n <button\n key={group.key}\n type=\"button\"\n onClick={() => setSection(group.key)}\n className=\"flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-sm text-foreground transition-colors hover:bg-muted/60\"\n >\n <Folder className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate\">{group.label}</span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">{group.children.length}</span>\n <ChevronRight className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n </button>\n )\n }\n const active = normalizeRoute(group.route) === normalizeRoute(currentPath)\n const Icon = isHomeRoute(group.route) ? House : FileText\n return (\n <button\n key={group.key}\n type=\"button\"\n role=\"option\"\n aria-selected={active}\n onClick={() => {\n onNavigate(group.route!)\n setOpen(false)\n }}\n className={cn(\n 'flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-sm transition-colors',\n active ? 'bg-muted font-medium text-foreground' : 'text-foreground hover:bg-muted/60',\n )}\n >\n <Icon className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate\">{group.label}</span>\n {active ? <Check className=\"h-4 w-4 shrink-0 text-muted-foreground\" /> : null}\n </button>\n )\n })\n ) : matches.length ? (\n matches.map((page) => {\n const active = normalizeRoute(page.route) === normalizeRoute(currentPath)\n const Icon = isHomeRoute(page.route) ? House : FileText\n return (\n <button\n key={page.route}\n type=\"button\"\n role=\"option\"\n aria-selected={active}\n onClick={() => {\n onNavigate(page.route)\n setOpen(false)\n }}\n className={cn(\n 'flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-sm transition-colors',\n active ? 'bg-muted font-medium text-foreground' : 'text-foreground hover:bg-muted/60',\n )}\n >\n <Icon className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate\">{page.label}</span>\n {active ? <Check className=\"h-4 w-4 shrink-0 text-muted-foreground\" /> : null}\n </button>\n )\n })\n ) : (\n <p className=\"px-2.5 py-6 text-center text-xs text-muted-foreground\">{emptyLabel}</p>\n )}\n </div>\n </div>\n ) : null}\n </div>\n )\n}\n","import * as React from 'react'\nimport { Monitor, Smartphone, RotateCw, ExternalLink, Code2, Eye } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { PublishButton } from './PublishButton'\nimport { PagePicker } from './PagePicker'\nimport type {\n BuilderLabels,\n BuilderMode,\n BuilderPublishContract,\n BuilderTarget,\n BuilderViewport,\n} from '../types'\n\nconst iconButton =\n 'flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-foreground/10 hover:text-foreground disabled:pointer-events-none disabled:opacity-40'\n\n/** Domain + path, the way a browser bar reads — the scheme is noise here. */\nfunction addressOf(url: string | null, path: string): string {\n if (!url) return path\n try {\n const parsed = new URL(url)\n const base = parsed.host + parsed.pathname.replace(/\\/+$/, '')\n return path === '/' ? base + '/' : base + path\n } catch {\n return path\n }\n}\n\n/**\n * macOS window buttons, and they do what those buttons do. A light with no\n * handler is not rendered dead — it is not rendered.\n */\nfunction TrafficLights({\n onClose,\n onToggleChat,\n onToggleWide,\n labels,\n}: {\n onClose?: () => void\n onToggleChat?: () => void\n onToggleWide?: () => void\n labels?: BuilderLabels\n}) {\n const lights = [\n { id: 'close', color: 'bg-[#ff5f57]', label: labels?.close ?? 'Sair', onClick: onClose },\n { id: 'minimize', color: 'bg-[#febc2e]', label: labels?.toggleChat ?? 'Recolher a conversa', onClick: onToggleChat },\n { id: 'zoom', color: 'bg-[#28c840]', label: labels?.toggleWide ?? 'Dar a tela toda ao app', onClick: onToggleWide },\n ].filter((light) => !!light.onClick)\n\n if (!lights.length) return null\n\n return (\n <div className=\"flex shrink-0 items-center gap-1.5 pl-1\">\n {lights.map((light) => (\n <button\n key={light.id}\n type=\"button\"\n title={light.label}\n aria-label={light.label}\n onClick={light.onClick}\n className=\"flex h-4 w-4 items-center justify-center rounded-full transition-transform hover:scale-125 active:scale-95\"\n >\n <span className={cn('h-3 w-3 rounded-full', light.color)} />\n </button>\n ))}\n </div>\n )\n}\n\n/**\n * One row, the shape of a browser: window buttons, then the address bar the\n * width of the page, then what you do to it. The page owns this bar — the\n * shell's own is gone on an immersive route — so there is exactly one.\n */\nexport function BuilderChrome({\n target,\n currentPath,\n routes,\n onNavigate,\n viewport,\n onViewportChange,\n onReload,\n mode,\n onModeChange,\n publish,\n onClose,\n onToggleChat,\n onToggleWide,\n chromeEnd,\n labels,\n}: {\n target: BuilderTarget\n currentPath: string\n routes: string[]\n onNavigate: (route: string) => void\n viewport: BuilderViewport\n onViewportChange: (viewport: BuilderViewport) => void\n onReload: () => void\n mode: BuilderMode\n onModeChange?: (mode: BuilderMode) => void\n publish?: BuilderPublishContract\n onClose?: () => void\n onToggleChat?: () => void\n onToggleWide?: () => void\n chromeEnd?: React.ReactNode\n labels?: BuilderLabels\n}) {\n const address = addressOf(target.url, currentPath)\n const openTarget = target.liveUrl ?? target.url\n // The icon states WHERE YOU ARE, the way a browser's does; the tooltip states\n // what a click does. Showing the next state instead made the control read as\n // a claim about the canvas that was never true.\n const Device = viewport === 'desktop' ? Monitor : Smartphone\n const deviceLabel = viewport === 'desktop' ? 'Ver no celular' : 'Ver no computador'\n\n return (\n // Same 56px as the companion column's header (RightRail), so the two read\n // as one window bar rather than two rows that nearly line up.\n <div className=\"flex h-14 shrink-0 items-center gap-2 border-b border-border px-3\">\n {/* No window buttons on a phone: the frame is a device, not a window, and\n the three dots would be spending the narrowest row's width saying so. */}\n {viewport === 'desktop' ? (\n <TrafficLights\n onClose={onClose}\n onToggleChat={onToggleChat}\n onToggleWide={onToggleWide}\n labels={labels}\n />\n ) : null}\n\n {onModeChange ? (\n <div className=\"ml-1 flex shrink-0 items-center gap-0.5 rounded-full bg-muted/60 p-0.5\">\n {([\n { id: 'preview' as const, icon: Eye, title: labels?.preview ?? 'Visual' },\n { id: 'code' as const, icon: Code2, title: labels?.code ?? 'Código' },\n ]).map(({ id, icon: Icon, title }) => (\n <button\n key={id}\n type=\"button\"\n title={title}\n aria-label={title}\n aria-pressed={mode === id}\n onClick={() => onModeChange(id)}\n className={cn(\n 'flex h-7 items-center gap-1.5 rounded-full px-2.5 text-xs font-medium transition-colors',\n mode === id ? 'bg-card text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {title}\n </button>\n ))}\n </div>\n ) : null}\n\n {/* The address bar IS the row: the device toggle lives at its left, the\n way a browser puts the shield or the lock there. */}\n <PagePicker\n routes={routes}\n currentPath={currentPath}\n onNavigate={onNavigate}\n fallback={address}\n searchLabel={labels?.searchPage}\n emptyLabel={labels?.noPage}\n leading={\n <button\n type=\"button\"\n title={deviceLabel}\n aria-label={deviceLabel}\n onClick={() => onViewportChange(viewport === 'desktop' ? 'mobile' : 'desktop')}\n className=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-foreground/10 hover:text-foreground\"\n >\n <Device className=\"h-4 w-4\" />\n </button>\n }\n />\n\n <button\n type=\"button\"\n title={labels?.viewLive ?? 'Abrir em uma aba'}\n aria-label={labels?.viewLive ?? 'Abrir em uma aba'}\n disabled={!openTarget}\n onClick={() => openTarget && window.open(openTarget, '_blank', 'noopener,noreferrer')}\n className={iconButton}\n >\n <ExternalLink className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n title={labels?.reload ?? 'Recarregar'}\n aria-label={labels?.reload ?? 'Recarregar'}\n onClick={onReload}\n className={iconButton}\n >\n <RotateCw className=\"h-4 w-4\" />\n </button>\n\n {chromeEnd}\n <PublishButton publish={publish} labels={labels} />\n </div>\n )\n}\n","import * as React from 'react'\nimport { Loader2, AlertTriangle } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport type { BuilderFrameController } from '../hooks/useBuilderFrame'\nimport type { BuilderLabels, BuilderTarget } from '../types'\n\n// The window around it is what narrows on mobile (see AppBuilder), so the frame\n// itself always fills whatever it was given.\nconst FRAME = 'h-full w-full'\n\nexport function BuilderCanvas({\n target,\n frame,\n labels,\n}: {\n target: BuilderTarget\n frame: BuilderFrameController\n labels?: BuilderLabels\n}) {\n // Dragging a divider anywhere in the host moves the pointer over the canvas,\n // and a cross-origin frame swallows every move event once it does.\n const [dragging, setDragging] = React.useState(false)\n React.useEffect(() => {\n const down = (event: PointerEvent) => {\n const el = event.target as HTMLElement | null\n if (el?.closest('[role=\"separator\"]')) setDragging(true)\n }\n const up = () => setDragging(false)\n window.addEventListener('pointerdown', down, true)\n window.addEventListener('pointerup', up, true)\n return () => {\n window.removeEventListener('pointerdown', down, true)\n window.removeEventListener('pointerup', up, true)\n }\n }, [])\n\n if (!frame.src) return null\n\n return (\n <div className=\"relative flex min-h-0 flex-1 justify-center overflow-hidden\">\n <iframe\n key={`${frame.src}#${frame.nonce}`}\n ref={frame.frameRef}\n src={frame.src}\n title={target.name}\n onLoad={frame.onLoad}\n className={cn('border-0 bg-white', FRAME, dragging && 'pointer-events-none')}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-modals\"\n />\n\n {frame.loading && !frame.failed && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <Loader2 className=\"h-5 w-5 animate-spin text-muted-foreground\" />\n </div>\n )}\n\n {frame.failed && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 bg-background/95 p-6 text-center\">\n <AlertTriangle className=\"h-6 w-6 text-muted-foreground\" />\n <p className=\"text-sm font-medium text-foreground\">\n {labels?.loadFailed ?? 'Não foi possível carregar o app aqui dentro.'}\n </p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">\n {labels?.loadFailedHint\n ?? 'O servidor pode estar bloqueando a exibição em outra página. Abra em uma nova aba enquanto isso.'}\n </p>\n <button\n type=\"button\"\n onClick={() => frame.src && window.open(frame.src, '_blank', 'noopener,noreferrer')}\n className=\"mt-1 rounded-full border border-border px-3 py-1.5 text-xs font-medium text-foreground hover:bg-muted\"\n >\n {labels?.openInTab ?? 'Abrir em nova aba'}\n </button>\n </div>\n )}\n </div>\n )\n}\n","import * as React from 'react'\nimport { Globe } from 'lucide-react'\nimport type { BuilderLabels } from '../types'\n\nexport function BuilderEmpty({ labels, onAction }: { labels?: BuilderLabels; onAction?: () => void }) {\n return (\n <div className=\"flex h-full flex-col items-center justify-center gap-3 p-8 text-center\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <Globe className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n <p className=\"text-sm font-medium text-foreground\">\n {labels?.emptyTitle ?? 'Nenhum app vinculado ainda'}\n </p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">\n {labels?.emptyBody ?? 'Vincule o projeto para editá-lo aqui, conversando com o assistente.'}\n </p>\n {onAction ? (\n <button\n type=\"button\"\n onClick={onAction}\n className=\"mt-1 rounded-full border border-border px-3 py-1.5 text-xs font-medium text-foreground hover:bg-muted\"\n >\n {labels?.emptyAction ?? 'Vincular em Configurações'}\n </button>\n ) : null}\n </div>\n )\n}\n","// Host side of the picker protocol both the storefront and the platform's\n// injected overlay already speak. v1 listens for navigation and drives the\n// frame; activate/picked are declared so the overlay lands without\n// renegotiating the channel.\nexport const BUILDER_MESSAGES = {\n activate: 'ACTIVATE_ELEMENT_PICKER',\n deactivate: 'DEACTIVATE_ELEMENT_PICKER',\n ready: 'ELEMENT_PICKER_READY',\n picked: 'ELEMENT_PICKED',\n cancelled: 'ELEMENT_PICKER_CANCELLED',\n navigation: 'NAVIGATION_CHANGE',\n} as const\n\nexport interface BuilderPickedBlock {\n path: string\n type: string\n rect?: { top: number; left: number; width: number; height: number }\n}\n\n/** The channel the platform's injected script already speaks (route-discovery.ts). */\nexport const ROUTES_SOURCE = 'fayz-routes'\nexport const ROUTES_PARENT_SOURCE = 'fayz-routes-parent'\n\nexport interface BuilderBridgeHandlers {\n onRoutes?: (routes: string[]) => void\n onNavigate?: (path: string) => void\n onReady?: () => void\n onPicked?: (block: BuilderPickedBlock) => void\n onCancelled?: () => void\n}\n\n/**\n * Listen to one frame. `origin` is derived from the canvas URL by us — a frame\n * that announces its own origin is a frame that can lie about it.\n */\nexport function connectBuilderBridge(\n frame: HTMLIFrameElement,\n origin: string,\n handlers: BuilderBridgeHandlers,\n): () => void {\n const win = typeof window === 'undefined' ? undefined : window\n if (!win) return () => {}\n\n const onMessage = (event: MessageEvent) => {\n if (event.origin !== origin) return\n if (event.source !== frame.contentWindow) return\n const data = event.data as\n | { source?: string; type?: string; path?: string; route?: string; routes?: string[]; data?: BuilderPickedBlock }\n | null\n\n if (data?.source === ROUTES_SOURCE) {\n if (data.type === 'ROUTES_DISCOVERED' && Array.isArray(data.routes)) handlers.onRoutes?.(data.routes)\n else if (data.type === 'ROUTE_CHANGED' && typeof data.route === 'string') handlers.onNavigate?.(data.route)\n return\n }\n\n switch (data?.type) {\n case BUILDER_MESSAGES.navigation:\n if (typeof data.path === 'string') handlers.onNavigate?.(data.path)\n break\n case BUILDER_MESSAGES.ready:\n handlers.onReady?.()\n break\n case BUILDER_MESSAGES.picked:\n if (data.data) handlers.onPicked?.(data.data)\n break\n case BUILDER_MESSAGES.cancelled:\n handlers.onCancelled?.()\n break\n }\n }\n\n win.addEventListener('message', onMessage)\n return () => win.removeEventListener('message', onMessage)\n}\n\n/** Ask the app to go somewhere. Same message its injected script listens for. */\nexport function navigateBuilder(\n frame: HTMLIFrameElement | null,\n origin: string | null,\n route: string,\n): void {\n postToBuilder(frame, origin, { source: ROUTES_PARENT_SOURCE, type: 'NAVIGATE', route })\n}\n\n/** Outbound always names the expected origin — never '*'. */\nexport function postToBuilder(\n frame: HTMLIFrameElement | null,\n origin: string | null,\n message: Record<string, unknown>,\n): void {\n if (!frame?.contentWindow || !origin) return\n frame.contentWindow.postMessage(message, origin)\n}\n","// Ported from the Fayz editor (apps/web/src/utils/previewUrlBuilder.ts): the one\n// part of its preview with real logic and no dependency. When the editor mounts\n// this surface it deletes its copy.\n\nexport function getBaseUrl(url: string): string {\n return url.split('?')[0].split('#')[0].replace(/\\/$/, '')\n}\n\nexport function getQueryString(url: string): string {\n const parts = url.split('?')\n return parts.length > 1 ? parts[1].split('#')[0] : ''\n}\n\n/** Point a preview URL at a route, keeping the query the container needs. */\nexport function buildIframeUrl(baseUrl: string, route: string): string {\n const cleanBase = getBaseUrl(baseUrl)\n const queryString = getQueryString(baseUrl)\n\n // Hash routing: the route IS the fragment, so it goes after the query.\n if (route.startsWith('#/')) {\n return `${cleanBase}${queryString ? '?' + queryString : ''}${route}`\n }\n\n // A route can carry its own anchor (\"/#pricing\"), which belongs last.\n const hashIndex = route.indexOf('#')\n const routePath = hashIndex === -1 ? route : route.substring(0, hashIndex)\n const hashFragment = hashIndex === -1 ? '' : route.substring(hashIndex)\n\n let result = `${cleanBase}${routePath === '/' ? '' : routePath}`\n if (queryString) result += `?${queryString}`\n if (hashFragment) result += hashFragment\n return result\n}\n\nexport function addCacheBuster(url: string, now: number = Date.now()): string {\n return `${url}${url.includes('?') ? '&' : '?'}_cb=${now}`\n}\n\nexport function extractRouteFromUrl(fullUrl: string, baseUrl: string): string {\n try {\n const full = new URL(fullUrl)\n const base = new URL(baseUrl)\n if (full.host !== base.host) return '/'\n\n let pathname = full.pathname\n if (base.pathname !== '/' && pathname.startsWith(base.pathname)) {\n pathname = pathname.slice(base.pathname.length)\n }\n if (!pathname.startsWith('/')) pathname = '/' + pathname\n return pathname || '/'\n } catch {\n return '/'\n }\n}\n\nexport function isValidPreviewUrl(url: string | null | undefined): boolean {\n if (!url) return false\n try {\n const parsed = new URL(url)\n return parsed.protocol === 'http:' || parsed.protocol === 'https:'\n } catch {\n return false\n }\n}\n\nexport function getUrlOrigin(url: string): string | null {\n try {\n return new URL(url).origin\n } catch {\n return null\n }\n}\n","import * as React from 'react'\nimport { connectBuilderBridge, navigateBuilder } from '../lib/bridge'\nimport { buildIframeUrl, getUrlOrigin } from '../lib/url'\nimport type { BuilderElementContext } from '../types'\n\nexport interface BuilderFrameController {\n frameRef: React.MutableRefObject<HTMLIFrameElement | null>\n /** Remount key — the only reliable way to reload a cross-origin document. */\n nonce: number\n src: string | null\n origin: string | null\n loading: boolean\n failed: boolean\n currentPath: string\n /** Routes the app announced through its own discovery script. */\n routes: string[]\n onLoad: () => void\n reload: () => void\n navigate: (path: string) => void\n}\n\n/** A cross-origin frame that never loads never errors either, so time is the signal. */\nconst LOAD_TIMEOUT_MS = 8000\n\nexport function useBuilderFrame(\n url: string | null,\n handlers?: { onNavigate?: (path: string) => void; onPick?: (context: BuilderElementContext) => void },\n): BuilderFrameController {\n const frameRef = React.useRef<HTMLIFrameElement | null>(null)\n const [nonce, setNonce] = React.useState(0)\n const [loading, setLoading] = React.useState(true)\n const [failed, setFailed] = React.useState(false)\n const [currentPath, setCurrentPath] = React.useState('/')\n const [routes, setRoutes] = React.useState<string[]>([])\n\n const origin = React.useMemo(() => (url ? getUrlOrigin(url) : null), [url])\n // The initial document only. Intra-app navigation happens inside the frame,\n // so following currentPath here would reload the page on every click.\n const src = React.useMemo(() => (url ? buildIframeUrl(url, '/') : null), [url])\n\n const cb = React.useRef(handlers)\n cb.current = handlers\n\n React.useEffect(() => {\n setLoading(true)\n setFailed(false)\n }, [src, nonce])\n\n React.useEffect(() => {\n if (!loading) return\n const timer = setTimeout(() => setFailed(true), LOAD_TIMEOUT_MS)\n return () => clearTimeout(timer)\n }, [loading, src, nonce])\n\n React.useEffect(() => {\n const frame = frameRef.current\n if (!frame || !origin) return\n return connectBuilderBridge(frame, origin, {\n onRoutes: setRoutes,\n onNavigate: (path) => {\n setCurrentPath(path)\n cb.current?.onNavigate?.(path)\n },\n onPicked: (block) => cb.current?.onPick?.({ selector: block.path, tagName: block.type }),\n })\n }, [origin, nonce])\n\n const reload = React.useCallback(() => setNonce((n) => n + 1), [])\n\n // The app moves itself; we only ask. Rebuilding the src would reload the\n // whole thing and lose whatever state the page was in.\n const navigate = React.useCallback(\n (path: string) => {\n setCurrentPath(path)\n navigateBuilder(frameRef.current, origin, path)\n },\n [origin],\n )\n\n const onLoad = React.useCallback(() => {\n setLoading(false)\n setFailed(false)\n }, [])\n\n return { frameRef, nonce, src, origin, loading, failed, currentPath, routes, onLoad, reload, navigate }\n}\n","import * as React from 'react'\nimport { cn } from '../lib/cn'\nimport { BuilderChrome } from './BuilderChrome'\nimport { BuilderCanvas } from './BuilderCanvas'\nimport { BuilderEmpty } from './BuilderEmpty'\nimport { useBuilderFrame } from '../hooks/useBuilderFrame'\nimport type { AppBuilderProps, BuilderElementContext, BuilderViewport } from '../types'\n\n/**\n * The app-builder surface: a window bar, the app running inside it, and the\n * seams for the three things every builder also needs — seeing the code,\n * publishing, and talking to whoever is doing the work.\n *\n * It draws its OWN bar instead of portalling into a host's header. That is what\n * lets the same component sit in the Fayz editor and in an admin shell.\n */\nexport function AppBuilder({\n target,\n mode = 'preview',\n onModeChange,\n code,\n chat,\n publish,\n onClose,\n onToggleChat,\n onToggleWide,\n onNavigate,\n onPick,\n viewport: viewportProp,\n onViewportChange,\n empty,\n labels,\n slots,\n className,\n frame: frameProp,\n}: AppBuilderProps) {\n // `chatContract` is declared on the props and deliberately not read yet: the\n // only sender is the element picker, which is the next milestone. Taking it\n // out of the contract now would make that milestone an API change.\n const [internalViewport, setInternalViewport] = React.useState<BuilderViewport>('desktop')\n const viewport = viewportProp ?? internalViewport\n const setViewport = onViewportChange ?? setInternalViewport\n\n // A pick is only worth reporting when something can act on it: the host's\n // callback, or the conversation the host mounted.\n // A pick goes wherever the host says. There is no picker UI yet — the wire is\n // live so the overlay lands without renegotiating who a pick belongs to.\n const handlePick = React.useCallback(\n (context: BuilderElementContext) => onPick?.(context),\n [onPick],\n )\n\n // The host may own the controller (it needs the handle to drive the canvas\n // from an agent tool or a button); otherwise the surface owns one. Passing a\n // null url to the unused one keeps it from running timers for nothing.\n const ownFrame = useBuilderFrame(frameProp ? null : target.url, { onNavigate, onPick: handlePick })\n const frame = frameProp ?? ownFrame\n\n const body = !target.url ? (\n (empty ?? <BuilderEmpty labels={labels} />)\n ) : mode === 'code' && code ? (\n <div className=\"min-h-0 flex-1 overflow-hidden\">{code}</div>\n ) : (\n <BuilderCanvas target={target} frame={frame} labels={labels} />\n )\n\n // Mobile narrows the WHOLE window, chrome and all — a desktop-width toolbar\n // over a phone-width page is a claim about a device nobody is holding.\n const mobile = viewport === 'mobile' && !!target.url\n\n return (\n <div className={cn('flex h-full min-h-0 overflow-hidden', className)}>\n <div className={cn('flex min-w-0 flex-1 flex-col overflow-hidden', mobile && 'items-center bg-muted/30 py-3')}>\n <div\n className={cn(\n 'flex min-h-0 w-full flex-1 flex-col overflow-hidden',\n mobile && 'max-w-[420px] rounded-2xl border border-border bg-card shadow-xl',\n )}\n >\n <BuilderChrome\n target={target}\n currentPath={frame.currentPath}\n routes={frame.routes}\n onNavigate={frame.navigate}\n viewport={viewport}\n onViewportChange={setViewport}\n onReload={frame.reload}\n mode={mode}\n onModeChange={code ? onModeChange : undefined}\n publish={publish}\n onClose={onClose}\n onToggleChat={onToggleChat}\n onToggleWide={onToggleWide}\n chromeEnd={slots?.chromeEnd}\n labels={labels}\n />\n {body}\n </div>\n {slots?.belowCanvas}\n </div>\n\n {chat ? (\n <div className=\"hidden w-[min(28rem,32%)] shrink-0 border-l border-border md:flex md:flex-col md:overflow-hidden\">\n {chat}\n </div>\n ) : null}\n </div>\n )\n}\n","import * as React from 'react'\nimport { Loader2, AlertCircle } from 'lucide-react'\nimport type { BuilderLabels } from '../types'\n\n/**\n * A site IS linked, and there is nothing to load yet.\n *\n * Distinct from {@link BuilderEmpty} because the two states are opposite\n * answers to the same question. Both leave `target.url` null, so the surface\n * cannot tell them apart on its own — the host does, by whether it resolved a\n * project at all. Showing \"nenhum site vinculado\" to someone who linked one\n * thirty seconds ago reads as the link having failed, and the repair they then\n * attempt is to link it again.\n *\n * Three reasons there is nothing to show, and they are NOT interchangeable:\n *\n * - `starting` — the container is coming up. A cold start syncs the project's\n * files and runs an npm install (~24s measured), so this is the common case\n * the first time a merchant opens the tab, and it resolves on its own.\n * - `failed` — it will not resolve on its own. This is the only state with a\n * button, because it is the only one where waiting is the wrong thing to do.\n * - neither — no container is being attempted (the app holds no platform\n * credentials), so the site is only reachable once it has been published.\n */\nexport function BuilderPending({\n labels,\n name,\n phase,\n error,\n onRetry,\n onAction,\n}: {\n labels?: BuilderLabels\n /** The linked site's name, so the screen names what it is waiting for. */\n name?: string\n phase?: 'starting' | 'failed'\n error?: string\n /** Only meaningful with phase 'failed'. */\n onRetry?: () => void\n /** Opens the project where the build is actually visible. Omitted = no button. */\n onAction?: () => void\n}) {\n if (phase === 'failed') {\n return (\n <Shell\n icon={<AlertCircle className=\"h-6 w-6 text-destructive\" />}\n title={labels?.previewFailedTitle ?? 'O preview não subiu'}\n // The platform's message is shown rather than replaced: \"não foi\n // possível\" tells nobody whether to retry, wait, or report it.\n body={error ?? labels?.previewFailedBody ?? 'Tente de novo em alguns instantes.'}\n action={onRetry ? { label: labels?.previewRetry ?? 'Tentar de novo', onClick: onRetry } : undefined}\n />\n )\n }\n\n if (phase === 'starting') {\n return (\n <Shell\n icon={<Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />}\n title={labels?.previewStartingTitle ?? (name ? `Abrindo ${name}…` : 'Abrindo o site…')}\n body={\n labels?.previewStartingBody\n ?? 'O ambiente do site está subindo. Na primeira vez leva alguns segundos.'\n }\n />\n )\n }\n\n return (\n <Shell\n icon={<Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />}\n title={labels?.pendingTitle ?? (name ? `${name} está sendo construído` : 'Site em construção')}\n body={\n labels?.pendingBody\n ?? 'Assim que a primeira publicação terminar, o site aparece aqui para você editar.'\n }\n action={onAction ? { label: labels?.pendingAction ?? 'Acompanhar no fayz', onClick: onAction } : undefined}\n />\n )\n}\n\nfunction Shell({\n icon,\n title,\n body,\n action,\n}: {\n icon: React.ReactNode\n title: string\n body: string\n action?: { label: string; onClick: () => void }\n}) {\n return (\n <div className=\"flex h-full flex-col items-center justify-center gap-3 p-8 text-center\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-muted\">{icon}</div>\n <p className=\"text-sm font-medium text-foreground\">{title}</p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">{body}</p>\n {action ? (\n <button\n type=\"button\"\n onClick={action.onClick}\n className=\"mt-1 rounded-full border border-border px-3 py-1.5 text-xs font-medium text-foreground hover:bg-muted\"\n >\n {action.label}\n </button>\n ) : null}\n </div>\n )\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { BuilderLabels } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* A site IS linked, and there is nothing to load yet.
|
|
5
|
+
*
|
|
6
|
+
* Distinct from {@link BuilderEmpty} because the two states are opposite
|
|
7
|
+
* answers to the same question. Both leave `target.url` null, so the surface
|
|
8
|
+
* cannot tell them apart on its own — the host does, by whether it resolved a
|
|
9
|
+
* project at all. Showing "nenhum site vinculado" to someone who linked one
|
|
10
|
+
* thirty seconds ago reads as the link having failed, and the repair they then
|
|
11
|
+
* attempt is to link it again.
|
|
12
|
+
*
|
|
13
|
+
* Three reasons there is nothing to show, and they are NOT interchangeable:
|
|
14
|
+
*
|
|
15
|
+
* - `starting` — the container is coming up. A cold start syncs the project's
|
|
16
|
+
* files and runs an npm install (~24s measured), so this is the common case
|
|
17
|
+
* the first time a merchant opens the tab, and it resolves on its own.
|
|
18
|
+
* - `failed` — it will not resolve on its own. This is the only state with a
|
|
19
|
+
* button, because it is the only one where waiting is the wrong thing to do.
|
|
20
|
+
* - neither — no container is being attempted (the app holds no platform
|
|
21
|
+
* credentials), so the site is only reachable once it has been published.
|
|
22
|
+
*/
|
|
23
|
+
export declare function BuilderPending({ labels, name, phase, error, onRetry, onAction, }: {
|
|
24
|
+
labels?: BuilderLabels;
|
|
25
|
+
/** The linked site's name, so the screen names what it is waiting for. */
|
|
26
|
+
name?: string;
|
|
27
|
+
phase?: 'starting' | 'failed';
|
|
28
|
+
error?: string;
|
|
29
|
+
/** Only meaningful with phase 'failed'. */
|
|
30
|
+
onRetry?: () => void;
|
|
31
|
+
/** Opens the project where the build is actually visible. Omitted = no button. */
|
|
32
|
+
onAction?: () => void;
|
|
33
|
+
}): React.JSX.Element;
|
|
34
|
+
//# sourceMappingURL=BuilderPending.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BuilderPending.d.ts","sourceRoot":"","sources":["../../src/components/BuilderPending.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAE7C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,IAAI,EACJ,KAAK,EACL,KAAK,EACL,OAAO,EACP,QAAQ,GACT,EAAE;IACD,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB,qBAsCA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { AppBuilder } from './components/AppBuilder';
|
|
|
2
2
|
export { BuilderChrome } from './components/BuilderChrome';
|
|
3
3
|
export { BuilderCanvas } from './components/BuilderCanvas';
|
|
4
4
|
export { BuilderEmpty } from './components/BuilderEmpty';
|
|
5
|
+
export { BuilderPending } from './components/BuilderPending';
|
|
5
6
|
export { PublishButton } from './components/PublishButton';
|
|
6
7
|
export { useBuilderFrame } from './hooks/useBuilderFrame';
|
|
7
8
|
export type { BuilderFrameController } from './hooks/useBuilderFrame';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACrG,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC/F,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAChE,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAC7E,OAAO,EACL,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,YAAY,EACZ,iBAAiB,GAClB,MAAM,WAAW,CAAA;AAClB,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,WAAW,EACX,sBAAsB,EACtB,aAAa,EACb,eAAe,GAChB,MAAM,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACrG,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC/F,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAChE,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAC7E,OAAO,EACL,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,YAAY,EACZ,iBAAiB,GAClB,MAAM,WAAW,CAAA;AAClB,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,WAAW,EACX,sBAAsB,EACtB,aAAa,EACb,eAAe,GAChB,MAAM,SAAS,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { AppBuilder, BUILDER_MESSAGES, BuilderCanvas, BuilderChrome, BuilderEmpty, PagePicker, PublishButton, addCacheBuster, buildIframeUrl, connectBuilderBridge, extractRouteFromUrl, getBaseUrl, getQueryString, getUrlOrigin, isHomeRoute, isValidPreviewUrl, labelForRoute, navigateBuilder, normalizeRoute, postToBuilder, toPageGroups, toPages, useBuilderFrame } from './chunk-
|
|
1
|
+
export { AppBuilder, BUILDER_MESSAGES, BuilderCanvas, BuilderChrome, BuilderEmpty, BuilderPending, PagePicker, PublishButton, addCacheBuster, buildIframeUrl, connectBuilderBridge, extractRouteFromUrl, getBaseUrl, getQueryString, getUrlOrigin, isHomeRoute, isValidPreviewUrl, labelForRoute, navigateBuilder, normalizeRoute, postToBuilder, toPageGroups, toPages, useBuilderFrame } from './chunk-GTK7MRYT.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/plugin.js
CHANGED
|
@@ -1,11 +1,96 @@
|
|
|
1
|
-
import { useBuilderFrame, AppBuilder, BuilderEmpty } from './chunk-
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
1
|
+
import { useBuilderFrame, AppBuilder, BuilderPending, BuilderEmpty } from './chunk-GTK7MRYT.js';
|
|
2
|
+
import * as React4 from 'react';
|
|
3
|
+
import React4__default from 'react';
|
|
4
4
|
import { registerPluginFactory } from '@fayz-ai/core';
|
|
5
|
-
import { useRightRailStore, useAssistantInviteStore, openAssistantAs, adminNavigateTo, askAI, useOrganizationStore, useFayzProjectsStore, defaultProjectOf, useAgentSurface } from '@fayz-ai/admin';
|
|
5
|
+
import { useRightRailStore, useAssistantInviteStore, openAssistantAs, isPlatformConnected, requestProjectChange, adminNavigateTo, askAI, useOrganizationStore, useFayzProjectsStore, defaultProjectOf, getGenerationStatus, useAgentSurface, getPreview, startPreview } from '@fayz-ai/admin';
|
|
6
6
|
import { useLayoutStore } from '@fayz-ai/ui';
|
|
7
7
|
import { jsx } from 'react/jsx-runtime';
|
|
8
8
|
|
|
9
|
+
var BOOT_POLL_MS = 3e3;
|
|
10
|
+
var ALIVE_POLL_MS = 6e4;
|
|
11
|
+
var BOOT_TIMEOUT_MS = 18e4;
|
|
12
|
+
function isReady(state) {
|
|
13
|
+
return state.status === "RUNNING" && state.healthy === true;
|
|
14
|
+
}
|
|
15
|
+
function isDead(state) {
|
|
16
|
+
return state.status === "ERROR";
|
|
17
|
+
}
|
|
18
|
+
function usePreviewContainer(projectId) {
|
|
19
|
+
const [container, setContainer] = React4.useState({ phase: "idle", url: null });
|
|
20
|
+
const [attempt, setAttempt] = React4.useState(0);
|
|
21
|
+
const retry = React4.useCallback(() => setAttempt((n) => n + 1), []);
|
|
22
|
+
React4.useEffect(() => {
|
|
23
|
+
if (!projectId || !isPlatformConnected()) {
|
|
24
|
+
setContainer({ phase: "idle", url: null });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
let cancelled = false;
|
|
28
|
+
let timer;
|
|
29
|
+
const startedAt = Date.now();
|
|
30
|
+
const settle = (state) => {
|
|
31
|
+
if (isReady(state)) {
|
|
32
|
+
setContainer({ phase: "ready", url: state.url });
|
|
33
|
+
timer = setTimeout(tick, ALIVE_POLL_MS);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (isDead(state)) {
|
|
37
|
+
setContainer({ phase: "failed", url: null, error: "O preview parou com erro." });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (Date.now() - startedAt > BOOT_TIMEOUT_MS) {
|
|
41
|
+
setContainer({ phase: "failed", url: null, error: "O preview demorou demais para subir." });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
setContainer({ phase: "starting", url: null });
|
|
45
|
+
timer = setTimeout(tick, BOOT_POLL_MS);
|
|
46
|
+
};
|
|
47
|
+
const tick = async () => {
|
|
48
|
+
if (cancelled) return;
|
|
49
|
+
try {
|
|
50
|
+
settle(await getPreview(projectId, { checkHealth: true }));
|
|
51
|
+
} catch (cause) {
|
|
52
|
+
if (cancelled) return;
|
|
53
|
+
if (Date.now() - startedAt > BOOT_TIMEOUT_MS) {
|
|
54
|
+
setContainer({
|
|
55
|
+
phase: "failed",
|
|
56
|
+
url: null,
|
|
57
|
+
error: cause instanceof Error ? cause.message : "N\xE3o foi poss\xEDvel falar com o preview."
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
timer = setTimeout(tick, BOOT_POLL_MS);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
void (async () => {
|
|
65
|
+
setContainer({ phase: "starting", url: null });
|
|
66
|
+
try {
|
|
67
|
+
const current = await getPreview(projectId, { checkHealth: true });
|
|
68
|
+
if (cancelled) return;
|
|
69
|
+
if (isReady(current)) {
|
|
70
|
+
settle(current);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
await startPreview(projectId);
|
|
74
|
+
if (cancelled) return;
|
|
75
|
+
timer = setTimeout(tick, BOOT_POLL_MS);
|
|
76
|
+
} catch (cause) {
|
|
77
|
+
if (cancelled) return;
|
|
78
|
+
setContainer({
|
|
79
|
+
phase: "failed",
|
|
80
|
+
url: null,
|
|
81
|
+
error: cause instanceof Error ? cause.message : "N\xE3o foi poss\xEDvel iniciar o preview."
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
})();
|
|
85
|
+
return () => {
|
|
86
|
+
cancelled = true;
|
|
87
|
+
if (timer) clearTimeout(timer);
|
|
88
|
+
};
|
|
89
|
+
}, [projectId, attempt]);
|
|
90
|
+
return { ...container, retry };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/admin/target.ts
|
|
9
94
|
function env(key) {
|
|
10
95
|
const bag = import.meta.env;
|
|
11
96
|
return bag?.[key];
|
|
@@ -15,23 +100,28 @@ function useAdminBuilderTarget(options) {
|
|
|
15
100
|
const projects = useFayzProjectsStore((s) => s.projects);
|
|
16
101
|
const load = useFayzProjectsStore((s) => s.load);
|
|
17
102
|
const loadedFor = useFayzProjectsStore((s) => s.loadedFor);
|
|
18
|
-
|
|
103
|
+
React4.useEffect(() => {
|
|
19
104
|
if (loadedFor !== (currentOrgId ?? null)) void load(currentOrgId);
|
|
20
105
|
}, [currentOrgId, loadedFor, load]);
|
|
21
106
|
const settled = loadedFor === (currentOrgId ?? null);
|
|
22
107
|
const active = defaultProjectOf(projects);
|
|
23
|
-
|
|
108
|
+
const container = usePreviewContainer(active?.fayzProjectId ?? null);
|
|
109
|
+
if (!active) return { target: null, loading: !settled, preview: { phase: "idle", retry: container.retry } };
|
|
24
110
|
const metadata = active.metadata ?? {};
|
|
25
111
|
const perTenant = typeof metadata.sandbox_url === "string" ? metadata.sandbox_url : null;
|
|
26
|
-
const
|
|
112
|
+
const override = perTenant ?? options?.sandboxUrl ?? env("VITE_APP_BUILDER_SANDBOX_URL") ?? null;
|
|
27
113
|
return {
|
|
28
114
|
target: {
|
|
29
115
|
projectId: active.fayzProjectId,
|
|
30
116
|
name: active.name,
|
|
31
|
-
|
|
117
|
+
// The published site is the last fallback, not the goal: it is the app as
|
|
118
|
+
// it was at the last publish, and a project that has never been published
|
|
119
|
+
// has none at all.
|
|
120
|
+
url: override ?? container.url ?? active.previewUrl,
|
|
32
121
|
liveUrl: active.previewUrl
|
|
33
122
|
},
|
|
34
|
-
loading: false
|
|
123
|
+
loading: false,
|
|
124
|
+
preview: { phase: container.phase, error: container.error, retry: container.retry }
|
|
35
125
|
};
|
|
36
126
|
}
|
|
37
127
|
var INSTRUCTIONS = [
|
|
@@ -58,9 +148,9 @@ function tool(id, name, description, properties, required, mode = "read") {
|
|
|
58
148
|
};
|
|
59
149
|
}
|
|
60
150
|
function useBuilderAgentSurface(deps) {
|
|
61
|
-
const ref =
|
|
151
|
+
const ref = React4.useRef(deps);
|
|
62
152
|
ref.current = deps;
|
|
63
|
-
const contribution =
|
|
153
|
+
const contribution = React4.useMemo(
|
|
64
154
|
() => ({
|
|
65
155
|
id: "app_builder.canvas",
|
|
66
156
|
pluginId: "app_builder",
|
|
@@ -152,9 +242,9 @@ function useBuilderAgentSurface(deps) {
|
|
|
152
242
|
var EMPTY_TARGET = { projectId: null, name: "", url: null, liveUrl: null };
|
|
153
243
|
var INVITE_ID = "app_builder.site";
|
|
154
244
|
function AdminAppBuilder({ options }) {
|
|
155
|
-
const { target: resolved, loading } = useAdminBuilderTarget(options);
|
|
245
|
+
const { target: resolved, loading, preview } = useAdminBuilderTarget(options);
|
|
156
246
|
const target = resolved ?? EMPTY_TARGET;
|
|
157
|
-
const [viewport, setViewport] =
|
|
247
|
+
const [viewport, setViewport] = React4.useState("desktop");
|
|
158
248
|
const frame = useBuilderFrame(target.url);
|
|
159
249
|
const openPanel = useRightRailStore((s) => s.openPanel);
|
|
160
250
|
const closeRail = useRightRailStore((s) => s.close);
|
|
@@ -162,7 +252,7 @@ function AdminAppBuilder({ options }) {
|
|
|
162
252
|
const sidebarCollapsed = useLayoutStore((s) => s.sidebarCollapsed);
|
|
163
253
|
const setSidebarCollapsed = useLayoutStore((s) => s.setSidebarCollapsed);
|
|
164
254
|
const setInvite = useAssistantInviteStore((s) => s.setInvite);
|
|
165
|
-
|
|
255
|
+
React4.useEffect(() => {
|
|
166
256
|
openPanel("chat");
|
|
167
257
|
openAssistantAs("setup");
|
|
168
258
|
setInvite(
|
|
@@ -186,8 +276,8 @@ function AdminAppBuilder({ options }) {
|
|
|
186
276
|
);
|
|
187
277
|
return () => setInvite(null, INVITE_ID);
|
|
188
278
|
}, [openPanel, setInvite, options?.labels]);
|
|
189
|
-
const collapsedByUs =
|
|
190
|
-
|
|
279
|
+
const collapsedByUs = React4.useRef(false);
|
|
280
|
+
React4.useEffect(() => {
|
|
191
281
|
if (!useLayoutStore.getState().sidebarCollapsed) {
|
|
192
282
|
collapsedByUs.current = true;
|
|
193
283
|
setSidebarCollapsed(true);
|
|
@@ -196,24 +286,59 @@ function AdminAppBuilder({ options }) {
|
|
|
196
286
|
if (collapsedByUs.current) setSidebarCollapsed(false);
|
|
197
287
|
};
|
|
198
288
|
}, [setSidebarCollapsed]);
|
|
289
|
+
const [building, setBuilding] = React4.useState(false);
|
|
290
|
+
const requestChange = React4.useMemo(() => {
|
|
291
|
+
if (options?.onRequestChange) return options.onRequestChange;
|
|
292
|
+
if (!isPlatformConnected()) return void 0;
|
|
293
|
+
return async ({ projectId: projectId2, instruction }) => {
|
|
294
|
+
await requestProjectChange(projectId2, instruction);
|
|
295
|
+
setBuilding(true);
|
|
296
|
+
return "Pedido enviado ao construtor. O site recarrega aqui quando a mudan\xE7a terminar.";
|
|
297
|
+
};
|
|
298
|
+
}, [options?.onRequestChange]);
|
|
299
|
+
const projectId = target.projectId;
|
|
300
|
+
React4.useEffect(() => {
|
|
301
|
+
if (!building || !projectId) return;
|
|
302
|
+
let cancelled = false;
|
|
303
|
+
let timer;
|
|
304
|
+
const poll = async () => {
|
|
305
|
+
if (cancelled) return;
|
|
306
|
+
try {
|
|
307
|
+
const status = await getGenerationStatus(projectId);
|
|
308
|
+
if (cancelled) return;
|
|
309
|
+
if (!status.building) {
|
|
310
|
+
setBuilding(false);
|
|
311
|
+
frame.reload();
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
} catch {
|
|
315
|
+
}
|
|
316
|
+
timer = setTimeout(poll, 5e3);
|
|
317
|
+
};
|
|
318
|
+
timer = setTimeout(poll, 5e3);
|
|
319
|
+
return () => {
|
|
320
|
+
cancelled = true;
|
|
321
|
+
if (timer) clearTimeout(timer);
|
|
322
|
+
};
|
|
323
|
+
}, [building, projectId, frame]);
|
|
199
324
|
useBuilderAgentSurface({
|
|
200
325
|
target,
|
|
201
326
|
currentPath: frame.currentPath,
|
|
202
327
|
viewport,
|
|
203
328
|
actions: { navigate: frame.navigate, reload: frame.reload, setViewport },
|
|
204
|
-
onRequestChange:
|
|
329
|
+
onRequestChange: requestChange
|
|
205
330
|
});
|
|
206
|
-
const [publishing, setPublishing] =
|
|
331
|
+
const [publishing, setPublishing] = React4.useState(false);
|
|
207
332
|
const publish = options?.onPublish;
|
|
208
|
-
const publishContract =
|
|
333
|
+
const publishContract = React4.useMemo(() => {
|
|
209
334
|
if (!publish || !target.projectId) return void 0;
|
|
210
|
-
const
|
|
335
|
+
const projectId2 = target.projectId;
|
|
211
336
|
return {
|
|
212
337
|
state: publishing ? "publishing" : "idle",
|
|
213
338
|
publish: async () => {
|
|
214
339
|
setPublishing(true);
|
|
215
340
|
try {
|
|
216
|
-
await publish({ projectId });
|
|
341
|
+
await publish({ projectId: projectId2 });
|
|
217
342
|
} finally {
|
|
218
343
|
setPublishing(false);
|
|
219
344
|
}
|
|
@@ -232,7 +357,28 @@ function AdminAppBuilder({ options }) {
|
|
|
232
357
|
onClose: () => adminNavigateTo("/"),
|
|
233
358
|
onToggleChat: () => railOpen ? closeRail() : openPanel("chat"),
|
|
234
359
|
onToggleWide: () => setSidebarCollapsed(!sidebarCollapsed),
|
|
235
|
-
empty: loading ? /* @__PURE__ */ jsx("div", { className: "h-full" }) :
|
|
360
|
+
empty: loading ? /* @__PURE__ */ jsx("div", { className: "h-full" }) : resolved ? (
|
|
361
|
+
// A project resolved but has no address yet. Three different reasons —
|
|
362
|
+
// the container is booting, it failed, or none is being attempted and
|
|
363
|
+
// the site simply has not been published. `target.url` is null in all
|
|
364
|
+
// of them, so only the host, which knows the container's phase, can
|
|
365
|
+
// tell them apart.
|
|
366
|
+
/* @__PURE__ */ jsx(
|
|
367
|
+
BuilderPending,
|
|
368
|
+
{
|
|
369
|
+
labels: options?.labels,
|
|
370
|
+
name: resolved.name,
|
|
371
|
+
phase: preview.phase === "starting" || preview.phase === "failed" ? preview.phase : void 0,
|
|
372
|
+
error: preview.error,
|
|
373
|
+
onRetry: preview.retry,
|
|
374
|
+
onAction: resolved.projectId ? () => window.open(
|
|
375
|
+
`https://fayz.ai/editor/${resolved.projectId}`,
|
|
376
|
+
"_blank",
|
|
377
|
+
"noopener,noreferrer"
|
|
378
|
+
) : void 0
|
|
379
|
+
}
|
|
380
|
+
)
|
|
381
|
+
) : /* @__PURE__ */ jsx(BuilderEmpty, { labels: options?.labels, onAction: () => adminNavigateTo("/settings/sites") }),
|
|
236
382
|
labels: options?.labels
|
|
237
383
|
}
|
|
238
384
|
);
|
|
@@ -242,7 +388,7 @@ function AdminAppBuilder({ options }) {
|
|
|
242
388
|
var EDIT = { feature: "site", action: "edit" };
|
|
243
389
|
function createAppBuilderPlugin(options) {
|
|
244
390
|
const route = options?.route ?? "/site";
|
|
245
|
-
const PageComponent = () =>
|
|
391
|
+
const PageComponent = () => React4__default.createElement(AdminAppBuilder, { options });
|
|
246
392
|
PageComponent.displayName = "AdminAppBuilder";
|
|
247
393
|
return {
|
|
248
394
|
id: "app_builder",
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/admin/target.ts","../src/admin/agent-surface.ts","../src/admin/AdminAppBuilder.tsx","../src/plugin.ts"],"names":["React","React2"],"mappings":"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","file":"plugin.js","sourcesContent":["import * as React from 'react'\nimport { useFayzProjectsStore, defaultProjectOf, useOrganizationStore } from '@fayz-ai/admin'\nimport type { BuilderTarget } from '../types'\n\nexport interface AdminTargetOptions {\n /** Address of the running preview container, when the host knows it. */\n sandboxUrl?: string\n}\n\nfunction env(key: string): string | undefined {\n const bag = (import.meta as unknown as { env?: Record<string, string | undefined> }).env\n return bag?.[key]\n}\n\n/**\n * The tenant's default site row, as a builder target.\n *\n * The canvas is THE APP — the running preview container — never the platform's\n * editor: embedding the editor would put its chat inside ours and hand the\n * merchant two conversations for one question. With no sandbox address known it\n * falls back to the published site, which is still the app, just yesterday's.\n */\nexport interface AdminTargetState {\n target: BuilderTarget | null\n /** The tenant's projects have not answered yet — \"none\" is not the answer. */\n loading: boolean\n}\n\nexport function useAdminBuilderTarget(options?: AdminTargetOptions): AdminTargetState {\n const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id)\n const projects = useFayzProjectsStore((s) => s.projects)\n const load = useFayzProjectsStore((s) => s.load)\n const loadedFor = useFayzProjectsStore((s) => s.loadedFor)\n\n // The page can be entered by URL, before the sidebar widget loaded anything.\n React.useEffect(() => {\n if (loadedFor !== (currentOrgId ?? null)) void load(currentOrgId)\n }, [currentOrgId, loadedFor, load])\n\n // Rendering \"no site linked\" before the first read comes back flashed a wrong\n // answer at everyone who has one.\n const settled = loadedFor === (currentOrgId ?? null)\n const active = defaultProjectOf(projects)\n if (!active) return { target: null, loading: !settled }\n\n const metadata = (active.metadata ?? {}) as Record<string, unknown>\n const perTenant = typeof metadata.sandbox_url === 'string' ? metadata.sandbox_url : null\n const sandboxUrl = perTenant ?? options?.sandboxUrl ?? env('VITE_APP_BUILDER_SANDBOX_URL') ?? null\n\n return {\n target: {\n projectId: active.fayzProjectId,\n name: active.name,\n url: sandboxUrl ?? active.previewUrl,\n liveUrl: active.previewUrl,\n },\n loading: false,\n }\n}\n","import * as React from 'react'\nimport { useAgentSurface } from '@fayz-ai/admin'\nimport type { PluginAITool } from '@fayz-ai/core'\nimport type { BuilderTarget, BuilderViewport } from '../types'\n\nconst INSTRUCTIONS = [\n 'The user is looking at their own app inside the admin. The canvas on the left is the running',\n 'app; you are the column on the right.',\n 'Use builder_navigate/builder_reload/builder_set_viewport to move the canvas so you are both',\n 'looking at the same thing before discussing a change.',\n \"To change the app itself, call builder_request_change with the user's intent in one sentence.\",\n 'Never claim a change was applied unless that tool says so.',\n].join(' ')\n\nfunction tool(\n id: string,\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n mode: 'read' | 'persist' = 'read',\n): PluginAITool {\n return {\n id,\n name,\n description,\n mode,\n parameters: { type: 'object', properties, required } as PluginAITool['parameters'],\n execution: { plane: 'client' },\n // Moving the canvas is what looking together costs; a confirmation card per\n // scroll would make the colleague useless at the one thing it is for.\n requiresConfirmation: false,\n role: 'setup',\n permission: { feature: 'site', action: 'edit' },\n }\n}\n\nexport interface BuilderAgentSurfaceDeps {\n target: BuilderTarget\n currentPath: string\n viewport: BuilderViewport\n actions: {\n navigate: (path: string) => void\n reload: () => void\n setViewport: (viewport: BuilderViewport) => void\n }\n onRequestChange?: (input: { projectId: string; path: string; instruction: string }) => Promise<string> | string\n}\n\nexport function useBuilderAgentSurface(deps: BuilderAgentSurfaceDeps): void {\n const ref = React.useRef(deps)\n ref.current = deps\n\n const contribution = React.useMemo(\n () => ({\n id: 'app_builder.canvas',\n pluginId: 'app_builder',\n role: 'setup' as const,\n instructions: INSTRUCTIONS,\n describe: () => {\n const d = ref.current\n return {\n title: `Site — ${d.target.name}`,\n state: {\n projectId: d.target.projectId ?? null,\n projectName: d.target.name,\n currentPath: d.currentPath,\n viewport: d.viewport,\n liveUrl: d.target.liveUrl ?? null,\n canApplyChanges: !!d.onRequestChange,\n },\n }\n },\n tools: [\n {\n tool: tool(\n 'app_builder.navigate',\n 'builder_navigate',\n 'Point the canvas at a path of the app (e.g. \"/\", \"/produtos\").',\n { path: { type: 'string', description: 'Path starting with /' } },\n ['path'],\n ),\n execute: (args: Record<string, unknown>) => {\n const path = String(args.path ?? '/')\n ref.current.actions.navigate(path)\n return { ok: true, path }\n },\n },\n {\n tool: tool('app_builder.reload', 'builder_reload', 'Reload the canvas.', {}, []),\n execute: () => {\n ref.current.actions.reload()\n return { ok: true }\n },\n },\n {\n tool: tool(\n 'app_builder.set_viewport',\n 'builder_set_viewport',\n 'Show the app at a device width.',\n { viewport: { type: 'string', enum: ['desktop', 'mobile'] } },\n ['viewport'],\n ),\n execute: (args: Record<string, unknown>) => {\n const viewport = String(args.viewport ?? 'desktop') as BuilderViewport\n ref.current.actions.setViewport(viewport)\n return { ok: true, viewport }\n },\n },\n {\n tool: tool(\n 'app_builder.request_change',\n 'builder_request_change',\n 'Ask the builder to change the app the user is looking at.',\n { instruction: { type: 'string', description: 'One sentence describing the change' } },\n ['instruction'],\n 'persist',\n ),\n execute: async (args: Record<string, unknown>) => {\n const d = ref.current\n const instruction = String(args.instruction ?? '').trim()\n if (!instruction) return { error: 'empty_instruction' }\n if (!d.onRequestChange || !d.target.projectId) {\n return {\n error: 'not_connected',\n message: 'The build path is not wired up yet — nothing was changed.',\n }\n }\n const result = await d.onRequestChange({\n projectId: d.target.projectId,\n path: d.currentPath,\n instruction,\n })\n return { ok: true, message: result }\n },\n },\n ],\n }),\n [],\n )\n\n useAgentSurface(contribution)\n}\n","import * as React from 'react'\nimport {\n adminNavigateTo,\n askAI,\n openAssistantAs,\n useAssistantInviteStore,\n useRightRailStore,\n} from '@fayz-ai/admin'\nimport { useLayoutStore } from '@fayz-ai/ui'\nimport { AppBuilder } from '../components/AppBuilder'\nimport { BuilderEmpty } from '../components/BuilderEmpty'\nimport { useBuilderFrame } from '../hooks/useBuilderFrame'\nimport { useAdminBuilderTarget } from './target'\nimport { useBuilderAgentSurface } from './agent-surface'\nimport type { AppBuilderPluginOptions } from './options'\nimport type { BuilderTarget, BuilderViewport } from '../types'\n\nconst EMPTY_TARGET: BuilderTarget = { projectId: null, name: '', url: null, liveUrl: null }\nconst INVITE_ID = 'app_builder.site'\n\n/**\n * The admin's wiring of the surface: where the target comes from, what the\n * window buttons do here, and which colleague is on duty. Everything in this\n * file is host-specific — the surface itself knows none of it.\n */\nexport function AdminAppBuilder({ options }: { options?: AppBuilderPluginOptions }) {\n const { target: resolved, loading } = useAdminBuilderTarget(options)\n const target = resolved ?? EMPTY_TARGET\n const [viewport, setViewport] = React.useState<BuilderViewport>('desktop')\n\n // Owned here, not by the surface, because the agent tools drive it.\n const frame = useBuilderFrame(target.url)\n\n const openPanel = useRightRailStore((s) => s.openPanel)\n const closeRail = useRightRailStore((s) => s.close)\n const railOpen = useRightRailStore((s) => s.open)\n const sidebarCollapsed = useLayoutStore((s) => s.sidebarCollapsed)\n const setSidebarCollapsed = useLayoutStore((s) => s.setSidebarCollapsed)\n\n const setInvite = useAssistantInviteStore((s) => s.setInvite)\n\n // The screen IS the conversation: the canvas is what you point at while you\n // ask. What the colleague opens with has to be about the site — the generic\n // \"vamos deixar a loja pronta pra vender\" is the right pitch on the dashboard\n // and the wrong one in front of the site's own home page.\n React.useEffect(() => {\n openPanel('chat')\n openAssistantAs('setup')\n setInvite(\n {\n id: INVITE_ID,\n role: 'setup',\n persona: options?.labels?.assistantPersona ?? 'Site da loja',\n headline: options?.labels?.assistantHeadline ?? 'O que você quer mudar no site?',\n description:\n options?.labels?.assistantDescription\n ?? 'Peça a mudança em português — texto, cor, imagem, seção — e ela aparece aqui do lado.',\n placeholder: options?.labels?.assistantPlaceholder ?? 'Ex.: troque o banner da home',\n suggestions: options?.labels?.assistantSuggestions ?? [\n { label: 'Trocar a imagem principal da home' },\n { label: 'Mudar as cores da loja' },\n { label: 'Criar uma página de contato' },\n ],\n // Docked, never a hero: the hero would cover the canvas the invite is\n // about.\n auto: false,\n },\n INVITE_ID,\n )\n return () => setInvite(null, INVITE_ID)\n }, [openPanel, setInvite, options?.labels])\n\n // Entering the builder gives the canvas the desk. Only the collapse WE caused\n // is undone on the way out, so a menu the user closed by hand stays closed.\n const collapsedByUs = React.useRef(false)\n React.useEffect(() => {\n if (!useLayoutStore.getState().sidebarCollapsed) {\n collapsedByUs.current = true\n setSidebarCollapsed(true)\n }\n return () => {\n if (collapsedByUs.current) setSidebarCollapsed(false)\n }\n }, [setSidebarCollapsed])\n\n useBuilderAgentSurface({\n target,\n currentPath: frame.currentPath,\n viewport,\n actions: { navigate: frame.navigate, reload: frame.reload, setViewport },\n onRequestChange: options?.onRequestChange,\n })\n\n const [publishing, setPublishing] = React.useState(false)\n const publish = options?.onPublish\n const publishContract = React.useMemo(() => {\n if (!publish || !target.projectId) return undefined\n const projectId = target.projectId\n return {\n state: publishing ? ('publishing' as const) : ('idle' as const),\n publish: async () => {\n setPublishing(true)\n try {\n await publish({ projectId })\n } finally {\n setPublishing(false)\n }\n },\n }\n }, [publish, target.projectId, publishing])\n\n return (\n <AppBuilder\n target={target}\n frame={frame}\n viewport={viewport}\n onViewportChange={setViewport}\n publish={publishContract}\n chatContract={{ send: (message, context) => askAI({ prompt: message, hint: context?.selector }) }}\n onClose={() => adminNavigateTo('/')}\n onToggleChat={() => (railOpen ? closeRail() : openPanel('chat'))}\n onToggleWide={() => setSidebarCollapsed(!sidebarCollapsed)}\n empty={\n loading ? (\n <div className=\"h-full\" />\n ) : (\n <BuilderEmpty labels={options?.labels} onAction={() => adminNavigateTo('/settings/sites')} />\n )\n }\n labels={options?.labels}\n />\n )\n}\n","import React from 'react'\nimport type { PluginManifest } from '@fayz-ai/core'\nimport { registerPluginFactory } from '@fayz-ai/core'\nimport { AdminAppBuilder } from './admin/AdminAppBuilder'\nimport type { AppBuilderPluginOptions } from './admin/options'\n\nexport type { AppBuilderPluginOptions } from './admin/options'\nexport { AdminAppBuilder } from './admin/AdminAppBuilder'\nexport { useAdminBuilderTarget } from './admin/target'\n\nconst EDIT = { feature: 'site', action: 'edit' as const }\n\n/**\n * The admin's mount of the builder surface. Everything host-specific — the\n * target, the rail, the agent — lives behind this door, so the surface itself\n * stays importable by an app that has none of it.\n */\nexport function createAppBuilderPlugin(options?: AppBuilderPluginOptions): PluginManifest {\n const route = options?.route ?? '/site'\n\n const PageComponent: React.ComponentType<unknown> = () =>\n React.createElement(AdminAppBuilder, { options })\n PageComponent.displayName = 'AdminAppBuilder'\n\n return {\n id: 'app_builder',\n name: options?.navLabel ?? 'Site',\n icon: 'PenSquare',\n version: '1.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n defaultAgentRole: 'setup',\n declaredFeatures: [{ id: 'site', label: 'Site', group: 'Convert' }],\n // No nav entry on purpose: the door is the \"Editar\" action on the site\n // widget in the sidebar footer (the app points site.editRoute here).\n navigation: [],\n routes: [\n {\n path: route,\n component: PageComponent,\n immersive: true,\n title: options?.navLabel ?? 'Site',\n permission: EDIT,\n },\n ],\n widgets: [],\n }\n}\n\nregisterPluginFactory('app_builder', createAppBuilderPlugin as (config?: Record<string, unknown>) => PluginManifest)\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/admin/preview.ts","../src/admin/target.ts","../src/admin/agent-surface.ts","../src/admin/AdminAppBuilder.tsx","../src/plugin.ts"],"names":["React","React2","React3","isPlatformConnected","projectId"],"mappings":"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","file":"plugin.js","sourcesContent":["import * as React from 'react'\nimport { getPreview, startPreview, isPlatformConnected, type PreviewState } from '@fayz-ai/admin'\n\n/**\n * The running preview container, as one hook.\n *\n * The canvas is supposed to show THE APP — the container the platform runs for\n * this project — and until now the admin had no way to get one: the console's\n * container routes are session-JWT only, so the surface fell back to the\n * published site, which is the app as it was at the last publish rather than as\n * it is now.\n *\n * Three things happen here, and they are one loop rather than three because\n * they share a single fact: the container's state.\n *\n * 1. START — only after a status read says it is not already up. A blind\n * start on every mount would resync files and could restart a container\n * the merchant is looking at.\n * 2. WAIT — poll until `healthy`, not until `RUNNING`. A container can be\n * running with a dev server that has not bound a port yet (~24s on a cold\n * start), and pointing the iframe at it then shows a connection error the\n * merchant reads as a broken site.\n * 3. KEEP ALIVE — the same poll, slower. Reading the state touches\n * `lastActiveAt` on the platform, which is what its idle reaper checks, so\n * watching the preview is what keeps it. There is deliberately no separate\n * heartbeat to forget to call.\n *\n * It never stops the container on unmount. Navigating away from the Site tab\n * for a minute is not a decision to throw away a warm container and pay the\n * cold start again — the platform's 30-minute idle reaper is the right authority\n * on when it goes.\n */\n\nexport type PreviewPhase =\n /** No project, or no platform credentials — nothing to do. */\n | 'idle'\n /** Container is coming up, or its dev server has not answered yet. */\n | 'starting'\n /** Serving: point the canvas at `url`. */\n | 'ready'\n | 'failed'\n\nexport interface PreviewContainer {\n phase: PreviewPhase\n /** Only set in 'ready' — a URL that is not serving yet is worse than none. */\n url: string | null\n error?: string\n /** Run the whole sequence again. The only exit from 'failed'. */\n retry: () => void\n}\n\n/** While coming up. Fast enough that a ~24s start does not feel unattended. */\nconst BOOT_POLL_MS = 3_000\n/** Once ready — this is the keepalive, so it only has to beat the idle reaper. */\nconst ALIVE_POLL_MS = 60_000\n/** A cold start is ~24s; past this something is wrong and saying so beats spinning. */\nconst BOOT_TIMEOUT_MS = 180_000\n\nfunction isReady(state: PreviewState): boolean {\n return state.status === 'RUNNING' && state.healthy === true\n}\n\n/** Terminal from the platform's side — polling will not improve it. */\nfunction isDead(state: PreviewState): boolean {\n return state.status === 'ERROR'\n}\n\nexport function usePreviewContainer(projectId: string | null | undefined): PreviewContainer {\n const [container, setContainer] = React.useState<{\n phase: PreviewPhase\n url: string | null\n error?: string\n }>({ phase: 'idle', url: null })\n // Bumping this re-runs the effect, which is the entire retry: the sequence\n // already handles \"already up\" and \"needs starting\", so replaying it is\n // correct whether the failure was the start or a poll.\n const [attempt, setAttempt] = React.useState(0)\n const retry = React.useCallback(() => setAttempt((n) => n + 1), [])\n\n React.useEffect(() => {\n if (!projectId || !isPlatformConnected()) {\n setContainer({ phase: 'idle', url: null })\n return\n }\n\n let cancelled = false\n let timer: ReturnType<typeof setTimeout> | undefined\n const startedAt = Date.now()\n\n // Every path out of a poll goes through here, so \"ready\" and \"still coming\n // up\" cannot end up scheduling different follow-ups by accident.\n const settle = (state: PreviewState) => {\n if (isReady(state)) {\n setContainer({ phase: 'ready', url: state.url })\n timer = setTimeout(tick, ALIVE_POLL_MS)\n return\n }\n if (isDead(state)) {\n setContainer({ phase: 'failed', url: null, error: 'O preview parou com erro.' })\n return\n }\n if (Date.now() - startedAt > BOOT_TIMEOUT_MS) {\n setContainer({ phase: 'failed', url: null, error: 'O preview demorou demais para subir.' })\n return\n }\n setContainer({ phase: 'starting', url: null })\n timer = setTimeout(tick, BOOT_POLL_MS)\n }\n\n const tick = async () => {\n if (cancelled) return\n try {\n settle(await getPreview(projectId, { checkHealth: true }))\n } catch (cause) {\n if (cancelled) return\n // A single failed poll is not a dead container — the platform restarts,\n // the tab sleeps, wifi drops. Only the boot timeout ends the loop.\n if (Date.now() - startedAt > BOOT_TIMEOUT_MS) {\n setContainer({\n phase: 'failed',\n url: null,\n error: cause instanceof Error ? cause.message : 'Não foi possível falar com o preview.',\n })\n return\n }\n timer = setTimeout(tick, BOOT_POLL_MS)\n }\n }\n\n void (async () => {\n setContainer({ phase: 'starting', url: null })\n try {\n // Ask before acting: if it is already up this costs one request and\n // avoids a file resync the merchant did not ask for.\n const current = await getPreview(projectId, { checkHealth: true })\n if (cancelled) return\n if (isReady(current)) {\n settle(current)\n return\n }\n await startPreview(projectId)\n if (cancelled) return\n timer = setTimeout(tick, BOOT_POLL_MS)\n } catch (cause) {\n if (cancelled) return\n setContainer({\n phase: 'failed',\n url: null,\n error: cause instanceof Error ? cause.message : 'Não foi possível iniciar o preview.',\n })\n }\n })()\n\n return () => {\n cancelled = true\n if (timer) clearTimeout(timer)\n }\n }, [projectId, attempt])\n\n return { ...container, retry }\n}\n","import * as React from 'react'\nimport { useFayzProjectsStore, defaultProjectOf, useOrganizationStore } from '@fayz-ai/admin'\nimport { usePreviewContainer, type PreviewPhase } from './preview'\nimport type { BuilderTarget } from '../types'\n\nexport interface AdminTargetOptions {\n /** Address of the running preview container, when the host knows it. */\n sandboxUrl?: string\n}\n\nfunction env(key: string): string | undefined {\n const bag = (import.meta as unknown as { env?: Record<string, string | undefined> }).env\n return bag?.[key]\n}\n\n/**\n * The tenant's default site row, as a builder target.\n *\n * The canvas is THE APP — the running preview container — never the platform's\n * editor: embedding the editor would put its chat inside ours and hand the\n * merchant two conversations for one question. With no sandbox address known it\n * falls back to the published site, which is still the app, just yesterday's.\n */\nexport interface AdminTargetState {\n target: BuilderTarget | null\n /** The tenant's projects have not answered yet — \"none\" is not the answer. */\n loading: boolean\n /** How the running container is doing, when there is a project to run one for. */\n preview: { phase: PreviewPhase; error?: string; retry: () => void }\n}\n\nexport function useAdminBuilderTarget(options?: AdminTargetOptions): AdminTargetState {\n const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id)\n const projects = useFayzProjectsStore((s) => s.projects)\n const load = useFayzProjectsStore((s) => s.load)\n const loadedFor = useFayzProjectsStore((s) => s.loadedFor)\n\n // The page can be entered by URL, before the sidebar widget loaded anything.\n React.useEffect(() => {\n if (loadedFor !== (currentOrgId ?? null)) void load(currentOrgId)\n }, [currentOrgId, loadedFor, load])\n\n // Rendering \"no site linked\" before the first read comes back flashed a wrong\n // answer at everyone who has one.\n const settled = loadedFor === (currentOrgId ?? null)\n const active = defaultProjectOf(projects)\n\n // Hooks cannot be called conditionally, so this runs before the early return\n // and is handed null when there is nothing to run — which is also the honest\n // input: no project, no container.\n const container = usePreviewContainer(active?.fayzProjectId ?? null)\n\n if (!active) return { target: null, loading: !settled, preview: { phase: 'idle', retry: container.retry } }\n\n const metadata = (active.metadata ?? {}) as Record<string, unknown>\n const perTenant = typeof metadata.sandbox_url === 'string' ? metadata.sandbox_url : null\n // Explicit addresses stay ahead of the container: they exist so someone\n // debugging can aim the canvas at their own dev server, and a hook that\n // silently overrode them would make that override look broken.\n const override = perTenant ?? options?.sandboxUrl ?? env('VITE_APP_BUILDER_SANDBOX_URL') ?? null\n\n return {\n target: {\n projectId: active.fayzProjectId,\n name: active.name,\n // The published site is the last fallback, not the goal: it is the app as\n // it was at the last publish, and a project that has never been published\n // has none at all.\n url: override ?? container.url ?? active.previewUrl,\n liveUrl: active.previewUrl,\n },\n loading: false,\n preview: { phase: container.phase, error: container.error, retry: container.retry },\n }\n}\n","import * as React from 'react'\nimport { useAgentSurface } from '@fayz-ai/admin'\nimport type { PluginAITool } from '@fayz-ai/core'\nimport type { BuilderTarget, BuilderViewport } from '../types'\n\nconst INSTRUCTIONS = [\n 'The user is looking at their own app inside the admin. The canvas on the left is the running',\n 'app; you are the column on the right.',\n 'Use builder_navigate/builder_reload/builder_set_viewport to move the canvas so you are both',\n 'looking at the same thing before discussing a change.',\n \"To change the app itself, call builder_request_change with the user's intent in one sentence.\",\n 'Never claim a change was applied unless that tool says so.',\n].join(' ')\n\nfunction tool(\n id: string,\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n mode: 'read' | 'persist' = 'read',\n): PluginAITool {\n return {\n id,\n name,\n description,\n mode,\n parameters: { type: 'object', properties, required } as PluginAITool['parameters'],\n execution: { plane: 'client' },\n // Moving the canvas is what looking together costs; a confirmation card per\n // scroll would make the colleague useless at the one thing it is for.\n requiresConfirmation: false,\n role: 'setup',\n permission: { feature: 'site', action: 'edit' },\n }\n}\n\nexport interface BuilderAgentSurfaceDeps {\n target: BuilderTarget\n currentPath: string\n viewport: BuilderViewport\n actions: {\n navigate: (path: string) => void\n reload: () => void\n setViewport: (viewport: BuilderViewport) => void\n }\n onRequestChange?: (input: { projectId: string; path: string; instruction: string }) => Promise<string> | string\n}\n\nexport function useBuilderAgentSurface(deps: BuilderAgentSurfaceDeps): void {\n const ref = React.useRef(deps)\n ref.current = deps\n\n const contribution = React.useMemo(\n () => ({\n id: 'app_builder.canvas',\n pluginId: 'app_builder',\n role: 'setup' as const,\n instructions: INSTRUCTIONS,\n describe: () => {\n const d = ref.current\n return {\n title: `Site — ${d.target.name}`,\n state: {\n projectId: d.target.projectId ?? null,\n projectName: d.target.name,\n currentPath: d.currentPath,\n viewport: d.viewport,\n liveUrl: d.target.liveUrl ?? null,\n canApplyChanges: !!d.onRequestChange,\n },\n }\n },\n tools: [\n {\n tool: tool(\n 'app_builder.navigate',\n 'builder_navigate',\n 'Point the canvas at a path of the app (e.g. \"/\", \"/produtos\").',\n { path: { type: 'string', description: 'Path starting with /' } },\n ['path'],\n ),\n execute: (args: Record<string, unknown>) => {\n const path = String(args.path ?? '/')\n ref.current.actions.navigate(path)\n return { ok: true, path }\n },\n },\n {\n tool: tool('app_builder.reload', 'builder_reload', 'Reload the canvas.', {}, []),\n execute: () => {\n ref.current.actions.reload()\n return { ok: true }\n },\n },\n {\n tool: tool(\n 'app_builder.set_viewport',\n 'builder_set_viewport',\n 'Show the app at a device width.',\n { viewport: { type: 'string', enum: ['desktop', 'mobile'] } },\n ['viewport'],\n ),\n execute: (args: Record<string, unknown>) => {\n const viewport = String(args.viewport ?? 'desktop') as BuilderViewport\n ref.current.actions.setViewport(viewport)\n return { ok: true, viewport }\n },\n },\n {\n tool: tool(\n 'app_builder.request_change',\n 'builder_request_change',\n 'Ask the builder to change the app the user is looking at.',\n { instruction: { type: 'string', description: 'One sentence describing the change' } },\n ['instruction'],\n 'persist',\n ),\n execute: async (args: Record<string, unknown>) => {\n const d = ref.current\n const instruction = String(args.instruction ?? '').trim()\n if (!instruction) return { error: 'empty_instruction' }\n if (!d.onRequestChange || !d.target.projectId) {\n return {\n error: 'not_connected',\n message: 'The build path is not wired up yet — nothing was changed.',\n }\n }\n const result = await d.onRequestChange({\n projectId: d.target.projectId,\n path: d.currentPath,\n instruction,\n })\n return { ok: true, message: result }\n },\n },\n ],\n }),\n [],\n )\n\n useAgentSurface(contribution)\n}\n","import * as React from 'react'\nimport {\n adminNavigateTo,\n askAI,\n openAssistantAs,\n useAssistantInviteStore,\n useRightRailStore,\n isPlatformConnected,\n requestProjectChange,\n getGenerationStatus,\n} from '@fayz-ai/admin'\nimport { useLayoutStore } from '@fayz-ai/ui'\nimport { AppBuilder } from '../components/AppBuilder'\nimport { BuilderEmpty } from '../components/BuilderEmpty'\nimport { BuilderPending } from '../components/BuilderPending'\nimport { useBuilderFrame } from '../hooks/useBuilderFrame'\nimport { useAdminBuilderTarget } from './target'\nimport { useBuilderAgentSurface } from './agent-surface'\nimport type { AppBuilderPluginOptions } from './options'\nimport type { BuilderTarget, BuilderViewport } from '../types'\n\nconst EMPTY_TARGET: BuilderTarget = { projectId: null, name: '', url: null, liveUrl: null }\nconst INVITE_ID = 'app_builder.site'\n\n/**\n * The admin's wiring of the surface: where the target comes from, what the\n * window buttons do here, and which colleague is on duty. Everything in this\n * file is host-specific — the surface itself knows none of it.\n */\nexport function AdminAppBuilder({ options }: { options?: AppBuilderPluginOptions }) {\n const { target: resolved, loading, preview } = useAdminBuilderTarget(options)\n const target = resolved ?? EMPTY_TARGET\n const [viewport, setViewport] = React.useState<BuilderViewport>('desktop')\n\n // Owned here, not by the surface, because the agent tools drive it.\n const frame = useBuilderFrame(target.url)\n\n const openPanel = useRightRailStore((s) => s.openPanel)\n const closeRail = useRightRailStore((s) => s.close)\n const railOpen = useRightRailStore((s) => s.open)\n const sidebarCollapsed = useLayoutStore((s) => s.sidebarCollapsed)\n const setSidebarCollapsed = useLayoutStore((s) => s.setSidebarCollapsed)\n\n const setInvite = useAssistantInviteStore((s) => s.setInvite)\n\n // The screen IS the conversation: the canvas is what you point at while you\n // ask. What the colleague opens with has to be about the site — the generic\n // \"vamos deixar a loja pronta pra vender\" is the right pitch on the dashboard\n // and the wrong one in front of the site's own home page.\n React.useEffect(() => {\n openPanel('chat')\n openAssistantAs('setup')\n setInvite(\n {\n id: INVITE_ID,\n role: 'setup',\n persona: options?.labels?.assistantPersona ?? 'Site da loja',\n headline: options?.labels?.assistantHeadline ?? 'O que você quer mudar no site?',\n description:\n options?.labels?.assistantDescription\n ?? 'Peça a mudança em português — texto, cor, imagem, seção — e ela aparece aqui do lado.',\n placeholder: options?.labels?.assistantPlaceholder ?? 'Ex.: troque o banner da home',\n suggestions: options?.labels?.assistantSuggestions ?? [\n { label: 'Trocar a imagem principal da home' },\n { label: 'Mudar as cores da loja' },\n { label: 'Criar uma página de contato' },\n ],\n // Docked, never a hero: the hero would cover the canvas the invite is\n // about.\n auto: false,\n },\n INVITE_ID,\n )\n return () => setInvite(null, INVITE_ID)\n }, [openPanel, setInvite, options?.labels])\n\n // Entering the builder gives the canvas the desk. Only the collapse WE caused\n // is undone on the way out, so a menu the user closed by hand stays closed.\n const collapsedByUs = React.useRef(false)\n React.useEffect(() => {\n if (!useLayoutStore.getState().sidebarCollapsed) {\n collapsedByUs.current = true\n setSidebarCollapsed(true)\n }\n return () => {\n if (collapsedByUs.current) setSidebarCollapsed(false)\n }\n }, [setSidebarCollapsed])\n\n // ---------------------------------------------------------------------\n // Handing a change to the platform's agent\n //\n // Two assistants, one app. The colleague in this rail knows the merchant's\n // business and is looking at the canvas with them; only the platform's agent\n // can edit the source. So the rail's `builder_request_change` tool relays one\n // sentence over and reports back, instead of a second chat window on screen.\n //\n // An app can still pass its own `onRequestChange` — that wins, because an app\n // that wired its own build path meant to.\n // ---------------------------------------------------------------------\n const [building, setBuilding] = React.useState(false)\n\n const requestChange = React.useMemo(() => {\n if (options?.onRequestChange) return options.onRequestChange\n if (!isPlatformConnected()) return undefined\n return async ({ projectId, instruction }: { projectId: string; instruction: string }) => {\n await requestProjectChange(projectId, instruction)\n setBuilding(true)\n return 'Pedido enviado ao construtor. O site recarrega aqui quando a mudança terminar.'\n }\n }, [options?.onRequestChange])\n\n // Watch until the build goes quiet, then reload the canvas — the merchant\n // asked for a change and should see it, not be told to refresh. Reloading\n // WHILE it writes is what shows a half-written app, so the poll waits for a\n // terminal status rather than a timer.\n const projectId = target.projectId\n React.useEffect(() => {\n if (!building || !projectId) return\n let cancelled = false\n let timer: ReturnType<typeof setTimeout> | undefined\n\n const poll = async () => {\n if (cancelled) return\n try {\n const status = await getGenerationStatus(projectId)\n if (cancelled) return\n if (!status.building) {\n setBuilding(false)\n frame.reload()\n return\n }\n } catch {\n // A failed poll is not a finished build. Keep waiting; the only way out\n // is a terminal status or the user leaving the screen.\n }\n timer = setTimeout(poll, 5_000)\n }\n\n timer = setTimeout(poll, 5_000)\n return () => {\n cancelled = true\n if (timer) clearTimeout(timer)\n }\n }, [building, projectId, frame])\n\n useBuilderAgentSurface({\n target,\n currentPath: frame.currentPath,\n viewport,\n actions: { navigate: frame.navigate, reload: frame.reload, setViewport },\n onRequestChange: requestChange,\n })\n\n const [publishing, setPublishing] = React.useState(false)\n const publish = options?.onPublish\n const publishContract = React.useMemo(() => {\n if (!publish || !target.projectId) return undefined\n const projectId = target.projectId\n return {\n state: publishing ? ('publishing' as const) : ('idle' as const),\n publish: async () => {\n setPublishing(true)\n try {\n await publish({ projectId })\n } finally {\n setPublishing(false)\n }\n },\n }\n }, [publish, target.projectId, publishing])\n\n return (\n <AppBuilder\n target={target}\n frame={frame}\n viewport={viewport}\n onViewportChange={setViewport}\n publish={publishContract}\n chatContract={{ send: (message, context) => askAI({ prompt: message, hint: context?.selector }) }}\n onClose={() => adminNavigateTo('/')}\n onToggleChat={() => (railOpen ? closeRail() : openPanel('chat'))}\n onToggleWide={() => setSidebarCollapsed(!sidebarCollapsed)}\n empty={\n loading ? (\n <div className=\"h-full\" />\n ) : resolved ? (\n // A project resolved but has no address yet. Three different reasons —\n // the container is booting, it failed, or none is being attempted and\n // the site simply has not been published. `target.url` is null in all\n // of them, so only the host, which knows the container's phase, can\n // tell them apart.\n <BuilderPending\n labels={options?.labels}\n name={resolved.name}\n phase={preview.phase === 'starting' || preview.phase === 'failed' ? preview.phase : undefined}\n error={preview.error}\n onRetry={preview.retry}\n onAction={\n resolved.projectId\n ? () =>\n window.open(\n `https://fayz.ai/editor/${resolved.projectId}`,\n '_blank',\n 'noopener,noreferrer',\n )\n : undefined\n }\n />\n ) : (\n <BuilderEmpty labels={options?.labels} onAction={() => adminNavigateTo('/settings/sites')} />\n )\n }\n labels={options?.labels}\n />\n )\n}\n","import React from 'react'\nimport type { PluginManifest } from '@fayz-ai/core'\nimport { registerPluginFactory } from '@fayz-ai/core'\nimport { AdminAppBuilder } from './admin/AdminAppBuilder'\nimport type { AppBuilderPluginOptions } from './admin/options'\n\nexport type { AppBuilderPluginOptions } from './admin/options'\nexport { AdminAppBuilder } from './admin/AdminAppBuilder'\nexport { useAdminBuilderTarget } from './admin/target'\n\nconst EDIT = { feature: 'site', action: 'edit' as const }\n\n/**\n * The admin's mount of the builder surface. Everything host-specific — the\n * target, the rail, the agent — lives behind this door, so the surface itself\n * stays importable by an app that has none of it.\n */\nexport function createAppBuilderPlugin(options?: AppBuilderPluginOptions): PluginManifest {\n const route = options?.route ?? '/site'\n\n const PageComponent: React.ComponentType<unknown> = () =>\n React.createElement(AdminAppBuilder, { options })\n PageComponent.displayName = 'AdminAppBuilder'\n\n return {\n id: 'app_builder',\n name: options?.navLabel ?? 'Site',\n icon: 'PenSquare',\n version: '1.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n defaultAgentRole: 'setup',\n declaredFeatures: [{ id: 'site', label: 'Site', group: 'Convert' }],\n // No nav entry on purpose: the door is the \"Editar\" action on the site\n // widget in the sidebar footer (the app points site.editRoute here).\n navigation: [],\n routes: [\n {\n path: route,\n component: PageComponent,\n immersive: true,\n title: options?.navLabel ?? 'Site',\n permission: EDIT,\n },\n ],\n widgets: [],\n }\n}\n\nregisterPluginFactory('app_builder', createAppBuilderPlugin as (config?: Record<string, unknown>) => PluginManifest)\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -48,6 +48,17 @@ export interface BuilderLabels {
|
|
|
48
48
|
emptyTitle?: string;
|
|
49
49
|
emptyBody?: string;
|
|
50
50
|
emptyAction?: string;
|
|
51
|
+
/** Shown when a site IS linked but has never been published — see BuilderPending. */
|
|
52
|
+
pendingTitle?: string;
|
|
53
|
+
pendingBody?: string;
|
|
54
|
+
pendingAction?: string;
|
|
55
|
+
/** Shown while the preview container is coming up. */
|
|
56
|
+
previewStartingTitle?: string;
|
|
57
|
+
previewStartingBody?: string;
|
|
58
|
+
/** Shown when it will not come up on its own. */
|
|
59
|
+
previewFailedTitle?: string;
|
|
60
|
+
previewFailedBody?: string;
|
|
61
|
+
previewRetry?: string;
|
|
51
62
|
loadFailed?: string;
|
|
52
63
|
loadFailedHint?: string;
|
|
53
64
|
openInTab?: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"fayz": {
|
|
4
4
|
"status": "preview"
|
|
5
5
|
},
|
|
6
|
-
"version": "
|
|
6
|
+
"version": "3.0.0",
|
|
7
7
|
"description": "[experimental] Fayz SDK — the app-builder surface: window chrome, live canvas, publish and chat seams",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"sideEffects": false,
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"dist"
|
|
25
25
|
],
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@fayz-ai/admin": ">=0.
|
|
28
|
-
"@fayz-ai/core": ">=0.
|
|
27
|
+
"@fayz-ai/admin": ">=0.21.0",
|
|
28
|
+
"@fayz-ai/core": ">=0.21.0",
|
|
29
29
|
"lucide-react": ">=0.400.0 <1.0.0",
|
|
30
30
|
"react": "^18.0.0 || ^19.0.0",
|
|
31
31
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
32
|
-
"@fayz-ai/ui": ">=0.
|
|
32
|
+
"@fayz-ai/ui": ">=0.21.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependenciesMeta": {
|
|
35
35
|
"@fayz-ai/admin": {
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
"react": "^18.3.0",
|
|
50
50
|
"tsup": "^8.2.0",
|
|
51
51
|
"typescript": "^5.5.0",
|
|
52
|
-
"@fayz-ai/admin": "^0.
|
|
53
|
-
"@fayz-ai/core": "^0.
|
|
54
|
-
"@fayz-ai/ui": "^0.
|
|
52
|
+
"@fayz-ai/admin": "^0.21.0",
|
|
53
|
+
"@fayz-ai/core": "^0.21.0",
|
|
54
|
+
"@fayz-ai/ui": "^0.21.0"
|
|
55
55
|
},
|
|
56
56
|
"license": "MIT",
|
|
57
57
|
"keywords": [
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/PublishButton.tsx","../src/lib/pages.ts","../src/lib/cn.ts","../src/components/PagePicker.tsx","../src/components/BuilderChrome.tsx","../src/components/BuilderCanvas.tsx","../src/components/BuilderEmpty.tsx","../src/lib/bridge.ts","../src/lib/url.ts","../src/hooks/useBuilderFrame.ts","../src/components/AppBuilder.tsx"],"names":["React","jsxs","jsx","Check","React2","Loader2","React4"],"mappings":"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","file":"chunk-45SFS6FV.js","sourcesContent":["import * as React from 'react'\nimport { Loader2, Check } from 'lucide-react'\nimport type { BuilderLabels, BuilderPublishContract } from '../types'\n\n/** The same button in both hosts; only the transport behind `publish` differs.\n * No contract means the path is not wired up here, and it says so. */\nexport function PublishButton({\n publish,\n labels,\n}: {\n publish?: BuilderPublishContract\n labels?: BuilderLabels\n}) {\n const label = labels?.publish ?? 'Publicar'\n const state = publish?.state ?? 'idle'\n const busy = state === 'publishing'\n const disabled = !publish || busy\n\n return (\n <button\n type=\"button\"\n onClick={() => publish?.publish()}\n disabled={disabled}\n title={\n publish\n ? publish.error ?? label\n : labels?.publishUnavailable ?? 'Publicar ainda não está ligado neste ambiente'\n }\n className=\"flex h-9 items-center gap-1.5 rounded-full bg-primary px-4 text-sm font-medium text-primary-foreground shadow-sm transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {busy ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" /> : null}\n {state === 'published' && !busy ? <Check className=\"h-3.5 w-3.5\" /> : null}\n {label}\n </button>\n )\n}\n","/** A route the app announced, named the way a person would say it. */\nexport interface BuilderPage {\n route: string\n label: string\n}\n\nconst HOME_LABELS: Record<string, string> = { '/': 'Início' }\n\n/** \"#/produtos\" and \"/produtos\" are the same page said two ways — hash routing\n * is a routing style, not a different address space. */\nexport function normalizeRoute(route: string): string {\n const clean = route.split('?')[0].replace(/^#/, '')\n return clean.startsWith('/') ? clean : `/${clean}`\n}\n\nexport function isHomeRoute(route: string): boolean {\n return normalizeRoute(route) === '/'\n}\n\nconst KNOWN: Record<string, string> = {\n produtos: 'Produtos',\n products: 'Produtos',\n carrinho: 'Carrinho',\n cart: 'Carrinho',\n checkout: 'Checkout',\n contato: 'Contato',\n contact: 'Contato',\n sobre: 'Sobre',\n about: 'Sobre',\n blog: 'Blog',\n colecoes: 'Coleções',\n collections: 'Coleções',\n cardapio: 'Cardápio',\n conta: 'Conta',\n account: 'Conta',\n pedidos: 'Pedidos',\n catalog: 'Catálogo',\n catalogo: 'Catálogo',\n privacy: 'Privacidade',\n terms: 'Termos',\n refunds: 'Reembolsos',\n receitas: 'Receitas',\n product: 'Produtos',\n collection: 'Coleções',\n}\n\n/**\n * \"/produtos/:slug\" → \"Produtos ▸ :slug\". A path is what the app calls the page;\n * this is what the person calls it, which is the whole point of the picker.\n */\nexport function labelForRoute(route: string): string {\n const clean = normalizeRoute(route)\n if (HOME_LABELS[clean]) return HOME_LABELS[clean]\n\n const segments = clean.split('/').filter(Boolean)\n if (!segments.length) return HOME_LABELS['/']\n\n return segments\n .map((segment) => {\n const key = segment.toLowerCase()\n if (KNOWN[key]) return KNOWN[key]\n const words = segment.replace(/^:/, '').replace(/[-_]+/g, ' ')\n return words.charAt(0).toUpperCase() + words.slice(1)\n })\n .join(' › ')\n}\n\n/** A leaf, or a section with the pages under it. */\nexport interface BuilderPageGroup {\n key: string\n label: string\n route?: string\n children: BuilderPage[]\n}\n\nconst GROUP_FROM = 3\n\n/**\n * One level of grouping, and only where it earns its place: eleven product\n * pages listed flat bury the four pages someone actually navigates to. Below\n * {@link GROUP_FROM} siblings the folder costs a click and saves nothing.\n */\nexport function toPageGroups(routes: string[]): BuilderPageGroup[] {\n const bySegment = new Map<string, BuilderPage[]>()\n for (const route of routes) {\n const segment = normalizeRoute(route).split('/').filter(Boolean)[0] ?? ''\n const list = bySegment.get(segment) ?? []\n list.push({ route, label: labelForRoute(route) })\n bySegment.set(segment, list)\n }\n\n const groups: BuilderPageGroup[] = []\n for (const [segment, pages] of bySegment) {\n if (pages.length < GROUP_FROM || !segment) {\n groups.push(...pages.map((page) => ({ key: page.route, label: page.label, route: page.route, children: [] })))\n continue\n }\n groups.push({\n key: segment,\n label: labelForRoute(`/${segment}`),\n children: pages.map((page) => ({\n route: page.route,\n // Inside the folder the section name is the folder's, not each row's.\n label: page.label.split(' › ').slice(1).join(' › ') || page.label,\n })),\n })\n }\n // Home first, then alphabetical. A comparator that only says \"home wins\"\n // when home is one of the two arguments is not an order, and sort showed it.\n const rank = (g: BuilderPageGroup) => (g.route && isHomeRoute(g.route) ? 0 : 1)\n return groups.sort((a, b) => rank(a) - rank(b) || a.label.localeCompare(b.label))\n}\n\nexport function toPages(routes: string[]): BuilderPage[] {\n return routes.map((route) => ({ route, label: labelForRoute(route) }))\n}\n","/** The whole of clsx we need. Keeping it local is what keeps this package free\n * of a design-system dependency, so both hosts can mount the surface. */\nexport function cn(...parts: Array<string | false | null | undefined>): string {\n return parts.filter(Boolean).join(' ')\n}\n","import * as React from 'react'\nimport { ChevronsUpDown, Search, House, FileText, Folder, ChevronRight, ChevronLeft, Check } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { isHomeRoute, labelForRoute, normalizeRoute, toPageGroups, toPages } from '../lib/pages'\n\n/**\n * The address bar as the app's own table of contents: the page you are on, by\n * its name, and the pages you can go to. A raw URL is the app's word for the\n * page; this is the person's.\n *\n * With no routes announced it stays a plain label — a picker that opens on\n * nothing is worse than no picker.\n */\nexport function PagePicker({\n routes,\n currentPath,\n onNavigate,\n fallback,\n leading,\n searchLabel = 'Buscar página',\n emptyLabel = 'Nenhuma página com esse nome',\n}: {\n routes: string[]\n currentPath: string\n onNavigate: (route: string) => void\n /** Shown when the app has not announced any route. */\n fallback: string\n leading?: React.ReactNode\n searchLabel?: string\n emptyLabel?: string\n}) {\n const [open, setOpen] = React.useState(false)\n const [query, setQuery] = React.useState('')\n const boxRef = React.useRef<HTMLDivElement | null>(null)\n const inputRef = React.useRef<HTMLInputElement | null>(null)\n\n const [section, setSection] = React.useState<string | null>(null)\n\n const pages = React.useMemo(() => toPages(routes), [routes])\n const groups = React.useMemo(() => toPageGroups(routes), [routes])\n const openSection = React.useMemo(() => groups.find((g) => g.key === section) ?? null, [groups, section])\n\n // Search reaches every page, folders and all — a name is easier to type than\n // to remember which section it lives in.\n const matches = React.useMemo(() => {\n const q = query.trim().toLowerCase()\n if (q) return pages.filter((p) => p.label.toLowerCase().includes(q) || p.route.toLowerCase().includes(q))\n if (openSection) return openSection.children\n return null\n }, [pages, query, openSection])\n\n React.useEffect(() => {\n if (!open) return\n const onDown = (event: MouseEvent) => {\n if (!boxRef.current?.contains(event.target as Node)) setOpen(false)\n }\n const onKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') setOpen(false)\n }\n document.addEventListener('mousedown', onDown)\n document.addEventListener('keydown', onKey)\n inputRef.current?.focus()\n return () => {\n document.removeEventListener('mousedown', onDown)\n document.removeEventListener('keydown', onKey)\n }\n }, [open])\n\n const label = pages.length ? labelForRoute(currentPath) : fallback\n\n if (!pages.length) {\n return (\n <div className=\"flex h-9 min-w-0 flex-1 items-center gap-2 rounded-full bg-muted/60 px-2\">\n {leading}\n <span className=\"min-w-0 flex-1 truncate text-xs text-muted-foreground\">{label}</span>\n </div>\n )\n }\n\n return (\n <div ref={boxRef} className=\"relative flex h-9 min-w-0 flex-1 items-center gap-2 rounded-full bg-muted/60 px-2\">\n {leading}\n <button\n type=\"button\"\n onClick={() => {\n setQuery('')\n setSection(null)\n setOpen((v) => !v)\n }}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n className=\"flex min-w-0 flex-1 items-center gap-1.5 rounded-full py-1 text-left text-xs font-medium text-foreground\"\n >\n <span className=\"min-w-0 truncate\">{label}</span>\n <ChevronsUpDown className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n </button>\n\n {open ? (\n <div\n role=\"listbox\"\n className=\"absolute left-0 top-[calc(100%+6px)] z-50 w-[min(22rem,100%)] overflow-hidden rounded-xl border border-border bg-card shadow-lg\"\n >\n {openSection && !query ? (\n <button\n type=\"button\"\n onClick={() => setSection(null)}\n className=\"flex w-full items-center gap-2 border-b border-border px-3 py-2 text-sm font-medium text-foreground hover:bg-muted/60\"\n >\n <ChevronLeft className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n {openSection.label}\n </button>\n ) : null}\n\n <div className=\"flex items-center gap-2 border-b border-border px-3 py-2\">\n <Search className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <input\n ref={inputRef}\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n placeholder={searchLabel}\n aria-label={searchLabel}\n className=\"w-full bg-transparent text-sm text-foreground outline-none placeholder:text-muted-foreground\"\n />\n </div>\n\n <div className=\"max-h-72 overflow-y-auto p-1\">\n {!matches ? (\n groups.map((group) => {\n if (!group.route) {\n return (\n <button\n key={group.key}\n type=\"button\"\n onClick={() => setSection(group.key)}\n className=\"flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-sm text-foreground transition-colors hover:bg-muted/60\"\n >\n <Folder className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate\">{group.label}</span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">{group.children.length}</span>\n <ChevronRight className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n </button>\n )\n }\n const active = normalizeRoute(group.route) === normalizeRoute(currentPath)\n const Icon = isHomeRoute(group.route) ? House : FileText\n return (\n <button\n key={group.key}\n type=\"button\"\n role=\"option\"\n aria-selected={active}\n onClick={() => {\n onNavigate(group.route!)\n setOpen(false)\n }}\n className={cn(\n 'flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-sm transition-colors',\n active ? 'bg-muted font-medium text-foreground' : 'text-foreground hover:bg-muted/60',\n )}\n >\n <Icon className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate\">{group.label}</span>\n {active ? <Check className=\"h-4 w-4 shrink-0 text-muted-foreground\" /> : null}\n </button>\n )\n })\n ) : matches.length ? (\n matches.map((page) => {\n const active = normalizeRoute(page.route) === normalizeRoute(currentPath)\n const Icon = isHomeRoute(page.route) ? House : FileText\n return (\n <button\n key={page.route}\n type=\"button\"\n role=\"option\"\n aria-selected={active}\n onClick={() => {\n onNavigate(page.route)\n setOpen(false)\n }}\n className={cn(\n 'flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-sm transition-colors',\n active ? 'bg-muted font-medium text-foreground' : 'text-foreground hover:bg-muted/60',\n )}\n >\n <Icon className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate\">{page.label}</span>\n {active ? <Check className=\"h-4 w-4 shrink-0 text-muted-foreground\" /> : null}\n </button>\n )\n })\n ) : (\n <p className=\"px-2.5 py-6 text-center text-xs text-muted-foreground\">{emptyLabel}</p>\n )}\n </div>\n </div>\n ) : null}\n </div>\n )\n}\n","import * as React from 'react'\nimport { Monitor, Smartphone, RotateCw, ExternalLink, Code2, Eye } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { PublishButton } from './PublishButton'\nimport { PagePicker } from './PagePicker'\nimport type {\n BuilderLabels,\n BuilderMode,\n BuilderPublishContract,\n BuilderTarget,\n BuilderViewport,\n} from '../types'\n\nconst iconButton =\n 'flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-foreground/10 hover:text-foreground disabled:pointer-events-none disabled:opacity-40'\n\n/** Domain + path, the way a browser bar reads — the scheme is noise here. */\nfunction addressOf(url: string | null, path: string): string {\n if (!url) return path\n try {\n const parsed = new URL(url)\n const base = parsed.host + parsed.pathname.replace(/\\/+$/, '')\n return path === '/' ? base + '/' : base + path\n } catch {\n return path\n }\n}\n\n/**\n * macOS window buttons, and they do what those buttons do. A light with no\n * handler is not rendered dead — it is not rendered.\n */\nfunction TrafficLights({\n onClose,\n onToggleChat,\n onToggleWide,\n labels,\n}: {\n onClose?: () => void\n onToggleChat?: () => void\n onToggleWide?: () => void\n labels?: BuilderLabels\n}) {\n const lights = [\n { id: 'close', color: 'bg-[#ff5f57]', label: labels?.close ?? 'Sair', onClick: onClose },\n { id: 'minimize', color: 'bg-[#febc2e]', label: labels?.toggleChat ?? 'Recolher a conversa', onClick: onToggleChat },\n { id: 'zoom', color: 'bg-[#28c840]', label: labels?.toggleWide ?? 'Dar a tela toda ao app', onClick: onToggleWide },\n ].filter((light) => !!light.onClick)\n\n if (!lights.length) return null\n\n return (\n <div className=\"flex shrink-0 items-center gap-1.5 pl-1\">\n {lights.map((light) => (\n <button\n key={light.id}\n type=\"button\"\n title={light.label}\n aria-label={light.label}\n onClick={light.onClick}\n className=\"flex h-4 w-4 items-center justify-center rounded-full transition-transform hover:scale-125 active:scale-95\"\n >\n <span className={cn('h-3 w-3 rounded-full', light.color)} />\n </button>\n ))}\n </div>\n )\n}\n\n/**\n * One row, the shape of a browser: window buttons, then the address bar the\n * width of the page, then what you do to it. The page owns this bar — the\n * shell's own is gone on an immersive route — so there is exactly one.\n */\nexport function BuilderChrome({\n target,\n currentPath,\n routes,\n onNavigate,\n viewport,\n onViewportChange,\n onReload,\n mode,\n onModeChange,\n publish,\n onClose,\n onToggleChat,\n onToggleWide,\n chromeEnd,\n labels,\n}: {\n target: BuilderTarget\n currentPath: string\n routes: string[]\n onNavigate: (route: string) => void\n viewport: BuilderViewport\n onViewportChange: (viewport: BuilderViewport) => void\n onReload: () => void\n mode: BuilderMode\n onModeChange?: (mode: BuilderMode) => void\n publish?: BuilderPublishContract\n onClose?: () => void\n onToggleChat?: () => void\n onToggleWide?: () => void\n chromeEnd?: React.ReactNode\n labels?: BuilderLabels\n}) {\n const address = addressOf(target.url, currentPath)\n const openTarget = target.liveUrl ?? target.url\n // The icon states WHERE YOU ARE, the way a browser's does; the tooltip states\n // what a click does. Showing the next state instead made the control read as\n // a claim about the canvas that was never true.\n const Device = viewport === 'desktop' ? Monitor : Smartphone\n const deviceLabel = viewport === 'desktop' ? 'Ver no celular' : 'Ver no computador'\n\n return (\n // Same 56px as the companion column's header (RightRail), so the two read\n // as one window bar rather than two rows that nearly line up.\n <div className=\"flex h-14 shrink-0 items-center gap-2 border-b border-border px-3\">\n {/* No window buttons on a phone: the frame is a device, not a window, and\n the three dots would be spending the narrowest row's width saying so. */}\n {viewport === 'desktop' ? (\n <TrafficLights\n onClose={onClose}\n onToggleChat={onToggleChat}\n onToggleWide={onToggleWide}\n labels={labels}\n />\n ) : null}\n\n {onModeChange ? (\n <div className=\"ml-1 flex shrink-0 items-center gap-0.5 rounded-full bg-muted/60 p-0.5\">\n {([\n { id: 'preview' as const, icon: Eye, title: labels?.preview ?? 'Visual' },\n { id: 'code' as const, icon: Code2, title: labels?.code ?? 'Código' },\n ]).map(({ id, icon: Icon, title }) => (\n <button\n key={id}\n type=\"button\"\n title={title}\n aria-label={title}\n aria-pressed={mode === id}\n onClick={() => onModeChange(id)}\n className={cn(\n 'flex h-7 items-center gap-1.5 rounded-full px-2.5 text-xs font-medium transition-colors',\n mode === id ? 'bg-card text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {title}\n </button>\n ))}\n </div>\n ) : null}\n\n {/* The address bar IS the row: the device toggle lives at its left, the\n way a browser puts the shield or the lock there. */}\n <PagePicker\n routes={routes}\n currentPath={currentPath}\n onNavigate={onNavigate}\n fallback={address}\n searchLabel={labels?.searchPage}\n emptyLabel={labels?.noPage}\n leading={\n <button\n type=\"button\"\n title={deviceLabel}\n aria-label={deviceLabel}\n onClick={() => onViewportChange(viewport === 'desktop' ? 'mobile' : 'desktop')}\n className=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-foreground/10 hover:text-foreground\"\n >\n <Device className=\"h-4 w-4\" />\n </button>\n }\n />\n\n <button\n type=\"button\"\n title={labels?.viewLive ?? 'Abrir em uma aba'}\n aria-label={labels?.viewLive ?? 'Abrir em uma aba'}\n disabled={!openTarget}\n onClick={() => openTarget && window.open(openTarget, '_blank', 'noopener,noreferrer')}\n className={iconButton}\n >\n <ExternalLink className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n title={labels?.reload ?? 'Recarregar'}\n aria-label={labels?.reload ?? 'Recarregar'}\n onClick={onReload}\n className={iconButton}\n >\n <RotateCw className=\"h-4 w-4\" />\n </button>\n\n {chromeEnd}\n <PublishButton publish={publish} labels={labels} />\n </div>\n )\n}\n","import * as React from 'react'\nimport { Loader2, AlertTriangle } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport type { BuilderFrameController } from '../hooks/useBuilderFrame'\nimport type { BuilderLabels, BuilderTarget } from '../types'\n\n// The window around it is what narrows on mobile (see AppBuilder), so the frame\n// itself always fills whatever it was given.\nconst FRAME = 'h-full w-full'\n\nexport function BuilderCanvas({\n target,\n frame,\n labels,\n}: {\n target: BuilderTarget\n frame: BuilderFrameController\n labels?: BuilderLabels\n}) {\n // Dragging a divider anywhere in the host moves the pointer over the canvas,\n // and a cross-origin frame swallows every move event once it does.\n const [dragging, setDragging] = React.useState(false)\n React.useEffect(() => {\n const down = (event: PointerEvent) => {\n const el = event.target as HTMLElement | null\n if (el?.closest('[role=\"separator\"]')) setDragging(true)\n }\n const up = () => setDragging(false)\n window.addEventListener('pointerdown', down, true)\n window.addEventListener('pointerup', up, true)\n return () => {\n window.removeEventListener('pointerdown', down, true)\n window.removeEventListener('pointerup', up, true)\n }\n }, [])\n\n if (!frame.src) return null\n\n return (\n <div className=\"relative flex min-h-0 flex-1 justify-center overflow-hidden\">\n <iframe\n key={`${frame.src}#${frame.nonce}`}\n ref={frame.frameRef}\n src={frame.src}\n title={target.name}\n onLoad={frame.onLoad}\n className={cn('border-0 bg-white', FRAME, dragging && 'pointer-events-none')}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-modals\"\n />\n\n {frame.loading && !frame.failed && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <Loader2 className=\"h-5 w-5 animate-spin text-muted-foreground\" />\n </div>\n )}\n\n {frame.failed && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 bg-background/95 p-6 text-center\">\n <AlertTriangle className=\"h-6 w-6 text-muted-foreground\" />\n <p className=\"text-sm font-medium text-foreground\">\n {labels?.loadFailed ?? 'Não foi possível carregar o app aqui dentro.'}\n </p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">\n {labels?.loadFailedHint\n ?? 'O servidor pode estar bloqueando a exibição em outra página. Abra em uma nova aba enquanto isso.'}\n </p>\n <button\n type=\"button\"\n onClick={() => frame.src && window.open(frame.src, '_blank', 'noopener,noreferrer')}\n className=\"mt-1 rounded-full border border-border px-3 py-1.5 text-xs font-medium text-foreground hover:bg-muted\"\n >\n {labels?.openInTab ?? 'Abrir em nova aba'}\n </button>\n </div>\n )}\n </div>\n )\n}\n","import * as React from 'react'\nimport { Globe } from 'lucide-react'\nimport type { BuilderLabels } from '../types'\n\nexport function BuilderEmpty({ labels, onAction }: { labels?: BuilderLabels; onAction?: () => void }) {\n return (\n <div className=\"flex h-full flex-col items-center justify-center gap-3 p-8 text-center\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <Globe className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n <p className=\"text-sm font-medium text-foreground\">\n {labels?.emptyTitle ?? 'Nenhum app vinculado ainda'}\n </p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">\n {labels?.emptyBody ?? 'Vincule o projeto para editá-lo aqui, conversando com o assistente.'}\n </p>\n {onAction ? (\n <button\n type=\"button\"\n onClick={onAction}\n className=\"mt-1 rounded-full border border-border px-3 py-1.5 text-xs font-medium text-foreground hover:bg-muted\"\n >\n {labels?.emptyAction ?? 'Vincular em Configurações'}\n </button>\n ) : null}\n </div>\n )\n}\n","// Host side of the picker protocol both the storefront and the platform's\n// injected overlay already speak. v1 listens for navigation and drives the\n// frame; activate/picked are declared so the overlay lands without\n// renegotiating the channel.\nexport const BUILDER_MESSAGES = {\n activate: 'ACTIVATE_ELEMENT_PICKER',\n deactivate: 'DEACTIVATE_ELEMENT_PICKER',\n ready: 'ELEMENT_PICKER_READY',\n picked: 'ELEMENT_PICKED',\n cancelled: 'ELEMENT_PICKER_CANCELLED',\n navigation: 'NAVIGATION_CHANGE',\n} as const\n\nexport interface BuilderPickedBlock {\n path: string\n type: string\n rect?: { top: number; left: number; width: number; height: number }\n}\n\n/** The channel the platform's injected script already speaks (route-discovery.ts). */\nexport const ROUTES_SOURCE = 'fayz-routes'\nexport const ROUTES_PARENT_SOURCE = 'fayz-routes-parent'\n\nexport interface BuilderBridgeHandlers {\n onRoutes?: (routes: string[]) => void\n onNavigate?: (path: string) => void\n onReady?: () => void\n onPicked?: (block: BuilderPickedBlock) => void\n onCancelled?: () => void\n}\n\n/**\n * Listen to one frame. `origin` is derived from the canvas URL by us — a frame\n * that announces its own origin is a frame that can lie about it.\n */\nexport function connectBuilderBridge(\n frame: HTMLIFrameElement,\n origin: string,\n handlers: BuilderBridgeHandlers,\n): () => void {\n const win = typeof window === 'undefined' ? undefined : window\n if (!win) return () => {}\n\n const onMessage = (event: MessageEvent) => {\n if (event.origin !== origin) return\n if (event.source !== frame.contentWindow) return\n const data = event.data as\n | { source?: string; type?: string; path?: string; route?: string; routes?: string[]; data?: BuilderPickedBlock }\n | null\n\n if (data?.source === ROUTES_SOURCE) {\n if (data.type === 'ROUTES_DISCOVERED' && Array.isArray(data.routes)) handlers.onRoutes?.(data.routes)\n else if (data.type === 'ROUTE_CHANGED' && typeof data.route === 'string') handlers.onNavigate?.(data.route)\n return\n }\n\n switch (data?.type) {\n case BUILDER_MESSAGES.navigation:\n if (typeof data.path === 'string') handlers.onNavigate?.(data.path)\n break\n case BUILDER_MESSAGES.ready:\n handlers.onReady?.()\n break\n case BUILDER_MESSAGES.picked:\n if (data.data) handlers.onPicked?.(data.data)\n break\n case BUILDER_MESSAGES.cancelled:\n handlers.onCancelled?.()\n break\n }\n }\n\n win.addEventListener('message', onMessage)\n return () => win.removeEventListener('message', onMessage)\n}\n\n/** Ask the app to go somewhere. Same message its injected script listens for. */\nexport function navigateBuilder(\n frame: HTMLIFrameElement | null,\n origin: string | null,\n route: string,\n): void {\n postToBuilder(frame, origin, { source: ROUTES_PARENT_SOURCE, type: 'NAVIGATE', route })\n}\n\n/** Outbound always names the expected origin — never '*'. */\nexport function postToBuilder(\n frame: HTMLIFrameElement | null,\n origin: string | null,\n message: Record<string, unknown>,\n): void {\n if (!frame?.contentWindow || !origin) return\n frame.contentWindow.postMessage(message, origin)\n}\n","// Ported from the Fayz editor (apps/web/src/utils/previewUrlBuilder.ts): the one\n// part of its preview with real logic and no dependency. When the editor mounts\n// this surface it deletes its copy.\n\nexport function getBaseUrl(url: string): string {\n return url.split('?')[0].split('#')[0].replace(/\\/$/, '')\n}\n\nexport function getQueryString(url: string): string {\n const parts = url.split('?')\n return parts.length > 1 ? parts[1].split('#')[0] : ''\n}\n\n/** Point a preview URL at a route, keeping the query the container needs. */\nexport function buildIframeUrl(baseUrl: string, route: string): string {\n const cleanBase = getBaseUrl(baseUrl)\n const queryString = getQueryString(baseUrl)\n\n // Hash routing: the route IS the fragment, so it goes after the query.\n if (route.startsWith('#/')) {\n return `${cleanBase}${queryString ? '?' + queryString : ''}${route}`\n }\n\n // A route can carry its own anchor (\"/#pricing\"), which belongs last.\n const hashIndex = route.indexOf('#')\n const routePath = hashIndex === -1 ? route : route.substring(0, hashIndex)\n const hashFragment = hashIndex === -1 ? '' : route.substring(hashIndex)\n\n let result = `${cleanBase}${routePath === '/' ? '' : routePath}`\n if (queryString) result += `?${queryString}`\n if (hashFragment) result += hashFragment\n return result\n}\n\nexport function addCacheBuster(url: string, now: number = Date.now()): string {\n return `${url}${url.includes('?') ? '&' : '?'}_cb=${now}`\n}\n\nexport function extractRouteFromUrl(fullUrl: string, baseUrl: string): string {\n try {\n const full = new URL(fullUrl)\n const base = new URL(baseUrl)\n if (full.host !== base.host) return '/'\n\n let pathname = full.pathname\n if (base.pathname !== '/' && pathname.startsWith(base.pathname)) {\n pathname = pathname.slice(base.pathname.length)\n }\n if (!pathname.startsWith('/')) pathname = '/' + pathname\n return pathname || '/'\n } catch {\n return '/'\n }\n}\n\nexport function isValidPreviewUrl(url: string | null | undefined): boolean {\n if (!url) return false\n try {\n const parsed = new URL(url)\n return parsed.protocol === 'http:' || parsed.protocol === 'https:'\n } catch {\n return false\n }\n}\n\nexport function getUrlOrigin(url: string): string | null {\n try {\n return new URL(url).origin\n } catch {\n return null\n }\n}\n","import * as React from 'react'\nimport { connectBuilderBridge, navigateBuilder } from '../lib/bridge'\nimport { buildIframeUrl, getUrlOrigin } from '../lib/url'\nimport type { BuilderElementContext } from '../types'\n\nexport interface BuilderFrameController {\n frameRef: React.MutableRefObject<HTMLIFrameElement | null>\n /** Remount key — the only reliable way to reload a cross-origin document. */\n nonce: number\n src: string | null\n origin: string | null\n loading: boolean\n failed: boolean\n currentPath: string\n /** Routes the app announced through its own discovery script. */\n routes: string[]\n onLoad: () => void\n reload: () => void\n navigate: (path: string) => void\n}\n\n/** A cross-origin frame that never loads never errors either, so time is the signal. */\nconst LOAD_TIMEOUT_MS = 8000\n\nexport function useBuilderFrame(\n url: string | null,\n handlers?: { onNavigate?: (path: string) => void; onPick?: (context: BuilderElementContext) => void },\n): BuilderFrameController {\n const frameRef = React.useRef<HTMLIFrameElement | null>(null)\n const [nonce, setNonce] = React.useState(0)\n const [loading, setLoading] = React.useState(true)\n const [failed, setFailed] = React.useState(false)\n const [currentPath, setCurrentPath] = React.useState('/')\n const [routes, setRoutes] = React.useState<string[]>([])\n\n const origin = React.useMemo(() => (url ? getUrlOrigin(url) : null), [url])\n // The initial document only. Intra-app navigation happens inside the frame,\n // so following currentPath here would reload the page on every click.\n const src = React.useMemo(() => (url ? buildIframeUrl(url, '/') : null), [url])\n\n const cb = React.useRef(handlers)\n cb.current = handlers\n\n React.useEffect(() => {\n setLoading(true)\n setFailed(false)\n }, [src, nonce])\n\n React.useEffect(() => {\n if (!loading) return\n const timer = setTimeout(() => setFailed(true), LOAD_TIMEOUT_MS)\n return () => clearTimeout(timer)\n }, [loading, src, nonce])\n\n React.useEffect(() => {\n const frame = frameRef.current\n if (!frame || !origin) return\n return connectBuilderBridge(frame, origin, {\n onRoutes: setRoutes,\n onNavigate: (path) => {\n setCurrentPath(path)\n cb.current?.onNavigate?.(path)\n },\n onPicked: (block) => cb.current?.onPick?.({ selector: block.path, tagName: block.type }),\n })\n }, [origin, nonce])\n\n const reload = React.useCallback(() => setNonce((n) => n + 1), [])\n\n // The app moves itself; we only ask. Rebuilding the src would reload the\n // whole thing and lose whatever state the page was in.\n const navigate = React.useCallback(\n (path: string) => {\n setCurrentPath(path)\n navigateBuilder(frameRef.current, origin, path)\n },\n [origin],\n )\n\n const onLoad = React.useCallback(() => {\n setLoading(false)\n setFailed(false)\n }, [])\n\n return { frameRef, nonce, src, origin, loading, failed, currentPath, routes, onLoad, reload, navigate }\n}\n","import * as React from 'react'\nimport { cn } from '../lib/cn'\nimport { BuilderChrome } from './BuilderChrome'\nimport { BuilderCanvas } from './BuilderCanvas'\nimport { BuilderEmpty } from './BuilderEmpty'\nimport { useBuilderFrame } from '../hooks/useBuilderFrame'\nimport type { AppBuilderProps, BuilderElementContext, BuilderViewport } from '../types'\n\n/**\n * The app-builder surface: a window bar, the app running inside it, and the\n * seams for the three things every builder also needs — seeing the code,\n * publishing, and talking to whoever is doing the work.\n *\n * It draws its OWN bar instead of portalling into a host's header. That is what\n * lets the same component sit in the Fayz editor and in an admin shell.\n */\nexport function AppBuilder({\n target,\n mode = 'preview',\n onModeChange,\n code,\n chat,\n publish,\n onClose,\n onToggleChat,\n onToggleWide,\n onNavigate,\n onPick,\n viewport: viewportProp,\n onViewportChange,\n empty,\n labels,\n slots,\n className,\n frame: frameProp,\n}: AppBuilderProps) {\n // `chatContract` is declared on the props and deliberately not read yet: the\n // only sender is the element picker, which is the next milestone. Taking it\n // out of the contract now would make that milestone an API change.\n const [internalViewport, setInternalViewport] = React.useState<BuilderViewport>('desktop')\n const viewport = viewportProp ?? internalViewport\n const setViewport = onViewportChange ?? setInternalViewport\n\n // A pick is only worth reporting when something can act on it: the host's\n // callback, or the conversation the host mounted.\n // A pick goes wherever the host says. There is no picker UI yet — the wire is\n // live so the overlay lands without renegotiating who a pick belongs to.\n const handlePick = React.useCallback(\n (context: BuilderElementContext) => onPick?.(context),\n [onPick],\n )\n\n // The host may own the controller (it needs the handle to drive the canvas\n // from an agent tool or a button); otherwise the surface owns one. Passing a\n // null url to the unused one keeps it from running timers for nothing.\n const ownFrame = useBuilderFrame(frameProp ? null : target.url, { onNavigate, onPick: handlePick })\n const frame = frameProp ?? ownFrame\n\n const body = !target.url ? (\n (empty ?? <BuilderEmpty labels={labels} />)\n ) : mode === 'code' && code ? (\n <div className=\"min-h-0 flex-1 overflow-hidden\">{code}</div>\n ) : (\n <BuilderCanvas target={target} frame={frame} labels={labels} />\n )\n\n // Mobile narrows the WHOLE window, chrome and all — a desktop-width toolbar\n // over a phone-width page is a claim about a device nobody is holding.\n const mobile = viewport === 'mobile' && !!target.url\n\n return (\n <div className={cn('flex h-full min-h-0 overflow-hidden', className)}>\n <div className={cn('flex min-w-0 flex-1 flex-col overflow-hidden', mobile && 'items-center bg-muted/30 py-3')}>\n <div\n className={cn(\n 'flex min-h-0 w-full flex-1 flex-col overflow-hidden',\n mobile && 'max-w-[420px] rounded-2xl border border-border bg-card shadow-xl',\n )}\n >\n <BuilderChrome\n target={target}\n currentPath={frame.currentPath}\n routes={frame.routes}\n onNavigate={frame.navigate}\n viewport={viewport}\n onViewportChange={setViewport}\n onReload={frame.reload}\n mode={mode}\n onModeChange={code ? onModeChange : undefined}\n publish={publish}\n onClose={onClose}\n onToggleChat={onToggleChat}\n onToggleWide={onToggleWide}\n chromeEnd={slots?.chromeEnd}\n labels={labels}\n />\n {body}\n </div>\n {slots?.belowCanvas}\n </div>\n\n {chat ? (\n <div className=\"hidden w-[min(28rem,32%)] shrink-0 border-l border-border md:flex md:flex-col md:overflow-hidden\">\n {chat}\n </div>\n ) : null}\n </div>\n )\n}\n"]}
|