@nextclaw/ui 0.14.1 → 0.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/dist/assets/{api-DPcvCLfa.js → api-BP_8IaxB.js} +7 -7
- package/dist/assets/channels-list-page-DEh5Jjqx.js +8 -0
- package/dist/assets/chat-page-BRB0N5WW.js +105 -0
- package/dist/assets/config-split-page-CRhlZ_pH.js +1 -0
- package/dist/assets/{confirm-dialog-CWh5FfK2.js → confirm-dialog-DsivFJ4r.js} +2 -2
- package/dist/assets/{desktop-update-config-DsRhBizi.js → desktop-update-config-B0w9p2ep.js} +1 -1
- package/dist/assets/{dist-DPrgcEC0.js → dist-CikkhOlq.js} +1 -1
- package/dist/assets/{dist-DsE4OsSS.js → dist-PVA_xL1D.js} +1 -1
- package/dist/assets/doc-browser-BoNJ7-tE.js +1 -0
- package/dist/assets/doc-browser-CdJ_d4ik.js +1 -0
- package/dist/assets/doc-browser-context-MTw4EvKd.js +1 -0
- package/dist/assets/{ellipsis-B81FStLm.js → ellipsis-y6vDtq4M.js} +1 -1
- package/dist/assets/{external-link-C_dmG-WJ.js → external-link-DVJIQf_G.js} +1 -1
- package/dist/assets/index-BiE-K8-q.css +1 -0
- package/dist/assets/index-D9BAE_L_.js +105 -0
- package/dist/assets/mcp-marketplace-page-B1SZNY5m.js +40 -0
- package/dist/assets/mcp-marketplace-page-Cq_Tw42T.js +1 -0
- package/dist/assets/middleware-CkFT3R4v.js +1 -0
- package/dist/assets/model-config-page-DotaTUHb.js +1 -0
- package/dist/assets/plus-BbZqquJe.js +1 -0
- package/dist/assets/provider-scoped-model-input-DsFRuWJH.js +1 -0
- package/dist/assets/providers-config-page-DW4tQSLN.js +1 -0
- package/dist/assets/{react-sZz5HSCm.js → react-VNqT5Zp7.js} +1 -1
- package/dist/assets/remote-B8TiUfwW.js +1 -0
- package/dist/assets/rotate-cw-DjHDTkCv.js +1 -0
- package/dist/assets/runtime-config-page-S6ErRHR8.js +1 -0
- package/dist/assets/{save-MzjoiHri.js → save-BOJ477H-.js} +1 -1
- package/dist/assets/{search-B29dE4GN.js → search-BEti5beA.js} +1 -1
- package/dist/assets/{search-config-page-Dl5sZzob.js → search-config-page-DGj5am03.js} +1 -1
- package/dist/assets/{secrets-config-page-C_l-IFCK.js → secrets-config-page--IzrIOid.js} +2 -2
- package/dist/assets/{select-BKmh05hd.js → select-hoj8dK4K.js} +2 -2
- package/dist/assets/{tag-chip-BS_7Ueom.js → tag-chip-T8-h-die.js} +1 -1
- package/dist/assets/use-config-CjRV2hwL.js +1 -0
- package/dist/assets/x-D9PXs_xP.js +1 -0
- package/dist/index.html +70 -19
- package/index.html +55 -5
- package/package.json +9 -9
- package/src/app/components/app-presenter-provider.tsx +11 -2
- package/src/app/components/layout/__tests__/app-layout.test.tsx +11 -2
- package/src/app/components/layout/__tests__/sidebar.layout.test.tsx +110 -79
- package/src/app/components/layout/app-layout.tsx +18 -4
- package/src/app/components/layout/header.tsx +3 -3
- package/src/app/components/layout/page-layout.tsx +2 -2
- package/src/app/components/layout/runtime-status-entry.tsx +7 -7
- package/src/app/components/layout/sidebar-items.tsx +194 -71
- package/src/app/components/layout/sidebar-rail.styles.ts +15 -0
- package/src/app/components/layout/sidebar.tsx +340 -83
- package/src/app/managers/viewport-layout.manager.ts +10 -0
- package/src/app/stores/viewport-layout.store.ts +39 -3
- package/src/app/styles/design-system.css +388 -26
- package/src/app/test/vitest-setup.ts +31 -0
- package/src/features/agents/components/__tests__/agents-page.test.tsx +62 -39
- package/src/features/agents/components/agents-page.tsx +10 -6
- package/src/features/chat/components/chat-sidebar-list-mode-switch.tsx +3 -3
- package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +145 -0
- package/src/features/chat/components/conversation/__tests__/chat-conversation-header.test.tsx +4 -2
- package/src/features/chat/components/conversation/__tests__/chat-conversation-panel.test.tsx +69 -762
- package/src/features/chat/components/conversation/__tests__/chat-conversation-workspace-section.test.tsx +132 -0
- package/src/features/chat/components/conversation/chat-conversation-content.tsx +22 -15
- package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +15 -16
- package/src/features/chat/components/conversation/chat-conversation-header.tsx +7 -6
- package/src/features/chat/components/conversation/chat-conversation-panel.tsx +19 -19
- package/src/features/chat/components/conversation/chat-conversation-skeleton.tsx +13 -13
- package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +10 -4
- package/src/features/chat/components/layout/__tests__/chat-sidebar-read-state.test.tsx +52 -11
- package/src/features/chat/components/layout/__tests__/chat-sidebar.test.tsx +18 -16
- package/src/features/chat/components/layout/chat-page-shell.tsx +1 -1
- package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +247 -0
- package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +93 -20
- package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +93 -36
- package/src/features/chat/components/layout/chat-sidebar.tsx +60 -93
- package/src/features/chat/components/providers/chat-presenter.provider.tsx +0 -6
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +225 -0
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +199 -0
- package/src/features/chat/features/conversation/components/session-conversation-area.tsx +308 -0
- package/src/features/chat/features/conversation/components/session-conversation-input.tsx +439 -0
- package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +194 -0
- package/src/features/chat/features/conversation/hooks/use-session-conversation-input-attachments.ts +66 -0
- package/src/features/chat/features/{input/hooks/use-chat-input-bar-query-state.ts → conversation/hooks/use-session-conversation-input-query.ts} +51 -20
- package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +281 -0
- package/src/features/chat/features/conversation/utils/session-conversation-input-toolbar.utils.ts +158 -0
- package/src/features/chat/features/input/hooks/__tests__/use-chat-input-surface-state.test.tsx +56 -0
- package/src/features/chat/features/input/hooks/use-chat-input-surface-state.ts +117 -0
- package/src/features/chat/features/input/input-surface-plugins/__tests__/panel-app-reference-plugin.test.ts +77 -0
- package/src/features/chat/features/input/input-surface-plugins/__tests__/slash-command-plugin.test.ts +108 -0
- package/src/features/chat/features/input/input-surface-plugins/chat-input-product-plugin-adapters.types.ts +10 -0
- package/src/features/chat/features/input/input-surface-plugins/input-surface-search.utils.ts +108 -0
- package/src/features/chat/features/input/input-surface-plugins/panel-app-reference-plugin.utils.ts +108 -0
- package/src/features/chat/features/input/input-surface-plugins/slash-command-plugin.utils.ts +161 -0
- package/src/features/chat/features/input/utils/__tests__/chat-composer-state.utils.test.ts +22 -1
- package/src/features/chat/features/input/utils/__tests__/chat-inline-token.utils.test.ts +26 -13
- package/src/features/chat/features/input/utils/__tests__/ncp-chat-input-availability.utils.test.ts +7 -28
- package/src/features/chat/features/input/utils/chat-composer-state.utils.ts +6 -0
- package/src/features/chat/features/input/utils/chat-inline-token.utils.ts +26 -51
- package/src/features/chat/features/input/utils/chat-input-bar.utils.ts +2 -0
- package/src/features/chat/features/input/utils/ncp-chat-input-availability.utils.ts +5 -6
- package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +47 -12
- package/src/features/chat/features/message/components/chat-inline-panel-app-card.tsx +7 -7
- package/src/features/chat/features/message/components/chat-message-list.container.tsx +99 -18
- package/src/features/chat/features/message/utils/__tests__/chat-message.utils.test.ts +31 -12
- package/src/features/chat/features/message/utils/chat-message-markdown-part.utils.ts +38 -0
- package/src/features/chat/features/message/utils/chat-message-part.utils.ts +1 -1
- package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +7 -7
- package/src/features/chat/features/session/components/chat-sidebar-session-list.tsx +6 -6
- package/src/features/chat/features/session/components/session-context-icon.tsx +2 -2
- package/src/features/chat/features/session/components/session-header/__tests__/chat-session-project-badge.test.tsx +2 -2
- package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +1 -1
- package/src/features/chat/features/session/components/session-header/chat-session-header-menu-item.tsx +1 -1
- package/src/features/chat/features/session/components/session-header/chat-session-metadata-dialog.tsx +1 -1
- package/src/features/chat/features/session/components/session-header/chat-session-project-badge.tsx +3 -3
- package/src/features/chat/features/session/components/session-run-badge.tsx +1 -1
- package/src/features/chat/features/session/hooks/__tests__/use-chat-session-project.test.tsx +3 -30
- package/src/features/chat/features/session/hooks/use-chat-session-project.ts +0 -5
- package/src/features/chat/features/session/utils/chat-run-metadata.utils.ts +8 -0
- package/src/features/chat/features/session-type/components/__tests__/chat-session-type-menu.test.tsx +2 -2
- package/src/features/chat/features/session-type/components/__tests__/chat-session-type-option-item.test.tsx +2 -0
- package/src/features/chat/features/session-type/components/chat-session-type-menu.tsx +2 -2
- package/src/features/chat/features/session-type/components/chat-session-type-option-item.tsx +2 -2
- package/src/features/chat/features/session-type/hooks/use-chat-session-type-state.ts +10 -2
- package/src/features/chat/features/welcome/components/__tests__/chat-conversation-welcome.test.tsx +49 -31
- package/src/features/chat/features/welcome/components/__tests__/chat-welcome.test.tsx +2 -9
- package/src/features/chat/features/welcome/components/chat-conversation-welcome.tsx +21 -10
- package/src/features/chat/features/welcome/components/chat-welcome-agent-picker.tsx +3 -3
- package/src/features/chat/features/welcome/components/chat-welcome-capability-grid.tsx +4 -4
- package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +14 -19
- package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +5 -5
- package/src/features/chat/features/welcome/components/chat-welcome.tsx +6 -6
- package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-project-options.utils.test.ts +6 -8
- package/src/features/chat/features/welcome/utils/chat-welcome-project-options.utils.ts +1 -16
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +54 -0
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +44 -76
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +5 -1
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +7 -1
- package/src/features/chat/features/workspace/hooks/use-chat-conversation-workspace-state.ts +40 -31
- package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +59 -1
- package/src/features/chat/features/workspace/utils/chat-thread-workspace-session.utils.ts +109 -0
- package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +44 -4
- package/src/features/chat/index.ts +0 -1
- package/src/features/chat/managers/__tests__/chat-session-list.manager.test.ts +51 -99
- package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +135 -21
- package/src/features/chat/managers/chat-session-list.manager.ts +12 -43
- package/src/features/chat/managers/chat-thread.manager.ts +108 -34
- package/src/features/chat/pages/__tests__/ncp-chat-page.test.ts +48 -1
- package/src/features/chat/pages/__tests__/ncp-chat-page.test.tsx +72 -0
- package/src/features/chat/pages/ncp-chat-page.tsx +0 -122
- package/src/features/chat/presenters/chat.presenter.ts +2 -19
- package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +31 -0
- package/src/features/chat/stores/chat-thread.store.ts +42 -26
- package/src/features/panel-apps/components/panel-app-list-item.tsx +8 -8
- package/src/features/panel-apps/components/panel-app-toolbar.tsx +4 -4
- package/src/features/panel-apps/components/panel-apps-list.tsx +20 -20
- package/src/features/panel-apps/hooks/use-panel-apps.ts +2 -1
- package/src/features/pwa/managers/__tests__/pwa-shell-theme.manager.test.ts +70 -6
- package/src/features/pwa/managers/pwa-shell-theme.manager.ts +10 -5
- package/src/features/service-apps/components/service-action-authorization-dialog.tsx +8 -8
- package/src/features/service-apps/components/service-apps-panel.tsx +24 -24
- package/src/features/settings/components/config/provider-advanced-settings-section.tsx +5 -5
- package/src/features/settings/components/config/provider-auth-section.tsx +7 -7
- package/src/features/settings/components/config/provider-form.tsx +10 -10
- package/src/features/settings/components/config/provider-models-section.tsx +16 -16
- package/src/features/settings/components/config/provider-pill-selector.tsx +1 -1
- package/src/features/settings/pages/providers-config-page.tsx +17 -17
- package/src/platforms/desktop/components/__tests__/desktop-app-shell.test.tsx +50 -10
- package/src/platforms/desktop/components/desktop-app-shell.tsx +34 -10
- package/src/platforms/desktop/components/desktop-window-chrome.tsx +41 -16
- package/src/shared/components/config-split-page.tsx +11 -11
- package/src/shared/components/doc-browser/doc-browser-home-page.tsx +2 -2
- package/src/shared/components/doc-browser/doc-browser-panel-parts.tsx +4 -4
- package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +4 -4
- package/src/shared/components/doc-browser/doc-browser.tsx +3 -3
- package/src/shared/components/resizable-right-panel/resizable-right-panel.tsx +1 -1
- package/src/shared/components/ui/actions/icon-action-button.tsx +1 -1
- package/src/shared/components/ui/button.tsx +4 -4
- package/src/shared/components/ui/card.tsx +4 -4
- package/src/shared/components/ui/dialog.tsx +5 -5
- package/src/shared/components/ui/input.tsx +1 -1
- package/src/shared/components/ui/label.tsx +1 -1
- package/src/shared/components/ui/popover.tsx +1 -1
- package/src/shared/components/ui/select.tsx +3 -3
- package/src/shared/components/ui/switch.tsx +3 -3
- package/src/shared/components/ui/tab-strip/__tests__/compact-tab-strip.test.tsx +24 -1
- package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +8 -4
- package/src/shared/components/ui/tabs.tsx +4 -4
- package/src/shared/components/ui/textarea.tsx +1 -1
- package/src/shared/lib/i18n/locales/en-US/chat.json +20 -2
- package/src/shared/lib/i18n/locales/en-US/core.json +9 -2
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +20 -2
- package/src/shared/lib/i18n/locales/zh-CN/core.json +9 -2
- package/src/shared/lib/theme/index.ts +94 -52
- package/src/shared/lib/ui-document-title/__tests__/ui-document-title.test.ts +49 -0
- package/src/shared/lib/ui-document-title/index.ts +50 -21
- package/dist/assets/channels-list-page-D6jtziu4.js +0 -8
- package/dist/assets/chat-page-BBnNJoKG.js +0 -105
- package/dist/assets/config-split-page-BCJhqdK9.js +0 -1
- package/dist/assets/doc-browser-C8xOF_9F.js +0 -1
- package/dist/assets/doc-browser-DgQedeAn.js +0 -1
- package/dist/assets/doc-browser-context-B46tQGmO.js +0 -1
- package/dist/assets/index-7o1WdUbU.js +0 -103
- package/dist/assets/index-DQWmEWzk.css +0 -1
- package/dist/assets/mcp-marketplace-page-CWZN7ohK.js +0 -1
- package/dist/assets/mcp-marketplace-page-Dzull_4-.js +0 -40
- package/dist/assets/model-config-page-Cv0O3BIj.js +0 -1
- package/dist/assets/plus-Bnt56oqG.js +0 -1
- package/dist/assets/provider-scoped-model-input-Duuh7i3h.js +0 -1
- package/dist/assets/providers-config-page-CPDz0Lxc.js +0 -1
- package/dist/assets/remote-B0LMs8u7.js +0 -1
- package/dist/assets/rotate-cw-BfyG_KEF.js +0 -1
- package/dist/assets/runtime-config-page-q0fvv8ME.js +0 -1
- package/dist/assets/use-config-DZkBWIdL.js +0 -1
- package/dist/assets/x-CW2KO-Hz.js +0 -1
- package/src/features/chat/components/conversation/chat-conversation-alerts.tsx +0 -37
- package/src/features/chat/features/input/components/__tests__/chat-attachment-upload-limit.test.ts +0 -38
- package/src/features/chat/features/input/components/chat-input-bar.container.tsx +0 -496
- package/src/features/chat/features/message/utils/chat-message-inline-content.utils.ts +0 -95
- package/src/features/chat/managers/__tests__/chat-input.manager.test.ts +0 -448
- package/src/features/chat/managers/__tests__/chat-run-snapshot.manager.test.ts +0 -129
- package/src/features/chat/managers/__tests__/chat-run.manager.test.ts +0 -236
- package/src/features/chat/managers/__tests__/chat-session-preference-sync.manager.test.ts +0 -219
- package/src/features/chat/managers/chat-input.manager.ts +0 -430
- package/src/features/chat/managers/chat-run.manager.ts +0 -110
- package/src/features/chat/managers/chat-session-preference-sync.manager.ts +0 -142
- package/src/features/chat/stores/chat-input.store.ts +0 -104
- /package/dist/assets/{config-hints-CTqBnCDp.js → config-hints-BkYBc7z0.js} +0 -0
|
@@ -1,21 +1,45 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
-
import { pwaShellThemeManager } from '@/features/pwa';
|
|
2
|
+
import { pwaShellThemeManager } from '@/features/pwa/managers/pwa-shell-theme.manager';
|
|
3
3
|
|
|
4
4
|
describe('PwaShellThemeManager', () => {
|
|
5
5
|
beforeEach(() => {
|
|
6
|
-
document.head.innerHTML = '<meta name="theme-color" content="#
|
|
6
|
+
document.head.innerHTML = '<meta name="theme-color" content="#FFFFFF" />';
|
|
7
7
|
document.body.innerHTML = '<div id="root"></div>';
|
|
8
8
|
document.documentElement.removeAttribute('data-theme');
|
|
9
9
|
document.documentElement.style.backgroundColor = '';
|
|
10
10
|
document.body.style.backgroundColor = '';
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
+
it('applies natural shell colors by default', () => {
|
|
14
|
+
pwaShellThemeManager.syncCurrentTheme();
|
|
15
|
+
|
|
16
|
+
const meta = document.querySelector('meta[name="theme-color"]');
|
|
17
|
+
expect(meta?.getAttribute('content')).toBe('#FAF9F7');
|
|
18
|
+
expect(document.body.style.backgroundColor).toBe('rgb(250, 249, 247)');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('applies natural shell colors explicitly', () => {
|
|
22
|
+
pwaShellThemeManager.syncTheme('natural');
|
|
23
|
+
|
|
24
|
+
const meta = document.querySelector('meta[name="theme-color"]');
|
|
25
|
+
expect(meta?.getAttribute('content')).toBe('#FAF9F7');
|
|
26
|
+
expect(document.body.style.backgroundColor).toBe('rgb(250, 249, 247)');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('applies minimal shell colors explicitly', () => {
|
|
30
|
+
pwaShellThemeManager.syncTheme('minimal');
|
|
31
|
+
|
|
32
|
+
const meta = document.querySelector('meta[name="theme-color"]');
|
|
33
|
+
expect(meta?.getAttribute('content')).toBe('#FFFFFF');
|
|
34
|
+
expect(document.body.style.backgroundColor).toBe('rgb(255, 255, 255)');
|
|
35
|
+
});
|
|
36
|
+
|
|
13
37
|
it('applies warm shell colors', () => {
|
|
14
38
|
pwaShellThemeManager.syncTheme('warm');
|
|
15
39
|
|
|
16
40
|
const meta = document.querySelector('meta[name="theme-color"]');
|
|
17
|
-
expect(meta?.getAttribute('content')).toBe('#
|
|
18
|
-
expect(document.body.style.backgroundColor).toBe('rgb(
|
|
41
|
+
expect(meta?.getAttribute('content')).toBe('#FAF8F4');
|
|
42
|
+
expect(document.body.style.backgroundColor).toBe('rgb(250, 248, 244)');
|
|
19
43
|
});
|
|
20
44
|
|
|
21
45
|
it('applies cool shell colors from current theme attribute', () => {
|
|
@@ -24,7 +48,47 @@ describe('PwaShellThemeManager', () => {
|
|
|
24
48
|
pwaShellThemeManager.syncCurrentTheme();
|
|
25
49
|
|
|
26
50
|
const meta = document.querySelector('meta[name="theme-color"]');
|
|
27
|
-
expect(meta?.getAttribute('content')).toBe('#
|
|
28
|
-
expect(document.body.style.backgroundColor).toBe('rgb(248, 250,
|
|
51
|
+
expect(meta?.getAttribute('content')).toBe('#F8FAFC');
|
|
52
|
+
expect(document.body.style.backgroundColor).toBe('rgb(248, 250, 252)');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('applies dawn shell colors from current theme attribute', () => {
|
|
56
|
+
document.documentElement.setAttribute('data-theme', 'dawn');
|
|
57
|
+
|
|
58
|
+
pwaShellThemeManager.syncCurrentTheme();
|
|
59
|
+
|
|
60
|
+
const meta = document.querySelector('meta[name="theme-color"]');
|
|
61
|
+
expect(meta?.getAttribute('content')).toBe('#FAF7F4');
|
|
62
|
+
expect(document.body.style.backgroundColor).toBe('rgb(250, 247, 244)');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('applies graphite shell colors from current theme attribute', () => {
|
|
66
|
+
document.documentElement.setAttribute('data-theme', 'graphite');
|
|
67
|
+
|
|
68
|
+
pwaShellThemeManager.syncCurrentTheme();
|
|
69
|
+
|
|
70
|
+
const meta = document.querySelector('meta[name="theme-color"]');
|
|
71
|
+
expect(meta?.getAttribute('content')).toBe('#F8F8F7');
|
|
72
|
+
expect(document.body.style.backgroundColor).toBe('rgb(248, 248, 247)');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('maps the legacy leaf theme to warm shell colors', () => {
|
|
76
|
+
document.documentElement.setAttribute('data-theme', 'leaf');
|
|
77
|
+
|
|
78
|
+
pwaShellThemeManager.syncCurrentTheme();
|
|
79
|
+
|
|
80
|
+
const meta = document.querySelector('meta[name="theme-color"]');
|
|
81
|
+
expect(meta?.getAttribute('content')).toBe('#FAF8F4');
|
|
82
|
+
expect(document.body.style.backgroundColor).toBe('rgb(250, 248, 244)');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('applies probe shell colors from current theme attribute', () => {
|
|
86
|
+
document.documentElement.setAttribute('data-theme', 'probe');
|
|
87
|
+
|
|
88
|
+
pwaShellThemeManager.syncCurrentTheme();
|
|
89
|
+
|
|
90
|
+
const meta = document.querySelector('meta[name="theme-color"]');
|
|
91
|
+
expect(meta?.getAttribute('content')).toBe('#FEFCF6');
|
|
92
|
+
expect(document.body.style.backgroundColor).toBe('rgb(254, 252, 246)');
|
|
29
93
|
});
|
|
30
94
|
});
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { normalizeTheme, type UiTheme } from '@/shared/lib/theme';
|
|
2
2
|
|
|
3
3
|
const PWA_SHELL_THEME_COLORS: Record<UiTheme, string> = {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
natural: '#FAF9F7',
|
|
5
|
+
minimal: '#FFFFFF',
|
|
6
|
+
warm: '#FAF8F4',
|
|
7
|
+
cool: '#F8FAFC',
|
|
8
|
+
dawn: '#FAF7F4',
|
|
9
|
+
graphite: '#F8F8F7',
|
|
10
|
+
probe: '#FEFCF6'
|
|
6
11
|
};
|
|
7
12
|
|
|
8
13
|
export class PwaShellThemeManager {
|
|
@@ -22,8 +27,8 @@ export class PwaShellThemeManager {
|
|
|
22
27
|
return;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
|
-
const currentTheme = document.documentElement.getAttribute('data-theme')
|
|
26
|
-
this.syncTheme(currentTheme);
|
|
30
|
+
const currentTheme = document.documentElement.getAttribute('data-theme');
|
|
31
|
+
this.syncTheme(normalizeTheme(currentTheme) ?? 'natural');
|
|
27
32
|
};
|
|
28
33
|
|
|
29
34
|
private updateThemeMeta = (themeColor: string) => {
|
|
@@ -37,10 +37,10 @@ export function ServiceActionAuthorizationDialog() {
|
|
|
37
37
|
</DialogDescription>
|
|
38
38
|
</DialogHeader>
|
|
39
39
|
{pending ? (
|
|
40
|
-
<div className="space-y-3 rounded-md border border-
|
|
40
|
+
<div className="space-y-3 rounded-md border border-border bg-muted/60 p-3 text-sm">
|
|
41
41
|
<AuthorizationField label={t('serviceActionAuthorizationSource')} value={pending.panelAppId} />
|
|
42
42
|
<div className="space-y-2">
|
|
43
|
-
<div className="text-xs font-medium text-
|
|
43
|
+
<div className="text-xs font-medium text-muted-foreground">
|
|
44
44
|
{t('serviceActionAuthorizationActions')}
|
|
45
45
|
</div>
|
|
46
46
|
<div className="max-h-64 space-y-2 overflow-auto">
|
|
@@ -78,18 +78,18 @@ function AuthorizationActionItem({
|
|
|
78
78
|
};
|
|
79
79
|
}) {
|
|
80
80
|
return (
|
|
81
|
-
<div className="space-y-1 rounded border border-
|
|
81
|
+
<div className="space-y-1 rounded border border-border bg-card px-3 py-2">
|
|
82
82
|
<div className="flex items-start justify-between gap-3">
|
|
83
|
-
<div className="min-w-0 break-words text-xs font-medium text-
|
|
83
|
+
<div className="min-w-0 break-words text-xs font-medium text-foreground">
|
|
84
84
|
{action.actionTitle ?? action.actionId}
|
|
85
85
|
</div>
|
|
86
86
|
<div className="shrink-0 rounded bg-amber-50 px-1.5 py-0.5 text-[11px] font-medium text-amber-700">
|
|
87
87
|
{action.risk ?? 'dangerous'}
|
|
88
88
|
</div>
|
|
89
89
|
</div>
|
|
90
|
-
<div className="break-words text-[11px] text-
|
|
90
|
+
<div className="break-words text-[11px] text-muted-foreground">{action.actionId}</div>
|
|
91
91
|
{action.actionDescription ? (
|
|
92
|
-
<div className="break-words text-xs text-
|
|
92
|
+
<div className="break-words text-xs text-muted-foreground">{action.actionDescription}</div>
|
|
93
93
|
) : null}
|
|
94
94
|
</div>
|
|
95
95
|
);
|
|
@@ -104,8 +104,8 @@ function AuthorizationField({
|
|
|
104
104
|
}) {
|
|
105
105
|
return (
|
|
106
106
|
<div className="grid grid-cols-[5rem_minmax(0,1fr)] gap-3">
|
|
107
|
-
<div className="text-xs font-medium text-
|
|
108
|
-
<div className="min-w-0 break-words text-xs text-
|
|
107
|
+
<div className="text-xs font-medium text-muted-foreground">{label}</div>
|
|
108
|
+
<div className="min-w-0 break-words text-xs text-foreground">{value}</div>
|
|
109
109
|
</div>
|
|
110
110
|
);
|
|
111
111
|
}
|
|
@@ -62,7 +62,7 @@ export function ServiceAppsPanel({
|
|
|
62
62
|
|
|
63
63
|
if (serviceApps.isLoading || serviceActions.isLoading || serviceActionGrants.isLoading) {
|
|
64
64
|
return (
|
|
65
|
-
<div className="flex h-full items-center justify-center text-sm text-
|
|
65
|
+
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
|
|
66
66
|
{t('serviceAppsLoading')}
|
|
67
67
|
</div>
|
|
68
68
|
);
|
|
@@ -90,13 +90,13 @@ export function ServiceAppsPanel({
|
|
|
90
90
|
};
|
|
91
91
|
|
|
92
92
|
return (
|
|
93
|
-
<div className="flex h-full min-h-0 flex-col bg-
|
|
94
|
-
<div className="flex items-center justify-between gap-2 border-b border-
|
|
93
|
+
<div className="flex h-full min-h-0 flex-col bg-card text-card-foreground">
|
|
94
|
+
<div className="flex items-center justify-between gap-2 border-b border-border/70 px-4 py-3">
|
|
95
95
|
<div className="flex min-w-0 items-center gap-2">
|
|
96
96
|
{headerContent ?? (
|
|
97
97
|
<>
|
|
98
98
|
<Server className="h-4 w-4 text-primary" />
|
|
99
|
-
<div className="truncate text-sm font-semibold text-
|
|
99
|
+
<div className="truncate text-sm font-semibold text-foreground">{t('serviceAppsTitle')}</div>
|
|
100
100
|
</>
|
|
101
101
|
)}
|
|
102
102
|
</div>
|
|
@@ -110,7 +110,7 @@ export function ServiceAppsPanel({
|
|
|
110
110
|
</div>
|
|
111
111
|
|
|
112
112
|
{apps.length === 0 ? (
|
|
113
|
-
<div className="flex flex-1 items-center justify-center px-6 text-center text-sm text-
|
|
113
|
+
<div className="flex flex-1 items-center justify-center px-6 text-center text-sm text-muted-foreground">
|
|
114
114
|
{t('serviceAppsEmpty')}
|
|
115
115
|
</div>
|
|
116
116
|
) : (
|
|
@@ -172,15 +172,15 @@ function ServiceAppCard({
|
|
|
172
172
|
|
|
173
173
|
return (
|
|
174
174
|
<TooltipProvider delayDuration={250}>
|
|
175
|
-
<section className="rounded-lg border border-
|
|
175
|
+
<section className="rounded-lg border border-border bg-card p-3">
|
|
176
176
|
<div className="flex items-start justify-between gap-3">
|
|
177
177
|
<div className="min-w-0">
|
|
178
178
|
<div className="flex items-center gap-2">
|
|
179
|
-
<div className="truncate text-sm font-semibold text-
|
|
179
|
+
<div className="truncate text-sm font-semibold text-foreground">{app.title}</div>
|
|
180
180
|
<ServiceAppStatusBadge status={app.status} />
|
|
181
181
|
</div>
|
|
182
182
|
{app.description ? (
|
|
183
|
-
<div className="mt-1 line-clamp-2 text-xs text-
|
|
183
|
+
<div className="mt-1 line-clamp-2 text-xs text-muted-foreground">{app.description}</div>
|
|
184
184
|
) : null}
|
|
185
185
|
{app.lastError ? (
|
|
186
186
|
<div className="mt-2 rounded bg-rose-50 px-2 py-1 text-xs text-rose-700">{app.lastError}</div>
|
|
@@ -207,7 +207,7 @@ function ServiceAppCard({
|
|
|
207
207
|
<PopoverTrigger asChild>
|
|
208
208
|
<button
|
|
209
209
|
type="button"
|
|
210
|
-
className="rounded-md p-1.5 text-
|
|
210
|
+
className="rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground disabled:opacity-50"
|
|
211
211
|
aria-label={t('serviceAppsMoreActions')}
|
|
212
212
|
disabled={deletePending}
|
|
213
213
|
>
|
|
@@ -309,7 +309,7 @@ function getServiceAppStatusView(status: ServiceAppStatus): {
|
|
|
309
309
|
};
|
|
310
310
|
case 'stopped':
|
|
311
311
|
return {
|
|
312
|
-
className: 'bg-
|
|
312
|
+
className: 'bg-muted text-muted-foreground',
|
|
313
313
|
icon: PauseCircle,
|
|
314
314
|
label: t('serviceAppsStatus_stopped'),
|
|
315
315
|
tooltip: t('serviceAppsStatusHint_stopped'),
|
|
@@ -317,7 +317,7 @@ function getServiceAppStatusView(status: ServiceAppStatus): {
|
|
|
317
317
|
case 'idle':
|
|
318
318
|
default:
|
|
319
319
|
return {
|
|
320
|
-
className: 'bg-
|
|
320
|
+
className: 'bg-muted text-muted-foreground',
|
|
321
321
|
icon: CircleDashed,
|
|
322
322
|
label: t('serviceAppsStatus_idle'),
|
|
323
323
|
tooltip: t('serviceAppsStatusHint_idle'),
|
|
@@ -345,7 +345,7 @@ function ServiceAppIconButton({
|
|
|
345
345
|
type="button"
|
|
346
346
|
onClick={onClick}
|
|
347
347
|
disabled={disabled}
|
|
348
|
-
className="rounded-md p-1.5 text-
|
|
348
|
+
className="rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:text-muted-foreground/40 disabled:opacity-60 disabled:hover:bg-transparent"
|
|
349
349
|
aria-label={label}
|
|
350
350
|
>
|
|
351
351
|
<Icon className="h-3.5 w-3.5" />
|
|
@@ -374,7 +374,7 @@ function ServiceAppMenuItem({
|
|
|
374
374
|
type="button"
|
|
375
375
|
className={cn(
|
|
376
376
|
'flex w-full items-center gap-2 rounded-lg px-2.5 py-2 text-left text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50',
|
|
377
|
-
destructive ? 'text-destructive hover:bg-destructive/10' : 'text-
|
|
377
|
+
destructive ? 'text-destructive hover:bg-destructive/10' : 'text-muted-foreground hover:bg-accent hover:text-accent-foreground',
|
|
378
378
|
)}
|
|
379
379
|
disabled={disabled}
|
|
380
380
|
onClick={onClick}
|
|
@@ -403,7 +403,7 @@ function ServiceAppDiagnostics({ app }: { app: ServiceAppRecordView }) {
|
|
|
403
403
|
}
|
|
404
404
|
|
|
405
405
|
return (
|
|
406
|
-
<dl className="mt-3 grid grid-cols-[4.5rem_minmax(0,1fr)] gap-x-2 gap-y-1 border-t border-
|
|
406
|
+
<dl className="mt-3 grid grid-cols-[4.5rem_minmax(0,1fr)] gap-x-2 gap-y-1 border-t border-border/70 pt-2 text-[11px]">
|
|
407
407
|
{rows.map((row) => (
|
|
408
408
|
<ServiceAppDiagnosticRow key={row.label} label={row.label} value={row.value} />
|
|
409
409
|
))}
|
|
@@ -420,8 +420,8 @@ function ServiceAppDiagnosticRow({
|
|
|
420
420
|
}) {
|
|
421
421
|
return (
|
|
422
422
|
<>
|
|
423
|
-
<dt className="text-
|
|
424
|
-
<dd className="min-w-0 truncate font-mono text-
|
|
423
|
+
<dt className="text-muted-foreground/70">{label}</dt>
|
|
424
|
+
<dd className="min-w-0 truncate font-mono text-muted-foreground" title={value}>
|
|
425
425
|
{value}
|
|
426
426
|
</dd>
|
|
427
427
|
</>
|
|
@@ -438,36 +438,36 @@ function ServiceActionRow({
|
|
|
438
438
|
onRevoke: (grant: ServiceActionGrantView) => void;
|
|
439
439
|
}) {
|
|
440
440
|
return (
|
|
441
|
-
<div className="rounded bg-
|
|
441
|
+
<div className="rounded bg-muted/60 px-2 py-1.5">
|
|
442
442
|
<div className="flex items-center justify-between gap-2">
|
|
443
443
|
<div className="flex min-w-0 items-center gap-2">
|
|
444
|
-
<Wrench className="h-3.5 w-3.5 shrink-0 text-
|
|
444
|
+
<Wrench className="h-3.5 w-3.5 shrink-0 text-muted-foreground/70" />
|
|
445
445
|
<div className="min-w-0">
|
|
446
|
-
<div className="truncate text-xs font-medium text-
|
|
446
|
+
<div className="truncate text-xs font-medium text-foreground">{action.title ?? action.name}</div>
|
|
447
447
|
{action.description ? (
|
|
448
|
-
<div className="truncate text-[11px] text-
|
|
448
|
+
<div className="truncate text-[11px] text-muted-foreground">{action.description}</div>
|
|
449
449
|
) : null}
|
|
450
450
|
</div>
|
|
451
451
|
</div>
|
|
452
452
|
<div className="flex shrink-0 items-center gap-1">
|
|
453
453
|
{action.runtimeState ? (
|
|
454
|
-
<span className="rounded bg-
|
|
454
|
+
<span className="rounded bg-card px-1.5 py-0.5 text-[11px] text-muted-foreground">
|
|
455
455
|
{t(`serviceAppsRuntimeState_${action.runtimeState}`)}
|
|
456
456
|
</span>
|
|
457
457
|
) : null}
|
|
458
|
-
<span className="rounded bg-
|
|
458
|
+
<span className="rounded bg-card px-1.5 py-0.5 text-[11px] text-muted-foreground">{action.risk}</span>
|
|
459
459
|
</div>
|
|
460
460
|
</div>
|
|
461
461
|
{grants.map((grant) => (
|
|
462
462
|
<div key={`${grant.caller.surface}:${grant.caller.appId}:${grant.actionId}`} className="mt-1 flex items-center justify-between gap-2 pl-5">
|
|
463
|
-
<div className="flex min-w-0 items-center gap-1.5 text-[11px] text-
|
|
463
|
+
<div className="flex min-w-0 items-center gap-1.5 text-[11px] text-muted-foreground">
|
|
464
464
|
<ShieldCheck className="h-3 w-3 shrink-0 text-emerald-500" />
|
|
465
465
|
<span className="truncate">{t('serviceAppsGrantedTo')} {grant.caller.appId}</span>
|
|
466
466
|
</div>
|
|
467
467
|
<button
|
|
468
468
|
type="button"
|
|
469
469
|
onClick={() => onRevoke(grant)}
|
|
470
|
-
className="rounded-md p-1 text-
|
|
470
|
+
className="rounded-md p-1 text-muted-foreground/70 transition-colors hover:bg-background hover:text-rose-600"
|
|
471
471
|
title={t('serviceAppsRevokeGrant')}
|
|
472
472
|
aria-label={t('serviceAppsRevokeGrant')}
|
|
473
473
|
>
|
|
@@ -24,11 +24,11 @@ export function ProviderAdvancedSettingsSection(props: ProviderAdvancedSettingsS
|
|
|
24
24
|
} = props;
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
|
-
<div className="border-t border-
|
|
27
|
+
<div className="border-t border-border/70 pt-4">
|
|
28
28
|
<button
|
|
29
29
|
type="button"
|
|
30
30
|
onClick={() => onShowAdvancedChange(!showAdvanced)}
|
|
31
|
-
className="flex w-full items-center justify-between text-sm text-
|
|
31
|
+
className="flex w-full items-center justify-between text-sm text-muted-foreground transition-colors hover:text-foreground"
|
|
32
32
|
>
|
|
33
33
|
<span className="flex items-center gap-1.5">
|
|
34
34
|
<Settings2 className="h-3.5 w-3.5" />
|
|
@@ -41,7 +41,7 @@ export function ProviderAdvancedSettingsSection(props: ProviderAdvancedSettingsS
|
|
|
41
41
|
<div className="mt-4 space-y-5">
|
|
42
42
|
{supportsWireApi ? (
|
|
43
43
|
<div className="space-y-2">
|
|
44
|
-
<Label htmlFor="wireApi" className="text-sm font-medium text-
|
|
44
|
+
<Label htmlFor="wireApi" className="text-sm font-medium text-foreground">
|
|
45
45
|
{wireApiLabel}
|
|
46
46
|
</Label>
|
|
47
47
|
{shouldUseWireApiPills ? (
|
|
@@ -68,9 +68,9 @@ export function ProviderAdvancedSettingsSection(props: ProviderAdvancedSettingsS
|
|
|
68
68
|
) : null}
|
|
69
69
|
|
|
70
70
|
<div className="space-y-2">
|
|
71
|
-
<Label className="text-sm font-medium text-
|
|
71
|
+
<Label className="text-sm font-medium text-foreground">{extraHeadersLabel}</Label>
|
|
72
72
|
<KeyValueEditor value={extraHeaders} onChange={onExtraHeadersChange} />
|
|
73
|
-
<p className="text-xs text-
|
|
73
|
+
<p className="text-xs text-muted-foreground">{t('providerExtraHeadersHelpShort')}</p>
|
|
74
74
|
</div>
|
|
75
75
|
</div>
|
|
76
76
|
) : null}
|
|
@@ -29,13 +29,13 @@ export function ProviderAuthSection(props: ProviderAuthSectionProps) {
|
|
|
29
29
|
|
|
30
30
|
return (
|
|
31
31
|
<div className="space-y-2 rounded-xl border border-primary/20 bg-primary-50/50 p-3">
|
|
32
|
-
<Label className="text-sm font-medium text-
|
|
32
|
+
<Label className="text-sm font-medium text-foreground">
|
|
33
33
|
{providerAuth.displayName || t('providerAuthSectionTitle')}
|
|
34
34
|
</Label>
|
|
35
|
-
{providerAuthNote ? <p className="text-xs text-
|
|
35
|
+
{providerAuthNote ? <p className="text-xs text-muted-foreground">{providerAuthNote}</p> : null}
|
|
36
36
|
{providerAuthMethodsCount > 1 ? (
|
|
37
37
|
<div className="space-y-2">
|
|
38
|
-
<Label className="text-xs font-medium text-
|
|
38
|
+
<Label className="text-xs font-medium text-foreground">{t('providerAuthMethodLabel')}</Label>
|
|
39
39
|
{shouldUseAuthMethodPills ? (
|
|
40
40
|
<ProviderPillSelector
|
|
41
41
|
value={resolvedAuthMethodId}
|
|
@@ -44,7 +44,7 @@ export function ProviderAuthSection(props: ProviderAuthSectionProps) {
|
|
|
44
44
|
/>
|
|
45
45
|
) : (
|
|
46
46
|
<Select value={resolvedAuthMethodId} onValueChange={onAuthMethodChange}>
|
|
47
|
-
<SelectTrigger className="h-8 rounded-lg
|
|
47
|
+
<SelectTrigger className="h-8 rounded-lg">
|
|
48
48
|
<SelectValue placeholder={t('providerAuthMethodPlaceholder')} />
|
|
49
49
|
</SelectTrigger>
|
|
50
50
|
<SelectContent>
|
|
@@ -56,7 +56,7 @@ export function ProviderAuthSection(props: ProviderAuthSectionProps) {
|
|
|
56
56
|
</SelectContent>
|
|
57
57
|
</Select>
|
|
58
58
|
)}
|
|
59
|
-
{selectedAuthMethodHint ? <p className="text-xs text-
|
|
59
|
+
{selectedAuthMethodHint ? <p className="text-xs text-muted-foreground">{selectedAuthMethodHint}</p> : null}
|
|
60
60
|
</div>
|
|
61
61
|
) : null}
|
|
62
62
|
<div className="flex flex-wrap items-center gap-2">
|
|
@@ -85,12 +85,12 @@ export function ProviderAuthSection(props: ProviderAuthSectionProps) {
|
|
|
85
85
|
</Button>
|
|
86
86
|
) : null}
|
|
87
87
|
{authSessionId ? (
|
|
88
|
-
<span className="text-xs text-
|
|
88
|
+
<span className="text-xs text-muted-foreground">
|
|
89
89
|
{t('providerAuthSessionLabel')}: {authSessionId.slice(0, 8)}…
|
|
90
90
|
</span>
|
|
91
91
|
) : null}
|
|
92
92
|
</div>
|
|
93
|
-
{authStatusMessage ? <p className="text-xs text-
|
|
93
|
+
{authStatusMessage ? <p className="text-xs text-muted-foreground">{authStatusMessage}</p> : null}
|
|
94
94
|
</div>
|
|
95
95
|
);
|
|
96
96
|
}
|
|
@@ -329,8 +329,8 @@ export function ProviderForm({ providerName, onProviderDeleted }: ProviderFormPr
|
|
|
329
329
|
return (
|
|
330
330
|
<ConfigSplitEmptyPane>
|
|
331
331
|
<div>
|
|
332
|
-
<h3 className='text-base font-semibold text-
|
|
333
|
-
<p className='mt-2 text-sm text-
|
|
332
|
+
<h3 className='text-base font-semibold text-foreground'>{t('providersSelectTitle')}</h3>
|
|
333
|
+
<p className='mt-2 text-sm text-muted-foreground'>{t('providersSelectDescription')}</p>
|
|
334
334
|
</div>
|
|
335
335
|
</ConfigSplitEmptyPane>
|
|
336
336
|
);
|
|
@@ -437,13 +437,13 @@ function ProviderFormDetailPane(props: ProviderFormDetailPaneProps) {
|
|
|
437
437
|
<ConfigSplitDetailPane>
|
|
438
438
|
<ConfigSplitPaneHeader className='px-6 py-4'>
|
|
439
439
|
<div className='flex items-center justify-between'>
|
|
440
|
-
<h3 className='truncate text-lg font-semibold text-
|
|
440
|
+
<h3 className='truncate text-lg font-semibold text-foreground'>{providerTitle}</h3>
|
|
441
441
|
<div className='flex items-center gap-3'>
|
|
442
442
|
<button
|
|
443
443
|
type='button'
|
|
444
444
|
onClick={onDeleteProvider}
|
|
445
445
|
disabled={isDeletePending}
|
|
446
|
-
className='text-
|
|
446
|
+
className='text-muted-foreground/70 transition-colors hover:text-red-500'
|
|
447
447
|
title={t('providerDelete')}
|
|
448
448
|
>
|
|
449
449
|
<Trash2 className='h-4 w-4' />
|
|
@@ -456,7 +456,7 @@ function ProviderFormDetailPane(props: ProviderFormDetailPaneProps) {
|
|
|
456
456
|
<form onSubmit={onSubmit} className='flex min-h-0 flex-1 flex-col'>
|
|
457
457
|
<ConfigSplitPaneBody className='space-y-5 px-6 py-5'>
|
|
458
458
|
<div className='space-y-2'>
|
|
459
|
-
<Label htmlFor='providerDisplayName' className='text-sm font-medium text-
|
|
459
|
+
<Label htmlFor='providerDisplayName' className='text-sm font-medium text-foreground'>
|
|
460
460
|
{t('providerDisplayName')}
|
|
461
461
|
</Label>
|
|
462
462
|
<Input
|
|
@@ -467,11 +467,11 @@ function ProviderFormDetailPane(props: ProviderFormDetailPaneProps) {
|
|
|
467
467
|
placeholder={context.defaultDisplayName || t('providerDisplayNamePlaceholder')}
|
|
468
468
|
className='rounded-xl'
|
|
469
469
|
/>
|
|
470
|
-
<p className='text-xs text-
|
|
470
|
+
<p className='text-xs text-muted-foreground'>{t('providerDisplayNameHelpShort')}</p>
|
|
471
471
|
</div>
|
|
472
472
|
|
|
473
473
|
<div className='space-y-2'>
|
|
474
|
-
<Label htmlFor='apiKey' className='text-sm font-medium text-
|
|
474
|
+
<Label htmlFor='apiKey' className='text-sm font-medium text-foreground'>
|
|
475
475
|
{context.apiKeyHint?.label ?? t('apiKey')}
|
|
476
476
|
</Label>
|
|
477
477
|
<MaskedInput
|
|
@@ -482,7 +482,7 @@ function ProviderFormDetailPane(props: ProviderFormDetailPaneProps) {
|
|
|
482
482
|
placeholder={context.apiKeyHint?.placeholder ?? t('enterApiKey')}
|
|
483
483
|
className='rounded-xl'
|
|
484
484
|
/>
|
|
485
|
-
<p className='text-xs text-
|
|
485
|
+
<p className='text-xs text-muted-foreground'>{t('leaveBlankToKeepUnchanged')}</p>
|
|
486
486
|
</div>
|
|
487
487
|
|
|
488
488
|
<ProviderAuthSection
|
|
@@ -503,7 +503,7 @@ function ProviderFormDetailPane(props: ProviderFormDetailPaneProps) {
|
|
|
503
503
|
/>
|
|
504
504
|
|
|
505
505
|
<div className='space-y-2'>
|
|
506
|
-
<Label htmlFor='apiBase' className='text-sm font-medium text-
|
|
506
|
+
<Label htmlFor='apiBase' className='text-sm font-medium text-foreground'>
|
|
507
507
|
{context.apiBaseHint?.label ?? t('apiBase')}
|
|
508
508
|
</Label>
|
|
509
509
|
<Input
|
|
@@ -514,7 +514,7 @@ function ProviderFormDetailPane(props: ProviderFormDetailPaneProps) {
|
|
|
514
514
|
placeholder={context.defaultApiBase || context.apiBaseHint?.placeholder || 'https://api.example.com'}
|
|
515
515
|
className='rounded-xl'
|
|
516
516
|
/>
|
|
517
|
-
<p className='text-xs text-
|
|
517
|
+
<p className='text-xs text-muted-foreground'>{context.apiBaseHelpText}</p>
|
|
518
518
|
</div>
|
|
519
519
|
|
|
520
520
|
<ProviderModelsSection
|
|
@@ -49,7 +49,7 @@ export function ProviderModelsSection(props: ProviderModelsSectionProps) {
|
|
|
49
49
|
return (
|
|
50
50
|
<div className="space-y-2">
|
|
51
51
|
<div className="flex items-center justify-between">
|
|
52
|
-
<Label className="text-sm font-medium text-
|
|
52
|
+
<Label className="text-sm font-medium text-foreground">{t('providerModelsTitle')}</Label>
|
|
53
53
|
{!showModelInput ? (
|
|
54
54
|
<button
|
|
55
55
|
type="button"
|
|
@@ -99,8 +99,8 @@ export function ProviderModelsSection(props: ProviderModelsSectionProps) {
|
|
|
99
99
|
) : null}
|
|
100
100
|
|
|
101
101
|
{models.length === 0 ? (
|
|
102
|
-
<div className="rounded-xl border border-dashed border-
|
|
103
|
-
<p className="text-sm text-
|
|
102
|
+
<div className="rounded-xl border border-dashed border-border bg-muted/60 px-4 py-6 text-center">
|
|
103
|
+
<p className="text-sm text-muted-foreground">{t('providerModelsEmptyShort')}</p>
|
|
104
104
|
{!showModelInput ? (
|
|
105
105
|
<button
|
|
106
106
|
type="button"
|
|
@@ -123,14 +123,14 @@ export function ProviderModelsSection(props: ProviderModelsSectionProps) {
|
|
|
123
123
|
return (
|
|
124
124
|
<div
|
|
125
125
|
key={modelName}
|
|
126
|
-
className="group inline-flex max-w-full items-center gap-1 rounded-full border border-
|
|
126
|
+
className="group inline-flex max-w-full items-center gap-1 rounded-full border border-border bg-card px-3 py-1.5"
|
|
127
127
|
>
|
|
128
|
-
<span className="max-w-[140px] truncate text-sm text-
|
|
128
|
+
<span className="max-w-[140px] truncate text-sm text-foreground sm:max-w-[220px]">{modelName}</span>
|
|
129
129
|
<Popover>
|
|
130
130
|
<PopoverTrigger asChild>
|
|
131
131
|
<button
|
|
132
132
|
type="button"
|
|
133
|
-
className="inline-flex h-5 w-5 items-center justify-center rounded-full text-
|
|
133
|
+
className="inline-flex h-5 w-5 items-center justify-center rounded-full text-muted-foreground/70 opacity-100 transition-opacity hover:bg-accent hover:text-accent-foreground md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100"
|
|
134
134
|
aria-label={t('providerModelThinkingTitle')}
|
|
135
135
|
title={t('providerModelThinkingTitle')}
|
|
136
136
|
>
|
|
@@ -138,16 +138,16 @@ export function ProviderModelsSection(props: ProviderModelsSectionProps) {
|
|
|
138
138
|
</button>
|
|
139
139
|
</PopoverTrigger>
|
|
140
140
|
<PopoverContent className="w-80 space-y-3">
|
|
141
|
-
<div className="flex items-center justify-between gap-3 rounded-lg border border-
|
|
141
|
+
<div className="flex items-center justify-between gap-3 rounded-lg border border-border bg-muted/60 px-3 py-2">
|
|
142
142
|
<div className="min-w-0">
|
|
143
|
-
<p className="text-xs font-semibold text-
|
|
144
|
-
<p className="text-xs text-
|
|
143
|
+
<p className="text-xs font-semibold text-foreground">{t('providerModelVisionTitle')}</p>
|
|
144
|
+
<p className="text-xs text-muted-foreground">{t('providerModelVisionHint')}</p>
|
|
145
145
|
</div>
|
|
146
146
|
<Switch checked={visionEnabled} onCheckedChange={(checked) => onSetModelVision(modelName, checked)} />
|
|
147
147
|
</div>
|
|
148
148
|
<div className="space-y-1">
|
|
149
|
-
<p className="text-xs font-semibold text-
|
|
150
|
-
<p className="text-xs text-
|
|
149
|
+
<p className="text-xs font-semibold text-foreground">{t('providerModelThinkingTitle')}</p>
|
|
150
|
+
<p className="text-xs text-muted-foreground">{t('providerModelThinkingHint')}</p>
|
|
151
151
|
</div>
|
|
152
152
|
<div className="flex flex-wrap gap-1.5">
|
|
153
153
|
{thinkingLevels.map((level) => {
|
|
@@ -160,7 +160,7 @@ export function ProviderModelsSection(props: ProviderModelsSectionProps) {
|
|
|
160
160
|
className={`rounded-full border px-2.5 py-1 text-xs font-medium transition-colors ${
|
|
161
161
|
selected
|
|
162
162
|
? 'border-primary bg-primary text-white'
|
|
163
|
-
: 'border-
|
|
163
|
+
: 'border-border bg-card text-muted-foreground hover:border-primary/40 hover:bg-accent/70 hover:text-accent-foreground'
|
|
164
164
|
}`}
|
|
165
165
|
>
|
|
166
166
|
{formatThinkingLevelLabel(level)}
|
|
@@ -169,7 +169,7 @@ export function ProviderModelsSection(props: ProviderModelsSectionProps) {
|
|
|
169
169
|
})}
|
|
170
170
|
</div>
|
|
171
171
|
<div className="space-y-1.5">
|
|
172
|
-
<Label className="text-xs font-medium text-
|
|
172
|
+
<Label className="text-xs font-medium text-foreground">{t('providerModelThinkingDefault')}</Label>
|
|
173
173
|
<Select
|
|
174
174
|
value={defaultThinkingLevel ?? '__none__'}
|
|
175
175
|
onValueChange={(value) =>
|
|
@@ -177,7 +177,7 @@ export function ProviderModelsSection(props: ProviderModelsSectionProps) {
|
|
|
177
177
|
}
|
|
178
178
|
disabled={supportedLevels.length === 0}
|
|
179
179
|
>
|
|
180
|
-
<SelectTrigger className="h-8 rounded-lg
|
|
180
|
+
<SelectTrigger className="h-8 rounded-lg text-xs">
|
|
181
181
|
<SelectValue />
|
|
182
182
|
</SelectTrigger>
|
|
183
183
|
<SelectContent>
|
|
@@ -190,7 +190,7 @@ export function ProviderModelsSection(props: ProviderModelsSectionProps) {
|
|
|
190
190
|
</SelectContent>
|
|
191
191
|
</Select>
|
|
192
192
|
{supportedLevels.length === 0 ? (
|
|
193
|
-
<p className="text-xs text-
|
|
193
|
+
<p className="text-xs text-muted-foreground">{t('providerModelThinkingNoSupported')}</p>
|
|
194
194
|
) : null}
|
|
195
195
|
</div>
|
|
196
196
|
</PopoverContent>
|
|
@@ -198,7 +198,7 @@ export function ProviderModelsSection(props: ProviderModelsSectionProps) {
|
|
|
198
198
|
<button
|
|
199
199
|
type="button"
|
|
200
200
|
onClick={() => onRemoveModel(modelName)}
|
|
201
|
-
className="inline-flex h-5 w-5 items-center justify-center rounded-full text-
|
|
201
|
+
className="inline-flex h-5 w-5 items-center justify-center rounded-full text-muted-foreground/70 opacity-100 transition-opacity hover:bg-accent hover:text-accent-foreground md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100"
|
|
202
202
|
aria-label={t('remove')}
|
|
203
203
|
>
|
|
204
204
|
<X className="h-3 w-3" />
|
|
@@ -16,7 +16,7 @@ export function ProviderPillSelector(props: ProviderPillSelectorProps) {
|
|
|
16
16
|
type="button"
|
|
17
17
|
onClick={() => onChange(option.value)}
|
|
18
18
|
aria-pressed={selected}
|
|
19
|
-
className={`rounded-full border px-3 py-1.5 text-xs font-medium transition-colors ${selected ? 'border-primary bg-primary text-
|
|
19
|
+
className={`rounded-full border px-3 py-1.5 text-xs font-medium transition-colors ${selected ? 'border-primary bg-primary text-primary-foreground shadow-sm' : 'border-border bg-card text-muted-foreground hover:border-primary/40 hover:bg-accent/70 hover:text-accent-foreground'}`}
|
|
20
20
|
>
|
|
21
21
|
{option.label}
|
|
22
22
|
</button>
|