@agent-native/toolkit 0.201.1 → 0.202.0-nightly-20261006033736
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/agent-native.eject.json +39 -12
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +292 -23
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/context.d.ts +5 -0
- package/dist/app/agentkit/react/context.d.ts.map +1 -1
- package/dist/app/agentkit/react/context.js +5 -0
- package/dist/app/agentkit/react/context.js.map +1 -1
- package/dist/app/agentkit/react/styles.css +78 -3
- package/dist/app/auth/AuthPage.d.ts.map +1 -1
- package/dist/app/auth/AuthPage.js +7 -14
- package/dist/app/auth/AuthPage.js.map +1 -1
- package/dist/app/auth/server.d.ts +6 -0
- package/dist/app/auth/server.d.ts.map +1 -0
- package/dist/app/auth/server.js +19 -0
- package/dist/app/auth/server.js.map +1 -0
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +164 -83
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/AgentSidebar.d.ts +2 -1
- package/dist/app/chat/AgentSidebar.d.ts.map +1 -1
- package/dist/app/chat/AgentSidebar.js +2 -2
- package/dist/app/chat/AgentSidebar.js.map +1 -1
- package/dist/app/chat/agentkit-chat/guided-questions.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/guided-questions.js +13 -3
- package/dist/app/chat/agentkit-chat/guided-questions.js.map +1 -1
- package/dist/app/chat/chat/surface-types.d.ts +2 -0
- package/dist/app/chat/chat/surface-types.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +41 -0
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +41 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +41 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +41 -0
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +41 -0
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +41 -0
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +41 -0
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +41 -0
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +41 -0
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +41 -0
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +41 -0
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +41 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/shared/StarfieldBackground.d.ts +1 -6
- package/dist/app/shared/StarfieldBackground.d.ts.map +1 -1
- package/dist/app/shared/StarfieldBackground.js +1 -368
- package/dist/app/shared/StarfieldBackground.js.map +1 -1
- package/dist/app/shared/WaveBackground.d.ts +5 -0
- package/dist/app/shared/WaveBackground.d.ts.map +1 -0
- package/dist/app/shared/WaveBackground.js +34 -0
- package/dist/app/shared/WaveBackground.js.map +1 -0
- package/dist/app/shared/WebGlWaveBackground.d.ts +9 -0
- package/dist/app/shared/WebGlWaveBackground.d.ts.map +1 -0
- package/dist/app/shared/WebGlWaveBackground.js +433 -0
- package/dist/app/shared/WebGlWaveBackground.js.map +1 -0
- package/dist/app/shared/index.d.ts +1 -0
- package/dist/app/shared/index.d.ts.map +1 -1
- package/dist/app/shared/index.js +1 -0
- package/dist/app/shared/index.js.map +1 -1
- package/dist/app/shared/ocean/bloom-blur.wgsl +43 -0
- package/dist/app/shared/ocean/bloom-blur.wgsl.js +1 -0
- package/dist/app/shared/ocean/bloom-bright.wgsl +21 -0
- package/dist/app/shared/ocean/bloom-bright.wgsl.js +1 -0
- package/dist/app/shared/ocean/bloom-composite.wgsl +40 -0
- package/dist/app/shared/ocean/bloom-composite.wgsl.js +1 -0
- package/dist/app/shared/ocean/brand-colors.d.ts +9 -0
- package/dist/app/shared/ocean/brand-colors.d.ts.map +1 -0
- package/dist/app/shared/ocean/brand-colors.js +45 -0
- package/dist/app/shared/ocean/brand-colors.js.map +1 -0
- package/dist/app/shared/ocean/camera.d.ts +5 -0
- package/dist/app/shared/ocean/camera.d.ts.map +1 -0
- package/dist/app/shared/ocean/camera.js +24 -0
- package/dist/app/shared/ocean/camera.js.map +1 -0
- package/dist/app/shared/ocean/hero-ocean-background.d.ts +8 -0
- package/dist/app/shared/ocean/hero-ocean-background.d.ts.map +1 -0
- package/dist/app/shared/ocean/hero-ocean-background.js +186 -0
- package/dist/app/shared/ocean/hero-ocean-background.js.map +1 -0
- package/dist/app/shared/ocean/ifft-stage.wgsl +36 -0
- package/dist/app/shared/ocean/ifft-stage.wgsl.js +1 -0
- package/dist/app/shared/ocean/initial-spectrum.wgsl +36 -0
- package/dist/app/shared/ocean/initial-spectrum.wgsl.js +1 -0
- package/dist/app/shared/ocean/noise.wgsl +24 -0
- package/dist/app/shared/ocean/noise.wgsl.js +1 -0
- package/dist/app/shared/ocean/normal-foam.wgsl +32 -0
- package/dist/app/shared/ocean/normal-foam.wgsl.js +1 -0
- package/dist/app/shared/ocean/ocean-colors.d.ts +6 -0
- package/dist/app/shared/ocean/ocean-colors.d.ts.map +1 -0
- package/dist/app/shared/ocean/ocean-colors.js +6 -0
- package/dist/app/shared/ocean/ocean-colors.js.map +1 -0
- package/dist/app/shared/ocean/ocean-common.wgsl +15 -0
- package/dist/app/shared/ocean/ocean-common.wgsl.js +1 -0
- package/dist/app/shared/ocean/ocean-graph.d.ts +12 -0
- package/dist/app/shared/ocean/ocean-graph.d.ts.map +1 -0
- package/dist/app/shared/ocean/ocean-graph.js +16 -0
- package/dist/app/shared/ocean/ocean-graph.js.map +1 -0
- package/dist/app/shared/ocean/particles.wgsl +139 -0
- package/dist/app/shared/ocean/particles.wgsl.js +1 -0
- package/dist/app/shared/ocean/present.wgsl +40 -0
- package/dist/app/shared/ocean/present.wgsl.js +1 -0
- package/dist/app/shared/ocean/renderer.d.ts +66 -0
- package/dist/app/shared/ocean/renderer.d.ts.map +1 -0
- package/dist/app/shared/ocean/renderer.js +535 -0
- package/dist/app/shared/ocean/renderer.js.map +1 -0
- package/dist/app/shared/ocean/spectrum.wgsl +35 -0
- package/dist/app/shared/ocean/spectrum.wgsl.js +1 -0
- package/dist/app/shared/ocean/tuning.d.ts +48 -0
- package/dist/app/shared/ocean/tuning.d.ts.map +1 -0
- package/dist/app/shared/ocean/tuning.js +74 -0
- package/dist/app/shared/ocean/tuning.js.map +1 -0
- package/dist/app/shared/ocean/webgpu-support.d.ts +3 -0
- package/dist/app/shared/ocean/webgpu-support.d.ts.map +1 -0
- package/dist/app/shared/ocean/webgpu-support.js +13 -0
- package/dist/app/shared/ocean/webgpu-support.js.map +1 -0
- package/dist/app/sharing/AccessRequestApprovalPage.d.ts +23 -0
- package/dist/app/sharing/AccessRequestApprovalPage.d.ts.map +1 -0
- package/dist/app/sharing/AccessRequestApprovalPage.js +95 -0
- package/dist/app/sharing/AccessRequestApprovalPage.js.map +1 -0
- package/dist/app/sharing/AccessRequestsSection.d.ts +5 -0
- package/dist/app/sharing/AccessRequestsSection.d.ts.map +1 -0
- package/dist/app/sharing/AccessRequestsSection.js +47 -0
- package/dist/app/sharing/AccessRequestsSection.js.map +1 -0
- package/dist/app/sharing/ResourceAccessScreen.d.ts +53 -0
- package/dist/app/sharing/ResourceAccessScreen.d.ts.map +1 -0
- package/dist/app/sharing/ResourceAccessScreen.js +132 -0
- package/dist/app/sharing/ResourceAccessScreen.js.map +1 -0
- package/dist/app/sharing/ShareButton.d.ts.map +1 -1
- package/dist/app/sharing/ShareButton.js +4 -2
- package/dist/app/sharing/ShareButton.js.map +1 -1
- package/dist/app/sharing/ShareDialog.d.ts.map +1 -1
- package/dist/app/sharing/ShareDialog.js +7 -5
- package/dist/app/sharing/ShareDialog.js.map +1 -1
- package/dist/app/sharing/index.d.ts +2 -0
- package/dist/app/sharing/index.d.ts.map +1 -1
- package/dist/app/sharing/index.js +2 -0
- package/dist/app/sharing/index.js.map +1 -1
- package/dist/app/styles/agent-native.css +21 -1
- package/dist/app/styles/tokens/agent-kit.css +3 -1
- package/dist/composer/AgentSuggestionBar.d.ts +1 -1
- package/dist/composer/AgentSuggestionBar.d.ts.map +1 -1
- package/dist/composer/AgentSuggestionBar.js +75 -6
- package/dist/composer/AgentSuggestionBar.js.map +1 -1
- package/package.json +14 -4
- package/src/app/agentkit/react/components.tsx +492 -60
- package/src/app/agentkit/react/context.tsx +10 -0
- package/src/app/agentkit/react/lifecycle.spec.tsx +487 -1
- package/src/app/agentkit/react/styles.css +78 -3
- package/src/app/auth/AuthPage.spec.tsx +11 -7
- package/src/app/auth/AuthPage.tsx +16 -35
- package/src/app/auth/server.spec.ts +68 -0
- package/src/app/auth/server.ts +29 -0
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +287 -290
- package/src/app/chat/AgentKitAssistantChat.tsx +219 -116
- package/src/app/chat/AgentSidebar.tsx +3 -0
- package/src/app/chat/agentkit-chat/guided-questions.flow.spec.tsx +85 -0
- package/src/app/chat/agentkit-chat/guided-questions.tsx +12 -5
- package/src/app/chat/chat/surface-types.ts +2 -0
- package/src/app/i18n/catalogs/ar-SA.ts +44 -0
- package/src/app/i18n/catalogs/de-DE.ts +55 -0
- package/src/app/i18n/catalogs/en-US.ts +46 -0
- package/src/app/i18n/catalogs/es-ES.ts +53 -0
- package/src/app/i18n/catalogs/fr-FR.ts +53 -0
- package/src/app/i18n/catalogs/hi-IN.ts +47 -0
- package/src/app/i18n/catalogs/ja-JP.ts +54 -0
- package/src/app/i18n/catalogs/ko-KR.ts +50 -0
- package/src/app/i18n/catalogs/pt-BR.ts +52 -0
- package/src/app/i18n/catalogs/zh-CN.ts +42 -0
- package/src/app/i18n/catalogs/zh-TW.ts +43 -0
- package/src/app/shared/StarfieldBackground.tsx +4 -423
- package/src/app/shared/WaveBackground.spec.tsx +104 -0
- package/src/app/shared/WaveBackground.tsx +60 -0
- package/src/app/shared/WebGlWaveBackground.spec.tsx +106 -0
- package/src/app/shared/WebGlWaveBackground.tsx +499 -0
- package/src/app/shared/index.ts +1 -0
- package/src/app/shared/ocean/bloom-blur.wgsl +43 -0
- package/src/app/shared/ocean/bloom-bright.wgsl +21 -0
- package/src/app/shared/ocean/bloom-composite.wgsl +40 -0
- package/src/app/shared/ocean/brand-colors.ts +49 -0
- package/src/app/shared/ocean/camera.ts +28 -0
- package/src/app/shared/ocean/hero-ocean-background.spec.tsx +369 -0
- package/src/app/shared/ocean/hero-ocean-background.tsx +238 -0
- package/src/app/shared/ocean/ifft-stage.wgsl +36 -0
- package/src/app/shared/ocean/initial-spectrum.wgsl +36 -0
- package/src/app/shared/ocean/noise.wgsl +24 -0
- package/src/app/shared/ocean/normal-foam.wgsl +32 -0
- package/src/app/shared/ocean/ocean-colors.ts +11 -0
- package/src/app/shared/ocean/ocean-common.wgsl +15 -0
- package/src/app/shared/ocean/ocean-graph.ts +29 -0
- package/src/app/shared/ocean/particles.wgsl +139 -0
- package/src/app/shared/ocean/present.wgsl +40 -0
- package/src/app/shared/ocean/renderer.spec.ts +100 -0
- package/src/app/shared/ocean/renderer.ts +693 -0
- package/src/app/shared/ocean/spectrum.wgsl +35 -0
- package/src/app/shared/ocean/tuning.ts +131 -0
- package/src/app/shared/ocean/webgpu-support.ts +12 -0
- package/src/app/sharing/AccessRequestApprovalPage.spec.tsx +276 -0
- package/src/app/sharing/AccessRequestApprovalPage.tsx +307 -0
- package/src/app/sharing/AccessRequestsSection.tsx +163 -0
- package/src/app/sharing/ResourceAccessScreen.spec.tsx +235 -0
- package/src/app/sharing/ResourceAccessScreen.tsx +331 -0
- package/src/app/sharing/ShareButton.spec.tsx +171 -5
- package/src/app/sharing/ShareButton.tsx +15 -2
- package/src/app/sharing/ShareDialog.spec.tsx +71 -2
- package/src/app/sharing/ShareDialog.tsx +24 -2
- package/src/app/sharing/index.ts +2 -0
- package/src/app/styles/agent-native.css +21 -1
- package/src/app/styles/agent-native.spec.ts +16 -3
- package/src/app/styles/tokens/agent-kit.css +3 -1
- package/src/composer/AgentSuggestionBar.overflow.spec.tsx +277 -0
- package/src/composer/AgentSuggestionBar.tsx +113 -8
- package/src/wgsl-env.d.ts +6 -0
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
} from "@tabler/icons-react";
|
|
28
28
|
import { type ReactNode } from "react";
|
|
29
29
|
|
|
30
|
+
import { AccessRequestsSection } from "./AccessRequestsSection.js";
|
|
30
31
|
import { AgentShareSection } from "./AgentShareSection.js";
|
|
31
32
|
|
|
32
33
|
export interface ShareDialogProps {
|
|
@@ -83,6 +84,12 @@ export function ShareDialog({
|
|
|
83
84
|
});
|
|
84
85
|
if (!open) return null;
|
|
85
86
|
const dialogTitle = title ?? controller.title;
|
|
87
|
+
const accessRequests = controller.canManage ? (
|
|
88
|
+
<AccessRequestsSection
|
|
89
|
+
resourceType={resourceType}
|
|
90
|
+
resourceId={resourceId}
|
|
91
|
+
/>
|
|
92
|
+
) : null;
|
|
86
93
|
const showTabList =
|
|
87
94
|
controller.tabs.length > 1 || controller.tabs[0]?.value !== "link";
|
|
88
95
|
|
|
@@ -132,12 +139,17 @@ export function ShareDialog({
|
|
|
132
139
|
|
|
133
140
|
<div className="px-5 py-4">
|
|
134
141
|
{controller.tabsEnabled && controller.activeTab === "link" ? (
|
|
135
|
-
<LinkTab
|
|
142
|
+
<LinkTab
|
|
143
|
+
controller={controller}
|
|
144
|
+
extras={linkTabExtras}
|
|
145
|
+
accessRequests={accessRequests}
|
|
146
|
+
/>
|
|
136
147
|
) : null}
|
|
137
148
|
{!controller.tabsEnabled || controller.activeTab === "invite" ? (
|
|
138
149
|
<InviteTab
|
|
139
150
|
controller={controller}
|
|
140
151
|
showVisibility={!controller.tabsEnabled}
|
|
152
|
+
accessRequests={accessRequests}
|
|
141
153
|
/>
|
|
142
154
|
) : null}
|
|
143
155
|
{controller.tabsEnabled && controller.activeTab === "embed"
|
|
@@ -184,9 +196,11 @@ function TabTrigger({
|
|
|
184
196
|
function LinkTab({
|
|
185
197
|
controller,
|
|
186
198
|
extras,
|
|
199
|
+
accessRequests,
|
|
187
200
|
}: {
|
|
188
201
|
controller: ShareDialogController;
|
|
189
202
|
extras?: ReactNode;
|
|
203
|
+
accessRequests: ReactNode;
|
|
190
204
|
}) {
|
|
191
205
|
const Icon = VIS_ICONS[controller.visibility.value];
|
|
192
206
|
return (
|
|
@@ -218,7 +232,11 @@ function LinkTab({
|
|
|
218
232
|
</div>
|
|
219
233
|
</div>
|
|
220
234
|
</div>
|
|
221
|
-
<InviteTab
|
|
235
|
+
<InviteTab
|
|
236
|
+
controller={controller}
|
|
237
|
+
showVisibility={false}
|
|
238
|
+
accessRequests={accessRequests}
|
|
239
|
+
/>
|
|
222
240
|
{extras}
|
|
223
241
|
</div>
|
|
224
242
|
);
|
|
@@ -227,9 +245,11 @@ function LinkTab({
|
|
|
227
245
|
function InviteTab({
|
|
228
246
|
controller,
|
|
229
247
|
showVisibility,
|
|
248
|
+
accessRequests,
|
|
230
249
|
}: {
|
|
231
250
|
controller: ShareDialogController;
|
|
232
251
|
showVisibility: boolean;
|
|
252
|
+
accessRequests: ReactNode;
|
|
233
253
|
}) {
|
|
234
254
|
const Icon = VIS_ICONS[controller.visibility.value];
|
|
235
255
|
return (
|
|
@@ -256,6 +276,8 @@ function InviteTab({
|
|
|
256
276
|
</div>
|
|
257
277
|
) : null}
|
|
258
278
|
|
|
279
|
+
{accessRequests}
|
|
280
|
+
|
|
259
281
|
<div className="space-y-4">
|
|
260
282
|
<div className="text-sm font-semibold">
|
|
261
283
|
{controller.labels.peopleWithAccess}
|
package/src/app/sharing/index.ts
CHANGED
|
@@ -1065,6 +1065,19 @@
|
|
|
1065
1065
|
z-index: 1;
|
|
1066
1066
|
margin-bottom: -1.875rem;
|
|
1067
1067
|
padding-bottom: 0 !important;
|
|
1068
|
+
animation: agent-builder-setup-card-enter 220ms var(--ease-out-strong) both;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
@keyframes agent-builder-setup-card-enter {
|
|
1072
|
+
from {
|
|
1073
|
+
opacity: 0;
|
|
1074
|
+
transform: translateY(0.75rem);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
to {
|
|
1078
|
+
opacity: 1;
|
|
1079
|
+
transform: translateY(0);
|
|
1080
|
+
}
|
|
1068
1081
|
}
|
|
1069
1082
|
|
|
1070
1083
|
.agent-builder-setup-card--attached .agent-builder-setup-card__panel {
|
|
@@ -1241,6 +1254,10 @@
|
|
|
1241
1254
|
}
|
|
1242
1255
|
|
|
1243
1256
|
@media (prefers-reduced-motion: reduce) {
|
|
1257
|
+
.agent-builder-setup-card--attached {
|
|
1258
|
+
animation: none;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1244
1261
|
.agent-builder-setup-card--attached.animate-bounce-once {
|
|
1245
1262
|
animation: none;
|
|
1246
1263
|
}
|
|
@@ -1250,7 +1267,10 @@
|
|
|
1250
1267
|
min-height: var(--agent-kit-composer-min-height);
|
|
1251
1268
|
border-radius: var(--agent-kit-composer-radius);
|
|
1252
1269
|
border-color: var(--agent-kit-composer-border-color);
|
|
1253
|
-
background: var(
|
|
1270
|
+
background: var(
|
|
1271
|
+
--agent-kit-composer-surface,
|
|
1272
|
+
var(--agent-kit-raised-surface)
|
|
1273
|
+
);
|
|
1254
1274
|
box-shadow: var(--agent-kit-composer-elevation);
|
|
1255
1275
|
}
|
|
1256
1276
|
|
|
@@ -275,17 +275,30 @@ describe("agent-native shell surface tokens", () => {
|
|
|
275
275
|
);
|
|
276
276
|
});
|
|
277
277
|
|
|
278
|
-
it("
|
|
278
|
+
it("uses a subtle dark composer surface and a focused boundary", () => {
|
|
279
|
+
const css = readFileSync(new URL("./agent-native.css", import.meta.url), {
|
|
280
|
+
encoding: "utf8",
|
|
281
|
+
});
|
|
282
|
+
const agentkitCss = readFileSync(
|
|
283
|
+
new URL("../agentkit/react/styles.css", import.meta.url),
|
|
284
|
+
{ encoding: "utf8" },
|
|
285
|
+
);
|
|
279
286
|
const tokens = readFileSync(
|
|
280
287
|
new URL("./tokens/agent-kit.css", import.meta.url),
|
|
281
288
|
{ encoding: "utf8" },
|
|
282
289
|
);
|
|
283
290
|
|
|
284
291
|
expect(tokens).toMatch(
|
|
285
|
-
/:root\s*\{[\s\S]*?--agent-kit-composer-border-mix: 82%;[\s\S]*?--agent-kit-composer-focus-border-mix: 100%;[\s\S]*?--agent-kit-composer-border-color: color-mix\([\s\S]*?--agent-kit-composer-focus-border-color: color-mix\(/s,
|
|
292
|
+
/:root\s*\{[\s\S]*?--agent-kit-composer-surface: var\(--agent-kit-raised-surface\);[\s\S]*?--agent-kit-composer-border-mix: 82%;[\s\S]*?--agent-kit-composer-focus-border-mix: 100%;[\s\S]*?--agent-kit-composer-border-color: color-mix\([\s\S]*?--agent-kit-composer-focus-border-color: color-mix\(/s,
|
|
286
293
|
);
|
|
287
294
|
expect(tokens).toMatch(
|
|
288
|
-
/:is\(\.dark, :root\[data-theme="dark"\]:not\(\.light\)\)\s*\{[\s\S]*?--agent-kit-composer-border-mix:
|
|
295
|
+
/:is\(\.dark, :root\[data-theme="dark"\]:not\(\.light\)\)\s*\{[\s\S]*?--agent-kit-composer-surface: var\(--agent-kit-subtle-surface\);[\s\S]*?--agent-kit-composer-border-mix: 0%;[\s\S]*?--agent-kit-composer-focus-border-mix: 65%;[\s\S]*?--agent-kit-composer-border-color: color-mix\([\s\S]*?--agent-kit-composer-focus-border-color: color-mix\(/s,
|
|
296
|
+
);
|
|
297
|
+
expect(css).toMatch(
|
|
298
|
+
/background:\s*var\(\s*--agent-kit-composer-surface,\s*var\(--agent-kit-raised-surface\)\s*\);/,
|
|
299
|
+
);
|
|
300
|
+
expect(agentkitCss).toMatch(
|
|
301
|
+
/--agent-kit-composer-surface,\s*var\(--agentkit-surface\)/,
|
|
289
302
|
);
|
|
290
303
|
});
|
|
291
304
|
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
--agent-kit-composer-block-padding-end: 1rem;
|
|
44
44
|
--agent-kit-composer-min-height: 4.75rem;
|
|
45
45
|
--agent-kit-composer-radius: 1.25rem;
|
|
46
|
+
--agent-kit-composer-surface: var(--agent-kit-raised-surface);
|
|
46
47
|
--agent-kit-composer-border-mix: 82%;
|
|
47
48
|
--agent-kit-composer-focus-border-mix: 100%;
|
|
48
49
|
--agent-kit-composer-border-color: color-mix(
|
|
@@ -101,7 +102,8 @@
|
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
:is(.dark, :root[data-theme="dark"]:not(.light)) {
|
|
104
|
-
--agent-kit-composer-
|
|
105
|
+
--agent-kit-composer-surface: var(--agent-kit-subtle-surface);
|
|
106
|
+
--agent-kit-composer-border-mix: 0%;
|
|
105
107
|
--agent-kit-composer-focus-border-mix: 65%;
|
|
106
108
|
--agent-kit-composer-border-color: color-mix(
|
|
107
109
|
in srgb,
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
import React, { act } from "react";
|
|
8
|
+
import { createRoot, type Root } from "react-dom/client";
|
|
9
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
10
|
+
|
|
11
|
+
import type { ActionButtonProps } from "../design-system/types.js";
|
|
12
|
+
import { ToolkitProvider } from "../provider.js";
|
|
13
|
+
import { AgentSuggestionBar } from "./AgentSuggestionBar.js";
|
|
14
|
+
|
|
15
|
+
const DOCUMENT_SUGGESTIONS = [
|
|
16
|
+
"Summarize this document",
|
|
17
|
+
"Improve this document",
|
|
18
|
+
"Find the action items",
|
|
19
|
+
];
|
|
20
|
+
const CHIP_WIDTHS: Record<string, number> = {
|
|
21
|
+
"Summarize this document": 155,
|
|
22
|
+
"Improve this document": 144,
|
|
23
|
+
"Find the action items": 144,
|
|
24
|
+
};
|
|
25
|
+
// A 280px agent panel minus the bar's and scroller's inline padding.
|
|
26
|
+
const NARROWEST_SCROLLER_WIDTH = 252;
|
|
27
|
+
|
|
28
|
+
describe("AgentSuggestionBar overflow", () => {
|
|
29
|
+
let container: HTMLDivElement;
|
|
30
|
+
let root: Root;
|
|
31
|
+
let gapStyle: HTMLStyleElement;
|
|
32
|
+
let scrollerWidth: number;
|
|
33
|
+
let scrollOffset: number;
|
|
34
|
+
let resizeCallbacks: Array<() => void>;
|
|
35
|
+
let disconnectObserver: ReturnType<typeof vi.fn>;
|
|
36
|
+
const descriptors = new Map<string, PropertyDescriptor | undefined>();
|
|
37
|
+
|
|
38
|
+
const scroller = () =>
|
|
39
|
+
container.querySelector<HTMLElement>(
|
|
40
|
+
'[data-agent-suggestion-scroller="true"]',
|
|
41
|
+
)!;
|
|
42
|
+
const track = () =>
|
|
43
|
+
container.querySelector<HTMLElement>(
|
|
44
|
+
'[data-agent-suggestion-track="true"]',
|
|
45
|
+
)!;
|
|
46
|
+
const trackWidth = () =>
|
|
47
|
+
Number.parseFloat(
|
|
48
|
+
track().style.getPropertyValue("--agent-suggestion-track-width"),
|
|
49
|
+
);
|
|
50
|
+
const fadeEdges = () => ({
|
|
51
|
+
start: scroller().getAttribute("data-overflow-start"),
|
|
52
|
+
end: scroller().getAttribute("data-overflow-end"),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
function defineLayout(name: string, descriptor: PropertyDescriptor) {
|
|
56
|
+
descriptors.set(
|
|
57
|
+
name,
|
|
58
|
+
Object.getOwnPropertyDescriptor(HTMLElement.prototype, name),
|
|
59
|
+
);
|
|
60
|
+
Object.defineProperty(HTMLElement.prototype, name, {
|
|
61
|
+
configurable: true,
|
|
62
|
+
...descriptor,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function render(suggestions: string[]) {
|
|
67
|
+
act(() => {
|
|
68
|
+
root.render(
|
|
69
|
+
<AgentSuggestionBar
|
|
70
|
+
ariaLabel="Suggested prompts"
|
|
71
|
+
suggestions={suggestions}
|
|
72
|
+
onSelect={() => {}}
|
|
73
|
+
/>,
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function resizeScroller(width: number) {
|
|
79
|
+
scrollerWidth = width;
|
|
80
|
+
act(() => resizeCallbacks.forEach((callback) => callback()));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function scrollTo(offset: number) {
|
|
84
|
+
scrollOffset = offset;
|
|
85
|
+
act(() => {
|
|
86
|
+
scroller().dispatchEvent(new Event("scroll"));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
beforeEach(() => {
|
|
91
|
+
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
|
|
92
|
+
scrollerWidth = NARROWEST_SCROLLER_WIDTH;
|
|
93
|
+
scrollOffset = 0;
|
|
94
|
+
resizeCallbacks = [];
|
|
95
|
+
disconnectObserver = vi.fn();
|
|
96
|
+
vi.stubGlobal(
|
|
97
|
+
"ResizeObserver",
|
|
98
|
+
class {
|
|
99
|
+
constructor(callback: () => void) {
|
|
100
|
+
resizeCallbacks.push(callback);
|
|
101
|
+
}
|
|
102
|
+
observe() {}
|
|
103
|
+
disconnect = disconnectObserver;
|
|
104
|
+
},
|
|
105
|
+
);
|
|
106
|
+
vi.stubGlobal("requestAnimationFrame", (callback: FrameRequestCallback) => {
|
|
107
|
+
callback(0);
|
|
108
|
+
return 1;
|
|
109
|
+
});
|
|
110
|
+
vi.stubGlobal("cancelAnimationFrame", () => {});
|
|
111
|
+
|
|
112
|
+
gapStyle = document.createElement("style");
|
|
113
|
+
gapStyle.textContent =
|
|
114
|
+
'[data-agent-suggestion-track="true"] { column-gap: 4px; }';
|
|
115
|
+
document.head.appendChild(gapStyle);
|
|
116
|
+
|
|
117
|
+
defineLayout("getBoundingClientRect", {
|
|
118
|
+
value(this: HTMLElement) {
|
|
119
|
+
const width = CHIP_WIDTHS[this.textContent ?? ""] ?? 0;
|
|
120
|
+
return { width, height: 28, top: 0, left: 0, right: width, bottom: 28 };
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
defineLayout("clientWidth", {
|
|
124
|
+
get(this: HTMLElement) {
|
|
125
|
+
return this.dataset.agentSuggestionScroller ? scrollerWidth : 0;
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
defineLayout("scrollWidth", {
|
|
129
|
+
get(this: HTMLElement) {
|
|
130
|
+
if (!this.dataset.agentSuggestionScroller) return 0;
|
|
131
|
+
return Math.max(scrollerWidth, trackWidth());
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
defineLayout("scrollLeft", {
|
|
135
|
+
get() {
|
|
136
|
+
return scrollOffset;
|
|
137
|
+
},
|
|
138
|
+
set(value: number) {
|
|
139
|
+
scrollOffset = value;
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
container = document.createElement("div");
|
|
144
|
+
document.body.appendChild(container);
|
|
145
|
+
root = createRoot(container);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
afterEach(() => {
|
|
149
|
+
act(() => root.unmount());
|
|
150
|
+
container.remove();
|
|
151
|
+
gapStyle.remove();
|
|
152
|
+
for (const [name, descriptor] of descriptors) {
|
|
153
|
+
if (descriptor) {
|
|
154
|
+
Object.defineProperty(HTMLElement.prototype, name, descriptor);
|
|
155
|
+
} else {
|
|
156
|
+
delete (HTMLElement.prototype as unknown as Record<string, unknown>)[
|
|
157
|
+
name
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
descriptors.clear();
|
|
162
|
+
vi.unstubAllGlobals();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("wraps document suggestions onto two lines at the narrowest panel", () => {
|
|
166
|
+
render(DOCUMENT_SUGGESTIONS);
|
|
167
|
+
|
|
168
|
+
expect(
|
|
169
|
+
[...container.querySelectorAll("button")].map(
|
|
170
|
+
(button) => button.textContent,
|
|
171
|
+
),
|
|
172
|
+
).toEqual(DOCUMENT_SUGGESTIONS);
|
|
173
|
+
expect(track().className).toContain("flex-wrap");
|
|
174
|
+
expect(track().className).toContain("min-w-full");
|
|
175
|
+
// The measured width only lays the chips out in two lines once the track
|
|
176
|
+
// is sized by it; the mocked geometry here cannot show that on its own.
|
|
177
|
+
expect(track().className).toContain("w-(--agent-suggestion-track-width)");
|
|
178
|
+
expect(trackWidth()).toBe(144 + 4 + 144);
|
|
179
|
+
expect(fadeEdges()).toEqual({ start: null, end: "true" });
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("fades only the edges that still hide suggestions", () => {
|
|
183
|
+
render(DOCUMENT_SUGGESTIONS);
|
|
184
|
+
const hidden = trackWidth() - NARROWEST_SCROLLER_WIDTH;
|
|
185
|
+
|
|
186
|
+
scrollTo(hidden / 2);
|
|
187
|
+
expect(fadeEdges()).toEqual({ start: "true", end: "true" });
|
|
188
|
+
|
|
189
|
+
scrollTo(hidden);
|
|
190
|
+
expect(fadeEdges()).toEqual({ start: "true", end: null });
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("drops the fade once a resize lets every suggestion fit", () => {
|
|
194
|
+
render(DOCUMENT_SUGGESTIONS);
|
|
195
|
+
expect(fadeEdges().end).toBe("true");
|
|
196
|
+
|
|
197
|
+
resizeScroller(480);
|
|
198
|
+
expect(fadeEdges()).toEqual({ start: null, end: null });
|
|
199
|
+
|
|
200
|
+
resizeScroller(NARROWEST_SCROLLER_WIDTH);
|
|
201
|
+
expect(fadeEdges()).toEqual({ start: null, end: "true" });
|
|
202
|
+
|
|
203
|
+
act(() => root.unmount());
|
|
204
|
+
expect(disconnectObserver).toHaveBeenCalled();
|
|
205
|
+
root = createRoot(container);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it("scrolls a keyboard-focused suggestion out from under the fade", () => {
|
|
209
|
+
const scrollIntoView = vi.fn();
|
|
210
|
+
defineLayout("scrollIntoView", { value: scrollIntoView });
|
|
211
|
+
render(DOCUMENT_SUGGESTIONS);
|
|
212
|
+
const lastChip = [...container.querySelectorAll("button")].at(-1)!;
|
|
213
|
+
|
|
214
|
+
act(() => lastChip.focus());
|
|
215
|
+
|
|
216
|
+
expect(scrollIntoView).toHaveBeenCalledWith({
|
|
217
|
+
block: "nearest",
|
|
218
|
+
inline: "nearest",
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it("reveals a keyboard-focused suggestion rendered by a host's ActionButton", () => {
|
|
223
|
+
const scrollIntoView = vi.fn();
|
|
224
|
+
defineLayout("scrollIntoView", { value: scrollIntoView });
|
|
225
|
+
// Adapters receive only the props Button forwards, which omit onFocus.
|
|
226
|
+
const HostActionButton = ({
|
|
227
|
+
label,
|
|
228
|
+
onClick,
|
|
229
|
+
elementRef,
|
|
230
|
+
}: ActionButtonProps) => (
|
|
231
|
+
<button ref={elementRef} type="button" onClick={onClick}>
|
|
232
|
+
{label}
|
|
233
|
+
</button>
|
|
234
|
+
);
|
|
235
|
+
act(() => {
|
|
236
|
+
root.render(
|
|
237
|
+
<ToolkitProvider
|
|
238
|
+
designSystem={{ components: { ActionButton: HostActionButton } }}
|
|
239
|
+
>
|
|
240
|
+
<AgentSuggestionBar
|
|
241
|
+
ariaLabel="Suggested prompts"
|
|
242
|
+
suggestions={DOCUMENT_SUGGESTIONS}
|
|
243
|
+
onSelect={() => {}}
|
|
244
|
+
/>
|
|
245
|
+
</ToolkitProvider>,
|
|
246
|
+
);
|
|
247
|
+
});
|
|
248
|
+
const lastChip = [...container.querySelectorAll("button")].at(-1)!;
|
|
249
|
+
|
|
250
|
+
act(() => lastChip.focus());
|
|
251
|
+
|
|
252
|
+
expect(scrollIntoView).toHaveBeenCalledWith({
|
|
253
|
+
block: "nearest",
|
|
254
|
+
inline: "nearest",
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it("ships the fade and wrap styles for every host", () => {
|
|
259
|
+
const styles = readFileSync(
|
|
260
|
+
path.resolve(
|
|
261
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
262
|
+
"../app/agentkit/react/styles.css",
|
|
263
|
+
),
|
|
264
|
+
"utf8",
|
|
265
|
+
).replace(/\r\n/g, "\n");
|
|
266
|
+
|
|
267
|
+
expect(styles).toMatch(
|
|
268
|
+
/\[data-agent-suggestion-scroller="true"\]:is\(\s*\[data-overflow-start\],\s*\[data-overflow-end\]\s*\) \{[\s\S]*?mask-image: linear-gradient\(/,
|
|
269
|
+
);
|
|
270
|
+
expect(styles).toMatch(
|
|
271
|
+
/\[data-agent-suggestion-scroller="true"\]\[data-overflow-end\] \{\n --agent-suggestion-fade-end: 1\.5rem;/,
|
|
272
|
+
);
|
|
273
|
+
expect(styles).toMatch(
|
|
274
|
+
/\.agentkit-suggestions \[data-agent-suggestion-track="true"\] \{[\s\S]*?flex-wrap: wrap;[\s\S]*?inline-size: var\(--agent-suggestion-track-width\);[\s\S]*?min-inline-size: 100%;/,
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
useEffect,
|
|
3
|
+
useLayoutEffect,
|
|
4
|
+
useRef,
|
|
5
|
+
useState,
|
|
6
|
+
type FocusEvent,
|
|
7
|
+
type ReactNode,
|
|
8
|
+
} from "react";
|
|
2
9
|
|
|
3
10
|
import { Button } from "../ui/button.js";
|
|
4
11
|
import { cn } from "../utils.js";
|
|
5
12
|
|
|
13
|
+
const useBrowserLayoutEffect =
|
|
14
|
+
typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
15
|
+
|
|
6
16
|
export interface AgentSuggestionItem {
|
|
7
17
|
id: string;
|
|
8
18
|
label: string;
|
|
@@ -41,6 +51,90 @@ export function agentSuggestionPrompt(
|
|
|
41
51
|
: (suggestion.prompt ?? suggestion.label);
|
|
42
52
|
}
|
|
43
53
|
|
|
54
|
+
function twoLineTrackWidth(widths: readonly number[], gap: number): number {
|
|
55
|
+
const total =
|
|
56
|
+
widths.reduce((sum, width) => sum + width, 0) +
|
|
57
|
+
gap * Math.max(widths.length - 1, 0);
|
|
58
|
+
let narrowest = total;
|
|
59
|
+
let firstLine = -gap;
|
|
60
|
+
for (const width of widths.slice(0, -1)) {
|
|
61
|
+
firstLine += gap + width;
|
|
62
|
+
narrowest = Math.min(
|
|
63
|
+
narrowest,
|
|
64
|
+
Math.max(firstLine, total - firstLine - gap),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return narrowest;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Chrome does not scroll a partly visible chip into view when it takes
|
|
71
|
+
// keyboard focus, which leaves it under the edge fade. Listen on the track:
|
|
72
|
+
// a host's ActionButton adapter receives only the props Button forwards, and
|
|
73
|
+
// onFocus is not one of them.
|
|
74
|
+
function revealKeyboardFocusedChip(event: FocusEvent<HTMLDivElement>) {
|
|
75
|
+
const chip = event.target;
|
|
76
|
+
if (!(chip instanceof HTMLElement) || !chip.matches(":focus-visible")) return;
|
|
77
|
+
chip.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function useTwoLineSuggestionTrack(layoutKey: string) {
|
|
81
|
+
const scrollerRef = useRef<HTMLDivElement>(null);
|
|
82
|
+
const trackRef = useRef<HTMLDivElement>(null);
|
|
83
|
+
const [overflow, setOverflow] = useState({ start: false, end: false });
|
|
84
|
+
|
|
85
|
+
useBrowserLayoutEffect(() => {
|
|
86
|
+
const scroller = scrollerRef.current;
|
|
87
|
+
const track = trackRef.current;
|
|
88
|
+
if (!scroller || !track) return;
|
|
89
|
+
const chips = Array.from(track.children);
|
|
90
|
+
const updateOverflow = () => {
|
|
91
|
+
const offset = Math.abs(scroller.scrollLeft);
|
|
92
|
+
const start = offset > 1;
|
|
93
|
+
const end = offset + scroller.clientWidth < scroller.scrollWidth - 1;
|
|
94
|
+
setOverflow((current) =>
|
|
95
|
+
current.start === start && current.end === end
|
|
96
|
+
? current
|
|
97
|
+
: { start, end },
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
const update = () => {
|
|
101
|
+
const gap = Number.parseFloat(getComputedStyle(track).columnGap);
|
|
102
|
+
const width = twoLineTrackWidth(
|
|
103
|
+
chips.map((chip) => chip.getBoundingClientRect().width),
|
|
104
|
+
Number.isNaN(gap) ? 0 : gap,
|
|
105
|
+
);
|
|
106
|
+
track.style.setProperty(
|
|
107
|
+
"--agent-suggestion-track-width",
|
|
108
|
+
`${Math.ceil(width)}px`,
|
|
109
|
+
);
|
|
110
|
+
updateOverflow();
|
|
111
|
+
};
|
|
112
|
+
update();
|
|
113
|
+
|
|
114
|
+
// Resizing the track inside the observer callback resizes the observed
|
|
115
|
+
// scroller in the same frame, which the browser reports as a
|
|
116
|
+
// ResizeObserver loop error. Measure on the next frame instead.
|
|
117
|
+
let frame = 0;
|
|
118
|
+
const observer =
|
|
119
|
+
typeof ResizeObserver === "undefined"
|
|
120
|
+
? null
|
|
121
|
+
: new ResizeObserver(() => {
|
|
122
|
+
cancelAnimationFrame(frame);
|
|
123
|
+
frame = requestAnimationFrame(update);
|
|
124
|
+
});
|
|
125
|
+
observer?.observe(scroller);
|
|
126
|
+
for (const chip of chips) observer?.observe(chip);
|
|
127
|
+
scroller.addEventListener("scroll", updateOverflow, { passive: true });
|
|
128
|
+
return () => {
|
|
129
|
+
cancelAnimationFrame(frame);
|
|
130
|
+
observer?.disconnect();
|
|
131
|
+
scroller.removeEventListener("scroll", updateOverflow);
|
|
132
|
+
};
|
|
133
|
+
}, [layoutKey]);
|
|
134
|
+
|
|
135
|
+
return { scrollerRef, trackRef, overflow };
|
|
136
|
+
}
|
|
137
|
+
|
|
44
138
|
export function AgentSuggestionBar({
|
|
45
139
|
suggestions,
|
|
46
140
|
ariaLabel,
|
|
@@ -48,7 +142,11 @@ export function AgentSuggestionBar({
|
|
|
48
142
|
renderSuggestion,
|
|
49
143
|
className,
|
|
50
144
|
}: AgentSuggestionBarProps) {
|
|
51
|
-
|
|
145
|
+
const items = suggestions.map(normalizeAgentSuggestion);
|
|
146
|
+
const { scrollerRef, trackRef, overflow } = useTwoLineSuggestionTrack(
|
|
147
|
+
items.map((item) => item.id).join("\n"),
|
|
148
|
+
);
|
|
149
|
+
if (items.length === 0) return null;
|
|
52
150
|
|
|
53
151
|
return (
|
|
54
152
|
<section
|
|
@@ -57,12 +155,19 @@ export function AgentSuggestionBar({
|
|
|
57
155
|
className={cn("w-full min-w-0 overflow-hidden px-3 py-2", className)}
|
|
58
156
|
>
|
|
59
157
|
<div
|
|
158
|
+
ref={scrollerRef}
|
|
60
159
|
data-agent-suggestion-scroller="true"
|
|
61
|
-
|
|
160
|
+
data-overflow-start={overflow.start || undefined}
|
|
161
|
+
data-overflow-end={overflow.end || undefined}
|
|
162
|
+
className="w-full min-w-0 snap-x snap-proximity scroll-px-6 overflow-x-auto overscroll-x-contain px-0.5 py-px [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
|
62
163
|
>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
164
|
+
<div
|
|
165
|
+
ref={trackRef}
|
|
166
|
+
data-agent-suggestion-track="true"
|
|
167
|
+
className="flex w-(--agent-suggestion-track-width) min-w-full flex-wrap gap-1"
|
|
168
|
+
onFocus={revealKeyboardFocusedChip}
|
|
169
|
+
>
|
|
170
|
+
{items.map((suggestion) => (
|
|
66
171
|
<Button
|
|
67
172
|
key={suggestion.id}
|
|
68
173
|
type="button"
|
|
@@ -78,8 +183,8 @@ export function AgentSuggestionBar({
|
|
|
78
183
|
: suggestion.label}
|
|
79
184
|
</span>
|
|
80
185
|
</Button>
|
|
81
|
-
)
|
|
82
|
-
|
|
186
|
+
))}
|
|
187
|
+
</div>
|
|
83
188
|
</div>
|
|
84
189
|
</section>
|
|
85
190
|
);
|