@nextclaw/ui 0.6.6 → 0.6.8

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/assets/ChannelsList-DH5fzlPu.js +1 -0
  3. package/dist/assets/ChatPage-BrLCnJSb.js +34 -0
  4. package/dist/assets/DocBrowser-DPQHJVsZ.js +1 -0
  5. package/dist/assets/LogoBadge-FEb4_vSq.js +1 -0
  6. package/dist/assets/{MarketplacePage--wFfsNH0.js → MarketplacePage-BAVXYeZA.js} +2 -2
  7. package/dist/assets/ModelConfig-BqPXe7nw.js +1 -0
  8. package/dist/assets/ProvidersList-vpKPuIxV.js +1 -0
  9. package/dist/assets/RuntimeConfig-DTYSU4_d.js +1 -0
  10. package/dist/assets/{SecretsConfig-B25P3J7V.js → SecretsConfig-nNzs3YDm.js} +2 -2
  11. package/dist/assets/SessionsConfig-CHjeyqEQ.js +2 -0
  12. package/dist/assets/{card-CCSDsedj.js → card-73MmEZi7.js} +1 -1
  13. package/dist/assets/index-CTLvVlk8.js +7 -0
  14. package/dist/assets/index-DI6BuShn.css +1 -0
  15. package/dist/assets/input-1MCMs6Yf.js +1 -0
  16. package/dist/assets/{label-BxzAKPzU.js → label-C4Q8RlBJ.js} +1 -1
  17. package/dist/assets/{page-layout-DaLNSFKw.js → page-layout-CK0vcVmV.js} +1 -1
  18. package/dist/assets/session-run-status-BaNlKvi6.js +5 -0
  19. package/dist/assets/{switch-DHOCEi5L.js → switch-Bf8w_cF1.js} +1 -1
  20. package/dist/assets/{tabs-custom-zdFy3fnK.js → tabs-custom-B6Gw8gax.js} +1 -1
  21. package/dist/assets/{useConfirmDialog-D3ZVa92J.js → useConfirmDialog-B5CZ4EDN.js} +1 -1
  22. package/dist/assets/{vendor-Dj2ULvht.js → vendor-C--HHaLf.js} +6 -6
  23. package/dist/index.html +3 -3
  24. package/package.json +1 -1
  25. package/src/api/config.ts +53 -0
  26. package/src/api/types.ts +48 -0
  27. package/src/components/chat/ChatInputBar.tsx +341 -24
  28. package/src/components/chat/ChatPage.tsx +28 -12
  29. package/src/components/chat/ChatSidebar.tsx +12 -7
  30. package/src/components/common/BrandHeader.tsx +23 -0
  31. package/src/components/common/SessionRunBadge.tsx +23 -0
  32. package/src/components/config/ProviderForm.tsx +193 -29
  33. package/src/components/config/ProvidersList.tsx +1 -2
  34. package/src/components/config/SessionsConfig.tsx +22 -2
  35. package/src/components/layout/Sidebar.tsx +2 -6
  36. package/src/hooks/useConfig.ts +31 -0
  37. package/src/lib/i18n.ts +28 -1
  38. package/src/lib/logos.ts +0 -19
  39. package/src/lib/session-run-status.ts +63 -0
  40. package/dist/assets/ChannelsList-VqzbAMCc.js +0 -1
  41. package/dist/assets/ChatPage-CjZqsBmn.js +0 -34
  42. package/dist/assets/DocBrowser-DvU-iUeB.js +0 -1
  43. package/dist/assets/ModelConfig-cY5UsbfA.js +0 -1
  44. package/dist/assets/ProvidersList-qZwaFoFt.js +0 -1
  45. package/dist/assets/RuntimeConfig-BY2Axlte.js +0 -1
  46. package/dist/assets/SessionsConfig-CxA9gIBw.js +0 -2
  47. package/dist/assets/chat-message-pw9oafI4.js +0 -5
  48. package/dist/assets/index-CD8a2KMH.js +0 -2
  49. package/dist/assets/index-DKOXGZc8.css +0 -1
  50. package/dist/assets/logos-C3oHQ9kv.js +0 -1
  51. package/dist/assets/useConfig-CDl9UK5m.js +0 -6
