@nextclaw/ui 0.3.14 → 0.3.15

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.
@@ -1,38 +1,37 @@
1
- import { useUiStore } from '@/stores/ui.store';
2
1
  import { cn } from '@/lib/utils';
2
+ import { t } from '@/lib/i18n';
3
3
  import { Cpu, GitBranch, History, MessageSquare, Sparkles } from 'lucide-react';
4
+ import { NavLink } from 'react-router-dom';
4
5
 
5
6
  const navItems = [
6
7
  {
7
- id: 'model' as const,
8
+ target: '/model',
8
9
  label: 'Models',
9
10
  icon: Cpu,
10
11
  },
11
12
  {
12
- id: 'providers' as const,
13
+ target: '/providers',
13
14
  label: 'Providers',
14
15
  icon: Sparkles,
15
16
  },
16
17
  {
17
- id: 'channels' as const,
18
+ target: '/channels',
18
19
  label: 'Channels',
19
20
  icon: MessageSquare,
20
21
  },
21
22
  {
22
- id: 'runtime' as const,
23
+ target: '/runtime',
23
24
  label: 'Routing & Runtime',
24
25
  icon: GitBranch,
25
26
  },
26
27
  {
27
- id: 'sessions' as const,
28
- label: 'Sessions',
28
+ target: '/sessions',
29
+ label: t('sessions'),
29
30
  icon: History,
30
31
  }
31
32
  ];
32
33
 
