@agent-native/toolkit 0.213.1 → 0.216.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-native.eject.json +9 -0
- package/dist/app/agentkit/react/chat.d.ts.map +1 -1
- package/dist/app/agentkit/react/chat.js +2 -2
- package/dist/app/agentkit/react/chat.js.map +1 -1
- package/dist/app/agentkit/react/components.d.ts +4 -1
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +73 -13
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/context.d.ts +19 -1
- package/dist/app/agentkit/react/context.d.ts.map +1 -1
- package/dist/app/agentkit/react/context.js +7 -1
- package/dist/app/agentkit/react/context.js.map +1 -1
- package/dist/app/agentkit/react/index.d.ts +2 -0
- package/dist/app/agentkit/react/index.d.ts.map +1 -1
- package/dist/app/agentkit/react/index.js +2 -0
- package/dist/app/agentkit/react/index.js.map +1 -1
- package/dist/app/agentkit/react/message-content-order.d.ts +21 -0
- package/dist/app/agentkit/react/message-content-order.d.ts.map +1 -0
- package/dist/app/agentkit/react/message-content-order.js +173 -0
- package/dist/app/agentkit/react/message-content-order.js.map +1 -0
- package/dist/app/agentkit/react/root.d.ts +6 -1
- package/dist/app/agentkit/react/root.d.ts.map +1 -1
- package/dist/app/agentkit/react/root.js +2 -2
- package/dist/app/agentkit/react/root.js.map +1 -1
- package/dist/app/agentkit/react/styles.css +45 -8
- package/dist/app/agentkit/react/transcript-layout.d.ts +51 -0
- package/dist/app/agentkit/react/transcript-layout.d.ts.map +1 -0
- package/dist/app/agentkit/react/transcript-layout.js +34 -0
- package/dist/app/agentkit/react/transcript-layout.js.map +1 -0
- 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/AgentPanel.d.ts +16 -2
- package/dist/app/chat/AgentPanel.d.ts.map +1 -1
- package/dist/app/chat/AgentPanel.js +26 -5
- package/dist/app/chat/AgentPanel.js.map +1 -1
- package/dist/app/chat/chat/index.d.ts +2 -0
- package/dist/app/chat/chat/index.d.ts.map +1 -1
- package/dist/app/chat/chat/index.js.map +1 -1
- package/dist/app/chat/chat/surface-types.d.ts +15 -0
- package/dist/app/chat/chat/surface-types.d.ts.map +1 -1
- package/dist/app/chat/chat/surface-types.js.map +1 -1
- package/dist/app/chat/chat/tool-call-display.d.ts +7 -2
- package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
- package/dist/app/chat/chat/tool-call-display.js +10 -9
- package/dist/app/chat/chat/tool-call-display.js.map +1 -1
- package/dist/app/chat/chat/widgets/DataChartRenderer.d.ts.map +1 -1
- package/dist/app/chat/chat/widgets/DataChartRenderer.js +300 -33
- package/dist/app/chat/chat/widgets/DataChartRenderer.js.map +1 -1
- package/dist/app/chat/chat/widgets/DataChartWidget.d.ts +3 -2
- package/dist/app/chat/chat/widgets/DataChartWidget.d.ts.map +1 -1
- package/dist/app/chat/chat/widgets/DataChartWidget.js +18 -9
- package/dist/app/chat/chat/widgets/DataChartWidget.js.map +1 -1
- package/dist/app/chat/chat/widgets/DataInsightsWidget.js +1 -1
- package/dist/app/chat/chat/widgets/DataInsightsWidget.js.map +1 -1
- package/dist/app/chat/chat/widgets/DataTableWidget.d.ts +3 -2
- package/dist/app/chat/chat/widgets/DataTableWidget.d.ts.map +1 -1
- package/dist/app/chat/chat/widgets/DataTableWidget.js +10 -66
- package/dist/app/chat/chat/widgets/DataTableWidget.js.map +1 -1
- package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.d.ts +11 -0
- package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.d.ts.map +1 -0
- package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.js +133 -0
- package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.js.map +1 -0
- package/dist/app/chat/chat/widgets/builtin-tool-renderers.js +2 -2
- package/dist/app/chat/chat/widgets/builtin-tool-renderers.js.map +1 -1
- package/dist/app/chat/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/app/chat/mcp-apps/McpAppRenderer.js +6 -5
- package/dist/app/chat/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/app/chat/mcp-apps/mcp-app-theme.d.ts +2 -0
- package/dist/app/chat/mcp-apps/mcp-app-theme.d.ts.map +1 -0
- package/dist/app/chat/mcp-apps/mcp-app-theme.js +11 -0
- package/dist/app/chat/mcp-apps/mcp-app-theme.js.map +1 -0
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +9 -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 +9 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +9 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +9 -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 +9 -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 +9 -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 +9 -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 +9 -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 +9 -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 +9 -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 +9 -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 +9 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/providers/AppProviders.d.ts +2 -1
- package/dist/app/providers/AppProviders.d.ts.map +1 -1
- package/dist/app/providers/AppProviders.js +4 -3
- package/dist/app/providers/AppProviders.js.map +1 -1
- package/dist/app/providers/ThemeFamilySync.d.ts +2 -0
- package/dist/app/providers/ThemeFamilySync.d.ts.map +1 -0
- package/dist/app/providers/ThemeFamilySync.js +6 -0
- package/dist/app/providers/ThemeFamilySync.js.map +1 -0
- package/dist/app/settings/account/PreferencesSettings.d.ts.map +1 -1
- package/dist/app/settings/account/PreferencesSettings.js +2 -1
- package/dist/app/settings/account/PreferencesSettings.js.map +1 -1
- package/dist/app/settings/account/ThemeFamilySettings.d.ts +2 -0
- package/dist/app/settings/account/ThemeFamilySettings.d.ts.map +1 -0
- package/dist/app/settings/account/ThemeFamilySettings.js +31 -0
- package/dist/app/settings/account/ThemeFamilySettings.js.map +1 -0
- package/dist/app/settings/account/search-entries.d.ts.map +1 -1
- package/dist/app/settings/account/search-entries.js +6 -0
- package/dist/app/settings/account/search-entries.js.map +1 -1
- package/dist/app/shared/DefaultSpinner.d.ts.map +1 -1
- package/dist/app/shared/DefaultSpinner.js +4 -5
- package/dist/app/shared/DefaultSpinner.js.map +1 -1
- package/dist/app/shared/ErrorBoundary.d.ts +1 -0
- package/dist/app/shared/ErrorBoundary.d.ts.map +1 -1
- package/dist/app/shared/ErrorBoundary.js +27 -12
- package/dist/app/shared/ErrorBoundary.js.map +1 -1
- package/dist/app/shared/PoweredByBadge.d.ts.map +1 -1
- package/dist/app/shared/PoweredByBadge.js +8 -49
- package/dist/app/shared/PoweredByBadge.js.map +1 -1
- package/dist/app/styles/agent-conversation.css +0 -23
- package/dist/app/styles/agent-native.css +1 -1
- package/dist/app/styles/theme-families.css +66 -0
- package/dist/composer/ComposerContextBanner.d.ts +24 -0
- package/dist/composer/ComposerContextBanner.d.ts.map +1 -0
- package/dist/composer/ComposerContextBanner.js +9 -0
- package/dist/composer/ComposerContextBanner.js.map +1 -0
- package/dist/composer/ComposerModePicker.d.ts +26 -0
- package/dist/composer/ComposerModePicker.d.ts.map +1 -0
- package/dist/composer/ComposerModePicker.js +14 -0
- package/dist/composer/ComposerModePicker.js.map +1 -0
- package/dist/composer/index.d.ts +2 -0
- package/dist/composer/index.d.ts.map +1 -1
- package/dist/composer/index.js +2 -0
- package/dist/composer/index.js.map +1 -1
- package/dist/styles.css +1 -0
- package/package.json +3 -3
- package/src/app/agentkit/react/chat.tsx +2 -0
- package/src/app/agentkit/react/components.interaction.spec.tsx +107 -0
- package/src/app/agentkit/react/components.spec.tsx +40 -1
- package/src/app/agentkit/react/components.tsx +186 -31
- package/src/app/agentkit/react/context.tsx +29 -0
- package/src/app/agentkit/react/index.ts +2 -0
- package/src/app/agentkit/react/lifecycle.spec.tsx +289 -4
- package/src/app/agentkit/react/message-content-order.spec.ts +190 -0
- package/src/app/agentkit/react/message-content-order.ts +246 -0
- package/src/app/agentkit/react/root.tsx +11 -0
- package/src/app/agentkit/react/styles.css +45 -8
- package/src/app/agentkit/react/transcript-layout.spec.ts +72 -0
- package/src/app/agentkit/react/transcript-layout.ts +97 -0
- package/src/app/auth/AuthPage.attribution.spec.tsx +6 -0
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +58 -0
- package/src/app/chat/AgentKitAssistantChat.tsx +15 -1
- package/src/app/chat/AgentPanel.header.spec.ts +72 -14
- package/src/app/chat/AgentPanel.page-header-share.spec.tsx +101 -0
- package/src/app/chat/AgentPanel.tsx +111 -55
- package/src/app/chat/chat/index.ts +2 -0
- package/src/app/chat/chat/surface-types.ts +18 -0
- package/src/app/chat/chat/tool-call-display.spec.tsx +83 -0
- package/src/app/chat/chat/tool-call-display.tsx +40 -8
- package/src/app/chat/chat/widgets/DataChartRenderer.spec.tsx +849 -0
- package/src/app/chat/chat/widgets/DataChartRenderer.tsx +567 -72
- package/src/app/chat/chat/widgets/DataChartWidget.spec.tsx +432 -0
- package/src/app/chat/chat/widgets/DataChartWidget.ssr.spec.tsx +25 -0
- package/src/app/chat/chat/widgets/DataChartWidget.tsx +58 -33
- package/src/app/chat/chat/widgets/DataInsightsWidget.tsx +2 -2
- package/src/app/chat/chat/widgets/DataTableWidget.spec.tsx +37 -3
- package/src/app/chat/chat/widgets/DataTableWidget.tsx +22 -86
- package/src/app/chat/chat/widgets/DataWidgetDisplayControls.tsx +321 -0
- package/src/app/chat/chat/widgets/builtin-tool-renderers.tsx +5 -5
- package/src/app/chat/mcp-apps/McpAppRenderer.tsx +10 -5
- package/src/app/chat/mcp-apps/mcp-app-theme.spec.ts +30 -0
- package/src/app/chat/mcp-apps/mcp-app-theme.ts +11 -0
- package/src/app/i18n/catalogs/ar-SA.ts +10 -0
- package/src/app/i18n/catalogs/de-DE.ts +11 -0
- package/src/app/i18n/catalogs/en-US.ts +11 -0
- package/src/app/i18n/catalogs/es-ES.ts +12 -0
- package/src/app/i18n/catalogs/fr-FR.ts +12 -0
- package/src/app/i18n/catalogs/hi-IN.ts +10 -0
- package/src/app/i18n/catalogs/ja-JP.ts +11 -0
- package/src/app/i18n/catalogs/ko-KR.ts +10 -0
- package/src/app/i18n/catalogs/pt-BR.ts +11 -0
- package/src/app/i18n/catalogs/zh-CN.ts +9 -0
- package/src/app/i18n/catalogs/zh-TW.ts +10 -0
- package/src/app/providers/AppProviders.spec.tsx +71 -0
- package/src/app/providers/AppProviders.tsx +10 -0
- package/src/app/providers/ThemeFamilySync.tsx +6 -0
- package/src/app/settings/account/PreferencesSettings.spec.tsx +13 -2
- package/src/app/settings/account/PreferencesSettings.tsx +8 -0
- package/src/app/settings/account/ThemeFamilySettings.tsx +61 -0
- package/src/app/settings/account/search-entries.ts +6 -0
- package/src/app/shared/DefaultSpinner.spec.tsx +14 -0
- package/src/app/shared/DefaultSpinner.tsx +4 -5
- package/src/app/shared/ErrorBoundary.spec.tsx +45 -2
- package/src/app/shared/ErrorBoundary.tsx +37 -12
- package/src/app/shared/PoweredByBadge.spec.tsx +16 -0
- package/src/app/shared/PoweredByBadge.tsx +8 -50
- package/src/app/styles/agent-conversation.css +0 -23
- package/src/app/styles/agent-native.css +1 -1
- package/src/app/styles/agent-native.spec.ts +18 -0
- package/src/app/styles/theme-families.css +66 -0
- package/src/app/styles/theme-families.spec.ts +29 -0
- package/src/composer/ComposerContextBanner.spec.tsx +100 -0
- package/src/composer/ComposerContextBanner.tsx +77 -0
- package/src/composer/ComposerModePicker.spec.tsx +101 -0
- package/src/composer/ComposerModePicker.tsx +98 -0
- package/src/composer/index.ts +9 -0
- package/src/styles.css +1 -0
|
@@ -47,8 +47,6 @@ const containerStyle = (
|
|
|
47
47
|
opacity: 0.82,
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
const darkQuery = "(prefers-color-scheme: dark)";
|
|
51
|
-
|
|
52
50
|
export function PoweredByBadge({
|
|
53
51
|
position = "bottom-right",
|
|
54
52
|
variant = "badge",
|
|
@@ -91,54 +89,36 @@ export function PoweredByBadge({
|
|
|
91
89
|
.an-powered-badge-plain:hover {
|
|
92
90
|
opacity: 0.82 !important;
|
|
93
91
|
}
|
|
94
|
-
.dark .an-powered-badge:not(.an-powered-badge-plain) {
|
|
92
|
+
:is(html.dark, html[data-theme="dark"]:not(.light)) .an-powered-badge:not(.an-powered-badge-plain) {
|
|
95
93
|
background: rgba(255, 255, 255, 0.06) !important;
|
|
96
94
|
border-color: rgba(255, 255, 255, 0.08) !important;
|
|
97
95
|
color: rgba(215, 215, 215, 0.94) !important;
|
|
98
96
|
}
|
|
99
|
-
.dark .an-powered-logo-light {
|
|
97
|
+
:is(html.dark, html[data-theme="dark"]:not(.light)) .an-powered-logo-light {
|
|
100
98
|
display: none;
|
|
101
99
|
}
|
|
102
|
-
.dark .an-powered-logo-dark {
|
|
100
|
+
:is(html.dark, html[data-theme="dark"]:not(.light)) .an-powered-logo-dark {
|
|
103
101
|
display: block;
|
|
104
102
|
}
|
|
105
|
-
|
|
106
|
-
.an-powered-badge:not(.an-powered-badge-plain) {
|
|
107
|
-
background: rgba(255, 255, 255, 0.06) !important;
|
|
108
|
-
border-color: rgba(255, 255, 255, 0.08) !important;
|
|
109
|
-
color: rgba(215, 215, 215, 0.94) !important;
|
|
110
|
-
}
|
|
111
|
-
.an-powered-logo-light {
|
|
112
|
-
display: none;
|
|
113
|
-
}
|
|
114
|
-
.an-powered-logo-dark {
|
|
115
|
-
display: block;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
.light .an-powered-badge:not(.an-powered-badge-plain) {
|
|
103
|
+
:is(html.light, html[data-theme="light"]:not(.dark)) .an-powered-badge:not(.an-powered-badge-plain) {
|
|
119
104
|
background: rgba(0, 0, 0, 0.05) !important;
|
|
120
105
|
border-color: rgba(0, 0, 0, 0.06) !important;
|
|
121
106
|
color: rgba(95, 95, 95, 0.95) !important;
|
|
122
107
|
}
|
|
123
|
-
.light .an-powered-logo-light {
|
|
108
|
+
:is(html.light, html[data-theme="light"]:not(.dark)) .an-powered-logo-light {
|
|
124
109
|
display: block;
|
|
125
110
|
}
|
|
126
|
-
.light .an-powered-logo-dark {
|
|
111
|
+
:is(html.light, html[data-theme="light"]:not(.dark)) .an-powered-logo-dark {
|
|
127
112
|
display: none;
|
|
128
113
|
}
|
|
129
114
|
.an-powered-badge:not(.an-powered-badge-plain):hover {
|
|
130
115
|
opacity: 1 !important;
|
|
131
116
|
color: rgba(70, 70, 70, 1) !important;
|
|
132
117
|
}
|
|
133
|
-
|
|
134
|
-
.an-powered-badge:not(.an-powered-badge-plain):hover {
|
|
135
|
-
color: rgba(238, 238, 238, 1) !important;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
.dark .an-powered-badge:not(.an-powered-badge-plain):hover {
|
|
118
|
+
:is(html.dark, html[data-theme="dark"]:not(.light)) .an-powered-badge:not(.an-powered-badge-plain):hover {
|
|
139
119
|
color: rgba(238, 238, 238, 1) !important;
|
|
140
120
|
}
|
|
141
|
-
.light .an-powered-badge:not(.an-powered-badge-plain):hover {
|
|
121
|
+
:is(html.light, html[data-theme="light"]:not(.dark)) .an-powered-badge:not(.an-powered-badge-plain):hover {
|
|
142
122
|
color: rgba(70, 70, 70, 1) !important;
|
|
143
123
|
}
|
|
144
124
|
`}</style>
|
|
@@ -205,32 +185,10 @@ export function OpenSourceBadge({
|
|
|
205
185
|
max-width: calc(100vw - 2rem);
|
|
206
186
|
}
|
|
207
187
|
}
|
|
208
|
-
.dark .an-open-source-badge {
|
|
209
|
-
color: #00B5FF !important;
|
|
210
|
-
}
|
|
211
|
-
@media ${darkQuery} {
|
|
212
|
-
.an-open-source-badge {
|
|
213
|
-
color: #00B5FF !important;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
.light .an-open-source-badge {
|
|
217
|
-
color: #00B5FF !important;
|
|
218
|
-
}
|
|
219
188
|
.an-open-source-badge:hover {
|
|
220
189
|
opacity: 1 !important;
|
|
221
190
|
color: #33C4FF !important;
|
|
222
191
|
}
|
|
223
|
-
@media ${darkQuery} {
|
|
224
|
-
.an-open-source-badge:hover {
|
|
225
|
-
color: #33C4FF !important;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
.dark .an-open-source-badge:hover {
|
|
229
|
-
color: #33C4FF !important;
|
|
230
|
-
}
|
|
231
|
-
.light .an-open-source-badge:hover {
|
|
232
|
-
color: #33C4FF !important;
|
|
233
|
-
}
|
|
234
192
|
`}</style>
|
|
235
193
|
<a
|
|
236
194
|
href="https://github.com/BuilderIO/agent-native"
|
|
@@ -219,17 +219,6 @@
|
|
|
219
219
|
background: var(--shiki-dark-bg);
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
@media (prefers-color-scheme: dark) {
|
|
223
|
-
:root:not(.light) .agent-conversation-shiki pre {
|
|
224
|
-
background: var(--shiki-dark-bg, hsl(var(--muted) / 0.72));
|
|
225
|
-
color: var(--shiki-dark, hsl(var(--foreground)));
|
|
226
|
-
}
|
|
227
|
-
:root:not(.light) .agent-conversation-shiki pre span {
|
|
228
|
-
color: var(--shiki-dark);
|
|
229
|
-
background: var(--shiki-dark-bg);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
222
|
.agent-conversation-tool {
|
|
234
223
|
width: 100%;
|
|
235
224
|
border: 1px solid hsl(var(--border) / 0.9);
|
|
@@ -727,18 +716,6 @@
|
|
|
727
716
|
background: var(--shiki-dark-bg);
|
|
728
717
|
}
|
|
729
718
|
|
|
730
|
-
@media (prefers-color-scheme: dark) {
|
|
731
|
-
:root:not(.light) .agent-markdown-shiki pre {
|
|
732
|
-
background: var(--shiki-dark-bg);
|
|
733
|
-
color: var(--shiki-dark);
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
:root:not(.light) .agent-markdown-shiki pre span {
|
|
737
|
-
color: var(--shiki-dark);
|
|
738
|
-
background: var(--shiki-dark-bg);
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
|
|
742
719
|
.agent-tool-code .agent-markdown-shiki {
|
|
743
720
|
margin: 0;
|
|
744
721
|
border-radius: 0;
|
|
@@ -3,6 +3,24 @@ import { readFileSync } from "node:fs";
|
|
|
3
3
|
import { describe, expect, it } from "vitest";
|
|
4
4
|
|
|
5
5
|
describe("agent-native shell surface tokens", () => {
|
|
6
|
+
it("uses the selected theme class for dark utilities and chat markdown", () => {
|
|
7
|
+
const toolkitCss = readFileSync(
|
|
8
|
+
new URL("./agent-native.css", import.meta.url),
|
|
9
|
+
{ encoding: "utf8" },
|
|
10
|
+
);
|
|
11
|
+
const conversationCss = readFileSync(
|
|
12
|
+
new URL("./agent-conversation.css", import.meta.url),
|
|
13
|
+
{ encoding: "utf8" },
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
expect(toolkitCss).toContain(
|
|
17
|
+
"@custom-variant dark (&:where(.dark, .dark *));",
|
|
18
|
+
);
|
|
19
|
+
expect(conversationCss).not.toContain("prefers-color-scheme: dark");
|
|
20
|
+
expect(conversationCss).toContain(".dark .agent-conversation-shiki pre");
|
|
21
|
+
expect(conversationCss).toContain(".dark .agent-markdown-shiki pre");
|
|
22
|
+
});
|
|
23
|
+
|
|
6
24
|
it("keeps the composer surface opaque while preserving its muted blend", () => {
|
|
7
25
|
const css = readFileSync(new URL("./agent-native.css", import.meta.url), {
|
|
8
26
|
encoding: "utf8",
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The agent-native family uses the shared Tailwind/shadcn palette from the
|
|
3
|
+
* Design template. App styles remain the original family by default.
|
|
4
|
+
*/
|
|
5
|
+
:root[data-theme-family="agent-native"],
|
|
6
|
+
:root[data-theme-family="agent-native"][data-appearance] {
|
|
7
|
+
--background: 0 0% 100%;
|
|
8
|
+
--foreground: 0 0% 10%;
|
|
9
|
+
--card: 0 0% 100%;
|
|
10
|
+
--card-foreground: 0 0% 10%;
|
|
11
|
+
--popover: 0 0% 100%;
|
|
12
|
+
--popover-foreground: 0 0% 10%;
|
|
13
|
+
--primary: 0 0% 15%;
|
|
14
|
+
--primary-foreground: 0 0% 100%;
|
|
15
|
+
--secondary: 0 0% 95%;
|
|
16
|
+
--secondary-foreground: 0 0% 15%;
|
|
17
|
+
--muted: 0 0% 95%;
|
|
18
|
+
--muted-foreground: 0 0% 45%;
|
|
19
|
+
--accent: 0 0% 95%;
|
|
20
|
+
--accent-foreground: 0 0% 15%;
|
|
21
|
+
--destructive: 0 84% 60%;
|
|
22
|
+
--destructive-foreground: 0 0% 98%;
|
|
23
|
+
--border: 0 0% 90%;
|
|
24
|
+
--input: 0 0% 90%;
|
|
25
|
+
--ring: 0 0% 40%;
|
|
26
|
+
--radius: 0.5rem;
|
|
27
|
+
--sidebar-background: 0 0% 97%;
|
|
28
|
+
--sidebar-foreground: 0 0% 45%;
|
|
29
|
+
--sidebar-primary: 0 0% 15%;
|
|
30
|
+
--sidebar-primary-foreground: 0 0% 100%;
|
|
31
|
+
--sidebar-accent: 0 0% 95%;
|
|
32
|
+
--sidebar-accent-foreground: 0 0% 15%;
|
|
33
|
+
--sidebar-border: 0 0% 90%;
|
|
34
|
+
--sidebar-ring: 0 0% 40%;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.dark[data-theme-family="agent-native"],
|
|
38
|
+
.dark[data-theme-family="agent-native"][data-appearance] {
|
|
39
|
+
--background: 0 0% 13%;
|
|
40
|
+
--foreground: 0 0% 90%;
|
|
41
|
+
--card: 0 0% 15%;
|
|
42
|
+
--card-foreground: 0 0% 90%;
|
|
43
|
+
--popover: 0 0% 15%;
|
|
44
|
+
--popover-foreground: 0 0% 90%;
|
|
45
|
+
--primary: 0 0% 75%;
|
|
46
|
+
--primary-foreground: 0 0% 10%;
|
|
47
|
+
--secondary: 0 0% 18%;
|
|
48
|
+
--secondary-foreground: 0 0% 90%;
|
|
49
|
+
--muted: 0 0% 16%;
|
|
50
|
+
--muted-foreground: 0 0% 60%;
|
|
51
|
+
--accent: 0 0% 18%;
|
|
52
|
+
--accent-foreground: 0 0% 96%;
|
|
53
|
+
--destructive: 0 91% 71%;
|
|
54
|
+
--destructive-foreground: 0 0% 98%;
|
|
55
|
+
--border: 0 0% 24%;
|
|
56
|
+
--input: 0 0% 24%;
|
|
57
|
+
--ring: 0 0% 60%;
|
|
58
|
+
--sidebar-background: 0 0% 10%;
|
|
59
|
+
--sidebar-foreground: 0 0% 60%;
|
|
60
|
+
--sidebar-primary: 0 0% 75%;
|
|
61
|
+
--sidebar-primary-foreground: 0 0% 10%;
|
|
62
|
+
--sidebar-accent: 0 0% 16%;
|
|
63
|
+
--sidebar-accent-foreground: 0 0% 90%;
|
|
64
|
+
--sidebar-border: 0 0% 20%;
|
|
65
|
+
--sidebar-ring: 0 0% 60%;
|
|
66
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
|
|
5
|
+
const css = readFileSync(
|
|
6
|
+
new URL("./theme-families.css", import.meta.url),
|
|
7
|
+
"utf8",
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
describe("theme families", () => {
|
|
11
|
+
it("provides a shared palette for the resolved light and dark modes", () => {
|
|
12
|
+
expect(css).toContain(':root[data-theme-family="agent-native"]');
|
|
13
|
+
expect(css).toContain('.dark[data-theme-family="agent-native"]');
|
|
14
|
+
expect(css).toContain("--background: 0 0% 100%");
|
|
15
|
+
expect(css).toContain("--background: 0 0% 13%");
|
|
16
|
+
expect(css).not.toContain("prefers-color-scheme");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("keeps the selected family palette ahead of appearance presets", () => {
|
|
20
|
+
expect(css).toContain(
|
|
21
|
+
':root[data-theme-family="agent-native"][data-appearance]',
|
|
22
|
+
);
|
|
23
|
+
expect(css).toContain(
|
|
24
|
+
'.dark[data-theme-family="agent-native"][data-appearance]',
|
|
25
|
+
);
|
|
26
|
+
expect(css).toContain("--background: 0 0% 100%");
|
|
27
|
+
expect(css).toContain("--background: 0 0% 13%");
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import React, { act } from "react";
|
|
4
|
+
import { createRoot, type Root } from "react-dom/client";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
|
|
7
|
+
import { ComposerContextBanner } from "./ComposerContextBanner.js";
|
|
8
|
+
|
|
9
|
+
(
|
|
10
|
+
globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
|
|
11
|
+
).IS_REACT_ACT_ENVIRONMENT = true;
|
|
12
|
+
|
|
13
|
+
let container: HTMLDivElement;
|
|
14
|
+
let root: Root;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
container = document.createElement("div");
|
|
18
|
+
document.body.appendChild(container);
|
|
19
|
+
root = createRoot(container);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
act(() => root.unmount());
|
|
24
|
+
container.remove();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe("ComposerContextBanner", () => {
|
|
28
|
+
it("renders localized context actions and calls add and dismiss handlers", async () => {
|
|
29
|
+
const onAddContext = vi.fn();
|
|
30
|
+
const onDismiss = vi.fn();
|
|
31
|
+
|
|
32
|
+
await act(async () =>
|
|
33
|
+
root.render(
|
|
34
|
+
<ComposerContextBanner
|
|
35
|
+
ariaLabel="Context guidance"
|
|
36
|
+
addContextLabel="Add context"
|
|
37
|
+
dismissLabel="Dismiss context guidance"
|
|
38
|
+
onAddContext={onAddContext}
|
|
39
|
+
onDismiss={onDismiss}
|
|
40
|
+
>
|
|
41
|
+
Improve answers by adding data definitions.
|
|
42
|
+
</ComposerContextBanner>,
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const banner = container.querySelector<HTMLElement>(
|
|
47
|
+
'[data-agent-composer-slot="context-banner"]',
|
|
48
|
+
)!;
|
|
49
|
+
expect(banner.getAttribute("aria-label")).toBe("Context guidance");
|
|
50
|
+
expect(banner.classList).toContain("gap-1.5");
|
|
51
|
+
expect(banner.classList).toContain("px-2.5");
|
|
52
|
+
expect(banner.classList).toContain("py-2");
|
|
53
|
+
expect(banner.classList).toContain("rounded-lg");
|
|
54
|
+
expect(banner.textContent).toContain(
|
|
55
|
+
"Improve answers by adding data definitions.",
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const addContextButton = Array.from(
|
|
59
|
+
container.querySelectorAll<HTMLButtonElement>("button"),
|
|
60
|
+
).find((button) => button.textContent?.includes("Add context"))!;
|
|
61
|
+
expect(addContextButton.classList).toContain("px-1.5");
|
|
62
|
+
|
|
63
|
+
await act(async () => addContextButton.click());
|
|
64
|
+
await act(async () =>
|
|
65
|
+
container
|
|
66
|
+
.querySelector<HTMLButtonElement>(
|
|
67
|
+
'button[aria-label="Dismiss context guidance"]',
|
|
68
|
+
)!
|
|
69
|
+
.click(),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
expect(onAddContext).toHaveBeenCalledOnce();
|
|
73
|
+
expect(onDismiss).toHaveBeenCalledOnce();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("renders a host-provided decorative add-context icon", async () => {
|
|
77
|
+
await act(async () =>
|
|
78
|
+
root.render(
|
|
79
|
+
<ComposerContextBanner
|
|
80
|
+
ariaLabel="Context guidance"
|
|
81
|
+
addContextLabel="Add context"
|
|
82
|
+
addContextIcon={<svg data-testid="custom-action-icon" />}
|
|
83
|
+
onAddContext={vi.fn()}
|
|
84
|
+
>
|
|
85
|
+
Improve answers by adding data definitions.
|
|
86
|
+
</ComposerContextBanner>,
|
|
87
|
+
),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const button = container.querySelector<HTMLButtonElement>("button")!;
|
|
91
|
+
const actionIcon = container.querySelector<SVGSVGElement>(
|
|
92
|
+
'[data-testid="custom-action-icon"]',
|
|
93
|
+
)!;
|
|
94
|
+
|
|
95
|
+
expect(button.textContent).toBe("Add context");
|
|
96
|
+
expect(button.classList).toContain("px-1.5");
|
|
97
|
+
expect(Array.from(button.querySelectorAll("svg"))).toEqual([actionIcon]);
|
|
98
|
+
expect(actionIcon.parentElement?.getAttribute("aria-hidden")).toBe("true");
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { IconPlus, IconSparkles, IconX } from "@tabler/icons-react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
import { Button } from "../ui/button.js";
|
|
5
|
+
import { cn } from "../utils.js";
|
|
6
|
+
|
|
7
|
+
interface ComposerContextBannerBaseProps {
|
|
8
|
+
/** Localized name for the banner's content. */
|
|
9
|
+
ariaLabel: string;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
/** Localized label for the action that opens or adds context. */
|
|
12
|
+
addContextLabel: string;
|
|
13
|
+
onAddContext: () => void;
|
|
14
|
+
/** Optional decorative icon displayed after the add-context label. */
|
|
15
|
+
addContextIcon?: ReactNode;
|
|
16
|
+
icon?: ReactNode;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type ComposerContextBannerProps = ComposerContextBannerBaseProps &
|
|
21
|
+
(
|
|
22
|
+
| { dismissLabel?: never; onDismiss?: never }
|
|
23
|
+
| { dismissLabel: string; onDismiss: () => void }
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
/** Shared informational banner that hosts can place in `composerContextBannerSlot`. */
|
|
27
|
+
export function ComposerContextBanner({
|
|
28
|
+
ariaLabel,
|
|
29
|
+
children,
|
|
30
|
+
addContextLabel,
|
|
31
|
+
onAddContext,
|
|
32
|
+
addContextIcon,
|
|
33
|
+
dismissLabel,
|
|
34
|
+
onDismiss,
|
|
35
|
+
icon,
|
|
36
|
+
className,
|
|
37
|
+
}: ComposerContextBannerProps) {
|
|
38
|
+
return (
|
|
39
|
+
<aside
|
|
40
|
+
aria-label={ariaLabel}
|
|
41
|
+
data-agent-composer-slot="context-banner"
|
|
42
|
+
className={cn(
|
|
43
|
+
"agent-composer-context-banner mx-auto mb-2 flex w-full max-w-3xl items-center gap-1.5 rounded-lg border border-border bg-background px-2.5 py-2 text-xs text-muted-foreground",
|
|
44
|
+
className,
|
|
45
|
+
)}
|
|
46
|
+
>
|
|
47
|
+
<span className="shrink-0 text-primary">
|
|
48
|
+
{icon ?? <IconSparkles aria-hidden="true" className="size-4" />}
|
|
49
|
+
</span>
|
|
50
|
+
<span className="min-w-0 flex-1">{children}</span>
|
|
51
|
+
<Button
|
|
52
|
+
className="shrink-0 px-1.5"
|
|
53
|
+
onClick={onAddContext}
|
|
54
|
+
size="xs"
|
|
55
|
+
type="button"
|
|
56
|
+
variant="outline"
|
|
57
|
+
>
|
|
58
|
+
{addContextLabel}
|
|
59
|
+
<span aria-hidden="true">
|
|
60
|
+
{addContextIcon ?? <IconPlus aria-hidden="true" />}
|
|
61
|
+
</span>
|
|
62
|
+
</Button>
|
|
63
|
+
{onDismiss ? (
|
|
64
|
+
<Button
|
|
65
|
+
aria-label={dismissLabel}
|
|
66
|
+
className="shrink-0"
|
|
67
|
+
onClick={onDismiss}
|
|
68
|
+
size="icon-xs"
|
|
69
|
+
type="button"
|
|
70
|
+
variant="ghost"
|
|
71
|
+
>
|
|
72
|
+
<IconX aria-hidden="true" />
|
|
73
|
+
</Button>
|
|
74
|
+
) : null}
|
|
75
|
+
</aside>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import React, { act, useState } from "react";
|
|
4
|
+
import { createRoot, type Root } from "react-dom/client";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
|
|
7
|
+
import { ComposerModePicker } from "./ComposerModePicker.js";
|
|
8
|
+
|
|
9
|
+
(
|
|
10
|
+
globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
|
|
11
|
+
).IS_REACT_ACT_ENVIRONMENT = true;
|
|
12
|
+
|
|
13
|
+
let container: HTMLDivElement;
|
|
14
|
+
let root: Root;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
container = document.createElement("div");
|
|
18
|
+
document.body.appendChild(container);
|
|
19
|
+
root = createRoot(container);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
act(() => root.unmount());
|
|
24
|
+
container.remove();
|
|
25
|
+
document.body.querySelectorAll('[role="menu"]').forEach((element) => {
|
|
26
|
+
if (!container.contains(element)) element.remove();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
function ModePickerHarness({
|
|
31
|
+
onChange,
|
|
32
|
+
}: {
|
|
33
|
+
onChange: (value: string) => void;
|
|
34
|
+
}) {
|
|
35
|
+
const [value, setValue] = useState("ask");
|
|
36
|
+
return (
|
|
37
|
+
<ComposerModePicker
|
|
38
|
+
ariaLabel="Ask mode"
|
|
39
|
+
options={[
|
|
40
|
+
{ value: "ask", label: "Ask", description: "Answer with context." },
|
|
41
|
+
{ value: "default", label: "Default" },
|
|
42
|
+
]}
|
|
43
|
+
value={value}
|
|
44
|
+
onValueChange={(next) => {
|
|
45
|
+
onChange(next);
|
|
46
|
+
setValue(next);
|
|
47
|
+
}}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
describe("ComposerModePicker", () => {
|
|
53
|
+
it("shows the selected host option and updates it through the shared menu", async () => {
|
|
54
|
+
const onChange = vi.fn();
|
|
55
|
+
await act(async () =>
|
|
56
|
+
root.render(<ModePickerHarness onChange={onChange} />),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const trigger = container.querySelector<HTMLButtonElement>(
|
|
60
|
+
'[data-agent-composer-slot="mode-picker"]',
|
|
61
|
+
)!;
|
|
62
|
+
expect(trigger.getAttribute("aria-label")).toBe("Ask mode: Ask");
|
|
63
|
+
|
|
64
|
+
await act(async () => {
|
|
65
|
+
trigger.dispatchEvent(
|
|
66
|
+
new MouseEvent("pointerdown", { bubbles: true, button: 0 }),
|
|
67
|
+
);
|
|
68
|
+
trigger.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
69
|
+
await Promise.resolve();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const defaultOption = Array.from(
|
|
73
|
+
document.body.querySelectorAll<HTMLElement>('[role="menuitemradio"]'),
|
|
74
|
+
).find((option) => option.textContent?.trim() === "Default");
|
|
75
|
+
expect(defaultOption).toBeDefined();
|
|
76
|
+
await act(async () => defaultOption!.click());
|
|
77
|
+
|
|
78
|
+
expect(onChange).toHaveBeenCalledWith("default");
|
|
79
|
+
expect(trigger.textContent).toContain("Default");
|
|
80
|
+
expect(trigger.getAttribute("aria-label")).toBe("Ask mode: Default");
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("keeps an unavailable selected value visible instead of choosing another mode", async () => {
|
|
84
|
+
await act(async () =>
|
|
85
|
+
root.render(
|
|
86
|
+
<ComposerModePicker
|
|
87
|
+
ariaLabel="Ask mode"
|
|
88
|
+
options={[{ value: "ask", label: "Ask" }]}
|
|
89
|
+
value="custom"
|
|
90
|
+
onValueChange={() => {}}
|
|
91
|
+
/>,
|
|
92
|
+
),
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const trigger = container.querySelector<HTMLButtonElement>(
|
|
96
|
+
'[data-agent-composer-slot="mode-picker"]',
|
|
97
|
+
);
|
|
98
|
+
expect(trigger?.textContent).toContain("custom");
|
|
99
|
+
expect(trigger?.getAttribute("aria-label")).toBe("Ask mode: custom");
|
|
100
|
+
});
|
|
101
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { IconChevronDown } from "@tabler/icons-react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
DropdownMenu,
|
|
6
|
+
DropdownMenuContent,
|
|
7
|
+
DropdownMenuRadioGroup,
|
|
8
|
+
DropdownMenuRadioItem,
|
|
9
|
+
DropdownMenuTrigger,
|
|
10
|
+
} from "../ui/dropdown-menu.js";
|
|
11
|
+
import { cn } from "../utils.js";
|
|
12
|
+
|
|
13
|
+
export interface ComposerModeOption {
|
|
14
|
+
/** Stable host-defined mode identifier. */
|
|
15
|
+
value: string;
|
|
16
|
+
/** Localized visible label supplied by the host. */
|
|
17
|
+
label: string;
|
|
18
|
+
/** Optional localized explanation shown in the menu. */
|
|
19
|
+
description?: string;
|
|
20
|
+
/** Optional host-provided icon. */
|
|
21
|
+
icon?: ReactNode;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ComposerModePickerProps {
|
|
26
|
+
/** Localized accessible name for this choice, such as "Ask mode". */
|
|
27
|
+
ariaLabel: string;
|
|
28
|
+
value: string;
|
|
29
|
+
options: readonly ComposerModeOption[];
|
|
30
|
+
onValueChange: (value: string) => void;
|
|
31
|
+
className?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A shared, host-configurable mode picker for composer modes that are not part
|
|
36
|
+
* of the framework's built-in Act/Plan execution setting.
|
|
37
|
+
*/
|
|
38
|
+
export function ComposerModePicker({
|
|
39
|
+
ariaLabel,
|
|
40
|
+
value,
|
|
41
|
+
options,
|
|
42
|
+
onValueChange,
|
|
43
|
+
className,
|
|
44
|
+
}: ComposerModePickerProps) {
|
|
45
|
+
const selectedOption = options.find((option) => option.value === value);
|
|
46
|
+
const selectedLabel = selectedOption?.label ?? value;
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<DropdownMenu>
|
|
50
|
+
<DropdownMenuTrigger asChild>
|
|
51
|
+
<button
|
|
52
|
+
type="button"
|
|
53
|
+
aria-label={`${ariaLabel}: ${selectedLabel}`}
|
|
54
|
+
data-agent-composer-slot="mode-picker"
|
|
55
|
+
className={cn(
|
|
56
|
+
"agent-composer-mode-picker inline-flex h-7 max-w-48 shrink-0 items-center gap-1 rounded-md px-2 text-xs font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
>
|
|
60
|
+
{selectedOption?.icon}
|
|
61
|
+
<span className="min-w-0 truncate">{selectedLabel}</span>
|
|
62
|
+
<IconChevronDown
|
|
63
|
+
aria-hidden="true"
|
|
64
|
+
className="size-3 shrink-0 opacity-60"
|
|
65
|
+
/>
|
|
66
|
+
</button>
|
|
67
|
+
</DropdownMenuTrigger>
|
|
68
|
+
<DropdownMenuContent
|
|
69
|
+
side="top"
|
|
70
|
+
align="start"
|
|
71
|
+
collisionPadding={8}
|
|
72
|
+
className="agent-composer-mode-picker-menu min-w-48"
|
|
73
|
+
>
|
|
74
|
+
<DropdownMenuRadioGroup value={value} onValueChange={onValueChange}>
|
|
75
|
+
{options.map((option) => (
|
|
76
|
+
<DropdownMenuRadioItem
|
|
77
|
+
key={option.value}
|
|
78
|
+
value={option.value}
|
|
79
|
+
indicator="check"
|
|
80
|
+
disabled={option.disabled}
|
|
81
|
+
className="agent-composer-mode-picker-option pe-3"
|
|
82
|
+
>
|
|
83
|
+
{option.icon}
|
|
84
|
+
<span className="min-w-0 flex-1">
|
|
85
|
+
<span className="block truncate">{option.label}</span>
|
|
86
|
+
{option.description ? (
|
|
87
|
+
<span className="mt-0.5 block whitespace-normal text-xs text-muted-foreground">
|
|
88
|
+
{option.description}
|
|
89
|
+
</span>
|
|
90
|
+
) : null}
|
|
91
|
+
</span>
|
|
92
|
+
</DropdownMenuRadioItem>
|
|
93
|
+
))}
|
|
94
|
+
</DropdownMenuRadioGroup>
|
|
95
|
+
</DropdownMenuContent>
|
|
96
|
+
</DropdownMenu>
|
|
97
|
+
);
|
|
98
|
+
}
|
package/src/composer/index.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
export { FileReference } from "./extensions/FileReference.js";
|
|
2
|
+
export {
|
|
3
|
+
ComposerContextBanner,
|
|
4
|
+
type ComposerContextBannerProps,
|
|
5
|
+
} from "./ComposerContextBanner.js";
|
|
6
|
+
export {
|
|
7
|
+
ComposerModePicker,
|
|
8
|
+
type ComposerModeOption,
|
|
9
|
+
type ComposerModePickerProps,
|
|
10
|
+
} from "./ComposerModePicker.js";
|
|
2
11
|
export {
|
|
3
12
|
useComposerDefaultActions,
|
|
4
13
|
mergeComposerMenuItems,
|