package/src/lib/i18n.ts CHANGED
@@ -254,6 +254,21 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
254
254
  providerApiBaseHelpShort: { zh: '一般只需填写域名,系统自动补全路径', en: 'Usually just the domain; path auto-appended' },
255
255
  providerExtraHeadersHelpShort: { zh: '可选,用于自定义鉴权等场景', en: 'Optional, for custom auth etc.' },
256
256
  providerAdvancedSettings: { zh: '高级设置', en: 'Advanced Settings' },
257
+ providerAuthSectionTitle: { zh: '提供商授权', en: 'Provider Authorization' },
258
+ providerAuthStarting: { zh: '启动中...', en: 'Starting...' },
259
+ providerAuthAuthorizing: { zh: '授权中...', en: 'Authorizing...' },
260
+ providerAuthAuthorizeInBrowser: { zh: '浏览器授权', en: 'Authorize in Browser' },
261
+ providerAuthWaitingBrowser: { zh: '等待浏览器完成授权...', en: 'Waiting for browser authorization...' },
262
+ providerAuthCompleted: { zh: '授权已完成。', en: 'Authorization completed.' },
263
+ providerAuthOpenPrompt: { zh: '请在浏览器完成授权,验证码:', en: 'Open browser and complete authorization (code: ' },
264
+ providerAuthOpenPromptSuffix: { zh: '', en: ')' },
265
+ providerAuthStartFailed: { zh: '启动授权失败', en: 'Failed to start authorization' },
266
+ providerAuthImportFromCli: { zh: '从 Qwen CLI 导入', en: 'Import From Qwen CLI' },
267
+ providerAuthImporting: { zh: '导入中...', en: 'Importing...' },
268
+ providerAuthImportSuccess: { zh: '已从 CLI 导入凭证。', en: 'Imported provider credentials from CLI.' },
269
+ providerAuthImportStatusPrefix: { zh: 'CLI 导入成功。', en: 'Imported credentials from CLI successfully.' },
270
+ providerAuthImportFailed: { zh: '导入凭证失败', en: 'Failed to import credentials' },
271
+ providerAuthSessionLabel: { zh: '会话', en: 'Session' },
257
272
  resetToDefault: { zh: '恢复默认', en: 'Reset to Default' },
258
273
  leaveBlankToKeepUnchanged: { zh: '留空则保持不变', en: 'Leave blank to keep unchanged' },
259
274
 
@@ -467,6 +482,8 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
467
482
  sessionsApplyingChanges: { zh: '正在应用会话变更...', en: 'Applying session changes...' },
468
483
  sessionsUnknownChannel: { zh: '未知渠道', en: 'Unknown channel' },
469
484
  sessionsAllChannels: { zh: '全部渠道', en: 'All Channels' },
485
+ sessionsRunStatusRunning: { zh: '运行中', en: 'Running' },
486
+ sessionsRunStatusQueued: { zh: '排队中', en: 'Queued' },
470
487
  sessionsMetadata: { zh: '元信息', en: 'Metadata' },
471
488
  sessionsNoSelectionTitle: { zh: '未选择会话', en: 'No Session Selected' },