33
34
  export function Sidebar() {
34
- const { activeTab, setActiveTab } = useUiStore();
35
-
36
35
  return (
37
36
  <aside className="w-[240px] bg-transparent flex flex-col h-full py-6 px-4">
38
37
  {/* Logo Area */}
@@ -50,25 +49,28 @@ export function Sidebar() {
50
49
  <ul className="space-y-1">
51
50
  {navItems.map((item) => {
52
51
  const Icon = item.icon;
53
- const isActive = activeTab === item.id;
54
52
 
55
53
  return (
56
- <li key={item.id}>
57
- <button
58
- onClick={() => setActiveTab(item.id)}
59
- className={cn(
54
+ <li key={item.target}>
55
+ <NavLink
56
+ to={item.target}
57
+ className={({ isActive }) => cn(
60
58
  'group w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-all duration-fast',
61
59
  isActive
62
60
  ? 'bg-primary-100 text-primary-700'
63
61
  : 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'
64
62
  )}
65
63
  >
66
- <Icon className={cn(
67
- 'h-4 w-4 transition-transform duration-fast group-hover:scale-110',
68
- isActive ? 'text-primary' : 'text-gray-500'
69
- )} />
70
- <span className="flex-1 text-left">{item.label}</span>
71
- </button>
64
+ {({ isActive }) => (
65
+ <>
66
+ <Icon className={cn(
67
+ 'h-4 w-4 transition-transform duration-fast group-hover:scale-110',
68
+ isActive ? 'text-primary' : 'text-gray-500'
69
+ )} />
70
+ <span className="flex-1 text-left">{item.label}</span>
71
+ </>
72
+ )}
73
+ </NavLink>
72
74
  </li>
73
75
  );
74
76
  })}
package/src/lib/i18n.ts CHANGED
@@ -100,6 +100,43 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
100
100
  replyDelayMs: { zh: '回复延迟(ms)', en: 'Reply Delay (ms)' },
101
101
  secret: { zh: '密钥', en: 'Secret' },
102
102
 
103
+ // Sessions
104
+ sessionsPageTitle: { zh: '会话管理', en: 'Sessions' },
105
+ sessionsPageDescription: {
106
+ zh: '管理会话:筛选、按渠道分组、查看历史、改标签/偏好模型、清空和删除。',
107
+ en: 'Manage sessions: filter, group by channel, inspect history, edit metadata, clear, and delete.'
108
+ },
109
+ sessionsFiltersTitle: { zh: '筛选', en: 'Filters' },
110
+ sessionsFiltersDescription: { zh: '按关键词、活跃窗口和分组方式筛选会话。', en: 'Filter sessions by query, activity window, and grouping mode.' },
111
+ sessionsSearchPlaceholder: { zh: '搜索 key 或标签', en: 'Search session key or label' },
112
+ sessionsActiveMinutesPlaceholder: { zh: '活跃分钟(0=不限)', en: 'Active minutes (0 = no limit)' },
113
+ sessionsLimitPlaceholder: { zh: '展示上限', en: 'Limit' },
114
+ sessionsGroupModeLabel: { zh: '分组方式', en: 'Grouping' },
115
+ sessionsGroupModeAll: { zh: '不分组 / 全部', en: 'All (No grouping)' },
116
+ sessionsGroupModeByChannel: { zh: '按渠道分组', en: 'Group by channel' },
117
+ sessionsListTitle: { zh: '会话列表', en: 'Session list' },
118
+ sessionsTotalLabel: { zh: '总数', en: 'Total' },
119
+ sessionsCurrentLabel: { zh: '当前展示', en: 'Showing' },
120
+ sessionsLoading: { zh: '加载会话中...', en: 'Loading sessions...' },
121
+ sessionsEmpty: { zh: '暂无会话。', en: 'No sessions yet.' },
122
+ sessionsKeyLabel: { zh: '键', en: 'Key' },
123
+ sessionsChannelLabel: { zh: '渠道', en: 'Channel' },
124
+ sessionsMessagesLabel: { zh: '消息数', en: 'Messages' },
125
+ sessionsUpdatedLabel: { zh: '更新时间', en: 'Updated' },
126
+ sessionsLastRoleLabel: { zh: '最后角色', en: 'Last Role' },
127
+ sessionsLabelPlaceholder: { zh: '会话标签(可选)', en: 'Session label (optional)' },
128
+ sessionsModelPlaceholder: { zh: '偏好模型(可选)', en: 'Preferred model (optional)' },
129
+ sessionsShowHistory: { zh: '查看历史', en: 'View history' },
130
+ sessionsHideHistory: { zh: '隐藏历史', en: 'Hide history' },
131
+ sessionsSaveMeta: { zh: '保存元信息', en: 'Save metadata' },
132
+ sessionsClearHistory: { zh: '清空历史', en: 'Clear history' },
133
+ sessionsDeleteConfirm: { zh: '确认删除会话', en: 'Delete session' },
134
+ sessionsHistoryTitle: { zh: '历史', en: 'History' },
135
+ sessionsHistoryDescription: { zh: '最近 200 条消息(展示窗口)。', en: 'Latest 200 messages (display window).' },
136
+ sessionsHistoryLoading: { zh: '加载历史中...', en: 'Loading history...' },
137
+ sessionsApplyingChanges: { zh: '正在应用会话变更...', en: 'Applying session changes...' },
138
+ sessionsUnknownChannel: { zh: '未知渠道', en: 'Unknown channel' },
139
+
103
140
  // UI
104
141
  saveVerifyConnect: { zh: '保存并验证 / 连接', en: 'Save & Verify / Connect' },
105
142
 
package/src/main.tsx CHANGED
@@ -1,10 +1,13 @@
1
1
  import { StrictMode } from 'react';
2
2
  import { createRoot } from 'react-dom/client';
3
+ import { BrowserRouter } from 'react-router-dom';
3
4
  import App from './App';
4
5
  import './index.css';
5
6
 
6
7
  createRoot(document.getElementById('root')!).render(
7
8
  <StrictMode>
8
- <App />
9
+ <BrowserRouter>
10
+ <App />
11
+ </BrowserRouter>
9
12
  </StrictMode>
10
13
  );
@@ -3,10 +3,6 @@ import { create } from 'zustand';
3
3
  type ConnectionStatus = 'connected' | 'disconnected' | 'connecting';
4
4
 
5
5
  interface UiState {
6
- // Active configuration tab
7
- activeTab: 'model' | 'providers' | 'channels' | 'runtime' | 'sessions';
8
- setActiveTab: (tab: UiState['activeTab']) => void;
9
-
10
6
  // Connection status
11
7
  connectionStatus: ConnectionStatus;
12
8
  setConnectionStatus: (status: ConnectionStatus) => void;
@@ -23,9 +19,6 @@ interface UiState {
23
19
  }
24
20
 
25
21
  export const useUiStore = create<UiState>((set) => ({
26
- activeTab: 'model',
27
- setActiveTab: (tab) => set({ activeTab: tab }),
28
-
29
22
  connectionStatus: 'disconnected',
30
23
  setConnectionStatus: (status) => set({ connectionStatus: status }),
31
24