@nextclaw/ui 0.5.48 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/assets/ChannelsList-CkCpHSto.js +1 -0
  3. package/dist/assets/ChatPage-DM4XNsrW.js +32 -0
  4. package/dist/assets/DocBrowser-B5Aqiz6W.js +1 -0
  5. package/dist/assets/MarketplacePage-BIi0bBdW.js +49 -0
  6. package/dist/assets/ModelConfig-BTFiEAxQ.js +1 -0
  7. package/dist/assets/{ProvidersList-BXHpjVtO.js → ProvidersList-cdk1d-G_.js} +1 -1
  8. package/dist/assets/RuntimeConfig-CFqFsXmR.js +1 -0
  9. package/dist/assets/{SecretsConfig-KkgMzdt1.js → SecretsConfig-CIKasCek.js} +2 -2
  10. package/dist/assets/SessionsConfig-mnCLFtbo.js +2 -0
  11. package/dist/assets/{card-D7NY0Szf.js → card-C1BUfR85.js} +1 -1
  12. package/dist/assets/index-Dxas8MJ9.js +2 -0
  13. package/dist/assets/index-P4YzN9iS.css +1 -0
  14. package/dist/assets/{label-Ojs7Al6B.js → label-CwWfYbuj.js} +1 -1
  15. package/dist/assets/{logos-B1qBsCSi.js → logos-DDyjHSEU.js} +1 -1
  16. package/dist/assets/{page-layout-CUMMO0nN.js → page-layout-DKTRKcHL.js} +1 -1
  17. package/dist/assets/provider-models-y4mUDcGF.js +1 -0
  18. package/dist/assets/{switch-BdhS_16-.js → switch-Bi3yeYiC.js} +1 -1
  19. package/dist/assets/{tabs-custom-D261E5EA.js → tabs-custom-HZFNZrc0.js} +1 -1
  20. package/dist/assets/useConfig-CgzVQTZl.js +6 -0
  21. package/dist/assets/{useConfirmDialog-BUKGHDL6.js → useConfirmDialog-DwD21HlD.js} +2 -2
  22. package/dist/assets/{vendor-Dh04PGww.js → vendor-Ylg6Wdt_.js} +84 -69
  23. package/dist/index.html +3 -3
  24. package/package.json +2 -1
  25. package/src/App.tsx +10 -6
  26. package/src/api/config.ts +42 -1
  27. package/src/api/types.ts +29 -0
  28. package/src/components/chat/ChatConversationPanel.tsx +109 -85
  29. package/src/components/chat/ChatInputBar.tsx +245 -0
  30. package/src/components/chat/ChatPage.tsx +365 -187
  31. package/src/components/chat/ChatSidebar.tsx +242 -0
  32. package/src/components/chat/ChatThread.tsx +92 -25
  33. package/src/components/chat/ChatWelcome.tsx +61 -0
  34. package/src/components/chat/SkillsPicker.tsx +137 -0
  35. package/src/components/chat/useChatStreamController.ts +287 -56
  36. package/src/components/config/ChannelForm.tsx +1 -1
  37. package/src/components/config/ChannelsList.tsx +3 -3
  38. package/src/components/config/ModelConfig.tsx +11 -89
  39. package/src/components/config/RuntimeConfig.tsx +29 -1
  40. package/src/components/layout/AppLayout.tsx +42 -6
  41. package/src/components/layout/Sidebar.tsx +68 -62
  42. package/src/components/marketplace/MarketplacePage.tsx +13 -3
  43. package/src/components/ui/popover.tsx +31 -0
  44. package/src/hooks/useConfig.ts +18 -0
  45. package/src/lib/i18n.ts +53 -0
  46. package/src/lib/provider-models.ts +129 -0
  47. package/dist/assets/ChannelsList-C8cguFLc.js +0 -1
  48. package/dist/assets/ChatPage-BkHWNUNR.js +0 -32
  49. package/dist/assets/CronConfig-D-ESQlvk.js +0 -1
  50. package/dist/assets/DocBrowser-B9ZD6pAk.js +0 -1
  51. package/dist/assets/MarketplacePage-Ds_l9KTF.js +0 -49
  52. package/dist/assets/ModelConfig-N1tbLv9b.js +0 -1
  53. package/dist/assets/RuntimeConfig-KsKfkjgv.js +0 -1
  54. package/dist/assets/SessionsConfig-CWBp8IPf.js +0 -2
  55. package/dist/assets/index-BRBYYgR_.js +0 -2
  56. package/dist/assets/index-C5cdRzpO.css +0 -1
  57. package/dist/assets/useConfig-txxbxXnT.js +0 -6
