@truefoundry/trueforge-ui 0.2.4 → 0.3.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +85 -0
- package/README.md +55 -23
- package/dist/AgentCodeSnippets-NZOFJE57.js +74 -0
- package/dist/AgentCodeSnippets-NZOFJE57.js.map +1 -0
- package/dist/AgentMetricChart-JPU3MFQ2.js +15 -0
- package/dist/AgentOverview-EEBHJC32.js +167 -0
- package/dist/AgentOverview-EEBHJC32.js.map +1 -0
- package/dist/AgentSessionEventTimeline-26Z6IB3B.js +79 -0
- package/dist/AgentSessionEventTimeline-26Z6IB3B.js.map +1 -0
- package/dist/AgentSessionEventTimelineChart-CGCU7WBK.js +504 -0
- package/dist/AgentSessionEventTimelineChart-CGCU7WBK.js.map +1 -0
- package/dist/AgentSessions-3MPDZASK.js +275 -0
- package/dist/AgentSessions-3MPDZASK.js.map +1 -0
- package/dist/{ConnectorSettings-ODC3LVHN.js → ConnectorSettings-MXFRWWR6.js} +8 -6
- package/dist/{ConnectorSettings-ODC3LVHN.js.map → ConnectorSettings-MXFRWWR6.js.map} +1 -1
- package/dist/{DockLayout-TEOWEMSV.js → DockLayout-LM4AFMFY.js} +12 -11
- package/dist/{DockLayout-TEOWEMSV.js.map → DockLayout-LM4AFMFY.js.map} +1 -1
- package/dist/DrawerLayout-JR3O6RRB.js +184 -0
- package/dist/DrawerLayout-JR3O6RRB.js.map +1 -0
- package/dist/{ModelSettings-CKQ5CVAC.js → ModelSettings-G7IFNC2Y.js} +8 -6
- package/dist/{ModelSettings-CKQ5CVAC.js.map → ModelSettings-G7IFNC2Y.js.map} +1 -1
- package/dist/OpenUiFenceBlock-2TV5TQ6P.js +9 -0
- package/dist/OpenUiFenceBlock-2TV5TQ6P.js.map +1 -0
- package/dist/{SandboxSettings-HSCPYUOC.js → SandboxSettings-NXAANMAX.js} +8 -6
- package/dist/{SandboxSettings-HSCPYUOC.js.map → SandboxSettings-NXAANMAX.js.map} +1 -1
- package/dist/SchedulesPage-KKLUDO6B.js +15 -0
- package/dist/SchedulesPage-KKLUDO6B.js.map +1 -0
- package/dist/{SettingsBuilder-MYWRFXRI.js → SettingsBuilder-L34IQ56S.js} +26 -22
- package/dist/SettingsBuilder-L34IQ56S.js.map +1 -0
- package/dist/{ShellRouteSync-T4WLY57Q.js → ShellRouteSync-CEBETGEJ.js} +95 -22
- package/dist/ShellRouteSync-CEBETGEJ.js.map +1 -0
- package/dist/SidebarLayout-A2HJPPHS.js +308 -0
- package/dist/SidebarLayout-A2HJPPHS.js.map +1 -0
- package/dist/{SkillSettings-ECH6SHZ7.js → SkillSettings-FGGMSUNO.js} +8 -6
- package/dist/{SkillSettings-ECH6SHZ7.js.map → SkillSettings-FGGMSUNO.js.map} +1 -1
- package/dist/{TrueForgeUIWithRouter-KMHPOKLN.js → TrueForgeUIWithRouter-MZVJWJMB.js} +15 -11
- package/dist/{TrueForgeUIWithRouter-KMHPOKLN.js.map → TrueForgeUIWithRouter-MZVJWJMB.js.map} +1 -1
- package/dist/{WidgetLayout-4ZIG3RXV.js → WidgetLayout-6QM45OQQ.js} +19 -15
- package/dist/WidgetLayout-6QM45OQQ.js.map +1 -0
- package/dist/chunk-2XPPBEYF.js +74 -0
- package/dist/chunk-2XPPBEYF.js.map +1 -0
- package/dist/chunk-6O6FWUDW.js +1376 -0
- package/dist/chunk-6O6FWUDW.js.map +1 -0
- package/dist/chunk-7Z2C2K7F.js +578 -0
- package/dist/chunk-7Z2C2K7F.js.map +1 -0
- package/dist/{chunk-FXCYLEFB.js → chunk-BSIPI3KV.js} +18 -2
- package/dist/chunk-BSIPI3KV.js.map +1 -0
- package/dist/{chunk-255AE5NI.js → chunk-CYHJDKFB.js} +118 -33
- package/dist/chunk-CYHJDKFB.js.map +1 -0
- package/dist/chunk-DJUFS2BW.js +27 -0
- package/dist/chunk-DJUFS2BW.js.map +1 -0
- package/dist/chunk-DMMZSZTN.js +252 -0
- package/dist/chunk-DMMZSZTN.js.map +1 -0
- package/dist/chunk-FJW36PD7.js +180 -0
- package/dist/chunk-FJW36PD7.js.map +1 -0
- package/dist/chunk-M62XY4NC.js +555 -0
- package/dist/chunk-M62XY4NC.js.map +1 -0
- package/dist/{chunk-JRRCAKEP.js → chunk-MPNSO7E6.js} +2 -2
- package/dist/{chunk-CFLVPV5M.js → chunk-QC42MLAK.js} +7 -2
- package/dist/chunk-QC42MLAK.js.map +1 -0
- package/dist/chunk-RDXBMTP5.js +32 -0
- package/dist/chunk-RDXBMTP5.js.map +1 -0
- package/dist/chunk-SFZNIO6U.js +18 -0
- package/dist/chunk-SFZNIO6U.js.map +1 -0
- package/dist/chunk-U7KURWW3.js +840 -0
- package/dist/chunk-U7KURWW3.js.map +1 -0
- package/dist/chunk-WVE3F724.js +200 -0
- package/dist/chunk-WVE3F724.js.map +1 -0
- package/dist/{chunk-IFLE7OMM.js → chunk-XAU7QFG3.js} +180 -38
- package/dist/chunk-XAU7QFG3.js.map +1 -0
- package/dist/chunk-Y6S4OVVQ.js +16 -0
- package/dist/chunk-Y6S4OVVQ.js.map +1 -0
- package/dist/chunk-ZKNUMH2M.js +119 -0
- package/dist/chunk-ZKNUMH2M.js.map +1 -0
- package/dist/chunk-ZTMKFZQ3.js +13214 -0
- package/dist/chunk-ZTMKFZQ3.js.map +1 -0
- package/dist/{createTrueFoundryServer-B72bU-J7.d.ts → createTrueFoundryServer-CmZnBh_l.d.ts} +15 -4
- package/dist/index.d.ts +1199 -161
- package/dist/index.js +699 -69
- package/dist/index.js.map +1 -1
- package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +552 -12
- package/dist/plugins/trueforge-agent-server-adapter/index.js +506 -188
- package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +11 -10
- package/dist/DrawerLayout-2JOQ4EDZ.js +0 -159
- package/dist/DrawerLayout-2JOQ4EDZ.js.map +0 -1
- package/dist/OpenUiFenceBlock-3EFPY4JW.js +0 -9
- package/dist/SettingsBuilder-MYWRFXRI.js.map +0 -1
- package/dist/ShellRouteSync-T4WLY57Q.js.map +0 -1
- package/dist/SidebarLayout-6MHQYW45.js +0 -239
- package/dist/SidebarLayout-6MHQYW45.js.map +0 -1
- package/dist/WidgetLayout-4ZIG3RXV.js.map +0 -1
- package/dist/chunk-255AE5NI.js.map +0 -1
- package/dist/chunk-72LC2M3R.js +0 -567
- package/dist/chunk-72LC2M3R.js.map +0 -1
- package/dist/chunk-CFLVPV5M.js.map +0 -1
- package/dist/chunk-FXCYLEFB.js.map +0 -1
- package/dist/chunk-IFLE7OMM.js.map +0 -1
- package/dist/chunk-IWPDSPVA.js +0 -2068
- package/dist/chunk-IWPDSPVA.js.map +0 -1
- package/dist/chunk-OZTNBS6V.js +0 -75
- package/dist/chunk-OZTNBS6V.js.map +0 -1
- package/dist/chunk-PUFYHFND.js +0 -91
- package/dist/chunk-PUFYHFND.js.map +0 -1
- package/dist/chunk-WQULF5AT.js +0 -460
- package/dist/chunk-WQULF5AT.js.map +0 -1
- package/dist/chunk-XRTTKGKN.js +0 -6825
- package/dist/chunk-XRTTKGKN.js.map +0 -1
- package/dist/chunk-YIWUG6MC.js +0 -101
- package/dist/chunk-YIWUG6MC.js.map +0 -1
- /package/dist/{OpenUiFenceBlock-3EFPY4JW.js.map → AgentMetricChart-JPU3MFQ2.js.map} +0 -0
- /package/dist/{chunk-JRRCAKEP.js.map → chunk-MPNSO7E6.js.map} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truefoundry/trueforge-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-rc.1",
|
|
4
4
|
"description": "TrueForge Agent Chat UI (atoms + containers) built on assistant-ui, with owned theming, presets, and swappable slots.",
|
|
5
5
|
"author": "TrueFoundry",
|
|
6
6
|
"license": "MIT",
|
|
@@ -75,24 +75,27 @@
|
|
|
75
75
|
}
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@assistant-ui/core": "
|
|
79
|
-
"@assistant-ui/react": "
|
|
78
|
+
"@assistant-ui/core": "0.2.22",
|
|
79
|
+
"@assistant-ui/react": "0.14.27",
|
|
80
80
|
"@openuidev/react-headless": "^0.9.4",
|
|
81
81
|
"@openuidev/react-lang": "^0.2.9",
|
|
82
82
|
"@openuidev/react-ui": "^0.13.2",
|
|
83
|
-
"@truefoundry/assistant-ui-runtime": "0.1.
|
|
83
|
+
"@truefoundry/assistant-ui-runtime": "0.1.27",
|
|
84
|
+
"chart.js": "^4.5.1",
|
|
84
85
|
"clsx": "^2.1.1",
|
|
85
86
|
"lucide-react": "^0.562.0",
|
|
86
87
|
"monaco-editor": "^0.56.0",
|
|
87
88
|
"partial-json": "^0.1.7",
|
|
89
|
+
"react-chartjs-2": "^5.3.1",
|
|
88
90
|
"react-markdown": "^10.1.0",
|
|
91
|
+
"react-resizable-panels": "^4.12.3",
|
|
89
92
|
"react-router-dom": "^6 || ^7",
|
|
90
93
|
"react-syntax-highlighter": "^16.1.1",
|
|
91
94
|
"remark-gfm": "^4.0.1",
|
|
92
95
|
"tailwind-merge": "^3.6.0",
|
|
93
|
-
"truefoundry-gateway-sdk": "^0.4.
|
|
96
|
+
"truefoundry-gateway-sdk": "^0.4.2",
|
|
94
97
|
"zod": "^4.4.3",
|
|
95
|
-
"@truefoundry/trueforge-sdk": "0.1.
|
|
98
|
+
"@truefoundry/trueforge-sdk": "0.1.4-rc.1"
|
|
96
99
|
},
|
|
97
100
|
"devDependencies": {
|
|
98
101
|
"@eslint/js": "^9.39.0",
|
|
@@ -121,18 +124,16 @@
|
|
|
121
124
|
"vitest": "^4.1.9"
|
|
122
125
|
},
|
|
123
126
|
"scripts": {
|
|
124
|
-
"
|
|
125
|
-
"prebuild": "pnpm run sdk:build",
|
|
127
|
+
"prebuild": "pnpm -w run sdk:types",
|
|
126
128
|
"build": "rm -rf dist && tailwindcss --input src/build-styles.css --output dist/styles.css --minify && tsup",
|
|
127
129
|
"dev:watch": "pnpm run \"/^(dev:watch:js|dev:watch:css)$/\"",
|
|
128
130
|
"dev:watch:js": "tsup --watch",
|
|
129
131
|
"dev:watch:css": "tailwindcss --input src/build-styles.css --output dist/styles.css --watch",
|
|
130
132
|
"pack:tgz": "pnpm build && pnpm pack",
|
|
131
|
-
"pretest": "pnpm run sdk:build",
|
|
132
133
|
"test": "vitest run && pnpm test:package",
|
|
133
134
|
"test:package": "pnpm build && node test/packageExports.smoke.mjs",
|
|
134
135
|
"test:coverage": "vitest run --coverage",
|
|
135
|
-
"pretypecheck": "pnpm run sdk:
|
|
136
|
+
"pretypecheck": "pnpm -w run sdk:types",
|
|
136
137
|
"typecheck": "tsc --noEmit && tsc --noEmit -p test/tsconfig.json",
|
|
137
138
|
"lint": "eslint src test --ext .ts,.tsx",
|
|
138
139
|
"format": "prettier --write \"src/**/*.{ts,tsx,css,md}\" \"test/**/*.{ts,tsx}\" \"*.md\" \"docs/**/*.md\" --config ../../.prettierrc"
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import {
|
|
3
|
-
NamedAgentHeaderLabel,
|
|
4
|
-
ShellActions
|
|
5
|
-
} from "./chunk-OZTNBS6V.js";
|
|
6
|
-
import {
|
|
7
|
-
Thread,
|
|
8
|
-
ThreadListContainer
|
|
9
|
-
} from "./chunk-IWPDSPVA.js";
|
|
10
|
-
import "./chunk-FXCYLEFB.js";
|
|
11
|
-
import {
|
|
12
|
-
useAui
|
|
13
|
-
} from "./chunk-M6MHLVSO.js";
|
|
14
|
-
import {
|
|
15
|
-
useSlot
|
|
16
|
-
} from "./chunk-XRTTKGKN.js";
|
|
17
|
-
import {
|
|
18
|
-
Icon,
|
|
19
|
-
Spinner,
|
|
20
|
-
auiButtonClass
|
|
21
|
-
} from "./chunk-IFLE7OMM.js";
|
|
22
|
-
import {
|
|
23
|
-
useOptionalShellMode
|
|
24
|
-
} from "./chunk-WQULF5AT.js";
|
|
25
|
-
import "./chunk-JRRCAKEP.js";
|
|
26
|
-
import {
|
|
27
|
-
cn
|
|
28
|
-
} from "./chunk-72LC2M3R.js";
|
|
29
|
-
|
|
30
|
-
// src/layouts/DrawerLayout.tsx
|
|
31
|
-
import { lazy, Suspense, useEffect, useRef, useState } from "react";
|
|
32
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
33
|
-
var TruefoundrySettingsBuilder = lazy(() => import("./SettingsBuilder-MYWRFXRI.js"));
|
|
34
|
-
function DrawerLayout({ className }) {
|
|
35
|
-
const aui = useAui();
|
|
36
|
-
const shell = useOptionalShellMode();
|
|
37
|
-
const ClearChatButton = useSlot("ClearChatButton");
|
|
38
|
-
const SaveAgentButton = useSlot("SaveAgentButton");
|
|
39
|
-
const SelectAgentEmptyState = useSlot("SelectAgentEmptyState");
|
|
40
|
-
const [threadsOpen, setThreadsOpen] = useState(false);
|
|
41
|
-
const threadsBtnRef = useRef(null);
|
|
42
|
-
const dialogRef = useRef(null);
|
|
43
|
-
const mainRef = useRef(null);
|
|
44
|
-
const wasOpen = useRef(false);
|
|
45
|
-
const isIdle = shell?.mode.status === "idle";
|
|
46
|
-
const settingsOpen = shell?.settingsOpen === true;
|
|
47
|
-
useEffect(() => {
|
|
48
|
-
if (!threadsOpen) return;
|
|
49
|
-
const onKeyDown = (event) => {
|
|
50
|
-
if (event.key === "Escape") setThreadsOpen(false);
|
|
51
|
-
};
|
|
52
|
-
window.addEventListener("keydown", onKeyDown);
|
|
53
|
-
return () => window.removeEventListener("keydown", onKeyDown);
|
|
54
|
-
}, [threadsOpen]);
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
const main = mainRef.current;
|
|
57
|
-
if (threadsOpen) {
|
|
58
|
-
wasOpen.current = true;
|
|
59
|
-
if (main) main.inert = true;
|
|
60
|
-
dialogRef.current?.focus();
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
if (wasOpen.current) {
|
|
64
|
-
if (main) main.inert = false;
|
|
65
|
-
threadsBtnRef.current?.focus();
|
|
66
|
-
wasOpen.current = false;
|
|
67
|
-
}
|
|
68
|
-
}, [threadsOpen]);
|
|
69
|
-
const handleNewChat = () => {
|
|
70
|
-
if (shell?.isComposerEnabled) {
|
|
71
|
-
shell.openDraft();
|
|
72
|
-
} else {
|
|
73
|
-
shell?.setSettingsOpen(false);
|
|
74
|
-
aui.threads().switchToNewThread();
|
|
75
|
-
}
|
|
76
|
-
setThreadsOpen(false);
|
|
77
|
-
};
|
|
78
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("relative flex h-full min-h-0 w-full flex-col bg-primary-bg", className), children: [
|
|
79
|
-
/* @__PURE__ */ jsxs("header", { className: "flex shrink-0 items-center gap-1 border-b border-border bg-topbar-bg px-2 py-1.5", children: [
|
|
80
|
-
!settingsOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
81
|
-
/* @__PURE__ */ jsx(NamedAgentHeaderLabel, {}),
|
|
82
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
|
|
83
|
-
/* @__PURE__ */ jsx(ClearChatButton, {}),
|
|
84
|
-
/* @__PURE__ */ jsx(SaveAgentButton, {})
|
|
85
|
-
] }) : /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
|
|
86
|
-
/* @__PURE__ */ jsx(ShellActions, {}, "shell-actions"),
|
|
87
|
-
!settingsOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
88
|
-
shell?.isNewChatEnabled !== false ? /* @__PURE__ */ jsx(
|
|
89
|
-
"button",
|
|
90
|
-
{
|
|
91
|
-
type: "button",
|
|
92
|
-
"aria-label": "New chat",
|
|
93
|
-
title: "New chat",
|
|
94
|
-
className: auiButtonClass({ variant: "ghost", size: "icon" }),
|
|
95
|
-
onClick: handleNewChat,
|
|
96
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "plus" })
|
|
97
|
-
}
|
|
98
|
-
) : null,
|
|
99
|
-
/* @__PURE__ */ jsx(
|
|
100
|
-
"button",
|
|
101
|
-
{
|
|
102
|
-
ref: threadsBtnRef,
|
|
103
|
-
type: "button",
|
|
104
|
-
"aria-label": "Sessions",
|
|
105
|
-
"aria-expanded": threadsOpen,
|
|
106
|
-
className: "text-text-secondary hover:text-text-primary inline-flex size-8 cursor-pointer items-center justify-center rounded-md",
|
|
107
|
-
onClick: () => setThreadsOpen((v) => !v),
|
|
108
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "clock-rotate-left" })
|
|
109
|
-
}
|
|
110
|
-
)
|
|
111
|
-
] }) : null
|
|
112
|
-
] }),
|
|
113
|
-
/* @__PURE__ */ jsx("div", { ref: mainRef, className: "min-h-0 min-w-0 flex-1", children: settingsOpen ? /* @__PURE__ */ jsx(
|
|
114
|
-
Suspense,
|
|
115
|
-
{
|
|
116
|
-
fallback: /* @__PURE__ */ jsxs(
|
|
117
|
-
"div",
|
|
118
|
-
{
|
|
119
|
-
className: "flex h-full items-center justify-center",
|
|
120
|
-
role: "status",
|
|
121
|
-
"aria-live": "polite",
|
|
122
|
-
"aria-busy": "true",
|
|
123
|
-
children: [
|
|
124
|
-
/* @__PURE__ */ jsx(Spinner, { size: 28, className: "text-text-primary" }),
|
|
125
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
126
|
-
]
|
|
127
|
-
}
|
|
128
|
-
),
|
|
129
|
-
children: /* @__PURE__ */ jsx(TruefoundrySettingsBuilder, {})
|
|
130
|
-
}
|
|
131
|
-
) : isIdle ? /* @__PURE__ */ jsx(SelectAgentEmptyState, {}) : /* @__PURE__ */ jsx(Thread, {}) }),
|
|
132
|
-
threadsOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
133
|
-
/* @__PURE__ */ jsx(
|
|
134
|
-
"button",
|
|
135
|
-
{
|
|
136
|
-
type: "button",
|
|
137
|
-
"aria-label": "Close sessions",
|
|
138
|
-
className: "absolute inset-0 z-[9] cursor-pointer bg-[var(--overlay)]",
|
|
139
|
-
onClick: () => setThreadsOpen(false)
|
|
140
|
-
}
|
|
141
|
-
),
|
|
142
|
-
/* @__PURE__ */ jsx(
|
|
143
|
-
"div",
|
|
144
|
-
{
|
|
145
|
-
ref: dialogRef,
|
|
146
|
-
className: "absolute inset-y-0 right-0 z-10 flex w-full max-w-80 flex-col border-l border-border bg-sidebar-bg shadow-lg outline-none",
|
|
147
|
-
role: "dialog",
|
|
148
|
-
"aria-label": "Sessions",
|
|
149
|
-
tabIndex: -1,
|
|
150
|
-
children: /* @__PURE__ */ jsx(ThreadListContainer, { onThreadOpen: () => setThreadsOpen(false) })
|
|
151
|
-
}
|
|
152
|
-
)
|
|
153
|
-
] }) : null
|
|
154
|
-
] });
|
|
155
|
-
}
|
|
156
|
-
export {
|
|
157
|
-
DrawerLayout
|
|
158
|
-
};
|
|
159
|
-
//# sourceMappingURL=DrawerLayout-2JOQ4EDZ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/layouts/DrawerLayout.tsx"],"sourcesContent":["'use client';\n\nimport { lazy, Suspense, useEffect, useRef, useState } from 'react';\n\nimport { useAui } from '../assistant-ui.js';\nimport { NamedAgentHeaderLabel } from '../atoms/NamedAgentHeaderLabel.js';\nimport { ShellActions } from '../atoms/ShellActions.js';\nimport { auiButtonClass } from '../atoms/lib/buttonClasses.js';\nimport { cn } from '../atoms/lib/cn.js';\nimport { Spinner } from '../atoms/primitives/Spinner.js';\nimport { Thread } from '../containers/Thread.js';\nimport { ThreadListContainer } from '../containers/ThreadListContainer.js';\nimport { Icon } from '../icons/Icon.js';\nimport { useOptionalShellMode } from '../server/ShellModeContext.js';\nimport { useSlot } from '../theme/SlotsProvider.js';\n\nconst TruefoundrySettingsBuilder = lazy(() => import('../containers/SettingsBuilder/index.js'));\n\nexport function DrawerLayout({ className }: { className?: string }) {\n const aui = useAui();\n const shell = useOptionalShellMode();\n const ClearChatButton = useSlot('ClearChatButton');\n const SaveAgentButton = useSlot('SaveAgentButton');\n const SelectAgentEmptyState = useSlot('SelectAgentEmptyState');\n const [threadsOpen, setThreadsOpen] = useState(false);\n const threadsBtnRef = useRef<HTMLButtonElement>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n const mainRef = useRef<HTMLDivElement>(null);\n const wasOpen = useRef(false);\n const isIdle = shell?.mode.status === 'idle';\n const settingsOpen = shell?.settingsOpen === true;\n\n useEffect(() => {\n if (!threadsOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') setThreadsOpen(false);\n };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [threadsOpen]);\n\n useEffect(() => {\n const main = mainRef.current;\n if (threadsOpen) {\n wasOpen.current = true;\n if (main) main.inert = true;\n dialogRef.current?.focus();\n return;\n }\n if (wasOpen.current) {\n if (main) main.inert = false;\n threadsBtnRef.current?.focus();\n wasOpen.current = false;\n }\n }, [threadsOpen]);\n\n const handleNewChat = () => {\n if (shell?.isComposerEnabled) {\n shell.openDraft();\n } else {\n shell?.setSettingsOpen(false);\n aui.threads().switchToNewThread();\n }\n setThreadsOpen(false);\n };\n\n return (\n <div className={cn('relative flex h-full min-h-0 w-full flex-col bg-primary-bg', className)}>\n {/* Keep ShellActions mounted across Settings open/close so host action-slot state persists. */}\n <header className=\"flex shrink-0 items-center gap-1 border-b border-border bg-topbar-bg px-2 py-1.5\">\n {!settingsOpen ? (\n <>\n <NamedAgentHeaderLabel />\n <span className=\"min-w-0 flex-1\" />\n <ClearChatButton />\n <SaveAgentButton />\n </>\n ) : (\n <span className=\"min-w-0 flex-1\" />\n )}\n <ShellActions key=\"shell-actions\" />\n {!settingsOpen ? (\n <>\n {shell?.isNewChatEnabled !== false ? (\n <button\n type=\"button\"\n aria-label=\"New chat\"\n title=\"New chat\"\n className={auiButtonClass({ variant: 'ghost', size: 'icon' })}\n onClick={handleNewChat}\n >\n <Icon name=\"plus\" />\n </button>\n ) : null}\n <button\n ref={threadsBtnRef}\n type=\"button\"\n aria-label=\"Sessions\"\n aria-expanded={threadsOpen}\n className=\"text-text-secondary hover:text-text-primary inline-flex size-8 cursor-pointer items-center justify-center rounded-md\"\n onClick={() => setThreadsOpen(v => !v)}\n >\n <Icon name=\"clock-rotate-left\" />\n </button>\n </>\n ) : null}\n </header>\n <div ref={mainRef} className=\"min-h-0 min-w-0 flex-1\">\n {settingsOpen ? (\n <Suspense\n fallback={\n <div\n className=\"flex h-full items-center justify-center\"\n role=\"status\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <Spinner size={28} className=\"text-text-primary\" />\n <span className=\"sr-only\">Loading</span>\n </div>\n }\n >\n <TruefoundrySettingsBuilder />\n </Suspense>\n ) : isIdle ? (\n <SelectAgentEmptyState />\n ) : (\n <Thread />\n )}\n </div>\n {threadsOpen ? (\n <>\n <button\n type=\"button\"\n aria-label=\"Close sessions\"\n className=\"absolute inset-0 z-[9] cursor-pointer bg-[var(--overlay)]\"\n onClick={() => setThreadsOpen(false)}\n />\n <div\n ref={dialogRef}\n className=\"absolute inset-y-0 right-0 z-10 flex w-full max-w-80 flex-col border-l border-border bg-sidebar-bg shadow-lg outline-none\"\n role=\"dialog\"\n aria-label=\"Sessions\"\n tabIndex={-1}\n >\n <ThreadListContainer onThreadOpen={() => setThreadsOpen(false)} />\n </div>\n </>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/containers/SettingsBuilder/index.tsx"],"sourcesContent":["'use client';\n\nimport { lazy, Suspense, useCallback, useEffect, useMemo } from 'react';\n\nimport { useDraftCatalog } from '@/atoms/draft/DraftCatalogProvider.js';\nimport { auiButtonClass } from '@/atoms/lib/buttonClasses.js';\nimport { cn } from '@/atoms/lib/cn.js';\nimport { useCompactLayout } from '@/atoms/lib/CompactLayoutContext.js';\nimport { Spinner } from '@/atoms/primitives/Spinner.js';\nimport { Icon } from '@/icons/Icon.js';\nimport { useOptionalCatalogServer, useOptionalRefreshServerCapabilities } from '@/server/ServerContext.js';\nimport { useShellMode, type SettingsSection } from '@/server/ShellModeContext.js';\n\n// Section modules (and their list/catalog APIs) load only when that tab mounts.\nconst ModelSettings = lazy(() => import('./ModelSettings.js'));\nconst ConnectorSettings = lazy(() => import('./ConnectorSettings.js'));\nconst SkillSettings = lazy(() => import('./SkillSettings.js'));\nconst SandboxSettings = lazy(() => import('./SandboxSettings.js'));\n\nfunction SettingsSectionFallback() {\n return (\n <div className=\"flex flex-1 items-center justify-center py-8\" role=\"status\" aria-live=\"polite\" aria-busy=\"true\">\n <Spinner size={20} className=\"text-text-secondary\" />\n <span className=\"sr-only\">Loading</span>\n </div>\n );\n}\n\nconst TruefoundrySettingsBuilder = () => {\n const { settingsOpen, settingsSection: section, setSettingsOpen } = useShellMode();\n const catalog = useOptionalCatalogServer();\n const refreshServerCapabilities = useOptionalRefreshServerCapabilities();\n const { refresh: refreshDraftCatalog } = useDraftCatalog();\n // dock/widget panels are ~mobile width even on a wide viewport — keep Settings stacked.\n const compact = useCompactLayout();\n const hasSkills = catalog?.skillCatalog != null;\n const hasSandbox = catalog?.sandboxCatalog != null;\n\n const closeSettings = useCallback(() => {\n setSettingsOpen(false);\n }, [setSettingsOpen]);\n\n // Refresh catalogs whenever settings are closed or navigated away from.\n useEffect(() => {\n if (!settingsOpen) return;\n return () => {\n refreshDraftCatalog();\n refreshServerCapabilities?.();\n };\n }, [settingsOpen, refreshDraftCatalog, refreshServerCapabilities]);\n\n useEffect(() => {\n if (!hasSkills && section === 'skills') {\n setSettingsOpen(settingsOpen, 'models');\n }\n if (!hasSandbox && section === 'sandbox') {\n setSettingsOpen(settingsOpen, 'models');\n }\n }, [hasSkills, hasSandbox, section, settingsOpen, setSettingsOpen]);\n\n useEffect(() => {\n if (!settingsOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return;\n event.stopImmediatePropagation();\n closeSettings();\n };\n // Capture so layout Escape handlers (sessions drawer / widget) do not also fire.\n window.addEventListener('keydown', onKeyDown, true);\n return () => window.removeEventListener('keydown', onKeyDown, true);\n }, [closeSettings, settingsOpen]);\n\n const sections = useMemo<\n Array<{\n id: SettingsSection;\n label: string;\n icon: 'cpu' | 'plug' | 'lightbulb' | 'cube';\n }>\n >(() => {\n const baseSections: Array<{\n id: SettingsSection;\n label: string;\n icon: 'cpu' | 'plug' | 'lightbulb' | 'cube';\n }> = [\n { id: 'models', label: 'Models', icon: 'cpu' },\n { id: 'connectors', label: 'Connectors', icon: 'plug' },\n ];\n if (hasSkills) {\n baseSections.push({ id: 'skills', label: 'Skills', icon: 'lightbulb' });\n }\n if (hasSandbox) {\n baseSections.push({ id: 'sandbox', label: 'Sandbox providers', icon: 'cube' });\n }\n return baseSections;\n }, [hasSkills, hasSandbox]);\n\n if (!settingsOpen || !catalog) return null;\n\n return (\n <div className=\"flex h-full min-h-0 w-full flex-col bg-primary-bg\">\n <header className=\"flex shrink-0 items-center gap-2 border-b border-border px-2 py-1.5\">\n <button\n type=\"button\"\n aria-label=\"Back\"\n title=\"Back\"\n className={auiButtonClass({ variant: 'ghost', size: 'icon' })}\n onClick={closeSettings}\n >\n <Icon name=\"arrow-left\" />\n </button>\n <h1 className=\"text-lg font-semibold tracking-tight text-text-primary\">Settings</h1>\n </header>\n\n <div className={cn('flex min-h-0 flex-1 flex-col', !compact && 'md:flex-row')}>\n <nav\n aria-label=\"Settings sections\"\n className={cn(\n 'flex w-full gap-1 border-b border-border bg-secondary-bg/40 p-2',\n compact ? 'min-w-0' : 'justify-center md:w-48 md:flex-col md:justify-start md:border-b-0 md:border-r',\n )}\n >\n {sections.map(item => (\n <button\n key={item.id}\n type=\"button\"\n aria-current={section === item.id ? 'page' : undefined}\n {...(compact ? { title: item.label } : {})}\n className={cn(\n 'flex min-h-9 items-center gap-2 rounded-md px-3 text-sm font-medium transition-colors',\n 'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus-ring',\n // Narrow panels cannot fit fixed-width tabs, so tabs split the row instead.\n compact ? 'min-w-0 flex-1 justify-center gap-1.5 px-1.5' : 'shrink-0',\n section === item.id\n ? 'bg-primary-button-bg text-primary-button-text'\n : 'text-text-secondary hover:bg-ghost-button-hover/60 hover:text-text-primary',\n )}\n onClick={() => {\n setSettingsOpen(true, item.id);\n }}\n >\n <Icon name={item.icon} className=\"h-4 w-4 shrink-0\" />\n {compact ? <span className=\"truncate\">{item.label}</span> : item.label}\n </button>\n ))}\n </nav>\n\n <section className=\"flex flex-col h-full flex-1 overflow-y-hidden px-6 py-4\">\n <div className=\"w-full max-w-210 h-full min-h-0 flex flex-col mx-auto\">\n <Suspense fallback={<SettingsSectionFallback />}>\n {section === 'models' ? <ModelSettings /> : null}\n {section === 'connectors' ? <ConnectorSettings /> : null}\n {section === 'skills' && hasSkills ? <SkillSettings /> : null}\n {section === 'sandbox' && hasSandbox ? <SandboxSettings /> : null}\n </Suspense>\n </div>\n </section>\n </div>\n </div>\n );\n};\n\nexport default TruefoundrySettingsBuilder;\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routing/ShellRouteSync.tsx","../src/routing/derivePlace.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport { useLocation, useNavigate } from 'react-router-dom';\n\nimport { useOptionalServer } from '../server/ServerContext.js';\nimport { useShellMode } from '../server/ShellModeContext.js';\nimport { deriveChatPlace, derivePlace } from './derivePlace.js';\nimport { buildPath, matchPath, placesEqual } from './paths.js';\nimport type { ResolvedRoutes, RoutePlace, ShellSnapshot } from './types.js';\n\n/**\n * Single bidirectional bridge between shell state and the URL. Mounted under\n * `ShellModeProvider` but outside the keyed chat runtime so boot applies once.\n */\nexport function ShellRouteSync({\n routes,\n activeRemoteId,\n initialSettingsOpen,\n}: {\n routes: ResolvedRoutes;\n activeRemoteId: string | undefined;\n initialSettingsOpen: boolean;\n}) {\n const shell = useShellMode();\n const server = useOptionalServer();\n const navigate = useNavigate();\n const location = useLocation();\n\n const snapshot: ShellSnapshot = {\n settingsOpen: shell.settingsOpen,\n pendingSessionId: shell.pendingSessionId,\n activeRemoteId,\n mode: shell.mode,\n agentConfigMode: shell.agentConfigMode,\n };\n\n const place = derivePlace(snapshot);\n const placeKey = JSON.stringify(place);\n\n // Guards. `selfNavPathRef` marks a path we navigated to ourselves so the\n // URL->shell effect does not re-apply it. `prevPlaceRef` powers push/replace.\n const selfNavPathRef = useRef<string | null>(null);\n const prevPlaceRef = useRef<RoutePlace | null>(null);\n const bootedRef = useRef(false);\n // Latest session id the URL asked for, so slower lookups cannot bind over it.\n const requestedSessionRef = useRef<string | null>(null);\n // Boot owns the first URL; the ongoing effects skip their initial commit so\n // they do not fight boot with the stale first-render place.\n const shellSyncStartedRef = useRef(false);\n const urlSyncStartedRef = useRef(false);\n\n /**\n * A URL carries only the id, so ask the server whether it names a mutable\n * draft or an agent chat; guessing \"mutable\" opens an agent session as a\n * blank draft. `requestedSessionRef` drops replies a later place superseded.\n */\n const openSession = useCallback(\n (sessionId: string) => {\n requestedSessionRef.current = sessionId;\n if (server == null) {\n shell.openHistorySession({ sessionId });\n return;\n }\n void server\n .getSession({ sessionId })\n .then(session => {\n if (requestedSessionRef.current !== sessionId) return;\n shell.openHistorySession({\n sessionId,\n isMutable: session.isMutable,\n ...(session.agentName != null ? { agentName: session.agentName } : {}),\n });\n })\n .catch(() => {\n if (requestedSessionRef.current !== sessionId) return;\n // Unreachable session: bind by id alone rather than stranding the shell.\n shell.openHistorySession({ sessionId });\n });\n },\n [server, shell],\n );\n\n const applyPlace = useCallback(\n (target: RoutePlace) => {\n switch (target.type) {\n case 'settings':\n shell.setSettingsOpen(true);\n return;\n case 'session':\n if (shell.pendingSessionId === target.sessionId || activeRemoteId === target.sessionId) return;\n openSession(target.sessionId);\n return;\n case 'agent':\n shell.selectLibraryAgent({ isMutable: false, agentName: target.agentName });\n return;\n case 'root':\n shell.setSettingsOpen(false);\n switch (shell.agentConfigMode) {\n case 'AgentLibrary':\n shell.openLibraryHome();\n return;\n case 'AgentComposer':\n case 'AgentLibraryWithComposer':\n shell.openDraft();\n return;\n case 'SingleAgent':\n shell.clearChat();\n return;\n }\n }\n },\n [shell, activeRemoteId, openSession],\n );\n\n // Boot: URL wins, except an explicit `initialSettingsOpen` overlay. Boot is the\n // sole authority for the first commit and sets the final URL + `prevPlaceRef`.\n useEffect(() => {\n if (bootedRef.current) return;\n bootedRef.current = true;\n\n const urlPlace = matchPath(location.pathname, routes) ?? { type: 'root' };\n const settingsOnBoot = initialSettingsOpen || urlPlace.type === 'settings';\n\n if (urlPlace.type === 'settings') {\n shell.setSettingsOpen(true);\n } else {\n const chatPlace = deriveChatPlace(snapshot);\n if (!placesEqual(chatPlace, urlPlace)) applyPlace(urlPlace);\n if (initialSettingsOpen) shell.setSettingsOpen(true);\n }\n\n const desiredPlace: RoutePlace = settingsOnBoot ? { type: 'settings' } : urlPlace;\n const desiredPath = buildPath(desiredPlace, routes);\n prevPlaceRef.current = desiredPlace;\n if (desiredPath != null && desiredPath !== location.pathname) {\n selfNavPathRef.current = desiredPath;\n navigate({ pathname: desiredPath, search: location.search, hash: location.hash }, { replace: true });\n }\n // Boot runs once; snapshot is read imperatively here.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Shell -> URL: mirror the derived place. Skip the first commit (boot owns it).\n useEffect(() => {\n if (!bootedRef.current) return;\n if (!shellSyncStartedRef.current) {\n shellSyncStartedRef.current = true;\n return;\n }\n const target = buildPath(place, routes);\n if (target == null) return; // place has no configured URL (e.g. settings disabled)\n\n const prev = prevPlaceRef.current;\n prevPlaceRef.current = place;\n\n if (target === location.pathname) return;\n\n // Replace when a fresh chat just acquired its session id (same place, new id).\n const replace =\n place.type === 'session' && shell.pendingSessionId == null && prev != null && prev.type !== 'session';\n\n selfNavPathRef.current = target;\n // Only the pathname is ours; host query/hash state rides along unchanged.\n navigate({ pathname: target, search: location.search, hash: location.hash }, { replace });\n // location.pathname intentionally excluded: only react to shell-derived place changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [placeKey]);\n\n // URL -> shell: apply on genuine location changes (Back/Forward, manual edits).\n useEffect(() => {\n if (!bootedRef.current) return;\n if (!urlSyncStartedRef.current) {\n urlSyncStartedRef.current = true;\n return;\n }\n if (selfNavPathRef.current === location.pathname) {\n selfNavPathRef.current = null;\n return;\n }\n const urlPlace = matchPath(location.pathname, routes);\n if (urlPlace == null) {\n // Unknown path: normalize to root.\n const rootPath = routes.root;\n selfNavPathRef.current = rootPath;\n navigate({ pathname: rootPath, search: location.search, hash: location.hash }, { replace: true });\n applyPlace({ type: 'root' });\n return;\n }\n if (urlPlace.type !== 'settings' && shell.settingsOpen) {\n // Leaving settings via Back to a chat place.\n shell.setSettingsOpen(false);\n }\n applyPlace(urlPlace);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [location.pathname]);\n\n return null;\n}\n","import type { RoutePlace, ShellSnapshot } from './types.js';\n\n/**\n * The chat place implied by shell state, ignoring the settings overlay.\n * SingleAgent canonicalizes to `root` so `/` and `/agents/{name}` alias.\n */\nexport function deriveChatPlace(snapshot: ShellSnapshot): RoutePlace {\n // The live thread wins: reusing a mutable shell switches thread without a\n // remount, leaving `pendingSessionId` on the session the shell last opened.\n // It only leads while a requested session has not reported its thread yet.\n const sessionId = snapshot.activeRemoteId ?? snapshot.pendingSessionId;\n if (sessionId != null) return { type: 'session', sessionId };\n\n const { mode, agentConfigMode } = snapshot;\n if (mode.status === 'active' && !mode.isMutable && agentConfigMode !== 'SingleAgent') {\n const agentName = mode.agentName ?? mode.agentId;\n if (agentName != null) return { type: 'agent', agentName };\n }\n return { type: 'root' };\n}\n\n/** Full place including the settings overlay, which wins over the chat place. */\nexport function derivePlace(snapshot: ShellSnapshot): RoutePlace {\n if (snapshot.settingsOpen) return { type: 'settings' };\n return deriveChatPlace(snapshot);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import {
|
|
3
|
-
NamedAgentHeaderLabel,
|
|
4
|
-
ShellActions
|
|
5
|
-
} from "./chunk-OZTNBS6V.js";
|
|
6
|
-
import {
|
|
7
|
-
Thread,
|
|
8
|
-
ThreadListContainer
|
|
9
|
-
} from "./chunk-IWPDSPVA.js";
|
|
10
|
-
import "./chunk-FXCYLEFB.js";
|
|
11
|
-
import {
|
|
12
|
-
useAui
|
|
13
|
-
} from "./chunk-M6MHLVSO.js";
|
|
14
|
-
import {
|
|
15
|
-
useBrandName,
|
|
16
|
-
useChatHeaderContentVisible,
|
|
17
|
-
useSlot
|
|
18
|
-
} from "./chunk-XRTTKGKN.js";
|
|
19
|
-
import {
|
|
20
|
-
Icon,
|
|
21
|
-
Spinner,
|
|
22
|
-
auiButtonClass
|
|
23
|
-
} from "./chunk-IFLE7OMM.js";
|
|
24
|
-
import {
|
|
25
|
-
useOptionalShellMode
|
|
26
|
-
} from "./chunk-WQULF5AT.js";
|
|
27
|
-
import "./chunk-JRRCAKEP.js";
|
|
28
|
-
import {
|
|
29
|
-
cn
|
|
30
|
-
} from "./chunk-72LC2M3R.js";
|
|
31
|
-
|
|
32
|
-
// src/layouts/SidebarLayout.tsx
|
|
33
|
-
import { lazy, Suspense, useEffect, useRef, useState } from "react";
|
|
34
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
35
|
-
var TruefoundrySettingsBuilder = lazy(() => import("./SettingsBuilder-MYWRFXRI.js"));
|
|
36
|
-
var desktopCollapsed = false;
|
|
37
|
-
function SidebarLayout({ className }) {
|
|
38
|
-
const aui = useAui();
|
|
39
|
-
const shell = useOptionalShellMode();
|
|
40
|
-
const brandName = useBrandName();
|
|
41
|
-
const BrandLogo = useSlot("BrandLogo");
|
|
42
|
-
const AgentsLibraryButton = useSlot("AgentsLibraryButton");
|
|
43
|
-
const ClearChatButton = useSlot("ClearChatButton");
|
|
44
|
-
const SaveAgentButton = useSlot("SaveAgentButton");
|
|
45
|
-
const SelectAgentEmptyState = useSlot("SelectAgentEmptyState");
|
|
46
|
-
const [collapsed, setCollapsed] = useState(desktopCollapsed);
|
|
47
|
-
const setDesktopCollapsed = (value) => {
|
|
48
|
-
setCollapsed((prev) => {
|
|
49
|
-
const next = typeof value === "function" ? value(prev) : value;
|
|
50
|
-
desktopCollapsed = next;
|
|
51
|
-
return next;
|
|
52
|
-
});
|
|
53
|
-
};
|
|
54
|
-
const [mobileNavOpen, setMobileNavOpen] = useState(false);
|
|
55
|
-
const menuBtnRef = useRef(null);
|
|
56
|
-
const dialogRef = useRef(null);
|
|
57
|
-
const mainRef = useRef(null);
|
|
58
|
-
const wasOpen = useRef(false);
|
|
59
|
-
const isIdle = shell?.mode.status === "idle";
|
|
60
|
-
const settingsOpen = shell?.settingsOpen === true;
|
|
61
|
-
const hasChatHeaderContent = useChatHeaderContentVisible();
|
|
62
|
-
useEffect(() => {
|
|
63
|
-
if (!mobileNavOpen) return;
|
|
64
|
-
const onKeyDown = (event) => {
|
|
65
|
-
if (event.key === "Escape") setMobileNavOpen(false);
|
|
66
|
-
};
|
|
67
|
-
window.addEventListener("keydown", onKeyDown);
|
|
68
|
-
return () => window.removeEventListener("keydown", onKeyDown);
|
|
69
|
-
}, [mobileNavOpen]);
|
|
70
|
-
useEffect(() => {
|
|
71
|
-
const main = mainRef.current;
|
|
72
|
-
if (mobileNavOpen) {
|
|
73
|
-
wasOpen.current = true;
|
|
74
|
-
if (main) main.inert = true;
|
|
75
|
-
dialogRef.current?.focus();
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
if (wasOpen.current) {
|
|
79
|
-
if (main) main.inert = false;
|
|
80
|
-
menuBtnRef.current?.focus();
|
|
81
|
-
wasOpen.current = false;
|
|
82
|
-
}
|
|
83
|
-
}, [mobileNavOpen]);
|
|
84
|
-
const handleNewChat = () => {
|
|
85
|
-
if (shell?.isComposerEnabled) {
|
|
86
|
-
shell.openDraft();
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
shell?.setSettingsOpen(false);
|
|
90
|
-
void Promise.resolve(aui.threads().switchToNewThread()).catch(() => void 0);
|
|
91
|
-
};
|
|
92
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("relative flex h-full min-h-0 w-full min-w-0", className), children: [
|
|
93
|
-
/* @__PURE__ */ jsxs(
|
|
94
|
-
"aside",
|
|
95
|
-
{
|
|
96
|
-
className: cn(
|
|
97
|
-
"hidden min-h-0 shrink-0 flex-col border-r border-border bg-sidebar-bg transition-[width] duration-300 ease-in-out md:flex",
|
|
98
|
-
collapsed ? "w-16" : "w-64"
|
|
99
|
-
),
|
|
100
|
-
children: [
|
|
101
|
-
/* @__PURE__ */ jsxs(
|
|
102
|
-
"div",
|
|
103
|
-
{
|
|
104
|
-
className: cn("flex shrink-0 items-center px-3 py-3", collapsed ? "flex-col gap-3" : "justify-between gap-2"),
|
|
105
|
-
children: [
|
|
106
|
-
/* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 items-center text-text-primary", collapsed ? "justify-center" : "gap-2"), children: [
|
|
107
|
-
/* @__PURE__ */ jsx(BrandLogo, { className: "size-5 shrink-0 object-contain" }),
|
|
108
|
-
!collapsed ? /* @__PURE__ */ jsx("span", { className: "truncate text-lg font-semibold tracking-tight", children: brandName }) : null
|
|
109
|
-
] }),
|
|
110
|
-
/* @__PURE__ */ jsx(
|
|
111
|
-
"button",
|
|
112
|
-
{
|
|
113
|
-
type: "button",
|
|
114
|
-
"aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
115
|
-
title: collapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
116
|
-
"aria-expanded": !collapsed,
|
|
117
|
-
className: auiButtonClass({ variant: "ghost", size: "icon" }),
|
|
118
|
-
onClick: () => setDesktopCollapsed((value) => !value),
|
|
119
|
-
children: /* @__PURE__ */ jsx(Icon, { name: collapsed ? "panel-left-open" : "panel-left-close" })
|
|
120
|
-
}
|
|
121
|
-
)
|
|
122
|
-
]
|
|
123
|
-
}
|
|
124
|
-
),
|
|
125
|
-
/* @__PURE__ */ jsxs("nav", { className: "flex min-h-0 flex-1 flex-col items-center gap-2 px-3", hidden: !collapsed, "aria-label": "Sidebar", children: [
|
|
126
|
-
shell?.isNewChatEnabled !== false ? /* @__PURE__ */ jsx(
|
|
127
|
-
"button",
|
|
128
|
-
{
|
|
129
|
-
type: "button",
|
|
130
|
-
"aria-label": "Start new chat",
|
|
131
|
-
title: "New chat",
|
|
132
|
-
className: auiButtonClass({ variant: "ghost", size: "icon" }),
|
|
133
|
-
onClick: handleNewChat,
|
|
134
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "square-pen" })
|
|
135
|
-
}
|
|
136
|
-
) : null,
|
|
137
|
-
/* @__PURE__ */ jsx(AgentsLibraryButton, { compact: true })
|
|
138
|
-
] }),
|
|
139
|
-
/* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", hidden: collapsed, children: /* @__PURE__ */ jsx(ThreadListContainer, {}) }),
|
|
140
|
-
/* @__PURE__ */ jsx(
|
|
141
|
-
"footer",
|
|
142
|
-
{
|
|
143
|
-
className: cn(
|
|
144
|
-
"flex shrink-0 border-t border-border px-3 py-2",
|
|
145
|
-
collapsed ? "flex-col items-center gap-2" : "items-center gap-1"
|
|
146
|
-
),
|
|
147
|
-
children: /* @__PURE__ */ jsx(ShellActions, { className: collapsed ? "flex-col" : void 0 })
|
|
148
|
-
}
|
|
149
|
-
)
|
|
150
|
-
]
|
|
151
|
-
}
|
|
152
|
-
),
|
|
153
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col bg-primary-bg", children: [
|
|
154
|
-
/* @__PURE__ */ jsxs(
|
|
155
|
-
"header",
|
|
156
|
-
{
|
|
157
|
-
className: cn(
|
|
158
|
-
"flex shrink-0 items-center gap-1 border-b border-border bg-topbar-bg px-2 py-1.5",
|
|
159
|
-
// Desktop: hide when settings/idle or the thread header has nothing to show
|
|
160
|
-
// (empty untitled draft). Mobile still needs Sessions + ShellActions.
|
|
161
|
-
(settingsOpen || isIdle || !hasChatHeaderContent) && "md:hidden"
|
|
162
|
-
),
|
|
163
|
-
children: [
|
|
164
|
-
!settingsOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
165
|
-
/* @__PURE__ */ jsx(
|
|
166
|
-
"button",
|
|
167
|
-
{
|
|
168
|
-
ref: menuBtnRef,
|
|
169
|
-
type: "button",
|
|
170
|
-
"aria-label": "Sessions",
|
|
171
|
-
"aria-expanded": mobileNavOpen,
|
|
172
|
-
className: cn(auiButtonClass({ variant: "ghost", size: "icon" }), "md:hidden"),
|
|
173
|
-
onClick: () => setMobileNavOpen(true),
|
|
174
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "bars" })
|
|
175
|
-
}
|
|
176
|
-
),
|
|
177
|
-
/* @__PURE__ */ jsx(NamedAgentHeaderLabel, {}),
|
|
178
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
|
|
179
|
-
/* @__PURE__ */ jsx(ClearChatButton, {}),
|
|
180
|
-
/* @__PURE__ */ jsx(SaveAgentButton, {})
|
|
181
|
-
] }) : /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
|
|
182
|
-
/* @__PURE__ */ jsx("div", { className: "md:hidden", children: /* @__PURE__ */ jsx(ShellActions, {}) }, "mobile-shell-actions")
|
|
183
|
-
]
|
|
184
|
-
}
|
|
185
|
-
),
|
|
186
|
-
/* @__PURE__ */ jsx("div", { ref: mainRef, className: "min-h-0 min-w-0 flex-1", children: settingsOpen ? /* @__PURE__ */ jsx(
|
|
187
|
-
Suspense,
|
|
188
|
-
{
|
|
189
|
-
fallback: /* @__PURE__ */ jsxs(
|
|
190
|
-
"div",
|
|
191
|
-
{
|
|
192
|
-
className: "flex h-full items-center justify-center",
|
|
193
|
-
role: "status",
|
|
194
|
-
"aria-live": "polite",
|
|
195
|
-
"aria-busy": "true",
|
|
196
|
-
children: [
|
|
197
|
-
/* @__PURE__ */ jsx(Spinner, { size: 28, className: "text-text-primary" }),
|
|
198
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
199
|
-
]
|
|
200
|
-
}
|
|
201
|
-
),
|
|
202
|
-
children: /* @__PURE__ */ jsx(TruefoundrySettingsBuilder, {})
|
|
203
|
-
}
|
|
204
|
-
) : isIdle ? /* @__PURE__ */ jsx(SelectAgentEmptyState, {}) : /* @__PURE__ */ jsx(Thread, {}) })
|
|
205
|
-
] }),
|
|
206
|
-
mobileNavOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
207
|
-
/* @__PURE__ */ jsx(
|
|
208
|
-
"button",
|
|
209
|
-
{
|
|
210
|
-
type: "button",
|
|
211
|
-
"aria-label": "Close sessions",
|
|
212
|
-
className: "absolute inset-0 z-[9] cursor-pointer bg-[var(--overlay)] md:hidden",
|
|
213
|
-
onClick: () => setMobileNavOpen(false)
|
|
214
|
-
}
|
|
215
|
-
),
|
|
216
|
-
/* @__PURE__ */ jsxs(
|
|
217
|
-
"div",
|
|
218
|
-
{
|
|
219
|
-
ref: dialogRef,
|
|
220
|
-
className: "absolute inset-y-0 left-0 z-10 flex w-full max-w-80 flex-col border-r border-border bg-sidebar-bg shadow-lg outline-none md:hidden",
|
|
221
|
-
role: "dialog",
|
|
222
|
-
"aria-label": "Sessions",
|
|
223
|
-
tabIndex: -1,
|
|
224
|
-
children: [
|
|
225
|
-
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2 border-b border-border px-3 py-3 text-text-primary", children: [
|
|
226
|
-
/* @__PURE__ */ jsx(BrandLogo, { className: "size-5 shrink-0 object-contain" }),
|
|
227
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-lg font-semibold tracking-tight", children: brandName })
|
|
228
|
-
] }),
|
|
229
|
-
/* @__PURE__ */ jsx(ThreadListContainer, { onThreadOpen: () => setMobileNavOpen(false) })
|
|
230
|
-
]
|
|
231
|
-
}
|
|
232
|
-
)
|
|
233
|
-
] }) : null
|
|
234
|
-
] });
|
|
235
|
-
}
|
|
236
|
-
export {
|
|
237
|
-
SidebarLayout
|
|
238
|
-
};
|
|
239
|
-
//# sourceMappingURL=SidebarLayout-6MHQYW45.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/layouts/SidebarLayout.tsx"],"sourcesContent":["'use client';\n\nimport { lazy, Suspense, useEffect, useRef, useState } from 'react';\n\nimport { useAui } from '../assistant-ui.js';\nimport { auiButtonClass } from '../atoms/lib/buttonClasses.js';\nimport { cn } from '../atoms/lib/cn.js';\nimport { NamedAgentHeaderLabel } from '../atoms/NamedAgentHeaderLabel.js';\nimport { Spinner } from '../atoms/primitives/Spinner.js';\nimport { ShellActions } from '../atoms/ShellActions.js';\nimport { Thread } from '../containers/Thread.js';\nimport { ThreadListContainer } from '../containers/ThreadListContainer.js';\nimport { useChatHeaderContentVisible } from '../hooks/useChatChromeActionsVisible.js';\nimport { Icon } from '../icons/Icon.js';\nimport { useOptionalShellMode } from '../server/ShellModeContext.js';\nimport { useBrandName } from '../theme/brand.js';\nimport { useSlot } from '../theme/SlotsProvider.js';\n\nconst TruefoundrySettingsBuilder = lazy(() => import('../containers/SettingsBuilder/index.js'));\n\n// Survives ChatProvider remounts when openDraft / selectAgent bumps runtimeKey.\nlet desktopCollapsed = false;\n\nexport function SidebarLayout({ className }: { className?: string }) {\n const aui = useAui();\n const shell = useOptionalShellMode();\n const brandName = useBrandName();\n const BrandLogo = useSlot('BrandLogo');\n const AgentsLibraryButton = useSlot('AgentsLibraryButton');\n const ClearChatButton = useSlot('ClearChatButton');\n const SaveAgentButton = useSlot('SaveAgentButton');\n const SelectAgentEmptyState = useSlot('SelectAgentEmptyState');\n const [collapsed, setCollapsed] = useState(desktopCollapsed);\n const setDesktopCollapsed = (value: boolean | ((prev: boolean) => boolean)) => {\n setCollapsed(prev => {\n const next = typeof value === 'function' ? value(prev) : value;\n desktopCollapsed = next;\n return next;\n });\n };\n const [mobileNavOpen, setMobileNavOpen] = useState(false);\n const menuBtnRef = useRef<HTMLButtonElement>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n const mainRef = useRef<HTMLDivElement>(null);\n const wasOpen = useRef(false);\n const isIdle = shell?.mode.status === 'idle';\n const settingsOpen = shell?.settingsOpen === true;\n const hasChatHeaderContent = useChatHeaderContentVisible();\n\n useEffect(() => {\n if (!mobileNavOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') setMobileNavOpen(false);\n };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [mobileNavOpen]);\n\n useEffect(() => {\n const main = mainRef.current;\n if (mobileNavOpen) {\n wasOpen.current = true;\n if (main) main.inert = true;\n dialogRef.current?.focus();\n return;\n }\n if (wasOpen.current) {\n if (main) main.inert = false;\n menuBtnRef.current?.focus();\n wasOpen.current = false;\n }\n }, [mobileNavOpen]);\n\n const handleNewChat = () => {\n if (shell?.isComposerEnabled) {\n shell.openDraft();\n return;\n }\n shell?.setSettingsOpen(false);\n void Promise.resolve(aui.threads().switchToNewThread()).catch(() => undefined);\n };\n\n return (\n <div className={cn('relative flex h-full min-h-0 w-full min-w-0', className)}>\n {/* Desktop sidebar */}\n <aside\n className={cn(\n 'hidden min-h-0 shrink-0 flex-col border-r border-border bg-sidebar-bg transition-[width] duration-300 ease-in-out md:flex',\n collapsed ? 'w-16' : 'w-64',\n )}\n >\n <div\n className={cn('flex shrink-0 items-center px-3 py-3', collapsed ? 'flex-col gap-3' : 'justify-between gap-2')}\n >\n <div className={cn('flex min-w-0 items-center text-text-primary', collapsed ? 'justify-center' : 'gap-2')}>\n <BrandLogo className=\"size-5 shrink-0 object-contain\" />\n {!collapsed ? <span className=\"truncate text-lg font-semibold tracking-tight\">{brandName}</span> : null}\n </div>\n <button\n type=\"button\"\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n title={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n aria-expanded={!collapsed}\n className={auiButtonClass({ variant: 'ghost', size: 'icon' })}\n onClick={() => setDesktopCollapsed(value => !value)}\n >\n <Icon name={collapsed ? 'panel-left-open' : 'panel-left-close'} />\n </button>\n </div>\n\n {/* Keep both trees mounted; toggle with `hidden` so AgentsLibraryButton does not remount. */}\n <nav className=\"flex min-h-0 flex-1 flex-col items-center gap-2 px-3\" hidden={!collapsed} aria-label=\"Sidebar\">\n {shell?.isNewChatEnabled !== false ? (\n <button\n type=\"button\"\n aria-label=\"Start new chat\"\n title=\"New chat\"\n className={auiButtonClass({ variant: 'ghost', size: 'icon' })}\n onClick={handleNewChat}\n >\n <Icon name=\"square-pen\" />\n </button>\n ) : null}\n <AgentsLibraryButton compact />\n </nav>\n <div className=\"flex min-h-0 flex-1 flex-col overflow-hidden\" hidden={collapsed}>\n <ThreadListContainer />\n </div>\n\n <footer\n className={cn(\n 'flex shrink-0 border-t border-border px-3 py-2',\n collapsed ? 'flex-col items-center gap-2' : 'items-center gap-1',\n )}\n >\n <ShellActions className={collapsed ? 'flex-col' : undefined} />\n </footer>\n </aside>\n\n <div className=\"flex min-h-0 min-w-0 flex-1 flex-col bg-primary-bg\">\n {/* Mobile ShellActions stay mounted while Settings is open so host overrides (e.g. logout) do not remount.\n Desktop keeps shell chrome in the aside footer (always mounted). */}\n <header\n className={cn(\n 'flex shrink-0 items-center gap-1 border-b border-border bg-topbar-bg px-2 py-1.5',\n // Desktop: hide when settings/idle or the thread header has nothing to show\n // (empty untitled draft). Mobile still needs Sessions + ShellActions.\n (settingsOpen || isIdle || !hasChatHeaderContent) && 'md:hidden',\n )}\n >\n {!settingsOpen ? (\n <>\n <button\n ref={menuBtnRef}\n type=\"button\"\n aria-label=\"Sessions\"\n aria-expanded={mobileNavOpen}\n className={cn(auiButtonClass({ variant: 'ghost', size: 'icon' }), 'md:hidden')}\n onClick={() => setMobileNavOpen(true)}\n >\n <Icon name=\"bars\" />\n </button>\n <NamedAgentHeaderLabel />\n <span className=\"min-w-0 flex-1\" />\n <ClearChatButton />\n <SaveAgentButton />\n </>\n ) : (\n <span className=\"min-w-0 flex-1\" />\n )}\n <div key=\"mobile-shell-actions\" className=\"md:hidden\">\n <ShellActions />\n </div>\n </header>\n\n <div ref={mainRef} className=\"min-h-0 min-w-0 flex-1\">\n {settingsOpen ? (\n <Suspense\n fallback={\n <div\n className=\"flex h-full items-center justify-center\"\n role=\"status\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <Spinner size={28} className=\"text-text-primary\" />\n <span className=\"sr-only\">Loading</span>\n </div>\n }\n >\n <TruefoundrySettingsBuilder />\n </Suspense>\n ) : isIdle ? (\n <SelectAgentEmptyState />\n ) : (\n <Thread />\n )}\n </div>\n </div>\n\n {/* Mobile sessions drawer */}\n {mobileNavOpen ? (\n <>\n <button\n type=\"button\"\n aria-label=\"Close sessions\"\n className=\"absolute inset-0 z-[9] cursor-pointer bg-[var(--overlay)] md:hidden\"\n onClick={() => setMobileNavOpen(false)}\n />\n <div\n ref={dialogRef}\n className=\"absolute inset-y-0 left-0 z-10 flex w-full max-w-80 flex-col border-r border-border bg-sidebar-bg shadow-lg outline-none md:hidden\"\n role=\"dialog\"\n aria-label=\"Sessions\"\n tabIndex={-1}\n >\n <div className=\"flex shrink-0 items-center gap-2 border-b border-border px-3 py-3 text-text-primary\">\n <BrandLogo className=\"size-5 shrink-0 object-contain\" />\n <span className=\"truncate text-lg font-semibold tracking-tight\">{brandName}</span>\n </div>\n <ThreadListContainer onThreadOpen={() => setMobileNavOpen(false)} />\n </div>\n </>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/layouts/WidgetLayout.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { auiButtonClass } from '../atoms/lib/buttonClasses.js';\nimport { cn } from '../atoms/lib/cn.js';\nimport { CompactLayoutProvider } from '../atoms/lib/CompactLayoutContext.js';\nimport { Icon } from '../icons/Icon.js';\nimport { useSlot } from '../theme/SlotsProvider.js';\nimport { StackChatPanel } from './StackChatPanel.js';\n\n/** FAB-anchored panel with the same list ↔ thread stack as `dock`. */\nexport function WidgetLayout({ className }: { className?: string }) {\n const BrandLogo = useSlot('BrandLogo');\n const [open, setOpen] = useState(false);\n const fabRef = useRef<HTMLButtonElement>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n const wasOpen = useRef(false);\n\n useEffect(() => {\n if (!open) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && !dialogRef.current?.querySelector('dialog[open]')) {\n setOpen(false);\n }\n };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [open]);\n\n useEffect(() => {\n if (open) {\n wasOpen.current = true;\n dialogRef.current?.focus();\n return;\n }\n if (wasOpen.current) {\n fabRef.current?.focus();\n wasOpen.current = false;\n }\n }, [open]);\n\n return (\n <div className={cn('pointer-events-none relative h-full min-h-0 w-full', className)}>\n {open ? (\n <div\n ref={dialogRef}\n data-aui-compact-layout\n className=\"pointer-events-auto absolute right-[max(1.25rem,env(safe-area-inset-right,0px))] bottom-[calc(5.25rem+env(safe-area-inset-bottom,0px))] z-[19] flex h-[min(560px,calc(100%-6.5rem-env(safe-area-inset-bottom,0px)))] max-h-[calc(100%-6.5rem)] w-[min(380px,calc(100%-2.5rem))] flex-col overflow-hidden rounded-xl border border-border bg-primary-bg shadow-[0_16px_48px_color-mix(in_oklab,var(--shadow-color)_14%,transparent)] outline-none\"\n role=\"dialog\"\n aria-modal={true}\n aria-label=\"Chat\"\n tabIndex={-1}\n >\n <CompactLayoutProvider>\n <StackChatPanel\n threadHeaderEnd={\n <button\n type=\"button\"\n aria-label=\"Close\"\n title=\"Close\"\n className={auiButtonClass({ variant: 'ghost', size: 'icon' })}\n onClick={() => setOpen(false)}\n >\n <Icon name=\"xmark\" />\n </button>\n }\n />\n </CompactLayoutProvider>\n </div>\n ) : null}\n {/* Native FAB: inline colors beat host unlayered Tailwind (SDK utilities are layered). */}\n <button\n ref={fabRef}\n type=\"button\"\n className=\"pointer-events-auto absolute right-[max(1.25rem,env(safe-area-inset-right,0px))] bottom-[max(1.25rem,env(safe-area-inset-bottom,0px))] z-20 flex size-14 cursor-pointer items-center justify-center rounded-full text-sm font-medium shadow-[0_8px_24px_color-mix(in_oklab,var(--primary-button-bg)_45%,transparent)]\"\n style={{\n backgroundColor: 'var(--primary-button-bg)',\n color: 'var(--primary-button-text)',\n }}\n aria-expanded={open}\n aria-label={open ? 'Close chat' : 'Open chat'}\n onClick={() => setOpen(v => !v)}\n >\n {open ? (\n <span aria-hidden className=\"text-xl leading-none\">\n ×\n </span>\n ) : (\n <BrandLogo className=\"size-6\" />\n )}\n </button>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,WAAW,QAAQ,gBAAgB;AAyCxC,SAqBc,KArBd;AA/BG,SAAS,aAAa,EAAE,UAAU,GAA2B;AAClE,QAAM,YAAY,QAAQ,WAAW;AACrC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,SAAS,OAA0B,IAAI;AAC7C,QAAM,YAAY,OAAuB,IAAI;AAC7C,QAAM,UAAU,OAAO,KAAK;AAE5B,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,YAAY,CAAC,UAAyB;AAC1C,UAAI,MAAM,QAAQ,YAAY,CAAC,UAAU,SAAS,cAAc,cAAc,GAAG;AAC/E,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF;AACA,WAAO,iBAAiB,WAAW,SAAS;AAC5C,WAAO,MAAM,OAAO,oBAAoB,WAAW,SAAS;AAAA,EAC9D,GAAG,CAAC,IAAI,CAAC;AAET,YAAU,MAAM;AACd,QAAI,MAAM;AACR,cAAQ,UAAU;AAClB,gBAAU,SAAS,MAAM;AACzB;AAAA,IACF;AACA,QAAI,QAAQ,SAAS;AACnB,aAAO,SAAS,MAAM;AACtB,cAAQ,UAAU;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAET,SACE,qBAAC,SAAI,WAAW,GAAG,sDAAsD,SAAS,GAC/E;AAAA,WACC;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,2BAAuB;AAAA,QACvB,WAAU;AAAA,QACV,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,cAAW;AAAA,QACX,UAAU;AAAA,QAEV,8BAAC,yBACC;AAAA,UAAC;AAAA;AAAA,YACC,iBACE;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,cAAW;AAAA,gBACX,OAAM;AAAA,gBACN,WAAW,eAAe,EAAE,SAAS,SAAS,MAAM,OAAO,CAAC;AAAA,gBAC5D,SAAS,MAAM,QAAQ,KAAK;AAAA,gBAE5B,8BAAC,QAAK,MAAK,SAAQ;AAAA;AAAA,YACrB;AAAA;AAAA,QAEJ,GACF;AAAA;AAAA,IACF,IACE;AAAA,IAEJ;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,WAAU;AAAA,QACV,OAAO;AAAA,UACL,iBAAiB;AAAA,UACjB,OAAO;AAAA,QACT;AAAA,QACA,iBAAe;AAAA,QACf,cAAY,OAAO,eAAe;AAAA,QAClC,SAAS,MAAM,QAAQ,OAAK,CAAC,CAAC;AAAA,QAE7B,iBACC,oBAAC,UAAK,eAAW,MAAC,WAAU,wBAAuB,kBAEnD,IAEA,oBAAC,aAAU,WAAU,UAAS;AAAA;AAAA,IAElC;AAAA,KACF;AAEJ;","names":[]}
|