472
489
  sessionsNoSelectionDescription: {
@@ -500,8 +517,18 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
500
517
  chatHistoryLoading: { zh: '加载会话历史中...', en: 'Loading session history...' },
501
518
  chatNoMessages: { zh: '暂无消息,发送一条开始对话。', en: 'No messages yet. Send one to start.' },
502
519
  chatTyping: { zh: 'Agent 正在思考...', en: 'Agent is thinking...' },
503
- chatInputPlaceholder: { zh: '输入消息,Enter 发送,Shift + Enter 换行', en: 'Type a message, Enter to send, Shift + Enter for newline' },
520
+ chatInputPlaceholder: { zh: '输入消息,输入 / 选择技能,Enter 发送,Shift + Enter 换行', en: 'Type a message, type / to select skills, Enter to send, Shift + Enter for newline' },
504
521
  chatInputHint: { zh: '支持多轮上下文,默认走当前会话。', en: 'Multi-turn context is preserved in the current session.' },
522
+ chatSlashSectionCommands: { zh: '命令', en: 'Commands' },
523
+ chatSlashSectionSkills: { zh: '技能', en: 'Skills' },
524
+ chatSlashTypeCommand: { zh: '命令', en: 'Command' },
525
+ chatSlashTypeSkill: { zh: '技能', en: 'Skill' },
526
+ chatSlashSkillSpec: { zh: '标识', en: 'Spec' },
527
+ chatSlashLoading: { zh: '加载命令与技能中…', en: 'Loading commands and skills…' },
528
+ chatSlashNoResult: { zh: '无匹配项', en: 'No matches' },
529
+ chatSlashHint: { zh: '输入 / 触发命令或技能选择', en: 'Type / to access commands and skills' },
530
+ chatSlashCommandHint: { zh: '回车插入命令,继续输入参数后发送。', en: 'Press Enter to insert command, then add args and send.' },
531
+ chatSlashSkillHint: { zh: '回车把该技能加入本轮请求。', en: 'Press Enter to add this skill for the next turn.' },
505
532
  chatSend: { zh: '发送', en: 'Send' },
506
533
  chatStop: { zh: '停止', en: 'Stop' },
507
534
  chatStopPreparing: { zh: '正在建立可停止会话,请稍候…', en: 'Preparing stoppable run…' },
package/src/lib/logos.ts CHANGED
@@ -1,20 +1,5 @@
1
1
  type LogoMap = Record<string, string>;
2
2
 
3
- const PROVIDER_LOGOS: LogoMap = {
4
- openrouter: "openrouter.svg",
5
- aihubmix: "aihubmix.png",
6
- anthropic: "anthropic.svg",
7
- openai: "openai.svg",
8
- gemini: "gemini.svg",
9
- deepseek: "deepseek.png",
10
- zhipu: "zhipu.svg",
11
- dashscope: "dashscope.png",
12
- moonshot: "moonshot.png",
13
- minimax: "minimax.svg",
14
- vllm: "vllm.svg",
15
- groq: "groq.svg"
16
- };
17
-
18
3
  const CHANNEL_LOGOS: LogoMap = {
19
4
  telegram: "telegram.svg",
20
5
  slack: "slack.svg",
@@ -34,10 +19,6 @@ function resolveLogo(map: LogoMap, name: string): string | null {
34
19
  return file ? `/logos/${file}` : null;
35
20
  }
36
21
 
37
- export function getProviderLogo(name: string): string | null {
38
- return resolveLogo(PROVIDER_LOGOS, name);
39
- }
40
-
41
22
  export function getChannelLogo(name: string): string | null {
42
23
  return resolveLogo(CHANNEL_LOGOS, name);
43
24
  }
@@ -0,0 +1,63 @@
1
+ import type { ChatRunState, ChatRunView } from '@/api/types';
2
+
3
+ export type SessionRunStatus = Extract<ChatRunState, 'queued' | 'running'>;
4
+
5
+ const RUN_STATUS_PRIORITY: Record<SessionRunStatus, number> = {
6
+ queued: 1,
7
+ running: 2
8
+ };
9
+
10
+ function toSessionRunStatus(state: ChatRunState): SessionRunStatus | null {
11
+ if (state === 'queued' || state === 'running') {
12
+ return state;
13
+ }
14
+ return null;
15
+ }
16
+
17
+ function toComparableTimestamp(value?: string): number {
18
+ const parsed = Date.parse(value ?? '');
19
+ return Number.isFinite(parsed) ? parsed : 0;
20
+ }
21
+
22
+ function shouldReplaceRun(current: ChatRunView, next: ChatRunView): boolean {
23
+ const currentStatus = toSessionRunStatus(current.state);
24
+ const nextStatus = toSessionRunStatus(next.state);
25
+ if (!currentStatus || !nextStatus) {
26
+ return false;
27
+ }
28
+ const currentPriority = RUN_STATUS_PRIORITY[currentStatus];
29
+ const nextPriority = RUN_STATUS_PRIORITY[nextStatus];
30
+ if (nextPriority !== currentPriority) {
31
+ return nextPriority > currentPriority;
32
+ }
33
+ return toComparableTimestamp(next.requestedAt) >= toComparableTimestamp(current.requestedAt);
34
+ }
35
+
36
+ export function buildActiveRunBySessionKey(runs: readonly ChatRunView[]): Map<string, ChatRunView> {
37
+ const map = new Map<string, ChatRunView>();
38
+ for (const run of runs) {
39
+ const key = run.sessionKey?.trim();
40
+ if (!key || !toSessionRunStatus(run.state)) {
41
+ continue;
42
+ }
43
+ const current = map.get(key);
44
+ if (!current || shouldReplaceRun(current, run)) {
45
+ map.set(key, run);
46
+ }
47
+ }
48
+ return map;
49
+ }
50
+
51
+ export function buildSessionRunStatusByKey(
52
+ activeRunBySessionKey: ReadonlyMap<string, ChatRunView>
53
+ ): Map<string, SessionRunStatus> {
54
+ const map = new Map<string, SessionRunStatus>();
55
+ for (const [sessionKey, run] of activeRunBySessionKey.entries()) {
56
+ const status = toSessionRunStatus(run.state);
57
+ if (!status) {
58
+ continue;
59
+ }
60
+ map.set(sessionKey, status);
61
+ }
62
+ return map;
63
+ }
@@ -1 +0,0 @@
1
- import{r as j,j as a,at as Z,v as ee,aH as T,K as ae,a5 as te,aI as se,aJ as ne,aK as le,q as re,Y as oe,as as ce,n as ie}from"./vendor-Dj2ULvht.js";import{u as q,a as K,b as $,t as me,v as pe,I as D}from"./useConfig-CDl9UK5m.js";import{B as E,P as de,a as be}from"./page-layout-DaLNSFKw.js";import{L as ue}from"./label-BxzAKPzU.js";import{S as xe}from"./switch-DHOCEi5L.js";import{t as e,c as P,h as ye,S as ge,a as he,b as fe,d as we,e as je}from"./index-CD8a2KMH.js";import{C as ve,a as ke,L as H,d as J,S as z,c as Se,b as Ce}from"./logos-C3oHQ9kv.js";import{h as _}from"./config-hints-CApS3K_7.js";import{T as Ne}from"./tabs-custom-zdFy3fnK.js";function Ie({value:t,onChange:p,className:i,placeholder:c=""}){const[r,u]=j.useState(""),d=x=>{x.key==="Enter"&&r.trim()?(x.preventDefault(),p([...t,r.trim()]),u("")):x.key==="Backspace"&&!r&&t.length>0&&p(t.slice(0,-1))},g=x=>{p(t.filter((v,h)=>h!==x))};return a.jsxs("div",{className:P("flex flex-wrap gap-2 p-2 border rounded-md min-h-[42px]",i),children:[t.map((x,v)=>a.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-1 bg-primary text-primary-foreground rounded text-sm",children:[x,a.jsx("button",{type:"button",onClick:()=>g(v),className:"hover:text-red-300 transition-colors",children:a.jsx(Z,{className:"h-3 w-3"})})]},v)),a.jsx("input",{type:"text",value:r,onChange:x=>u(x.target.value),onKeyDown:d,className:"flex-1 outline-none min-w-[100px] bg-transparent text-sm",placeholder:c||e("enterTag")})]})}function Y(t){var c,r;const p=ye();return((c=t.tutorialUrls)==null?void 0:c[p])||((r=t.tutorialUrls)==null?void 0:r.default)||t.tutorialUrl}const B=[{value:"pairing",label:"pairing"},{value:"allowlist",label:"allowlist"},{value:"open",label:"open"},{value:"disabled",label:"disabled"}],R=[{value:"open",label:"open"},{value:"allowlist",label:"allowlist"},{value:"disabled",label:"disabled"}],Pe=[{value:"off",label:"off"},{value:"partial",label:"partial"},{value:"block",label:"block"},{value:"progress",label:"progress"}],Fe=t=>t.includes("token")||t.includes("secret")||t.includes("password")?a.jsx(ae,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("url")||t.includes("host")?a.jsx(te,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("email")||t.includes("mail")?a.jsx(se,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("id")||t.includes("from")?a.jsx(ne,{className:"h-3.5 w-3.5 text-gray-500"}):t==="enabled"||t==="consentGranted"?a.jsx(le,{className:"h-3.5 w-3.5 text-gray-500"}):a.jsx(re,{className:"h-3.5 w-3.5 text-gray-500"});function G(){return{telegram:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"token",type:"password",label:e("botToken")},{name:"allowFrom",type:"tags",label:e("allowFrom")},{name:"proxy",type:"text",label:e("proxy")},{name:"accountId",type:"text",label:e("accountId")},{name:"dmPolicy",type:"select",label:e("dmPolicy"),options:B},{name:"groupPolicy",type:"select",label:e("groupPolicy"),options:R},{name:"groupAllowFrom",type:"tags",label:e("groupAllowFrom")},{name:"requireMention",type:"boolean",label:e("requireMention")},{name:"mentionPatterns",type:"tags",label:e("mentionPatterns")},{name:"groups",type:"json",label:e("groupRulesJson")}],discord:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"token",type:"password",label:e("botToken")},{name:"allowBots",type:"boolean",label:e("allowBotMessages")},{name:"allowFrom",type:"tags",label:e("allowFrom")},{name:"gatewayUrl",type:"text",label:e("gatewayUrl")},{name:"intents",type:"number",label:e("intents")},{name:"proxy",type:"text",label:e("proxy")},{name:"mediaMaxMb",type:"number",label:e("attachmentMaxSizeMb")},{name:"streaming",type:"select",label:e("streamingMode"),options:Pe},{name:"draftChunk",type:"json",label:e("draftChunkingJson")},{name:"textChunkLimit",type:"number",label:e("textChunkLimit")},{name:"accountId",type:"text",label:e("accountId")},{name:"dmPolicy",type:"select",label:e("dmPolicy"),options:B},{name:"groupPolicy",type:"select",label:e("groupPolicy"),options:R},{name:"groupAllowFrom",type:"tags",label:e("groupAllowFrom")},{name:"requireMention",type:"boolean",label:e("requireMention")},{name:"mentionPatterns",type:"tags",label:e("mentionPatterns")},{name:"groups",type:"json",label:e("groupRulesJson")}],whatsapp:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"bridgeUrl",type:"text",label:e("bridgeUrl")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],feishu:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"appId",type:"text",label:e("appId")},{name:"appSecret",type:"password",label:e("appSecret")},{name:"encryptKey",type:"password",label:e("encryptKey")},{name:"verificationToken",type:"password",label:e("verificationToken")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],dingtalk:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"clientId",type:"text",label:e("clientId")},{name:"clientSecret",type:"password",label:e("clientSecret")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],wecom:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"corpId",type:"text",label:e("corpId")},{name:"agentId",type:"text",label:e("agentId")},{name:"secret",type:"password",label:e("secret")},{name:"token",type:"password",label:e("token")},{name:"callbackPort",type:"number",label:e("callbackPort")},{name:"callbackPath",type:"text",label:e("callbackPath")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],slack:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"mode",type:"text",label:e("mode")},{name:"webhookPath",type:"text",label:e("webhookPath")},{name:"allowBots",type:"boolean",label:e("allowBotMessages")},{name:"botToken",type:"password",label:e("botToken")},{name:"appToken",type:"password",label:e("appToken")}],email:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"consentGranted",type:"boolean",label:e("consentGranted")},{name:"imapHost",type:"text",label:e("imapHost")},{name:"imapPort",type:"number",label:e("imapPort")},{name:"imapUsername",type:"text",label:e("imapUsername")},{name:"imapPassword",type:"password",label:e("imapPassword")},{name:"fromAddress",type:"email",label:e("fromAddress")}],mochat:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"baseUrl",type:"text",label:e("baseUrl")},{name:"clawToken",type:"password",label:e("clawToken")},{name:"agentUserId",type:"text",label:e("agentUserId")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],qq:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"appId",type:"text",label:e("appId")},{name:"secret",type:"password",label:e("appSecret")},{name:"markdownSupport",type:"boolean",label:e("markdownSupport")},{name:"allowFrom",type:"tags",label:e("allowFrom")}]}}function A(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function V(t,p){const i={...t};for(const[c,r]of Object.entries(p)){const u=i[c];if(A(u)&&A(r)){i[c]=V(u,r);continue}i[c]=r}return i}function Te(t,p){const i=t.split("."),c={};let r=c;for(let u=0;u<i.length-1;u+=1){const d=i[u];r[d]={},r=r[d]}return r[i[i.length-1]]=p,c}function De({channelName:t}){var U,O;const{data:p}=q(),{data:i}=K(),{data:c}=$(),r=me(),u=pe(),[d,g]=j.useState({}),[x,v]=j.useState({}),[h,f]=j.useState(null),k=t?p==null?void 0:p.channels[t]:null,w=t?G()[t]??[]:[],o=c==null?void 0:c.uiHints,m=t?`channels.${t}`:null,S=((U=c==null?void 0:c.actions)==null?void 0:U.filter(s=>s.scope===m))??[],C=t&&(((O=_(`channels.${t}`,o))==null?void 0:O.label)??t),I=i==null?void 0:i.channels.find(s=>s.name===t),F=I?Y(I):void 0;j.useEffect(()=>{if(k){g({...k});const s={};(t?G()[t]??[]:[]).filter(l=>l.type==="json").forEach(l=>{const y=k[l.name];s[l.name]=JSON.stringify(y??{},null,2)}),v(s)}else g({}),v({})},[k,t]);const N=(s,n)=>{g(l=>({...l,[s]:n}))},L=s=>{if(s.preventDefault(),!t)return;const n={...d};for(const l of w){if(l.type!=="password")continue;const y=n[l.name];(typeof y!="string"||y.length===0)&&delete n[l.name]}for(const l of w){if(l.type!=="json")continue;const y=x[l.name]??"";try{n[l.name]=y.trim()?JSON.parse(y):{}}catch{T.error(`${e("invalidJson")}: ${l.name}`);return}}r.mutate({channel:t,data:n})},Q=s=>{if(!s||!t)return;const n=s.channels;if(!A(n))return;const l=n[t];A(l)&&g(y=>V(y,l))},W=async s=>{if(!(!t||!m)){f(s.id);try{let n={...d};s.saveBeforeRun&&(n={...n,...s.savePatch??{}},g(n),await r.mutateAsync({channel:t,data:n}));const l=await u.mutateAsync({actionId:s.id,data:{scope:m,draftConfig:Te(m,n)}});Q(l.patch),l.ok?T.success(l.message||e("success")):T.error(l.message||e("error"))}catch(n){const l=n instanceof Error?n.message:String(n);T.error(`${e("error")}: ${l}`)}finally{f(null)}}};if(!t||!I||!k)return a.jsx("div",{className:ve,children:a.jsxs("div",{children:[a.jsx("h3",{className:"text-base font-semibold text-gray-900",children:e("channelsSelectTitle")}),a.jsx("p",{className:"mt-2 text-sm text-gray-500",children:e("channelsSelectDescription")})]})});const M=!!k.enabled;return a.jsxs("div",{className:ke,children:[a.jsx("div",{className:"border-b border-gray-100 px-6 py-5",children:a.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[a.jsxs("div",{className:"min-w-0",children:[a.jsxs("div",{className:"flex items-center gap-3",children:[a.jsx(H,{name:t,src:J(t),className:P("h-9 w-9 rounded-lg border",M?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:a.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:t[0]})}),a.jsx("h3",{className:"truncate text-lg font-semibold text-gray-900 capitalize",children:C})]}),a.jsx("p",{className:"mt-2 text-sm text-gray-500",children:e("channelsFormDescription")}),F&&a.jsxs("a",{href:F,className:"mt-2 inline-flex items-center gap-1.5 text-xs text-primary transition-colors hover:text-primary-hover",children:[a.jsx(ee,{className:"h-3.5 w-3.5"}),e("channelsGuideTitle")]})]}),a.jsx(z,{status:M?"active":"inactive",label:M?e("statusActive"):e("statusInactive")})]})}),a.jsxs("form",{onSubmit:L,className:"flex min-h-0 flex-1 flex-col",children:[a.jsx("div",{className:"min-h-0 flex-1 space-y-6 overflow-y-auto overscroll-contain px-6 py-5",children:w.map(s=>{const n=t?_(`channels.${t}.${s.name}`,o):void 0,l=(n==null?void 0:n.label)??s.label,y=n==null?void 0:n.placeholder;return a.jsxs("div",{className:"space-y-2.5",children:[a.jsxs(ue,{htmlFor:s.name,className:"flex items-center gap-2 text-sm font-medium text-gray-900",children:[Fe(s.name),l]}),s.type==="boolean"&&a.jsxs("div",{className:"flex items-center justify-between rounded-xl bg-gray-50 p-3",children:[a.jsx("span",{className:"text-sm text-gray-500",children:d[s.name]?e("enabled"):e("disabled")}),a.jsx(xe,{id:s.name,checked:d[s.name]||!1,onCheckedChange:b=>N(s.name,b),className:"data-[state=checked]:bg-emerald-500"})]}),(s.type==="text"||s.type==="email")&&a.jsx(D,{id:s.name,type:s.type,value:d[s.name]||"",onChange:b=>N(s.name,b.target.value),placeholder:y,className:"rounded-xl"}),s.type==="password"&&a.jsx(D,{id:s.name,type:"password",value:d[s.name]||"",onChange:b=>N(s.name,b.target.value),placeholder:y??e("leaveBlankToKeepUnchanged"),className:"rounded-xl"}),s.type==="number"&&a.jsx(D,{id:s.name,type:"number",value:d[s.name]||0,onChange:b=>N(s.name,parseInt(b.target.value,10)||0),placeholder:y,className:"rounded-xl"}),s.type==="tags"&&a.jsx(Ie,{value:d[s.name]||[],onChange:b=>N(s.name,b)}),s.type==="select"&&a.jsxs(ge,{value:d[s.name]||"",onValueChange:b=>N(s.name,b),children:[a.jsx(he,{className:"rounded-xl",children:a.jsx(fe,{})}),a.jsx(we,{children:(s.options??[]).map(b=>a.jsx(je,{value:b.value,children:b.label},b.value))})]}),s.type==="json"&&a.jsx("textarea",{id:s.name,value:x[s.name]??"{}",onChange:b=>v(X=>({...X,[s.name]:b.target.value})),className:"min-h-[120px] w-full resize-none rounded-lg border border-gray-200 bg-white px-3 py-2 text-xs font-mono"})]},s.name)})}),a.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 border-t border-gray-100 px-6 py-4",children:[a.jsx("div",{className:"flex flex-wrap items-center gap-2",children:S.filter(s=>s.trigger==="manual").map(s=>a.jsx(E,{type:"button",onClick:()=>W(s),disabled:r.isPending||!!h,variant:"secondary",children:h===s.id?e("connecting"):s.title},s.id))}),a.jsx(E,{type:"submit",disabled:r.isPending||!!h,children:r.isPending?e("saving"):e("save")})]})]})]})}const Ae={telegram:"channelDescTelegram",slack:"channelDescSlack",email:"channelDescEmail",webhook:"channelDescWebhook",discord:"channelDescDiscord",feishu:"channelDescFeishu"};function qe(){const{data:t}=q(),{data:p}=K(),{data:i}=$(),[c,r]=j.useState("enabled"),[u,d]=j.useState(),[g,x]=j.useState(""),v=i==null?void 0:i.uiHints,h=p==null?void 0:p.channels,f=t==null?void 0:t.channels,k=[{id:"enabled",label:e("channelsTabEnabled"),count:(h??[]).filter(o=>{var m;return(m=f==null?void 0:f[o.name])==null?void 0:m.enabled}).length},{id:"all",label:e("channelsTabAll"),count:(h??[]).length}],w=j.useMemo(()=>{const o=g.trim().toLowerCase();return(h??[]).filter(m=>{var C;const S=((C=f==null?void 0:f[m.name])==null?void 0:C.enabled)||!1;return c==="enabled"?S:!0}).filter(m=>o?(m.displayName||m.name).toLowerCase().includes(o)||m.name.toLowerCase().includes(o):!0)},[c,f,h,g]);return j.useEffect(()=>{if(w.length===0){d(void 0);return}w.some(m=>m.name===u)||d(w[0].name)},[w,u]),!t||!p?a.jsx("div",{className:"p-8 text-gray-400",children:e("channelsLoading")}):a.jsxs(de,{className:"xl:flex xl:h-full xl:min-h-0 xl:flex-col xl:pb-0",children:[a.jsx(be,{title:e("channelsPageTitle"),description:e("channelsPageDescription")}),a.jsxs("div",{className:P(Ce,"xl:min-h-0 xl:flex-1"),children:[a.jsxs("section",{className:Se,children:[a.jsx("div",{className:"border-b border-gray-100 px-4 pt-4",children:a.jsx(Ne,{tabs:k,activeTab:c,onChange:r,className:"mb-0"})}),a.jsx("div",{className:"border-b border-gray-100 px-4 py-3",children:a.jsxs("div",{className:"relative",children:[a.jsx(oe,{className:"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400"}),a.jsx(D,{value:g,onChange:o=>x(o.target.value),placeholder:e("channelsFilterPlaceholder"),className:"h-10 rounded-xl pl-9"})]})}),a.jsxs("div",{className:"min-h-0 flex-1 space-y-2 overflow-y-auto overscroll-contain p-3",children:[w.map(o=>{const m=t.channels[o.name],S=(m==null?void 0:m.enabled)||!1,C=_(`channels.${o.name}`,v),I=Y(o),F=(C==null?void 0:C.help)||e(Ae[o.name]||"channelDescriptionDefault"),N=u===o.name;return a.jsx("button",{type:"button",onClick:()=>d(o.name),className:P("w-full rounded-xl border p-2.5 text-left transition-all",N?"border-primary/30 bg-primary-50/40 shadow-sm":"border-gray-200/70 bg-white hover:border-gray-300 hover:bg-gray-50/70"),children:a.jsxs("div",{className:"flex items-start justify-between gap-3",children:[a.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[a.jsx(H,{name:o.name,src:J(o.name),className:P("h-10 w-10 rounded-lg border",S?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:a.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:o.name[0]})}),a.jsxs("div",{className:"min-w-0",children:[a.jsx("p",{className:"truncate text-sm font-semibold text-gray-900",children:o.displayName||o.name}),a.jsx("p",{className:"line-clamp-1 text-[11px] text-gray-500",children:F})]})]}),a.jsxs("div",{className:"flex items-center gap-2",children:[I&&a.jsx("a",{href:I,onClick:L=>L.stopPropagation(),className:"inline-flex h-7 w-7 items-center justify-center rounded-md text-gray-300 transition-colors hover:bg-gray-100/70 hover:text-gray-500",title:e("channelsGuideTitle"),children:a.jsx(ce,{className:"h-3.5 w-3.5"})}),a.jsx(z,{status:S?"active":"inactive",label:S?e("statusActive"):e("statusInactive"),className:"min-w-[56px] justify-center"})]})]})},o.name)}),w.length===0&&a.jsxs("div",{className:"flex h-full min-h-[220px] flex-col items-center justify-center rounded-xl border border-dashed border-gray-200 bg-gray-50/70 py-10 text-center",children:[a.jsx("div",{className:"mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-white",children:a.jsx(ie,{className:"h-5 w-5 text-gray-300"})}),a.jsx("p",{className:"text-sm font-medium text-gray-700",children:e("channelsNoMatch")})]})]})]}),a.jsx(De,{channelName:u})]})]})}export{qe as ChannelsList};