@agent-native/toolkit 0.201.0 → 0.201.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/agent-native.eject.json +1 -0
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +21 -13
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/context.d.ts +15 -1
- package/dist/app/agentkit/react/context.d.ts.map +1 -1
- package/dist/app/agentkit/react/context.js +30 -4
- package/dist/app/agentkit/react/context.js.map +1 -1
- package/dist/app/agentkit/react/styles.css +11 -7
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +9 -4
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/FileStorageSetupPopover.d.ts.map +1 -1
- package/dist/app/chat/FileStorageSetupPopover.js +3 -2
- package/dist/app/chat/FileStorageSetupPopover.js.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +11 -5
- 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 +11 -5
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +11 -5
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +11 -5
- 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 +11 -5
- 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 +11 -5
- 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 +11 -5
- 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 +11 -5
- 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 +11 -5
- 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 +11 -5
- 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 +11 -5
- 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 +11 -5
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/onboarding/BuilderIncludedServices.d.ts +23 -0
- package/dist/app/onboarding/BuilderIncludedServices.d.ts.map +1 -0
- package/dist/app/onboarding/BuilderIncludedServices.js +67 -0
- package/dist/app/onboarding/BuilderIncludedServices.js.map +1 -0
- package/dist/app/onboarding/FirstRunOnboarding.d.ts.map +1 -1
- package/dist/app/onboarding/FirstRunOnboarding.js +10 -29
- package/dist/app/onboarding/FirstRunOnboarding.js.map +1 -1
- package/dist/app/resources/McpConnectionSuggestion.d.ts.map +1 -1
- package/dist/app/resources/McpConnectionSuggestion.js +55 -21
- package/dist/app/resources/McpConnectionSuggestion.js.map +1 -1
- package/dist/app/settings/BuilderConnectPopover.d.ts +1 -2
- package/dist/app/settings/BuilderConnectPopover.d.ts.map +1 -1
- package/dist/app/settings/BuilderConnectPopover.js +35 -21
- package/dist/app/settings/BuilderConnectPopover.js.map +1 -1
- package/dist/app/settings/deferred-builder-connect-popover.d.ts.map +1 -1
- package/dist/app/settings/deferred-builder-connect-popover.js +28 -1
- package/dist/app/settings/deferred-builder-connect-popover.js.map +1 -1
- package/dist/app/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/app/settings/useBuilderStatus.js +8 -1
- package/dist/app/settings/useBuilderStatus.js.map +1 -1
- package/dist/app/styles/tokens/agent-kit.css +23 -11
- package/dist/composer/MessageQueueDrawer.d.ts +5 -0
- package/dist/composer/MessageQueueDrawer.d.ts.map +1 -1
- package/dist/composer/MessageQueueDrawer.js +11 -5
- package/dist/composer/MessageQueueDrawer.js.map +1 -1
- package/package.json +4 -3
- package/src/app/agentkit/react/components.interaction.spec.tsx +13 -5
- package/src/app/agentkit/react/components.tsx +24 -14
- package/src/app/agentkit/react/context.tsx +53 -6
- package/src/app/agentkit/react/styles.css +11 -7
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +35 -16
- package/src/app/chat/AgentKitAssistantChat.tsx +13 -4
- package/src/app/chat/FileStorageSetupPopover.spec.tsx +129 -0
- package/src/app/chat/FileStorageSetupPopover.tsx +10 -3
- package/src/app/i18n/catalogs/ar-SA.ts +14 -5
- package/src/app/i18n/catalogs/de-DE.ts +15 -5
- package/src/app/i18n/catalogs/en-US.ts +14 -5
- package/src/app/i18n/catalogs/es-ES.ts +14 -5
- package/src/app/i18n/catalogs/fr-FR.ts +15 -5
- package/src/app/i18n/catalogs/hi-IN.ts +14 -5
- package/src/app/i18n/catalogs/ja-JP.ts +14 -5
- package/src/app/i18n/catalogs/ko-KR.ts +14 -5
- package/src/app/i18n/catalogs/pt-BR.ts +15 -5
- package/src/app/i18n/catalogs/zh-CN.ts +13 -5
- package/src/app/i18n/catalogs/zh-TW.ts +13 -5
- package/src/app/onboarding/BuilderIncludedServices.tsx +263 -0
- package/src/app/onboarding/FirstRunOnboarding.spec.tsx +23 -8
- package/src/app/onboarding/FirstRunOnboarding.tsx +22 -112
- package/src/app/resources/McpConnectionSuggestion.render.spec.tsx +54 -2
- package/src/app/resources/McpConnectionSuggestion.tsx +73 -25
- package/src/app/settings/BuilderConnectPopover.spec.tsx +175 -6
- package/src/app/settings/BuilderConnectPopover.tsx +87 -67
- package/src/app/settings/deferred-builder-connect-popover.tsx +46 -0
- package/src/app/settings/model/ModelSettingsPage.spec.tsx +8 -24
- package/src/app/settings/useBuilderStatus.spec.tsx +5 -0
- package/src/app/settings/useBuilderStatus.ts +8 -0
- package/src/app/styles/agent-native.spec.ts +5 -8
- package/src/app/styles/tokens/agent-kit.css +23 -11
- package/src/composer/MessageQueueDrawer.spec.tsx +20 -7
- package/src/composer/MessageQueueDrawer.tsx +47 -21
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import { Button } from "@agent-native/toolkit/ui/button";
|
|
1
3
|
import { cloneElement, lazy, Suspense } from "react";
|
|
2
4
|
|
|
3
5
|
import { LazyChunkErrorBoundary } from "../shared/LazyChunkErrorBoundary.js";
|
|
@@ -15,6 +17,50 @@ export { LazyChunkRetryFallback } from "../shared/LazyChunkRetryFallback.js";
|
|
|
15
17
|
export function DeferredBuilderConnectPopover(
|
|
16
18
|
props: BuilderConnectPopoverProps,
|
|
17
19
|
) {
|
|
20
|
+
const t = useT();
|
|
21
|
+
if (
|
|
22
|
+
props.flow.statusResolved === true &&
|
|
23
|
+
props.flow.agentNativeProvisioningEnabled !== true
|
|
24
|
+
) {
|
|
25
|
+
// Keep OAuth in the trusted click and avoid loading popover UI for sign-in-only flows.
|
|
26
|
+
const trigger = cloneElement(props.children, {
|
|
27
|
+
"aria-busy": undefined,
|
|
28
|
+
onClick: (event) => {
|
|
29
|
+
if (props.flow.connecting) {
|
|
30
|
+
event.preventDefault();
|
|
31
|
+
event.stopPropagation();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
props.children.props.onClick?.(event);
|
|
35
|
+
props.onTriggerClick?.(event);
|
|
36
|
+
if (event.defaultPrevented) return;
|
|
37
|
+
if (props.onConnect) props.onConnect(false);
|
|
38
|
+
else props.flow.start({ provisionAccount: false });
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
const cancelAction =
|
|
42
|
+
props.flow.connecting && props.flow.cancel ? (
|
|
43
|
+
<Button
|
|
44
|
+
type="button"
|
|
45
|
+
variant="ghost"
|
|
46
|
+
size="sm"
|
|
47
|
+
className="shrink-0"
|
|
48
|
+
onClick={props.flow.cancel}
|
|
49
|
+
>
|
|
50
|
+
{t("common.cancel")}
|
|
51
|
+
</Button>
|
|
52
|
+
) : null;
|
|
53
|
+
|
|
54
|
+
return cancelAction ? (
|
|
55
|
+
<span className="inline-flex max-w-full items-center gap-2">
|
|
56
|
+
<span className="contents">{trigger}</span>
|
|
57
|
+
{cancelAction}
|
|
58
|
+
</span>
|
|
59
|
+
) : (
|
|
60
|
+
<span className="contents">{trigger}</span>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
18
64
|
return (
|
|
19
65
|
<LazyChunkErrorBoundary fallback={<LazyChunkRetryFallback />}>
|
|
20
66
|
<Suspense
|
|
@@ -85,14 +85,11 @@ vi.mock("@agent-native/core/client/oauth-popup", () => ({
|
|
|
85
85
|
}));
|
|
86
86
|
|
|
87
87
|
vi.mock("../deferred-builder-connect-popover.js", () => ({
|
|
88
|
-
// The real popover asks whether to create an account, then calls onConnect.
|
|
89
88
|
DeferredBuilderConnectPopover: ({
|
|
90
89
|
children,
|
|
91
|
-
onConnect,
|
|
92
90
|
}: {
|
|
93
91
|
children: React.ReactElement<{ onClick?: () => void }>;
|
|
94
|
-
|
|
95
|
-
}) => React.cloneElement(children, { onClick: () => onConnect?.(false) }),
|
|
92
|
+
}) => React.cloneElement(children, { onClick: () => {} }),
|
|
96
93
|
}));
|
|
97
94
|
|
|
98
95
|
vi.mock("../shell/context.js", () => ({
|
|
@@ -388,15 +385,9 @@ describe("ModelSettingsPage", () => {
|
|
|
388
385
|
expect(buttons(row("provider-personal-builder"))).toEqual([
|
|
389
386
|
"Use Builder.io",
|
|
390
387
|
]);
|
|
391
|
-
|
|
392
|
-
(
|
|
393
|
-
|
|
394
|
-
).click();
|
|
395
|
-
});
|
|
396
|
-
expect(state.builder.start).toHaveBeenCalledWith({
|
|
397
|
-
provisionAccount: false,
|
|
398
|
-
scope: "personal",
|
|
399
|
-
});
|
|
388
|
+
expect(
|
|
389
|
+
row("provider-personal-builder").querySelector("button")?.disabled,
|
|
390
|
+
).toBe(false);
|
|
400
391
|
expect(row("provider-personal-anthropic").textContent).toContain(
|
|
401
392
|
"••••1234 · 2 models",
|
|
402
393
|
);
|
|
@@ -669,17 +660,10 @@ describe("ModelSettingsPage", () => {
|
|
|
669
660
|
expect(
|
|
670
661
|
document.querySelector('[data-testid="provider-dialog"]'),
|
|
671
662
|
).not.toBeNull();
|
|
672
|
-
|
|
673
|
-
(
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
) as HTMLElement
|
|
677
|
-
).click();
|
|
678
|
-
});
|
|
679
|
-
expect(state.builder.start).toHaveBeenCalledWith({
|
|
680
|
-
provisionAccount: false,
|
|
681
|
-
scope: "org",
|
|
682
|
-
});
|
|
663
|
+
const builderButton = [...empty.querySelectorAll("button")].find(
|
|
664
|
+
(button) => button.textContent === "Use Builder.io",
|
|
665
|
+
);
|
|
666
|
+
expect(builderButton?.disabled).toBe(false);
|
|
683
667
|
});
|
|
684
668
|
|
|
685
669
|
it("tells a restricted member with no provider to ask an admin", async () => {
|
|
@@ -265,6 +265,11 @@ describe("useBuilderStatus", () => {
|
|
|
265
265
|
|
|
266
266
|
expect(fetchMock).toHaveBeenCalledWith(
|
|
267
267
|
"/_agent-native/connection-status/builder",
|
|
268
|
+
expect.objectContaining({
|
|
269
|
+
headers: {
|
|
270
|
+
"x-agent-native-preview-origin": "http://localhost:3000",
|
|
271
|
+
},
|
|
272
|
+
}),
|
|
268
273
|
);
|
|
269
274
|
});
|
|
270
275
|
|
|
@@ -127,6 +127,11 @@ export function useBuilderStatus({
|
|
|
127
127
|
try {
|
|
128
128
|
const res = await fetch(
|
|
129
129
|
agentNativePath("/_agent-native/connection-status/builder"),
|
|
130
|
+
{
|
|
131
|
+
headers: {
|
|
132
|
+
"x-agent-native-preview-origin": window.location.origin,
|
|
133
|
+
},
|
|
134
|
+
},
|
|
130
135
|
);
|
|
131
136
|
if (!res.ok) {
|
|
132
137
|
keepLastGoodStatus(`Builder status unavailable (${res.status})`);
|
|
@@ -926,6 +931,9 @@ export function useBuilderConnectFlow(
|
|
|
926
931
|
);
|
|
927
932
|
}
|
|
928
933
|
const r = await fetch(statusUrl.href, {
|
|
934
|
+
headers: {
|
|
935
|
+
"x-agent-native-preview-origin": window.location.origin,
|
|
936
|
+
},
|
|
929
937
|
signal: signal ?? ownController?.signal,
|
|
930
938
|
});
|
|
931
939
|
if (!r.ok) return null;
|
|
@@ -261,34 +261,31 @@ describe("agent-native shell surface tokens", () => {
|
|
|
261
261
|
/\.agent-sidebar-panel\[data-agent-sidebar-animation="drawer"\][\s\S]*?box-shadow: var\(--agent-kit-drawer-elevation\);/s,
|
|
262
262
|
);
|
|
263
263
|
expect(tokens).toMatch(
|
|
264
|
-
|
|
264
|
+
/:is\(\.dark, :root\[data-theme="dark"\]:not\(\.light\)\)\s*\{[\s\S]*?--agent-kit-shadow-color: var\(--background\);[\s\S]*?--agent-kit-drawer-elevation:/s,
|
|
265
265
|
);
|
|
266
266
|
expect(css).not.toContain("hsl(var(--foreground) / 0.07)");
|
|
267
267
|
expect(css).not.toContain("hsl(var(--foreground) / 0.12)");
|
|
268
268
|
expect(css).not.toContain("hsl(var(--agent-shadow)");
|
|
269
269
|
expect(tokens).toContain("--agent-kit-shadow-color: var(--foreground);");
|
|
270
270
|
expect(tokens).toMatch(
|
|
271
|
-
|
|
271
|
+
/:is\(\.dark, :root\[data-theme="dark"\]:not\(\.light\)\)\s*\{[\s\S]*?--agent-kit-shadow-color: var\(--background\);[\s\S]*?--agent-kit-composer-elevation:[\s\S]*?hsl\(var\(--agent-kit-shadow-color\) \/ 0\.22\)/s,
|
|
272
272
|
);
|
|
273
273
|
expect(css).toMatch(
|
|
274
274
|
/::view-transition-old\(agent-native-sidebar-drawer\),\s*::view-transition-new\(agent-native-sidebar-drawer\)[\s\S]*?height: 100%;/s,
|
|
275
275
|
);
|
|
276
276
|
});
|
|
277
277
|
|
|
278
|
-
it("gives the
|
|
278
|
+
it("gives the composer a quiet boundary in both themes", () => {
|
|
279
279
|
const tokens = readFileSync(
|
|
280
280
|
new URL("./tokens/agent-kit.css", import.meta.url),
|
|
281
281
|
{ encoding: "utf8" },
|
|
282
282
|
);
|
|
283
283
|
|
|
284
284
|
expect(tokens).toMatch(
|
|
285
|
-
/:root\s*\{[\s\S]*?--agent-kit-composer-border-
|
|
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,
|
|
286
286
|
);
|
|
287
287
|
expect(tokens).toMatch(
|
|
288
|
-
|
|
289
|
-
);
|
|
290
|
-
expect(tokens).toMatch(
|
|
291
|
-
/\.dark\s*\{[\s\S]*?--agent-kit-composer-border-color: transparent;[\s\S]*?--agent-kit-composer-focus-border-color: transparent;/s,
|
|
288
|
+
/:is\(\.dark, :root\[data-theme="dark"\]:not\(\.light\)\)\s*\{[\s\S]*?--agent-kit-composer-border-mix: 40%;[\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,
|
|
292
289
|
);
|
|
293
290
|
});
|
|
294
291
|
|
|
@@ -43,13 +43,17 @@
|
|
|
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-border-
|
|
47
|
-
--agent-kit-composer-focus-border-
|
|
48
|
-
--agent-kit-composer-border-color:
|
|
49
|
-
|
|
46
|
+
--agent-kit-composer-border-mix: 82%;
|
|
47
|
+
--agent-kit-composer-focus-border-mix: 100%;
|
|
48
|
+
--agent-kit-composer-border-color: color-mix(
|
|
49
|
+
in srgb,
|
|
50
|
+
hsl(var(--border)) var(--agent-kit-composer-border-mix),
|
|
51
|
+
transparent
|
|
50
52
|
);
|
|
51
|
-
--agent-kit-composer-focus-border-color:
|
|
52
|
-
|
|
53
|
+
--agent-kit-composer-focus-border-color: color-mix(
|
|
54
|
+
in srgb,
|
|
55
|
+
hsl(var(--border)) var(--agent-kit-composer-focus-border-mix),
|
|
56
|
+
transparent
|
|
53
57
|
);
|
|
54
58
|
--agent-kit-composer-editor-padding-inline: 1rem;
|
|
55
59
|
--agent-kit-composer-editor-padding-block-start: 0.875rem;
|
|
@@ -96,11 +100,19 @@
|
|
|
96
100
|
}
|
|
97
101
|
}
|
|
98
102
|
|
|
99
|
-
.dark {
|
|
100
|
-
--agent-kit-composer-border-
|
|
101
|
-
--agent-kit-composer-focus-border-
|
|
102
|
-
--agent-kit-composer-border-color:
|
|
103
|
-
|
|
103
|
+
:is(.dark, :root[data-theme="dark"]:not(.light)) {
|
|
104
|
+
--agent-kit-composer-border-mix: 40%;
|
|
105
|
+
--agent-kit-composer-focus-border-mix: 65%;
|
|
106
|
+
--agent-kit-composer-border-color: color-mix(
|
|
107
|
+
in srgb,
|
|
108
|
+
hsl(var(--border)) var(--agent-kit-composer-border-mix),
|
|
109
|
+
transparent
|
|
110
|
+
);
|
|
111
|
+
--agent-kit-composer-focus-border-color: color-mix(
|
|
112
|
+
in srgb,
|
|
113
|
+
hsl(var(--border)) var(--agent-kit-composer-focus-border-mix),
|
|
114
|
+
transparent
|
|
115
|
+
);
|
|
104
116
|
--agent-kit-shadow-color: var(--background);
|
|
105
117
|
--agent-kit-control-elevation: 0 0.0625rem 0.125rem
|
|
106
118
|
hsl(var(--agent-kit-shadow-color) / 0.18);
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
|
|
13
13
|
const labels: MessageQueueDrawerLabels = {
|
|
14
14
|
region: "2 queued",
|
|
15
|
-
steer: "
|
|
16
|
-
steerHint: "
|
|
15
|
+
steer: "Send now",
|
|
16
|
+
steerHint: "Stops the current response, then sends this message.",
|
|
17
17
|
remove: "Remove from queue",
|
|
18
18
|
moreActions: "More actions",
|
|
19
19
|
};
|
|
@@ -58,8 +58,9 @@ describe("MessageQueueDrawer", () => {
|
|
|
58
58
|
onRemove={onRemove}
|
|
59
59
|
getItemActions={(item) => [
|
|
60
60
|
{
|
|
61
|
-
id: "
|
|
62
|
-
label: "
|
|
61
|
+
id: "send-next",
|
|
62
|
+
label: "Send next",
|
|
63
|
+
hint: "Send after the current response finishes",
|
|
63
64
|
onSelect: () => onMoveToTop(item),
|
|
64
65
|
},
|
|
65
66
|
]}
|
|
@@ -87,7 +88,7 @@ describe("MessageQueueDrawer", () => {
|
|
|
87
88
|
expect(container.querySelectorAll("li")).toHaveLength(2);
|
|
88
89
|
|
|
89
90
|
const steerButton = Array.from(container.querySelectorAll("button")).find(
|
|
90
|
-
(button) => button.textContent?.includes("
|
|
91
|
+
(button) => button.textContent?.includes("Send now"),
|
|
91
92
|
);
|
|
92
93
|
const removeButton = container.querySelector<HTMLButtonElement>(
|
|
93
94
|
'button[aria-label="Remove from queue"]',
|
|
@@ -116,7 +117,19 @@ describe("MessageQueueDrawer", () => {
|
|
|
116
117
|
await Promise.resolve();
|
|
117
118
|
});
|
|
118
119
|
const menuItem = document.querySelector<HTMLElement>('[role="menuitem"]');
|
|
119
|
-
expect(menuItem?.textContent).toContain("
|
|
120
|
+
expect(menuItem?.textContent).toContain("Send next");
|
|
121
|
+
await act(async () => {
|
|
122
|
+
menuItem?.dispatchEvent(
|
|
123
|
+
new PointerEvent("pointermove", {
|
|
124
|
+
bubbles: true,
|
|
125
|
+
pointerType: "mouse",
|
|
126
|
+
}),
|
|
127
|
+
);
|
|
128
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
129
|
+
});
|
|
130
|
+
expect(document.body.textContent).toContain(
|
|
131
|
+
"Send after the current response finishes",
|
|
132
|
+
);
|
|
120
133
|
act(() => menuItem?.click());
|
|
121
134
|
expect(onMoveToTop).toHaveBeenCalledWith(items[0]);
|
|
122
135
|
});
|
|
@@ -238,7 +251,7 @@ describe("MessageQueueDrawer", () => {
|
|
|
238
251
|
variant="recessed"
|
|
239
252
|
onRemove={() => undefined}
|
|
240
253
|
getItemActions={() => [
|
|
241
|
-
{ id: "
|
|
254
|
+
{ id: "send-next", label: "Send next", onSelect: () => {} },
|
|
242
255
|
]}
|
|
243
256
|
/>,
|
|
244
257
|
);
|
|
@@ -25,6 +25,7 @@ export interface MessageQueueItem {
|
|
|
25
25
|
export interface MessageQueueItemAction {
|
|
26
26
|
id: string;
|
|
27
27
|
label: ReactNode;
|
|
28
|
+
hint?: string;
|
|
28
29
|
icon?: ReactNode;
|
|
29
30
|
destructive?: boolean;
|
|
30
31
|
disabled?: boolean;
|
|
@@ -33,8 +34,12 @@ export interface MessageQueueItemAction {
|
|
|
33
34
|
|
|
34
35
|
export interface MessageQueueDrawerLabels {
|
|
35
36
|
region: string;
|
|
37
|
+
/** @deprecated Use sendNow. */
|
|
36
38
|
steer: string;
|
|
39
|
+
/** @deprecated Use sendNowHint. */
|
|
37
40
|
steerHint: string;
|
|
41
|
+
sendNow?: string;
|
|
42
|
+
sendNowHint?: string;
|
|
38
43
|
remove: string;
|
|
39
44
|
moreActions: string;
|
|
40
45
|
}
|
|
@@ -55,7 +60,6 @@ export interface MessageQueueDrawerProps {
|
|
|
55
60
|
className?: string;
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
const RECESSED_QUEUE_MAX_HEIGHT_PX = 160;
|
|
59
63
|
const RECESSED_QUEUE_VERTICAL_CHROME_PX = 10;
|
|
60
64
|
|
|
61
65
|
function recessedQueueHeight(items: readonly MessageQueueItem[]): number {
|
|
@@ -66,7 +70,7 @@ function recessedQueueHeight(items: readonly MessageQueueItem[]): number {
|
|
|
66
70
|
height + (item.images && item.images.length > 0 ? 56 : 36),
|
|
67
71
|
RECESSED_QUEUE_VERTICAL_CHROME_PX,
|
|
68
72
|
);
|
|
69
|
-
return
|
|
73
|
+
return contentHeight;
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
export function MessageQueueDrawer({
|
|
@@ -82,6 +86,8 @@ export function MessageQueueDrawer({
|
|
|
82
86
|
}: MessageQueueDrawerProps) {
|
|
83
87
|
const recessed = variant === "recessed";
|
|
84
88
|
const empty = items.length === 0;
|
|
89
|
+
const sendNow = labels.sendNow ?? labels.steer;
|
|
90
|
+
const sendNowHint = labels.sendNowHint ?? labels.steerHint;
|
|
85
91
|
const [openActionsItemId, setOpenActionsItemId] = useState<string | null>(
|
|
86
92
|
null,
|
|
87
93
|
);
|
|
@@ -121,8 +127,10 @@ export function MessageQueueDrawer({
|
|
|
121
127
|
>
|
|
122
128
|
<ul
|
|
123
129
|
className={cn(
|
|
124
|
-
"flex
|
|
125
|
-
recessed
|
|
130
|
+
"flex flex-col",
|
|
131
|
+
recessed
|
|
132
|
+
? "h-full gap-0 overflow-y-hidden py-0"
|
|
133
|
+
: "max-h-40 gap-0.5 overflow-y-auto py-1",
|
|
126
134
|
)}
|
|
127
135
|
>
|
|
128
136
|
{items.map((item) => {
|
|
@@ -131,7 +139,10 @@ export function MessageQueueDrawer({
|
|
|
131
139
|
return (
|
|
132
140
|
<li
|
|
133
141
|
key={item.id}
|
|
134
|
-
className=
|
|
142
|
+
className={cn(
|
|
143
|
+
"group flex min-h-9 min-w-0 items-center gap-2 px-4 text-[13px] leading-4 animate-in fade-in-0 slide-in-from-bottom-1 duration-200 ease-[var(--ease-collapse)] motion-reduce:animate-none",
|
|
144
|
+
recessed ? "py-0.5" : "py-1.5",
|
|
145
|
+
)}
|
|
135
146
|
>
|
|
136
147
|
<IconCornerDownRight
|
|
137
148
|
aria-hidden="true"
|
|
@@ -172,10 +183,10 @@ export function MessageQueueDrawer({
|
|
|
172
183
|
className="size-3.5"
|
|
173
184
|
strokeWidth={1.7}
|
|
174
185
|
/>
|
|
175
|
-
<span>{
|
|
186
|
+
<span>{sendNow}</span>
|
|
176
187
|
</Button>
|
|
177
188
|
</TooltipTrigger>
|
|
178
|
-
<TooltipContent>{
|
|
189
|
+
<TooltipContent>{sendNowHint}</TooltipContent>
|
|
179
190
|
</Tooltip>
|
|
180
191
|
) : null}
|
|
181
192
|
<Tooltip>
|
|
@@ -233,20 +244,35 @@ export function MessageQueueDrawer({
|
|
|
233
244
|
side="top"
|
|
234
245
|
sideOffset={4}
|
|
235
246
|
>
|
|
236
|
-
{actions.map((action) =>
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
247
|
+
{actions.map((action) => {
|
|
248
|
+
const menuItem = (
|
|
249
|
+
<DropdownMenuItem
|
|
250
|
+
key={action.id}
|
|
251
|
+
disabled={disabled || action.disabled}
|
|
252
|
+
onSelect={() => action.onSelect(item)}
|
|
253
|
+
className={cn(
|
|
254
|
+
action.destructive &&
|
|
255
|
+
"text-destructive focus:text-destructive",
|
|
256
|
+
)}
|
|
257
|
+
>
|
|
258
|
+
{action.icon}
|
|
259
|
+
{action.label}
|
|
260
|
+
</DropdownMenuItem>
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
return action.hint ? (
|
|
264
|
+
<Tooltip key={action.id}>
|
|
265
|
+
<TooltipTrigger asChild>
|
|
266
|
+
{menuItem}
|
|
267
|
+
</TooltipTrigger>
|
|
268
|
+
<TooltipContent side="right">
|
|
269
|
+
{action.hint}
|
|
270
|
+
</TooltipContent>
|
|
271
|
+
</Tooltip>
|
|
272
|
+
) : (
|
|
273
|
+
menuItem
|
|
274
|
+
);
|
|
275
|
+
})}
|
|
250
276
|
</DropdownMenuContent>
|
|
251
277
|
</DropdownMenu>
|
|
252
278
|
) : null}
|