@@ -0,0 +1,129 @@
1
+ import type { ConfigMetaView, ConfigView, ProviderConfigView } from '@/api/types';
2
+
3
+ export type ProviderModelCatalogItem = {
4
+ name: string;
5
+ displayName: string;
6
+ prefix: string;
7
+ aliases: string[];
8
+ models: string[];
9
+ configured: boolean;
10
+ };
11
+
12
+ export function normalizeStringList(input: string[] | null | undefined): string[] {
13
+ if (!input || input.length === 0) {
14
+ return [];
15
+ }
16
+ const deduped = new Set<string>();
17
+ for (const item of input) {
18
+ const trimmed = item.trim();
19
+ if (trimmed) {
20
+ deduped.add(trimmed);
21
+ }
22
+ }
23
+ return [...deduped];
24
+ }
25
+
26
+ export function stripProviderPrefix(model: string, prefix: string): string {
27
+ const trimmed = model.trim();
28
+ const cleanPrefix = prefix.trim();
29
+ if (!trimmed || !cleanPrefix) {
30
+ return trimmed;
31
+ }
32
+ const withSlash = `${cleanPrefix}/`;
33
+ if (trimmed.startsWith(withSlash)) {
34
+ return trimmed.slice(withSlash.length);
35
+ }
36
+ return trimmed;
37
+ }
38
+
39
+ export function toProviderLocalModel(model: string, aliases: string[]): string {
40
+ let normalized = model.trim();
41
+ if (!normalized) {
42
+ return '';
43
+ }
44
+ for (const alias of aliases) {
45
+ normalized = stripProviderPrefix(normalized, alias);
46
+ }
47
+ return normalized.trim();
48
+ }
49
+
50
+ export function composeProviderModel(prefix: string, localModel: string): string {
51
+ const normalizedModel = localModel.trim();
52
+ const normalizedPrefix = prefix.trim();
53
+ if (!normalizedModel) {
54
+ return '';
55
+ }
56
+ if (!normalizedPrefix) {
57
+ return normalizedModel;
58
+ }
59
+ return `${normalizedPrefix}/${normalizedModel}`;
60
+ }
61
+
62
+ export function findProviderByModel(
63
+ model: string,
64
+ providerCatalog: Array<{ name: string; aliases: string[] }>
65
+ ): string | null {
66
+ const trimmed = model.trim();
67
+ if (!trimmed) {
68
+ return null;
69
+ }
70
+ let bestMatch: { name: string; score: number } | null = null;
71
+ for (const provider of providerCatalog) {
72
+ for (const alias of provider.aliases) {
73
+ const cleanAlias = alias.trim();
74
+ if (!cleanAlias) {
75
+ continue;
76
+ }
77
+ if (trimmed === cleanAlias || trimmed.startsWith(`${cleanAlias}/`)) {
78
+ if (!bestMatch || cleanAlias.length > bestMatch.score) {
79
+ bestMatch = { name: provider.name, score: cleanAlias.length };
80
+ }
81
+ }
82
+ }
83
+ }
84
+ return bestMatch?.name ?? null;
85
+ }
86
+
87
+ function isProviderConfigured(provider: ProviderConfigView | undefined): boolean {
88
+ if (!provider) {
89
+ return false;
90
+ }
91
+ // Keep in sync with ProvidersList "已配置" tab: only apiKeySet counts as configured.
92
+ return provider.apiKeySet === true;
93
+ }
94
+
95
+ export function buildProviderModelCatalog(params: {
96
+ meta?: ConfigMetaView;
97
+ config?: ConfigView;
98
+ onlyConfigured?: boolean;
99
+ }): ProviderModelCatalogItem[] {
100
+ const { meta, config, onlyConfigured = false } = params;
101
+
102
+ const catalog = (meta?.providers ?? []).map((spec) => {
103
+ const providerConfig = config?.providers?.[spec.name];
104
+ const prefix = (spec.modelPrefix || spec.name || '').trim();
105
+ const aliases = normalizeStringList([spec.modelPrefix || '', spec.name || '']);
106
+ const defaultModels = normalizeStringList((spec.defaultModels ?? []).map((model) => toProviderLocalModel(model, aliases)));
107
+ const customModels = normalizeStringList(
108
+ (providerConfig?.models ?? []).map((model) => toProviderLocalModel(model, aliases))
109
+ );
110
+ const models = normalizeStringList([...defaultModels, ...customModels]);
111
+ const configDisplayName = providerConfig?.displayName?.trim();
112
+ const configured = isProviderConfigured(providerConfig);
113
+
114
+ return {
115
+ name: spec.name,
116
+ displayName: configDisplayName || spec.displayName || spec.name,
117
+ prefix,
118
+ aliases,
119
+ models,
120
+ configured
121
+ } satisfies ProviderModelCatalogItem;
122
+ });
123
+
124
+ if (!onlyConfigured) {
125
+ return catalog;
126
+ }
127
+
128
+ return catalog.filter((provider) => provider.configured && provider.models.length > 0);
129
+ }
@@ -1 +0,0 @@
1
- import{r as j,j as a,ab as Z,s as ee,ae as F,K as ae,a3 as te,af as se,ag as ne,ah as le,ai as re,U as oe,aj as ce,n as ie}from"./vendor-Dh04PGww.js";import{u as $,a as q,b as K,k as me,l as pe,I as T}from"./useConfig-txxbxXnT.js";import{B as E,P as de,a as be}from"./page-layout-CUMMO0nN.js";import{L as ue}from"./label-Ojs7Al6B.js";import{S as xe}from"./switch-BdhS_16-.js";import{t as e,c as D,g as ye,S as ge,a as he,b as fe,d as we,e as je}from"./index-BRBYYgR_.js";import{C as ve,a as ke,L as H,d as J,S as z,b as Se,c as Ce}from"./logos-B1qBsCSi.js";import{h as U}from"./config-hints-CApS3K_7.js";import{T as Ne}from"./tabs-custom-D261E5EA.js";function Pe({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:D("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"}],Ie=[{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:Ie},{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 _,O;const{data:p}=$(),{data:i}=q(),{data:c}=K(),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=((_=c==null?void 0:c.actions)==null?void 0:_.filter(s=>s.scope===m))??[],C=t&&(((O=U(`channels.${t}`,o))==null?void 0:O.label)??t),P=i==null?void 0:i.channels.find(s=>s.name===t),I=P?Y(P):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{F.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?F.success(l.message||e("success")):F.error(l.message||e("error"))}catch(n){const l=n instanceof Error?n.message:String(n);F.error(`${e("error")}: ${l}`)}finally{f(null)}}};if(!t||!P||!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:D("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")}),I&&a.jsxs("a",{href:I,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 px-6 py-5",children:w.map(s=>{const n=t?U(`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(T,{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(T,{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(T,{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(Pe,{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 $e(){const{data:t}=$(),{data:p}=q(),{data:i}=K(),[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,{children:[a.jsx(be,{title:e("channelsPageTitle"),description:e("channelsPageDescription")}),a.jsxs("div",{className:Se,children:[a.jsxs("section",{className:Ce,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(T,{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 p-3",children:[w.map(o=>{const m=t.channels[o.name],S=(m==null?void 0:m.enabled)||!1,C=U(`channels.${o.name}`,v),P=Y(o),I=(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:D("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:D("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:I})]})]}),a.jsxs("div",{className:"flex items-center gap-2",children:[P&&a.jsx("a",{href:P,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{$e as ChannelsList};