This commit is contained in:
zhangkai
2024-08-12 11:27:32 +08:00
parent 5199dbb6e5
commit e12f955105
166 changed files with 6288 additions and 991 deletions

BIN
.DS_Store vendored

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1,25 +1 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/favicon.ico" />
<script src="/node_modules/ace-builds/src-min-noconflict/ace.js" type="text/javascript"></script>
<title>NPCs</title>
<script type="module" crossorigin src="/assets/index-583c10b3.js"></script>
<link rel="modulepreload" crossorigin href="/assets/acebuilds-fbc0ccc6.js">
<link rel="modulepreload" crossorigin href="/assets/reactflow-c250d835.js">
<link rel="modulepreload" crossorigin href="/assets/reactdrop-be699031.js">
<link rel="modulepreload" crossorigin href="/assets/pdfjs-36654f0a.js">
<link rel="stylesheet" href="/assets/index-1055532c.css">
</head>
<body id='body' style="width: 100%; height:100%">
<noscript>You need to enable JavaScript to run this app.</noscript>
<div style="width: 100vw; height:100vh" id='root'></div>
</body>
</html>
<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"/><script src="/node_modules/ace-builds/src-min-noconflict/ace.js"></script><title>NPCs</title><script type="module" crossorigin src="/assets/index-b35a88c5.js"></script><link rel="modulepreload" crossorigin href="/assets/acebuilds-fbc0ccc6.js"><link rel="modulepreload" crossorigin href="/assets/reactflow-c250d835.js"><link rel="modulepreload" crossorigin href="/assets/reactdrop-be699031.js"><link rel="modulepreload" crossorigin href="/assets/pdfjs-36654f0a.js"><link rel="stylesheet" href="/assets/index-d15ff243.css"></head><body id="body" style="width:100%;height:100%"><noscript>You need to enable JavaScript to run this app.</noscript><div style="width:100vw;height:100vh" id="root"></div></body></html>

View File

@@ -21,25 +21,34 @@
"pleaseEnterCaptcha": "Please enter captcha"
},
"menu": {
"app": "App",
"skills": "Skills",
"app": "Chat",
"user": "User",
"github": "GitHub",
"bookopen": "Document",
"skills": "Build",
"knowledge": "Knowledge",
"evaluation": "Evaluation",
"models": "Models",
"system": "System",
"log": "Logs",
"themeSwitch": "Theme Switch",
"document": "Documentation",
"logout": "Logout",
"logoutDescription": "Log out",
"logoutContent": "Are you sure to log out",
"forBestExperience": "For the best experience, please access this website on a PC",
"onlineDocumentation": "Online Documentation"
"onlineDocumentation": "Online Documentation",
"changePwd": "Password"
},
"system": {
"userManagement": "User Management",
"roleManagement": "Role Management",
"userGroupsM": "UserGroup Management",
"systemConfiguration": "System Configuration",
"username": "Username",
"confirmDisable": "Confirm disabling this user?",
"roleSelect": "Select Role",
"roleSelect": "Select Roles",
"userGroupsSel": "Select UserGroups",
"roleList": "Role List",
"confirmText": "Are you sure you want to delete",
"roleName": "Role Name",
@@ -52,8 +61,41 @@
"roleNamePrompt": "Role name cannot exceed 50 characters",
"roleNameRequired": "Role name is required",
"roleNameExists": "Role name already exists",
"groupNameExists": "UserGroup name already exists",
"groupNamePrompt": "UserGroup name cannot exceed 30 characters",
"groupNameRequired": "UserGroup name is required",
"parameterConfig": "Parameter Configuration",
"language": "Language"
"language": "Language",
"assistantAuthorization": "Assistant Authorization",
"assistantName": "Assistant Name",
"userList": "User List",
"userGroupList": "UserGroup List",
"userGroup": "userGroup",
"role": "Role",
"searchUserGroups": "Search user groups",
"searchRoles": "Search roles",
"reset": "Reset",
"confirm": "Confirm",
"userGroupName": "Enter UserGroup Name",
"groupName": "UserGroup Name",
"admins": "Admin",
"flowControl": "Overall UserGroup Flow Control",
"AssistantFlowCtrl": "Assistant Flow Control",
"SkillFlowCtrl": "Skill Flow Control",
"createdBy": "CreatedBy",
"flowCtrlStrategy": "Flow control strategy",
"limit": "Limit",
"unlimited": "Unlimited",
"iconHover": "Simultaneously constrained by the overall traffic control strategy of the user group",
"maximum": "Up to",
"perMinute": "simultaneous online sessions",
"changeTime": "Modification Time",
"deleteGroup": "After deletion 【{{name}}】 will no longer exist, Do you want to delete it?",
"currentGroup": "Current UserGroup",
"defaultGroup": "DefaultGroup",
"resetPwd": "ResetPassword",
"selectGroup": "Please select a user group",
"selectRole": "Please select a role"
},
"skills": {
"manageTemplate": "Manage Skill Templates",
@@ -303,7 +345,40 @@
"knowledgeImg": "Knowledge Base Avatar",
"indexModel": "Index model",
"dataUp": "Single data upper limit",
"introduce": "Introduce"
"introduce": "Introduce",
"fileUploadResult": "Out of the {{total}} files uploaded, {{failed}} failed to upload.",
"modalTitle": "File Duplicate Prompt",
"modalMessage": "The following files already exist in the knowledge base. Continuing the upload will overwrite the original files and processing strategy. Do you want to proceed with overwrite?",
"keepOriginal": "Keep Original Files",
"override": "Override",
"toolName": "ToolName"
},
"evaluation": {
"id": "任务ID",
"filename": "测试文件名称",
"skillAssistant": "技能助手",
"status": "状态",
"score": "评测分数",
"createDate": "创建日期",
"download": "下载",
"confirmDeleteEvaluation": "确认删除该评测任务?",
"createTitle": "新建任务",
"selectLabel": "选择要评测的技能或者助手:",
"selectPlaceholder": "请选择",
"dataLabel": "测试集数据:",
"fileExpandName": "支持扩展名:",
"downloadTemplate": "下载模板文件",
"promptLabel": "评测指令文本:",
"enterExecType": "请选择要评测的技能或助手",
"enterUniqueId": "请选择技能或助手ID",
"enterVersion": "请选择技能的版本",
"enterFile": "请选择测试集数据",
"enterPrompt": "评测指令不能为空",
"fileSizeLimit": "文件大小限制在10M以内",
"evaluationCollection": "评测集合",
"tooltip": "该指令文本用于指导大模型对 ground truth 和 answer 提取要点,如无特别需求请勿修改",
"create": "创建",
"cancel": "取消"
},
"code": {
"editPythonCodeDescription": "Edit your Python code here. This code snippet accepts module imports and a function definition. Make sure your function returns a string.",
@@ -576,6 +651,41 @@
"result": "Test Result",
"outResultPlaceholder": "Click the button to output the result"
},
"resetPassword": {
"slogen": "Securely Reset Your Password",
"currentPassword": "Current Password",
"newPassword": "New Password",
"confirmNewPassword": "Confirm New Password",
"pleaseEnterCurrentPassword": "Please enter your current password.",
"pleaseEnterNewPassword": "Please enter your new password.",
"pleaseEnterConfirmPassword": "Please confirm your new password.",
"newPasswordTooShort": "New password must be at least 8 characters.",
"passwordMismatch": "The new passwords do not match.",
"resetButton": "Change Password",
"passwordResetSuccess": "Your password has been successfully reset.",
"adminResetSuccess": "Password has been successfully reset",
"resetFailed": "Pwd Reset Failed",
"notEmpty": "The new password cannot be empty"
},
"log": {
"auditManagement": "Audit Management",
"searchButton": "Search",
"resetButton": "Reset",
"auditId": "Audit ID",
"username": "Username",
"operationTime": "Operation Time",
"systemModule": "System Module",
"operationAction": "Operation Action",
"objectType": "Operation Object Type",
"operationObject": "Operation Object",
"ipAddress": "IP Address",
"remark": "Remark",
"selectUser": "Select User",
"selectUserGroup": "Select User Group",
"startDate": "Start Date",
"endDate": "End Date",
"actionBehavior": "Action Behavior"
},
"agents": {
"AgentInitializer":{
"display_name": "AgentInitializer",

View File

@@ -14,32 +14,42 @@
"pleaseEnterAccount": "请填写账号",
"pleaseEnterPassword": "请填写密码",
"accountTooShort": "账号过短",
"passwordTooShort": "请填写密码,至少6位",
"passwordTooShort": "请填写密码,至少7位",
"passwordError": "密码必须包含字母、数字!",
"passwordMismatch": "两次密码不一致",
"registrationSuccess": "注册成功,请输入密码进行登录"
},
"menu": {
"app": "聊天",
"user": "用户",
"bookopen": "帮助文档",
"github": "GitHub",
"app": "会 话",
"skills": "NPC",
"knowledge": "知识库",
"models": "模型",
"system": "账号",
"evaluation": "评 测",
"models": "模 型",
"system": "账 号",
"log": "审 计",
"themeSwitch": "主题切换",
"document": "文档",
"logout": "退出",
"logoutDescription": "退出登录",
"logoutContent": "确认退出登录吗",
"forBestExperience": "为了您的良好体验,请在 PC 端访问该网站",
"onlineDocumentation": "在线文档"
"onlineDocumentation": "在线文档",
"changePwd": "修改密码"
},
"system": {
"userManagement": "用户管理",
"userManagement": "用户管理",
"userGroupsM": "用户组管理",
"roleManagement": "角色管理",
"systemConfiguration": "系统配置",
"username": "用户名",
"confirmDisable": "确认禁用该用户?",
"roleSelect": "角色选择",
"userGroupsSel": "用户组选择",
"roleList": "角色列表",
"userGroupList": "用户组列表",
"confirmText": "是否删除",
"roleName": "角色名称",
"skillAuthorization": "能力授权",
@@ -49,10 +59,42 @@
"usePermission": "使用权限",
"managePermission": "管理权限",
"roleNamePrompt": "角色名称不能超过50字符",
"roleNameRequired": "角色名称不为空",
"roleNameRequired": "角色名称不为空",
"groupNameExists": "用户组名称不可重复",
"groupNamePrompt": "用户组名称不能超过30字符",
"groupNameRequired": "用户组名称不可为空",
"roleNameExists": "角色名称已存在",
"parameterConfig": "参数配置",
"language": "语言"
"language": "语言",
"assistantAuthorization": "NPC授权",
"assistantName": "NPC名称",
"userList": "用户列表",
"userGroup": "用户组",
"role": "角色",
"searchUserGroups": "搜索用户组",
"searchRoles": "搜索角色",
"reset": "重置",
"confirm": "确认",
"userGroupName": "输入用户组名称",
"groupName": "用户组名称",
"admins": "管理员",
"flowControl": "用户组整体流量控制",
"AssistantFlowCtrl": "NPC流量控制",
"SkillFlowCtrl": "能力流量控制",
"createdBy": "创建人",
"flowCtrlStrategy": "流量控制策略",
"limit": "有限制",
"unlimited": "无限制",
"iconHover": "同时受用户组整体流量控制策略约束",
"maximum": "最多",
"perMinute": "个同时在线会话",
"changeTime": "修改时间",
"deleteGroup": "删除后 【{{name}}】 将不再存在,是否删除?",
"currentGroup": "当前用户组",
"defaultGroup": "默认用户组",
"resetPwd": "重置密码",
"selectGroup": "请选择用户组",
"selectRole": "请选择角色"
},
"skills": {
"manageTemplate": "管理能力模板",
@@ -295,7 +337,41 @@
"knowledgeImg": "知识库头像",
"indexModel": "索引模型",
"dataUp": "单条数据上限",
"introduce": "介绍"
"introduce": "介绍",
"fileUploadResult": "共上传 {{total}} 份文件,有 {{failed}} 份文件上传失败",
"modalTitle": "文件重复提示",
"modalMessage": "以下文件在知识库中已存在,继续上传将会覆盖原有文件以及处理策略,是否覆盖?",
"keepOriginal": "不覆盖,保留原文件",
"override": "覆盖",
"toolName": "工具名称"
},
"evaluation": {
"id": "任务ID",
"filename": "测试文件名称",
"skillAssistant": "能力NPC",
"status": "状态",
"score": "评测分数",
"createDate": "创建日期",
"download": "下载",
"confirmDeleteEvaluation": "确认删除该评测任务?",
"createTitle": "新建任务",
"selectLabel": "选择要评测的能力或者NPC",
"selectPlaceholder": "请选择",
"selectInputPlaceholder": "请根据名称进行搜索",
"dataLabel": "测试集数据:",
"fileExpandName": "支持扩展名:",
"downloadTemplate": "下载模板文件",
"promptLabel": "评测指令文本:",
"enterExecType": "请选择要评测的能力或NPC",
"enterUniqueId": "请选择能力或NPCID",
"enterVersion": "请选择能力的版本",
"enterFile": "请选择测试集数据",
"enterPrompt": "评测指令不能为空",
"fileSizeLimit": "文件大小限制在10M以内",
"evaluationCollection": "评测集合",
"tooltip": "该指令文本用于指导大模型对 ground truth 和 answer 提取要点,如无特别需求请勿修改",
"create": "创建",
"cancel": "取消"
},
"code": {
"editPythonCodeDescription": "编辑你的 Python 代码此代码片段接受模块导入和一个函数定义。确保您的函数返回一个字符串。",
@@ -568,6 +644,41 @@
"result": "测试结果",
"outResultPlaceholder": "点击按钮,输出结果"
},
"resetPassword": {
"slogen": "安全地重置您的密码",
"currentPassword": "当前密码",
"newPassword": "新密码",
"confirmNewPassword": "确认新密码",
"pleaseEnterCurrentPassword": "请输入当前密码。",
"pleaseEnterNewPassword": "请输入新密码。",
"pleaseEnterConfirmPassword": "请确认新密码。",
"newPasswordTooShort": "新密码必须至少 7 个字符。",
"passwordMismatch": "新密码不匹配。",
"resetButton": "修改密码",
"passwordResetSuccess": "您的密码已成功修改",
"adminResetSuccess": "密码已重置",
"resetFailed": "密码重置失败",
"notEmpty": "新密码不能为空"
},
"log": {
"auditManagement": "审计管理",
"searchButton": "查询",
"resetButton": "重置",
"auditId": "审计ID",
"username": "用户名",
"operationTime": "操作时间",
"systemModule": "系统模块",
"operationAction": "操作行为",
"objectType": "操作对象类型",
"operationObject": "操作对象",
"ipAddress": "IP地址",
"remark": "备注",
"selectUser": "选择用户",
"selectUserGroup": "选择用户组",
"startDate": "开始日期",
"endDate": "结束日期",
"actionBehavior": "操作行为"
},
"agents": {
"AgentInitializer": {
"display_name": "AgentInitializer",

520
package-lock.json generated
View File

@@ -61,7 +61,9 @@
"react": "^18.2.0",
"react-ace": "^10.1.0",
"react-beautiful-dnd": "^13.1.1",
"react-color": "^2.19.3",
"react-cookie": "^4.1.1",
"react-day-picker": "^8.10.1",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-error-boundary": "^4.0.11",
@@ -115,6 +117,7 @@
"tailwindcss": "^3.3.3",
"typescript": "^5.2.2",
"vite": "^4.5.2",
"vite-plugin-html": "^3.2.2",
"vite-plugin-static-copy": "^0.17.0"
},
"engines": {
@@ -1283,6 +1286,14 @@
"react": ">= 16"
}
},
"node_modules/@icons/material": {
"version": "0.2.4",
"resolved": "https://registry.npmmirror.com/@icons/material/-/material-0.2.4.tgz",
"integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==",
"peerDependencies": {
"react": "*"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -1401,6 +1412,16 @@
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.6",
"resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.6.tgz",
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
"devOptional": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
@@ -4950,6 +4971,12 @@
"node": ">=8"
}
},
"node_modules/async": {
"version": "3.2.5",
"resolved": "https://registry.npmmirror.com/async/-/async-3.2.5.tgz",
"integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==",
"dev": true
},
"node_modules/async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz",
@@ -5284,6 +5311,12 @@
"safe-buffer": "~5.2.0"
}
},
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"dev": true
},
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
@@ -5432,6 +5465,16 @@
"node": ">=6"
}
},
"node_modules/camel-case": {
"version": "4.1.2",
"resolved": "https://registry.npmmirror.com/camel-case/-/camel-case-4.1.2.tgz",
"integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
"dev": true,
"dependencies": {
"pascal-case": "^3.1.2",
"tslib": "^2.0.3"
}
},
"node_modules/camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
@@ -5615,6 +5658,27 @@
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
},
"node_modules/clean-css": {
"version": "5.3.3",
"resolved": "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.3.tgz",
"integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==",
"dev": true,
"dependencies": {
"source-map": "~0.6.0"
},
"engines": {
"node": ">= 10.0"
}
},
"node_modules/clean-css/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/cli-cursor": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
@@ -5975,6 +6039,12 @@
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
"integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="
},
"node_modules/colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz",
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
"dev": true
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -6014,7 +6084,22 @@
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"optional": true
"devOptional": true
},
"node_modules/connect-history-api-fallback": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
"integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
"dev": true,
"engines": {
"node": ">=0.8"
}
},
"node_modules/consola": {
"version": "2.15.3",
"resolved": "https://registry.npmmirror.com/consola/-/consola-2.15.3.tgz",
"integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==",
"dev": true
},
"node_modules/console-control-strings": {
"version": "1.1.0",
@@ -6115,6 +6200,22 @@
"tiny-invariant": "^1.0.6"
}
},
"node_modules/css-select": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/css-select/-/css-select-4.3.0.tgz",
"integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
"dev": true,
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.0.1",
"domhandler": "^4.3.1",
"domutils": "^2.8.0",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-selector-tokenizer": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
@@ -6124,6 +6225,18 @@
"fastparse": "^1.1.2"
}
},
"node_modules/css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
"dev": true,
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css.escape": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
@@ -6401,6 +6514,16 @@
"node": ">=12"
}
},
"node_modules/date-fns": {
"version": "3.6.0",
"resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-3.6.0.tgz",
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
"peer": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
"node_modules/dayjs": {
"version": "1.11.10",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
@@ -6702,6 +6825,32 @@
"csstype": "^3.0.2"
}
},
"node_modules/dom-serializer": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz",
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
"dev": true,
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
]
},
"node_modules/domexception": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
@@ -6714,11 +6863,40 @@
"node": ">=12"
}
},
"node_modules/domhandler": {
"version": "4.3.1",
"resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz",
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"dev": true,
"dependencies": {
"domelementtype": "^2.2.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/dompurify": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.1.tgz",
"integrity": "sha512-tVP8C/GJwnABOn/7cx/ymx/hXpmBfWIPihC1aOEvS8GbMqy3pgeYtJk1HXN3CO7tu+8bpY18f6isjR5Cymj0TQ=="
},
"node_modules/domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"dev": true,
"dependencies": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/dot-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
@@ -6728,6 +6906,27 @@
"tslib": "^2.0.3"
}
},
"node_modules/dotenv": {
"version": "16.4.5",
"resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.4.5.tgz",
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/dotenv-expand": {
"version": "8.0.3",
"resolved": "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-8.0.3.tgz",
"integrity": "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/duplexer2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
@@ -6778,6 +6977,21 @@
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"node_modules/ejs": {
"version": "3.1.10",
"resolved": "https://registry.npmmirror.com/ejs/-/ejs-3.1.10.tgz",
"integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
"dev": true,
"dependencies": {
"jake": "^10.8.5"
},
"bin": {
"ejs": "bin/cli.js"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/electron-to-chromium": {
"version": "1.4.750",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.750.tgz",
@@ -7177,6 +7391,27 @@
"url": "https://github.com/sindresorhus/file-type?sponsor=1"
}
},
"node_modules/filelist": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/filelist/-/filelist-1.0.4.tgz",
"integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
"dev": true,
"dependencies": {
"minimatch": "^5.0.1"
}
},
"node_modules/filelist/node_modules/minimatch": {
"version": "5.1.6",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/filename-reserved-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz",
@@ -8168,6 +8403,15 @@
"node": ">=0.4"
}
},
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true,
"bin": {
"he": "bin/he"
}
},
"node_modules/highlight.js": {
"version": "10.7.3",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
@@ -8200,6 +8444,36 @@
"node": ">=12"
}
},
"node_modules/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmmirror.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
"integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==",
"dev": true,
"dependencies": {
"camel-case": "^4.1.2",
"clean-css": "^5.2.2",
"commander": "^8.3.0",
"he": "^1.2.0",
"param-case": "^3.0.4",
"relateurl": "^0.2.7",
"terser": "^5.10.0"
},
"bin": {
"html-minifier-terser": "cli.js"
},
"engines": {
"node": ">=12"
}
},
"node_modules/html-minifier-terser/node_modules/commander": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz",
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
"dev": true,
"engines": {
"node": ">= 12"
}
},
"node_modules/html-parse-stringify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
@@ -8909,6 +9183,46 @@
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/jake": {
"version": "10.9.2",
"resolved": "https://registry.npmmirror.com/jake/-/jake-10.9.2.tgz",
"integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==",
"dev": true,
"dependencies": {
"async": "^3.2.3",
"chalk": "^4.0.2",
"filelist": "^1.0.4",
"minimatch": "^3.1.2"
},
"bin": {
"jake": "bin/cli.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/jake/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/jake/node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/jest-diff": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz",
@@ -9432,6 +9746,11 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/material-colors": {
"version": "1.2.6",
"resolved": "https://registry.npmmirror.com/material-colors/-/material-colors-1.2.6.tgz",
"integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg=="
},
"node_modules/mathjax-full": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.2.tgz",
@@ -11789,6 +12108,16 @@
}
}
},
"node_modules/node-html-parser": {
"version": "5.4.2",
"resolved": "https://registry.npmmirror.com/node-html-parser/-/node-html-parser-5.4.2.tgz",
"integrity": "sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==",
"dev": true,
"dependencies": {
"css-select": "^4.2.1",
"he": "1.2.0"
}
},
"node_modules/node-releases": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
@@ -11862,6 +12191,18 @@
"set-blocking": "^2.0.0"
}
},
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"dev": true,
"dependencies": {
"boolbase": "^1.0.0"
},
"funding": {
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/nwsapi": {
"version": "2.2.9",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.9.tgz",
@@ -12080,6 +12421,16 @@
"node": ">=4"
}
},
"node_modules/param-case": {
"version": "3.0.4",
"resolved": "https://registry.npmmirror.com/param-case/-/param-case-3.0.4.tgz",
"integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
"dev": true,
"dependencies": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -12147,6 +12498,16 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/pascal-case": {
"version": "3.1.2",
"resolved": "https://registry.npmmirror.com/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"dev": true,
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
@@ -12215,6 +12576,12 @@
"node": ">=8"
}
},
"node_modules/pathe": {
"version": "0.2.0",
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-0.2.0.tgz",
"integrity": "sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==",
"dev": true
},
"node_modules/pdfjs-dist": {
"version": "3.10.111",
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.10.111.tgz",
@@ -13432,6 +13799,23 @@
"react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-color": {
"version": "2.19.3",
"resolved": "https://registry.npmmirror.com/react-color/-/react-color-2.19.3.tgz",
"integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==",
"dependencies": {
"@icons/material": "^0.2.4",
"lodash": "^4.17.15",
"lodash-es": "^4.17.15",
"material-colors": "^1.2.1",
"prop-types": "^15.5.10",
"reactcss": "^1.2.0",
"tinycolor2": "^1.4.1"
},
"peerDependencies": {
"react": "*"
}
},
"node_modules/react-colorful": {
"version": "5.6.1",
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz",
@@ -13454,6 +13838,19 @@
"react": ">= 16.3.0"
}
},
"node_modules/react-day-picker": {
"version": "8.10.1",
"resolved": "https://registry.npmmirror.com/react-day-picker/-/react-day-picker-8.10.1.tgz",
"integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==",
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/gpbl"
},
"peerDependencies": {
"date-fns": "^2.28.0 || ^3.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
@@ -13859,6 +14256,14 @@
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/reactcss": {
"version": "1.2.3",
"resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz",
"integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==",
"dependencies": {
"lodash": "^4.0.1"
}
},
"node_modules/reactflow": {
"version": "11.11.2",
"resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.11.2.tgz",
@@ -14149,6 +14554,15 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/relateurl": {
"version": "0.2.7",
"resolved": "https://registry.npmmirror.com/relateurl/-/relateurl-0.2.7.tgz",
"integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
"dev": true,
"engines": {
"node": ">= 0.10"
}
},
"node_modules/remark-breaks": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz",
@@ -15308,6 +15722,31 @@
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"devOptional": true,
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/source-map-support/node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"devOptional": true
},
"node_modules/source-map-support/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"devOptional": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/space-separated-tokens": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
@@ -15791,6 +16230,30 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"optional": true
},
"node_modules/terser": {
"version": "5.31.3",
"resolved": "https://registry.npmmirror.com/terser/-/terser-5.31.3.tgz",
"integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==",
"devOptional": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"engines": {
"node": ">=10"
}
},
"node_modules/terser/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"devOptional": true
},
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
@@ -15845,6 +16308,11 @@
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
"node_modules/tinycolor2": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz",
"integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
},
"node_modules/to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -16487,6 +16955,56 @@
}
}
},
"node_modules/vite-plugin-html": {
"version": "3.2.2",
"resolved": "https://registry.npmmirror.com/vite-plugin-html/-/vite-plugin-html-3.2.2.tgz",
"integrity": "sha512-vb9C9kcdzcIo/Oc3CLZVS03dL5pDlOFuhGlZYDCJ840BhWl/0nGeZWf3Qy7NlOayscY4Cm/QRgULCQkEZige5Q==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^4.2.0",
"colorette": "^2.0.16",
"connect-history-api-fallback": "^1.6.0",
"consola": "^2.15.3",
"dotenv": "^16.0.0",
"dotenv-expand": "^8.0.2",
"ejs": "^3.1.6",
"fast-glob": "^3.2.11",
"fs-extra": "^10.0.1",
"html-minifier-terser": "^6.1.0",
"node-html-parser": "^5.3.3",
"pathe": "^0.2.0"
},
"peerDependencies": {
"vite": ">=2.0.0"
}
},
"node_modules/vite-plugin-html/node_modules/@rollup/pluginutils": {
"version": "4.2.1",
"resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
"integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==",
"dev": true,
"dependencies": {
"estree-walker": "^2.0.1",
"picomatch": "^2.2.2"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/vite-plugin-html/node_modules/fs-extra": {
"version": "10.1.0",
"resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz",
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-static-copy": {
"version": "0.17.1",
"resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-0.17.1.tgz",

View File

@@ -56,7 +56,9 @@
"react": "^18.2.0",
"react-ace": "^10.1.0",
"react-beautiful-dnd": "^13.1.1",
"react-color": "^2.19.3",
"react-cookie": "^4.1.1",
"react-day-picker": "^8.10.1",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-error-boundary": "^4.0.11",
@@ -136,6 +138,7 @@
"tailwindcss": "^3.3.3",
"typescript": "^5.2.2",
"vite": "^4.5.2",
"vite-plugin-html": "^3.2.2",
"vite-plugin-static-copy": "^0.17.0"
},
"engines": {

View File

@@ -21,25 +21,34 @@
"pleaseEnterCaptcha": "Please enter captcha"
},
"menu": {
"app": "App",
"skills": "Skills",
"app": "Chat",
"user": "User",
"github": "GitHub",
"bookopen": "Document",
"skills": "Build",
"knowledge": "Knowledge",
"evaluation": "Evaluation",
"models": "Models",
"system": "System",
"log": "Logs",
"themeSwitch": "Theme Switch",
"document": "Documentation",
"logout": "Logout",
"logoutDescription": "Log out",
"logoutContent": "Are you sure to log out",
"forBestExperience": "For the best experience, please access this website on a PC",
"onlineDocumentation": "Online Documentation"
"onlineDocumentation": "Online Documentation",
"changePwd": "Password"
},
"system": {
"userManagement": "User Management",
"roleManagement": "Role Management",
"userGroupsM": "UserGroup Management",
"systemConfiguration": "System Configuration",
"username": "Username",
"confirmDisable": "Confirm disabling this user?",
"roleSelect": "Select Role",
"roleSelect": "Select Roles",
"userGroupsSel": "Select UserGroups",
"roleList": "Role List",
"confirmText": "Are you sure you want to delete",
"roleName": "Role Name",
@@ -52,8 +61,41 @@
"roleNamePrompt": "Role name cannot exceed 50 characters",
"roleNameRequired": "Role name is required",
"roleNameExists": "Role name already exists",
"groupNameExists": "UserGroup name already exists",
"groupNamePrompt": "UserGroup name cannot exceed 30 characters",
"groupNameRequired": "UserGroup name is required",
"parameterConfig": "Parameter Configuration",
"language": "Language"
"language": "Language",
"assistantAuthorization": "Assistant Authorization",
"assistantName": "Assistant Name",
"userList": "User List",
"userGroupList": "UserGroup List",
"userGroup": "userGroup",
"role": "Role",
"searchUserGroups": "Search user groups",
"searchRoles": "Search roles",
"reset": "Reset",
"confirm": "Confirm",
"userGroupName": "Enter UserGroup Name",
"groupName": "UserGroup Name",
"admins": "Admin",
"flowControl": "Overall UserGroup Flow Control",
"AssistantFlowCtrl": "Assistant Flow Control",
"SkillFlowCtrl": "Skill Flow Control",
"createdBy": "CreatedBy",
"flowCtrlStrategy": "Flow control strategy",
"limit": "Limit",
"unlimited": "Unlimited",
"iconHover": "Simultaneously constrained by the overall traffic control strategy of the user group",
"maximum": "Up to",
"perMinute": "simultaneous online sessions",
"changeTime": "Modification Time",
"deleteGroup": "After deletion 【{{name}}】 will no longer exist, Do you want to delete it?",
"currentGroup": "Current UserGroup",
"defaultGroup": "DefaultGroup",
"resetPwd": "ResetPassword",
"selectGroup": "Please select a user group",
"selectRole": "Please select a role"
},
"skills": {
"manageTemplate": "Manage Skill Templates",
@@ -303,7 +345,40 @@
"knowledgeImg": "Knowledge Base Avatar",
"indexModel": "Index model",
"dataUp": "Single data upper limit",
"introduce": "Introduce"
"introduce": "Introduce",
"fileUploadResult": "Out of the {{total}} files uploaded, {{failed}} failed to upload.",
"modalTitle": "File Duplicate Prompt",
"modalMessage": "The following files already exist in the knowledge base. Continuing the upload will overwrite the original files and processing strategy. Do you want to proceed with overwrite?",
"keepOriginal": "Keep Original Files",
"override": "Override",
"toolName": "ToolName"
},
"evaluation": {
"id": "任务ID",
"filename": "测试文件名称",
"skillAssistant": "技能助手",
"status": "状态",
"score": "评测分数",
"createDate": "创建日期",
"download": "下载",
"confirmDeleteEvaluation": "确认删除该评测任务?",
"createTitle": "新建任务",
"selectLabel": "选择要评测的技能或者助手:",
"selectPlaceholder": "请选择",
"dataLabel": "测试集数据:",
"fileExpandName": "支持扩展名:",
"downloadTemplate": "下载模板文件",
"promptLabel": "评测指令文本:",
"enterExecType": "请选择要评测的技能或助手",
"enterUniqueId": "请选择技能或助手ID",
"enterVersion": "请选择技能的版本",
"enterFile": "请选择测试集数据",
"enterPrompt": "评测指令不能为空",
"fileSizeLimit": "文件大小限制在10M以内",
"evaluationCollection": "评测集合",
"tooltip": "该指令文本用于指导大模型对 ground truth 和 answer 提取要点,如无特别需求请勿修改",
"create": "创建",
"cancel": "取消"
},
"code": {
"editPythonCodeDescription": "Edit your Python code here. This code snippet accepts module imports and a function definition. Make sure your function returns a string.",
@@ -576,6 +651,41 @@
"result": "Test Result",
"outResultPlaceholder": "Click the button to output the result"
},
"resetPassword": {
"slogen": "Securely Reset Your Password",
"currentPassword": "Current Password",
"newPassword": "New Password",
"confirmNewPassword": "Confirm New Password",
"pleaseEnterCurrentPassword": "Please enter your current password.",
"pleaseEnterNewPassword": "Please enter your new password.",
"pleaseEnterConfirmPassword": "Please confirm your new password.",
"newPasswordTooShort": "New password must be at least 8 characters.",
"passwordMismatch": "The new passwords do not match.",
"resetButton": "Change Password",
"passwordResetSuccess": "Your password has been successfully reset.",
"adminResetSuccess": "Password has been successfully reset",
"resetFailed": "Pwd Reset Failed",
"notEmpty": "The new password cannot be empty"
},
"log": {
"auditManagement": "Audit Management",
"searchButton": "Search",
"resetButton": "Reset",
"auditId": "Audit ID",
"username": "Username",
"operationTime": "Operation Time",
"systemModule": "System Module",
"operationAction": "Operation Action",
"objectType": "Operation Object Type",
"operationObject": "Operation Object",
"ipAddress": "IP Address",
"remark": "Remark",
"selectUser": "Select User",
"selectUserGroup": "Select User Group",
"startDate": "Start Date",
"endDate": "End Date",
"actionBehavior": "Action Behavior"
},
"agents": {
"AgentInitializer":{
"display_name": "AgentInitializer",

View File

@@ -14,32 +14,42 @@
"pleaseEnterAccount": "请填写账号",
"pleaseEnterPassword": "请填写密码",
"accountTooShort": "账号过短",
"passwordTooShort": "请填写密码,至少6位",
"passwordTooShort": "请填写密码,至少7位",
"passwordError": "密码必须包含字母、数字!",
"passwordMismatch": "两次密码不一致",
"registrationSuccess": "注册成功,请输入密码进行登录"
},
"menu": {
"app": "聊天",
"user": "用户",
"bookopen": "帮助文档",
"github": "GitHub",
"app": "会 话",
"skills": "NPC",
"knowledge": "知识库",
"models": "模型",
"system": "账号",
"evaluation": "评 测",
"models": "模 型",
"system": "账 号",
"log": "审 计",
"themeSwitch": "主题切换",
"document": "文档",
"logout": "退出",
"logoutDescription": "退出登录",
"logoutContent": "确认退出登录吗",
"forBestExperience": "为了您的良好体验,请在 PC 端访问该网站",
"onlineDocumentation": "在线文档"
"onlineDocumentation": "在线文档",
"changePwd": "修改密码"
},
"system": {
"userManagement": "用户管理",
"userManagement": "用户管理",
"userGroupsM": "用户组管理",
"roleManagement": "角色管理",
"systemConfiguration": "系统配置",
"username": "用户名",
"confirmDisable": "确认禁用该用户?",
"roleSelect": "角色选择",
"userGroupsSel": "用户组选择",
"roleList": "角色列表",
"userGroupList": "用户组列表",
"confirmText": "是否删除",
"roleName": "角色名称",
"skillAuthorization": "能力授权",
@@ -49,10 +59,42 @@
"usePermission": "使用权限",
"managePermission": "管理权限",
"roleNamePrompt": "角色名称不能超过50字符",
"roleNameRequired": "角色名称不为空",
"roleNameRequired": "角色名称不为空",
"groupNameExists": "用户组名称不可重复",
"groupNamePrompt": "用户组名称不能超过30字符",
"groupNameRequired": "用户组名称不可为空",
"roleNameExists": "角色名称已存在",
"parameterConfig": "参数配置",
"language": "语言"
"language": "语言",
"assistantAuthorization": "NPC授权",
"assistantName": "NPC名称",
"userList": "用户列表",
"userGroup": "用户组",
"role": "角色",
"searchUserGroups": "搜索用户组",
"searchRoles": "搜索角色",
"reset": "重置",
"confirm": "确认",
"userGroupName": "输入用户组名称",
"groupName": "用户组名称",
"admins": "管理员",
"flowControl": "用户组整体流量控制",
"AssistantFlowCtrl": "NPC流量控制",
"SkillFlowCtrl": "能力流量控制",
"createdBy": "创建人",
"flowCtrlStrategy": "流量控制策略",
"limit": "有限制",
"unlimited": "无限制",
"iconHover": "同时受用户组整体流量控制策略约束",
"maximum": "最多",
"perMinute": "个同时在线会话",
"changeTime": "修改时间",
"deleteGroup": "删除后 【{{name}}】 将不再存在,是否删除?",
"currentGroup": "当前用户组",
"defaultGroup": "默认用户组",
"resetPwd": "重置密码",
"selectGroup": "请选择用户组",
"selectRole": "请选择角色"
},
"skills": {
"manageTemplate": "管理能力模板",
@@ -295,7 +337,41 @@
"knowledgeImg": "知识库头像",
"indexModel": "索引模型",
"dataUp": "单条数据上限",
"introduce": "介绍"
"introduce": "介绍",
"fileUploadResult": "共上传 {{total}} 份文件,有 {{failed}} 份文件上传失败",
"modalTitle": "文件重复提示",
"modalMessage": "以下文件在知识库中已存在,继续上传将会覆盖原有文件以及处理策略,是否覆盖?",
"keepOriginal": "不覆盖,保留原文件",
"override": "覆盖",
"toolName": "工具名称"
},
"evaluation": {
"id": "任务ID",
"filename": "测试文件名称",
"skillAssistant": "能力NPC",
"status": "状态",
"score": "评测分数",
"createDate": "创建日期",
"download": "下载",
"confirmDeleteEvaluation": "确认删除该评测任务?",
"createTitle": "新建任务",
"selectLabel": "选择要评测的能力或者NPC",
"selectPlaceholder": "请选择",
"selectInputPlaceholder": "请根据名称进行搜索",
"dataLabel": "测试集数据:",
"fileExpandName": "支持扩展名:",
"downloadTemplate": "下载模板文件",
"promptLabel": "评测指令文本:",
"enterExecType": "请选择要评测的能力或NPC",
"enterUniqueId": "请选择能力或NPCID",
"enterVersion": "请选择能力的版本",
"enterFile": "请选择测试集数据",
"enterPrompt": "评测指令不能为空",
"fileSizeLimit": "文件大小限制在10M以内",
"evaluationCollection": "评测集合",
"tooltip": "该指令文本用于指导大模型对 ground truth 和 answer 提取要点,如无特别需求请勿修改",
"create": "创建",
"cancel": "取消"
},
"code": {
"editPythonCodeDescription": "编辑你的 Python 代码此代码片段接受模块导入和一个函数定义。确保您的函数返回一个字符串。",
@@ -568,6 +644,41 @@
"result": "测试结果",
"outResultPlaceholder": "点击按钮,输出结果"
},
"resetPassword": {
"slogen": "安全地重置您的密码",
"currentPassword": "当前密码",
"newPassword": "新密码",
"confirmNewPassword": "确认新密码",
"pleaseEnterCurrentPassword": "请输入当前密码。",
"pleaseEnterNewPassword": "请输入新密码。",
"pleaseEnterConfirmPassword": "请确认新密码。",
"newPasswordTooShort": "新密码必须至少 7 个字符。",
"passwordMismatch": "新密码不匹配。",
"resetButton": "修改密码",
"passwordResetSuccess": "您的密码已成功修改",
"adminResetSuccess": "密码已重置",
"resetFailed": "密码重置失败",
"notEmpty": "新密码不能为空"
},
"log": {
"auditManagement": "审计管理",
"searchButton": "查询",
"resetButton": "重置",
"auditId": "审计ID",
"username": "用户名",
"operationTime": "操作时间",
"systemModule": "系统模块",
"operationAction": "操作行为",
"objectType": "操作对象类型",
"operationObject": "操作对象",
"ipAddress": "IP地址",
"remark": "备注",
"selectUser": "选择用户",
"selectUserGroup": "选择用户组",
"startDate": "开始日期",
"endDate": "结束日期",
"actionBehavior": "操作行为"
},
"agents": {
"AgentInitializer": {
"display_name": "AgentInitializer",

BIN
src/.DS_Store vendored

Binary file not shown.

View File

@@ -34,7 +34,7 @@ import {
nodeIconsLucide,
nodeIMgsLucide
} from "../../../../utils";
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
import KnowledgeSelect from "@/components/bs-comp/selectComponent/knowledge";
export default function ParameterComponent({
left,
@@ -61,7 +61,7 @@ export default function ParameterComponent({
const updateNodeInternals = useUpdateNodeInternals();
const [position, setPosition] = useState(0);
const { closePopUp } = useContext(PopUpContext);
const { setTabsState, flow, setFlow } = useContext(TabsContext);
const { setTabsState, flow, version } = useContext(TabsContext);
const groupedEdge = useRef(null); // 用yu过滤菜单的数据
@@ -91,7 +91,7 @@ export default function ParameterComponent({
}, [id, data, reactFlowInstance])
// milvus 组件,知识库不为空是 embbeding取消必填限制
useEffect(() => {
const {embedding, index_name, collection_name, connection_args} = data.node.template
const { embedding, index_name, collection_name, connection_args } = data.node.template
if ((index_name || collection_name) && embedding) {
const hidden = disabled ? false : !!(collection_name || index_name).value
data.node.template.embedding.required = !hidden
@@ -101,7 +101,7 @@ export default function ParameterComponent({
}
}, [data, disabled])
const handleRemoveMilvusEmbeddingEdge = (nodeId) => {
const edges = reactFlowInstance.getEdges().filter(edge => edge.targetHandle.indexOf('Embeddings|embedding|'+nodeId) === -1)
const edges = reactFlowInstance.getEdges().filter(edge => edge.targetHandle.indexOf('Embeddings|embedding|' + nodeId) === -1)
reactFlowInstance.setEdges(edges)
}
const [myData, setMyData] = useState(useContext(typesContext).data);
@@ -219,7 +219,6 @@ export default function ParameterComponent({
}}
/> */}
<img src={Icon} className="w-[14px]" alt="" />
</div>
<span className="ps-2 text-xs text-foreground w-[400px]">
{getNodeNames()[item.family] ?? "Other"}{" "}
@@ -268,34 +267,6 @@ export default function ParameterComponent({
}
}, [tooltipTitle]);
// 记录快照
const {takeSnapshot} = useContext(undoRedoContext);
const { types, deleteNode } = useContext(typesContext);
// const onNodeDragStart: NodeDragHandler = useCallback(() => {
// // 👇 make dragging a node undoable
// takeSnapshot();
// // 👉 you can place your event handlers here
// }, [takeSnapshot]);
const onMouseDownColor = useCallback(() => {
// console.log(nodeColorsP)
// console.log(data,color,nodeColorsP,nodeColorsP[types[data.type]]);
// const type = types[data.type];
// Object.keys(nodeColors).forEach(element => {
// if(element != type){
// nodeColorsP[element] = "#000000"
// }
// });
// console.log(nodeColors);
// takeSnapshot();
// data.node.display_name = "1";
// console.log(flow)
},[takeSnapshot]);
// useEffect(() => {
// takeSnapshot();
// }, [nodeColors, nodeColorsP]);
return (
<div
ref={ref}
@@ -330,37 +301,36 @@ export default function ParameterComponent({
type === "int" ||
type === "variable" ||
type === "button" ||
type === "knowledge_one" ||
type === "knowledge_list" ||
type === "NestedDict" ||
type === "dict") &&
!optionalHandle ? (
<></>
) : (
<ShadTooltip
styleClasses={"tooltip-fixed-width custom-scroll nowheel"}
delayDuration={0}
content={refHtml.current}
side={left ? "left" : "right"}
>
<Handle
type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right}
id={id}
isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance)
}
onConnect={(params) => console.log('handle onConnect', params)}
className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ",
"h-3 w-3 rounded-full border-2 bg-background"
)}
onMouseDown={onMouseDownColor}
style={{
borderColor: color,
top: position,
}}
></Handle>
</ShadTooltip>
)}
!optionalHandle ? (<></>)
: (
<ShadTooltip
styleClasses={"tooltip-fixed-width custom-scroll nowheel"}
delayDuration={0}
content={refHtml.current}
side={left ? "left" : "right"}
>
<Handle
type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right}
id={id}
isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance)
}
className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ",
"h-3 w-3 rounded-full border-2 bg-background"
)}
style={{
borderColor: color,
top: position,
}}
></Handle>
</ShadTooltip>
)}
{/* 左侧input输入项 */}
{!data.node.template[name] ? null : left === true &&
@@ -390,10 +360,6 @@ export default function ParameterComponent({
) : ['index_name', 'collection_name'].includes(name) ? (
// 知识库选择
<CollectionNameComponent
setNodeClass={(nodeClass) => {
data.node = nodeClass;
}}
nodeClass={data.node}
disabled={disabled}
id={data.node.template[name].collection_id ?? ""}
value={data.node.template[name].value ?? ""}
@@ -410,6 +376,35 @@ export default function ParameterComponent({
/>
)}
</div>
) : left === true && type === "knowledge_one" ? (
// 单选知识库
<div className="mt-2 w-full">
<CollectionNameComponent
disabled={disabled}
id={data.node.template[name].collection_id ?? ""}
value={data.node.template[name].value ?? ""}
onSelect={(val, id) => { handleOnNewLibValue(val, id); val && handleRemoveMilvusEmbeddingEdge(data.id) }}
onChange={() => { }}
/>
</div>
) : left === true && type === "knowledge_list" ? (
// 多选知识库
<div className="mt-2 w-full">
<KnowledgeSelect
multiple
disabled={disabled}
value={data.node.template[name].value?.map?.((item) => ({
label: item.value,
value: item.key,
})) || []}
onChange={(vals) => {
handleOnNewValue(vals.map(v => ({
key: v.value,
value: v.label
})))
}}
/>
</div>
) : left === true && type === "bool" ? (
<div className="mt-2 w-full">
{/* switch */}
@@ -480,7 +475,6 @@ export default function ParameterComponent({
<PromptAreaComponent
field_name={name}
setNodeClass={(nodeClass, code) => {
console.log(nodeClass)
if (reactFlowInstance) {
reactFlowInstance.setNodes((nds) =>
nds.map((nd) => {
@@ -548,7 +542,7 @@ export default function ParameterComponent({
</div>
) : left === true && type === "variable" ? (
<div className="mt-2 w-full">
<VariablesComponent nodeId={data.id} flowId={flowId} onChange={(newValue) => {
<VariablesComponent vid={version?.id} nodeId={data.id} flowId={flowId} onChange={(newValue) => {
data.node!.template[name].value = newValue;
handleOnNewValue(newValue);
}} />

BIN
src/assets/.DS_Store vendored

Binary file not shown.

Binary file not shown.

BIN
src/assets/Login/reset.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

BIN
src/assets/nav/admin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
src/assets/nav/admin1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
src/assets/nav/icon6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
src/assets/nav/icon7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
src/assets/nav/mima.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 B

BIN
src/assets/nav/tuichu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 B

Binary file not shown.

View File

@@ -17,7 +17,8 @@ import { captureAndAlertRequestErrorHoc } from "../../controllers/request";
* 通过子组件VarDialog编辑每一项
*/
export default function VariablesComponent({ nodeId, flowId, onChange }: {
export default function VariablesComponent({vid, nodeId, flowId, onChange }: {
vid: number
nodeId: string
flowId: string
onChange: (val: any) => void
@@ -27,11 +28,12 @@ export default function VariablesComponent({ nodeId, flowId, onChange }: {
useEffect(() => {
// api nodeId -> items
flowId && getVariablesApi({
flowId && vid && getVariablesApi({
version_id: vid,
flow_id: flowId,
node_id: nodeId
}).then(arr => setItems(arr))
}, [flowId])
}, [flowId, vid])
const { openPopUp, closePopUp } = useContext(PopUpContext);
const { setErrorData } = useContext(alertContext);
@@ -60,6 +62,7 @@ export default function VariablesComponent({ nodeId, flowId, onChange }: {
const param: any = {
"flow_id": flowId,
"node_id": nodeId,
version_id: vid,
"variable_name": _item.name,
"value_type": Number(_item.type === VariableType.Select) + 1,
"value": _item.type === VariableType.Text ? _item.maxLength : _item.options.map(el => el.value).join(',')
@@ -68,7 +71,7 @@ export default function VariablesComponent({ nodeId, flowId, onChange }: {
param.id = _item.id
}
captureAndAlertRequestErrorHoc(saveVariableApi(param).then(res => {
const _items = items.map(item => item.id === _item.id ? { ..._item, id: res.id } : item)
const _items = items.map(item => item.id === _item.id ? { ..._item, id: res.id, update: true } : item)
// const hasValue = _items.find(item => item.name)
// 保存时 id传出去保存用来校验必填项
onChange(_items.map(el => el.name))

BIN
src/components/bs-comp/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -1,16 +1,18 @@
import { ClearIcon } from "@/components/bs-icons/clear";
import { FormIcon } from "@/components/bs-icons/form";
import { SendIcon } from "@/components/bs-icons/send";
import { Button } from "@/components/bs-ui/button";
import { Textarea } from "@/components/bs-ui/input";
import { useToast } from "@/components/bs-ui/toast/use-toast";
import { locationContext } from "@/contexts/locationContext";
import { PauseIcon } from "@radix-ui/react-icons";
import { useContext, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { useMessageStore } from "./messageStore";
import GuideQuestions from "./GuideQuestions";
import { ClearIcon } from "@/components/bs-icons/clear";
import { useMessageStore } from "./messageStore";
import { formatDate } from "@/util/utils";
import { StopIcon } from "@radix-ui/react-icons";
import duihua_send from "../../../assets/chat/duihua-send.png";
import { Button } from "@/components/bs-ui/button";
import { StopCircle } from "lucide-react";
export default function ChatInput({ clear, form, questions, inputForm, wsUrl, onBeforSend }) {
const { toast } = useToast()
@@ -21,11 +23,15 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
const [showWhenLocked, setShowWhenLocked] = useState(false) // 强制开启表单按钮不限制于input锁定
const [inputLock, setInputLock] = useState({ locked: false, reason: '' })
const { messages, chatId, createSendMsg, createWsMsg, updateCurrentMessage, destory, setShowGuideQuestion } = useMessageStore()
const { messages, hisMessages, chatId, createSendMsg, createWsMsg, updateCurrentMessage, destory, setShowGuideQuestion } = useMessageStore()
const currentChatIdRef = useRef(null)
const inputRef = useRef(null)
const continueRef = useRef(false)
// 停止状态
const [isStop, setIsStop] = useState(true)
const [stop, setStop] = useState({
show: false,
disable: false
})
/**
* 记录会话切换状态,等待消息加载完成时,控制表单在新会话自动展开
*/
@@ -36,16 +42,17 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
if (changeChatedRef.current) {
changeChatedRef.current = false
// 新建的 form 技能,弹出窗口并锁定 input
if (form && messages.length === 0) {
if (form && messages.length === 0 && hisMessages.length === 0) {
setInputLock({ locked: true, reason: '' })
setFormShow(true)
setShowWhenLocked(true)
}
}
}, [messages])
}, [messages, hisMessages])
useEffect(() => {
if (!chatId) return
continueRef.current = false
setInputLock({ locked: false, reason: '' })
// console.log('message chatid', messages, form, chatId);
setShowWhenLocked(false)
@@ -85,13 +92,14 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
const event = new Event('input', { bubbles: true, cancelable: true });
inputRef.current.value = ''
inputRef.current.dispatchEvent(event); // 触发调节input高度
const [wsMsg, inputKey] = onBeforSend('', value)
const contunue = continueRef.current ? 'continue' : ''
continueRef.current = false
const [wsMsg, inputKey] = onBeforSend(contunue, value)
// msg to store
createSendMsg(wsMsg.inputs, inputKey)
// 锁定 input
setInputLock({ locked: true, reason: '' })
await createWebSocket(chatId)
// console.log(wsMsg,inputKey);
sendWsMsg(wsMsg)
// 滚动聊天到底
@@ -100,15 +108,13 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
messageDom.scrollTop = messageDom.scrollHeight;
}
}
const stop = async () => {
const [wsMsg] = onBeforSend('', '')
wsMsg.action = "stop"
sendWsMsg(wsMsg)
// console.log(wsMsg);
// sendWsMsg(wsMsg)
}
const diffRef = useRef(0)
const sendWsMsg = async (msg) => {
try {
diffRef.current = Date.now()
// console.log('WebSocket send: ' + diffRef.current + ' 毫秒');
wsRef.current.send(JSON.stringify(msg))
} catch (error) {
toast({
@@ -128,14 +134,23 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
return new Promise((res, rej) => {
try {
let startTime = Date.now();
const ws = new WebSocket(`${webSocketProtocol}://${wsUrl}&chat_id=${chatId}`)
wsRef.current = ws
// websocket linsen
ws.onopen = () => {
// 记录连接成功的时间
let endTime = Date.now();
// 计算连接建立所需的时间
let connectionTime = endTime - startTime;
// console.log('WebSocket 连接建立时间: ' + connectionTime + ' 毫秒');
console.log("WebSocket connection established!");
res('ok')
};
ws.onmessage = (event) => {
// console.log(`WebSocket get: ${Date.now()} 毫秒与send差值${Date.now() - diffRef.current}毫秒`);
const data = JSON.parse(event.data);
const errorMsg = data.category === 'error' ? data.intermediate_steps : ''
// 异常类型处理,提示
@@ -145,13 +160,17 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
handleWsMessage(data)
// 群聊@自己时开启input
if (['end', 'end_cover'].includes(data.type) && data.receiver?.is_self) {
setInputLock({ locked: true, reason: '' })
setInputLock({ locked: false, reason: '' })
setStop({ show: false, disable: false })
continueRef.current = true
}
}
ws.onclose = (event) => {
wsRef.current = null
console.error('链接手动断开 event :>> ', event);
if ([1005, 1008].includes(event.code)) {
setStop({ show: false, disable: false })
if ([1005, 1008, 1009].includes(event.code)) {
console.warn('即将废弃 :>> ');
setInputLock({ locked: true, reason: event.reason })
} else {
@@ -167,8 +186,8 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
};
ws.onerror = (ev) => {
wsRef.current = null
setStop({ show: false, disable: false })
console.error('链接异常error', ev);
setIsStop(true)
toast({
title: `${t('chat.networkError')}:`,
variant: 'error',
@@ -189,15 +208,14 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
// 接受 ws 消息
const handleWsMessage = (data) => {
// console.log(data)
if (Array.isArray(data) && data.length) return
if (data.type === "begin") {
setIsStop(false)
}else if (data.type === 'start') {
if (data.type === 'start') {
// 非continue时展示stop按钮
!continueRef.current && setStop({ show: true, disable: false })
createWsMsg(data)
} else if (data.type === 'stream') {
//@ts-ignore
updateCurrentMessage({
flow_id: data.flow_id,
chat_id: data.chat_id,
message: data.message,
thought: data.intermediate_steps
@@ -209,16 +227,16 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
thought: data.intermediate_steps || '',
messageId: data.message_id,
noAccess: false,
liked: 0
liked: 0,
update_time: formatDate(new Date(), 'yyyy-MM-ddTHH:mm:ss')
}, data.type === 'end_cover')
} else if (data.type === "close") {
setIsStop(true)
setStop({ show: false, disable: false })
setInputLock({ locked: false, reason: '' })
}
}
// 监听重发消息事件
// 触发发送消息事件(重试、表单)
useEffect(() => {
const handleCustomEvent = (e) => {
if (!showWhenLocked && inputLock.locked) return console.error('弹窗已锁定,消息无法发送')
@@ -247,12 +265,12 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
// setInputEmpty(textarea.value.trim() === '')
}
return <div className="absolute bottom-0 w-full bg-[#fff] dark:bg-[#000000]">
<div className={`relative pt-[10px]`}>
return <div className="absolute bottom-0 w-full pt-1 bg-[#fff] dark:bg-[#000]">
<div className={`relative ${clear && 'pl-9'}`}>
{/* form */}
{
formShow && <div className="relative">
<div className="absolute left-0 bottom-2 bg-[#1a1a1a] px-4 py-2 rounded-md w-[50%] min-w-80">
<div className="absolute left-0 border bottom-2 bg-background-login px-4 py-2 rounded-md w-[50%] min-w-80 z-50">
{inputForm}
</div>
</div>
@@ -265,34 +283,51 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
onClick={handleClickGuideWord}
/>
{/* clear */}
{/* <div className="flex absolute left-0 top-4 z-10">
<div className="flex absolute left-0 top-4 z-10">
{
clear && <div
className={`w-6 h-6 rounded-sm hover:bg-gray-200 cursor-pointer flex justify-center items-center `}
onClick={() => { !inputLock.locked && destory() }}
><ClearIcon className={!showWhenLocked && inputLock.locked ? 'text-gray-400' : 'text-gray-950'} ></ClearIcon></div>
><ClearIcon className={`${!showWhenLocked && inputLock.locked ? 'text-gray-400' : 'text-gray-950'} dark:text-slate-50 dark:hover:bg-[#282828]`} ></ClearIcon></div>
}
</div> */}
{/* form */}
</div>
{/* form switch */}
<div className="flex absolute left-3 top-4 z-10">
{
form && <div
className={`w-6 h-6 rounded-sm hover:bg-gray-200 cursor-pointer flex justify-center items-center `}
onClick={() => (showWhenLocked || !inputLock.locked) && setFormShow(!formShow)}
><FormIcon className={!showWhenLocked && inputLock.locked ? 'text-gray-400' : 'text-gray-950'}></FormIcon></div>
><FormIcon className={!showWhenLocked && inputLock.locked ? 'text-gray-400' : 'text-gray-800'}></FormIcon></div>
}
</div>
{/* send */}
<div className="flex gap-2 absolute right-[2.5%] z-10">
<div
id="bs-send-btn"
className="w-[68px] h-[40px] bg-[#FFD54C] cursor-pointer flex justify-center items-center"
onClick={() => { !inputLock.locked && handleSendClick() }}
style={{borderRadius:"20px"}}
>
{/* <SendIcon className={inputLock.locked ? 'text-gray-400' : 'text-gray-950'}></SendIcon> */}
<img src={duihua_send} className="w-[20px]" alt="" />
</div>
{stop.show ?
<div
id="bs-send-btn"
className="w-[68px] h-[40px] bg-[#FFD54C] cursor-pointer flex justify-center items-center"
style={{borderRadius:"20px"}} onClick={() => {
if (stop.disable) return
setStop({ show: true, disable: true });
sendWsMsg({ "action": "stop" });
}}>
{/* <SendIcon className={`${inputLock.locked ? 'text-muted-foreground' : 'text-foreground'}`} /> */}
{/* <StopIcon className={`mt-1 rounded-sm bg-[#000000] cursor-pointer ${stop.disable && 'bg-muted-foreground text-muted-foreground'}`}
onClick={() => {
if (stop.disable) return
setStop({ show: true, disable: true });
sendWsMsg({ "action": "stop" });
}} /> */}
<div className="w-[16px] h-[16px] bg-[#000000]" style={{borderRadius:"3px"}}></div>
</div>
: <div
id="bs-send-btn"
className="w-[68px] h-[40px] bg-[#FFD54C] cursor-pointer flex justify-center items-center"
onClick={() => { !inputLock.locked && handleSendClick() }} style={{borderRadius:"20px"}}>
{/* <SendIcon className={`${inputLock.locked ? 'text-muted-foreground' : 'text-foreground'}`} /> */}
<img src={duihua_send} className="w-[20px]" alt="" />
</div>
}
</div>
{/* question */}
<textarea
@@ -303,8 +338,8 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
disabled={inputLock.locked}
onInput={handleTextAreaHeight}
placeholder={inputLock.locked ? inputLock.reason : t('chat.inputPlaceholder')}
// className={"resize-none py-4 pr-10 text-md min-h-6 max-h-[200px] scrollbar-hide dark:bg-[#2A2B2E] text-gray-800" + (form && ' pl-10')}
className="questionTextarea w-full resize-none border-none bg-transparent outline-none max-h-[160px]"
// className={"resize-none py-4 pr-10 text-md min-h-6 max-h-[200px] scrollbar-hide dark:bg-[#2A2B2E] text-gray-800" + (form && ' pl-10')}
onKeyDown={(event) => {
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
@@ -312,12 +347,7 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
}
}}
></textarea>
{!isStop && <div className=" absolute w-full flex justify-center bottom-32 pointer-events-none">
<Button className="rounded-full pointer-events-auto" variant="outline" disabled={isStop} onClick={() => { setIsStop(true); stop(); }}><StopCircle className="mr-2" />Stop</Button>
</div>}
{/* <p className="w-[100%] text-center text-[#666666]">内容由AI生成仅供参考</p> */}
</div>
<p className="text-center text-sm pt-2 pb-4 text-gray-400">{appConfig.dialogTips}</p>
</div>
};
};

View File

@@ -36,7 +36,9 @@ export default function FileBs({ data,flow_type }) {
<div className="w-fit min-h-8 rounded-2xl px-6 py-4 max-w-[90%]">
{data.sender && <p className="text-primary text-xs mb-2" style={{ background: avatarColor }}>{data.sender}</p>}
<div className="flex gap-2 ">
{data.flow_id && <TitleIconBg className="w-[40px] h-[40px]" img={data.avatar_img} id={data.avatar_color ? data.avatar_color : data.flow_id} ><img src={data.avatar_img ? data.avatar_img : (flow_type == "assistant" ? npcIcon : nengliIcon)} alt="" /></TitleIconBg>}
{/* {data.flow_id && <TitleIconBg className="w-[40px] h-[40px]" img={data.avatar_img} id={data.avatar_color ? data.avatar_color : data.flow_id} ><img src={data.avatar_img ? data.avatar_img : (flow_type == "assistant" ? npcIcon : nengliIcon)} alt="" /></TitleIconBg>} */}
{flow_type.id && <TitleIconBg className="w-[40px] h-[40px] mr-[10px]" img={flow_type.avatar_img} id={flow_type.avatar_color ? flow_type.avatar_color : flow_type.id} ><img src={flow_type.avatar_img ? flow_type.avatar_img : (flow_type.type == "assistant" ? npcIcon : nengliIcon)} alt="" /></TitleIconBg>}
{/* <div className="w-6 h-6 min-w-6 flex justify-center items-center rounded-full" style={{ background: avatarColor }} ><AvatarIcon /></div> */}
<div
className="flex gap-2 w-52 shadow-sm bg-[#1a1a1a] px-4 py-2 rounded-sm cursor-pointer"

View File

@@ -85,7 +85,6 @@ export default function MessageBs({ data, onUnlike = () => { }, flow_type, onSou
const handleCopyMessage = () => {
copyText(messageRef.current)
}
// console.log(data)
const chatId = useMessageStore(state => state.chatId)
return <div className="flex w-full py-1">
<div className="w-[100%]">
@@ -94,7 +93,7 @@ export default function MessageBs({ data, onUnlike = () => { }, flow_type, onSou
{/* {(data.flow_id == "06b1d374-ba97-46e6-8782-c56dec8dcc17" || data.flow_id == "ed8e21f6-9757-43d0-b076-8c6e81bb0580") && <img src={robot2} className="w-[50px]" alt=""/>}
{data.flow_id == "ca214b41-2b73-4585-b172-bf1e546cf6ec" && <img src={robot3} className="w-[50px]" alt=""/>}
{(data.flow_id != "06b1d374-ba97-46e6-8782-c56dec8dcc17" && data.flow_id != "ed8e21f6-9757-43d0-b076-8c6e81bb0580" && data.flow_id != "ca214b41-2b73-4585-b172-bf1e546cf6ec") && <img src={robot} className="w-[50px]" alt=""/>} */}
{data.flow_id && <TitleIconBg className="w-[40px] h-[40px] mr-[10px]" img={flow_type.avatar_img} id={flow_type.avatar_color ? flow_type.avatar_color : data.flow_id} ><img src={flow_type.avatar_img ? flow_type.avatar_img : (flow_type.type == "assistant" ? npcIcon : nengliIcon)} alt="" /></TitleIconBg>}
{flow_type && flow_type.id && <TitleIconBg className="w-[40px] h-[40px] mr-[10px]" img={flow_type.avatar_img} id={flow_type.avatar_color ? flow_type.avatar_color : flow_type.id} ><img src={flow_type.avatar_img ? flow_type.avatar_img : (flow_type.type == "assistant" ? npcIcon : nengliIcon)} alt="" /></TitleIconBg>}
<div ref={messageRef} className="text-sm max-w-[calc(100%-100px)]">
{/* <div className="chat-start-zk relative">

View File

@@ -10,7 +10,7 @@ import RunLog from "./RunLog";
import Separator from "./Separator";
import { useMessageStore } from "./messageStore";
export default function MessagePanne({ useName, guideWord, loadMore, flow_type }) {
export default function MessagePanne({logo, useName, guideWord, loadMore, flow_type }) {
const { t } = useTranslation()
const { chatId, messages } = useMessageStore()
@@ -75,7 +75,6 @@ export default function MessagePanne({ useName, guideWord, loadMore, flow_type }
} else if (msg.thought) {
type = 'system'
}
// console.log(type)
switch (type) {
case 'user':
return <MessageUser key={msg.id} useName={useName} data={msg} />;

View File

@@ -1,9 +1,22 @@
import ChatInput from "./ChatInput";
import MessagePanne from "./MessagePanne";
export default function ChatComponent({ clear = false, questions = [], form = false, useName, inputForm = null, guideWord, wsUrl, onBeforSend, type, loadMore = () => { } }) {
export default function ChatComponent({
stop = false,
logo = '',
clear = false,
questions = [],
form = false,
useName,
inputForm = null,
guideWord,
wsUrl,
onBeforSend,
type,
loadMore = () => { }
}) {
return <div className="relative h-full">
<MessagePanne useName={useName} guideWord={guideWord} loadMore={loadMore} flow_type={type}></MessagePanne>
<MessagePanne logo={logo} useName={useName} guideWord={guideWord} loadMore={loadMore} flow_type={type}></MessagePanne>
<ChatInput clear={clear} questions={questions} form={form} wsUrl={wsUrl} inputForm={inputForm} onBeforSend={onBeforSend} ></ChatInput>
</div>
};

View File

@@ -4,6 +4,7 @@ import { MessageDB, getChatHistory } from '@/controllers/API'
import { ChatMessageType } from '@/types/chat'
import { cloneDeep } from 'lodash'
import { create } from 'zustand'
import { formatDate } from '@/util/utils';
/**
* 会话消息管理
@@ -19,6 +20,8 @@ type State = {
/** 没有更多历史纪录 */
historyEnd: boolean,
messages: ChatMessageType[]
/** 历史回话独立存储 */
hisMessages: ChatMessageType[]
/**
* 控制引导问题的显示状态
*/
@@ -26,8 +29,8 @@ type State = {
}
type Actions = {
loadHistoryMsg: (flowid: string, chatId: string, flow_type: string) => Promise<void>;
loadMoreHistoryMsg: (flowid: string, flow_type: string) => Promise<void>;
loadHistoryMsg: (flowid: string, chatId: string, data: { appendHistory: boolean, lastMsg: string }, flow_type: string) => Promise<void>;
loadMoreHistoryMsg: (flowid: string, appendHistory: boolean, flow_type: string) => Promise<void>;
destory: () => void;
createSendMsg: (inputs: any, inputKey?: string) => void;
createWsMsg: (data: any) => void;
@@ -38,6 +41,7 @@ type Actions = {
insetSystemMsg: (text: string) => void;
insetBsMsg: (text: string) => void;
setShowGuideQuestion: (text: boolean) => void;
clearMsgs: () => void;
}
@@ -76,18 +80,32 @@ export const useMessageStore = create<State & Actions>((set, get) => ({
running: false,
chatId: '',
messages: [],
hisMessages: [],
historyEnd: false,
showGuideQuestion: false,
setShowGuideQuestion(bln: boolean) {
set({ showGuideQuestion: bln })
},
async loadHistoryMsg(flowid, chatId, flow_type) {
async loadHistoryMsg(flowid, chatId, { appendHistory, lastMsg }, flow_type) {
const res = await getChatHistory(flowid, chatId, 30, 0, flow_type)
const msgs = handleHistoryMsg(res)
currentChatId = chatId
set({ historyEnd: false, messages: msgs.reverse() })
const hisMessages = appendHistory ? [] : msgs.reverse()
if (hisMessages.length) {
hisMessages.push({
...bsMsgItem,
id: Math.random() * 1000000,
category: 'divider',
message: lastMsg,
})
}
set({
historyEnd: false,
messages: appendHistory ? msgs.reverse() : [],
hisMessages
})
},
async loadMoreHistoryMsg(flowid, flow_type) {
async loadMoreHistoryMsg(flowid, appendHistory, flow_type) {
if (get().running) return // 会话进行中禁止加载more历史
if (get().historyEnd) return // 没有更多历史纪录
const chatId = get().chatId
@@ -101,11 +119,16 @@ export const useMessageStore = create<State & Actions>((set, get) => ({
}
const msgs = handleHistoryMsg(res)
if (msgs.length) {
set({ messages: [...msgs.reverse(), ...prevMsgs] })
set({ [appendHistory ? 'messages' : 'hisMessages']: [...msgs.reverse(), ...prevMsgs] })
} else {
set({ historyEnd: true })
}
},
clearMsgs() {
setTimeout(() => {
set({ hisMessages: [], messages: [], historyEnd: true })
}, 0);
},
destory() {
set({ chatId: '', messages: [] })
},
@@ -122,7 +145,8 @@ export const useMessageStore = create<State & Actions>((set, get) => ({
category: '',
files: [],
end: false,
user_name: ""
user_name: "",
update_time: formatDate(new Date(), 'yyyy-MM-ddTHH:mm:ss')
}]
}))
},
@@ -151,13 +175,20 @@ export const useMessageStore = create<State & Actions>((set, get) => ({
// if (wsdata.end) {
// debugger
// }
console.log('change updateCurrentMessage');
// console.log('change updateCurrentMessage');
const messages = get().messages
const isRunLog = runLogsTypes.includes(wsdata.category);
// run log类型存在嵌套情况使用 extra 匹配 currentMessage; 否则取最近
const currentMessageIndex = isRunLog ?
messages.findLastIndex((msg) => msg.extra === wsdata.extra)
: messages.findLastIndex((msg) => !runLogsTypes.includes(msg.category))
let currentMessageIndex = 0
for (let i = messages.length - 1; i >= 0; i--) {
if (isRunLog && messages[i].extra === wsdata.extra) {
currentMessageIndex = i;
break;
} else if (!isRunLog && !runLogsTypes.includes(messages[i].category)) {
currentMessageIndex = i;
break;
}
}
const currentMessage = messages[currentMessageIndex]
const newCurrentMessage = {
@@ -166,13 +197,17 @@ export const useMessageStore = create<State & Actions>((set, get) => ({
id: isRunLog ? wsdata.extra : wsdata.messageId, // 每条消息必唯一
message: isRunLog ? JSON.parse(wsdata.message) : currentMessage.message + wsdata.message,
thought: currentMessage.thought + (wsdata.thought ? `${wsdata.thought}\n` : ''),
files: wsdata.files || null,
files: wsdata.files || [],
category: wsdata.category || '',
source: wsdata.source
}
// 无id补上如文件解析完成消息后端无返回messageid
if (!newCurrentMessage.id) {
newCurrentMessage.id = Math.random() * 1000000
// console.log('msg:', newCurrentMessage);
}
messages[currentMessageIndex] = newCurrentMessage
// console.log(messages,currentMessageIndex,newCurrentMessage)
// 会话特殊处理,兼容后端的缺陷
if (!isRunLog) {
// start - end 之间没有内容删除load

View File

@@ -0,0 +1,24 @@
import { useEffect, useRef } from "react";
export default function LoadMore({ onScrollLoad }) {
// scroll load
const footerRef = useRef<HTMLDivElement>(null)
useEffect(function () {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
onScrollLoad()
}
});
}, {
// root: null, // 视口
rootMargin: '0px', // 视口的边距
threshold: 0.1 // 目标元素超过视口的10%即触发回调
});
observer.observe(footerRef.current);
return () => footerRef.current && observer.unobserve(footerRef.current);
}, [])
return <div ref={footerRef} style={{ height: 20 }}></div>
};

View File

@@ -0,0 +1,48 @@
import MultiSelect from "@/components/bs-ui/select/multi";
import { getUsersApi } from "@/controllers/API/user";
import { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
export default function UsersSelect({ multiple = false, lockedValues = [], value, disabled = false, onChange, children }:
{ multiple?: boolean, lockedValues?: any[], value: any, disabled?: boolean, onChange: (a: any) => any, children?: (fun: any) => React.ReactNode }) {
const { t } = useTranslation()
const [options, setOptions] = useState<any>([]);
const originOptionsRef = useRef([])
const pageRef = useRef(1)
const reload = (page, name) => {
getUsersApi({ page, pageSize: 40, name }).then(res => {
pageRef.current = page
originOptionsRef.current = res.data
const opts = res.data.map(el => ({ label: el.user_name, value: el.user_id }))
setOptions(_ops => page > 1 ? [..._ops, ...opts] : opts)
})
}
useEffect(() => {
reload(1, '')
}, [])
// 加载更多
const loadMore = (name) => {
reload(pageRef.current + 1, name)
}
return <MultiSelect
className=" max-w-[630px]"
multiple={multiple}
value={value}
lockedValues={lockedValues}
disabled={disabled}
options={options}
placeholder={'请选择用户'}
searchPlaceholder={'搜索用户名称'}
onChange={onChange}
onLoad={() => reload(1, '')}
onSearch={(val) => reload(1, val)}
onScrollLoad={(val) => loadMore(val)}
>
{children?.(reload)}
</MultiSelect>
};

View File

@@ -0,0 +1,51 @@
import MultiSelect from "@/components/bs-ui/select/multi";
import { readFileLibDatabase } from "@/controllers/API";
import { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
export default function KnowledgeSelect({ multiple = false, value, disabled = false, onChange, children }:
{ multiple?: boolean, value: any, disabled?: boolean, onChange: (a: any) => any, children?: (fun: any) => React.ReactNode }) {
const { t } = useTranslation()
const [options, setOptions] = useState<any>([]);
const originOptionsRef = useRef([])
const pageRef = useRef(1)
const reload = (page, name) => {
readFileLibDatabase(page, 60, name).then(res => {
pageRef.current = page
originOptionsRef.current = res.data
const opts = res.data.map(el => ({ label: el.name, value: el.id }))
setOptions(_ops => page > 1 ? [..._ops, ...opts] : opts)
})
}
useEffect(() => {
reload(1, '')
}, [])
// const handleChange = (res) => {
// // id => obj
// onChange(res.map(el => originOptionsRef.current.find(el2 => el2.id === el)))
// }
// 加载更多
const loadMore = (name) => {
reload(pageRef.current + 1, name)
}
return <MultiSelect
multiple={multiple}
value={value}
disabled={disabled}
options={options}
placeholder={t('build.selectKnowledgeBase')}
searchPlaceholder={t('build.searchBaseName')}
onChange={onChange}
onLoad={() => reload(1, '')}
onSearch={(val) => reload(1, val)}
onScrollLoad={(val) => loadMore(val)}
>
{children?.(reload)}
</MultiSelect>
};

View File

@@ -19,6 +19,8 @@ import zidingyi1 from "../../../assets/npc/zidingyi1.png";
import zidingyi2 from "../../../assets/npc/zidingyi2.png";
import npcIcon from "../../../assets/npc/npcIcon.png";
import nengliIcon from "../../../assets/npc/nengliIcon.png";
import { useDebounce } from "@/util/hook";
import LoadMore from "../loadMore";
export default function SkillChatSheet({ children, onSelect }) {
const [open, setOpen] = useState(false)
@@ -30,34 +32,45 @@ export default function SkillChatSheet({ children, onSelect }) {
const [keyword, setKeyword] = useState(' ')
const allDataRef = useRef([])
useEffect(() => {
open && getChatOnlineApi().then(res => {
allDataRef.current = res
setKeyword('')
const pageRef = useRef(1)
const searchRef = useRef('')
const [options, setOptions] = useState<any>([])
const loadData = (more = false) => {
open && getChatOnlineApi(pageRef.current, searchRef.current).then(res => {
setOptions(opts => more ? [...opts, ...res] : res)
})
}
const debounceLoad = useDebounce(loadData, 600, false)
useEffect(() => {
// open && getChatOnlineApi().then(res => {
// allDataRef.current = res
// setKeyword('')
// })
// setKeyword(' ')
pageRef.current = 1
searchRef.current = ''
loadData()
}, [open])
const options = useMemo(() => {
return allDataRef.current.filter(el => el.name.toLowerCase().includes(keyword.toLowerCase()))
}, [keyword])
// const options = useMemo(() => {
// return allDataRef.current.filter(el => el.name.toLowerCase().includes(keyword.toLowerCase()))
// }, [keyword])
const handleSearch = (e) => {
pageRef.current = 1
searchRef.current = e.target.value
debounceLoad()
}
const handleLoadMore = () => {
pageRef.current++
loadData(true)
}
const render = (item: any) => (
<Flexbox align={'flex-start'} className={`selectNpcFlexbox relative`} onClick={() => { onSelect(item); setOpen(false) }}>
{/* <Avatar size={24} src={item.favicon} style={{ flex: 'none' }} /> */}
{/* <Flexbox>
<div style={{ fontSize: 15, fontWeight: 600 }}>{item.name}</div>
<div style={{ opacity: 0.6 }}>{item.name}</div>
</Flexbox> */}
{/* <Card key={item.id} className="w-[300px] overflow-hidden cursor-pointer" onClick={() => onSelect(item)}>
<CardHeader>
<CardTitle className=" flex items-center gap-2">
<div className={"rounded-full w-[30px] h-[30px] " + gradients[parseInt(item.id, 16) % gradients.length]}></div>
<span>{item.name}</span>
</CardTitle>
<CardDescription className="">{item.description}</CardDescription>
</CardHeader>
</Card> */}
<div className="npcInfoItemBg">
<span>
<span>
@@ -68,16 +81,11 @@ export default function SkillChatSheet({ children, onSelect }) {
</span>
</div>
<div>
{/* {(item.id == "06b1d374-ba97-46e6-8782-c56dec8dcc17" || item.id == "ed8e21f6-9757-43d0-b076-8c6e81bb0580") && <img src={robot2} className="w-[42px]" alt=""/>}
{item.id == "ca214b41-2b73-4585-b172-bf1e546cf6ec" && <img src={robot3} className="w-[42px]" alt=""/>}
{(item.id != "06b1d374-ba97-46e6-8782-c56dec8dcc17" && item.id != "ed8e21f6-9757-43d0-b076-8c6e81bb0580" && item.id != "ca214b41-2b73-4585-b172-bf1e546cf6ec") && <img src={robot} className="w-[42px]" alt=""/>} */}
{/* <img src={robot} className="w-[42px]" alt=""/> */}
<TitleIconBg className="w-[40px] h-[40px] min-w-[40px]" img={item.avatar_img} id={item.avatar_color ? item.avatar_color : item.id} ><img src={item.avatar_img ? item.avatar_img : (item.flow_type == "assistant" ? npcIcon : nengliIcon)} alt="" /></TitleIconBg>
<div>
<p>{item.name}</p>
<div>
{/* <div>绘画类</div>
<div>绘画类</div> */}
</div>
</div>
</div>
@@ -100,31 +108,12 @@ export default function SkillChatSheet({ children, onSelect }) {
<div className="w-[280px] p-6">
<SheetTitle></SheetTitle>
<SheetDescription className="text-[#999999]">使线NPC或能力</SheetDescription>
<SearchInput value={keyword} placeholder="搜索" className="my-6" onChange={(e) => setKeyword(e.target.value)} />
{/* <SearchInput value={keyword} placeholder="搜索" className="my-6" onChange={(e) => setKeyword(e.target.value)} /> */}
<SearchInput placeholder="搜索" className="my-6" onChange={handleSearch} />
</div>
<div className="w-[690px] overflow-y-auto bg-[#000000] scrollbar-hide skillSheet">
{/* {
options.length ? options.map((flow, i) => (
<CardComponent key={i}
id={i + 1}
data={flow}
title={flow.name}
description={flow.desc}
type="sheet"
icon={flow.flow_type === 'flow' ? SkillIcon : AssistantIcon}
footer={
<Badge className={`absolute right-0 bottom-0 rounded-none rounded-br-md ${flow.flow_type === 'flow' && 'bg-gray-950'}`}>
{flow.flow_type === 'flow' ? '技能' : 'NPC'}
</Badge>
}
onClick={() => { onSelect(flow); setOpen(false) }}
/>
)) : <div className="flex flex-col items-center justify-center pt-40 w-full">
<p className="text-sm text-muted-foreground mb-3">{t('build.empty')}</p>
<Button className="w-[200px]" onClick={() => navigate('/build/assist')}>{t('build.onlineSA')}</Button>
</div>
} */}
<SpotlightCard items={options} renderItem={render} className="mt-[14px] skillSheetSpotlightCard"/>
<LoadMore onScrollLoad={handleLoadMore} />
</div>
</div>
</SheetContent>

BIN
src/components/bs-icons/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -1,11 +1,11 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<g id="Group 468">
<g id="Group 466">
<rect id="Rectangle 221" x="8" y="9" width="12" height="1.71429" rx="0.857143" fill="#9CA3BA" />
<rect id="Rectangle 222" x="11.4285" y="7" width="5.14286" height="1.71429" rx="0.857143" fill="#9CA3BA" />
<rect id="Rectangle 221" x="8" y="9" width="12" height="1.71429" rx="0.857143" fill="#666" />
<rect id="Rectangle 222" x="11.4285" y="7" width="5.14286" height="1.71429" rx="0.857143" fill="#666" />
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd"
d="M9 12C9 11.4477 9.44772 11 10 11H18C18.5523 11 19 11.4477 19 12V19C19 20.1046 18.1046 21 17 21H11C9.89543 21 9 20.1046 9 19V12ZM12.7143 14C13.1877 14 13.5714 14.3838 13.5714 14.8571V17.1429C13.5714 17.6162 13.1877 18 12.7143 18C12.2409 18 11.8572 17.6162 11.8572 17.1429V14.8571C11.8572 14.3838 12.2409 14 12.7143 14ZM16.1429 14.8571C16.1429 14.3838 15.7591 14 15.2857 14C14.8123 14 14.4286 14.3838 14.4286 14.8571V17.1429C14.4286 17.6162 14.8123 18 15.2857 18C15.7591 18 16.1429 17.6162 16.1429 17.1429V14.8571Z"
fill="#9CA3BA" />
fill="#666" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -5,5 +5,5 @@ export const DelIcon = forwardRef<
SVGSVGElement & { className: any },
React.PropsWithChildren<{ className?: string }>
>((props, ref) => {
return <Del ref={ref} {...props} />;
return <Del className="text-[red]" ref={ref} {...props} />;
});

View File

@@ -0,0 +1,7 @@
<svg t="1718350872747" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2516"
width="20" height="20">
<path
d="M511.36 712.32L240.853333 441.813333l30.293334-30.293333 241.493333 241.493333 262.186667-241.92 29.013333 31.146667-292.48 270.08z"
p-id="2517">
</path>
</svg>

After

Width:  |  Height:  |  Size: 342 B

View File

@@ -0,0 +1,9 @@
import React, { forwardRef } from "react";
import { ReactComponent as DropDown } from "./DropDown.svg";
export const DropDownIcon = forwardRef<
SVGSVGElement & { className: any },
React.PropsWithChildren<{ className?: string }>
>((props, ref) => {
return <DropDown ref={ref} {...props} />;
});

View File

@@ -1,3 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.61375 12.536H9.09375V15H2.05375V3.8H9.01375V6.264H4.61375V8.12H8.61375V10.552H4.61375V12.536ZM15.1461 6.776C16.7621 6.776 18.1381 7.928 18.1381 10.088V15H15.7381V10.44C15.7381 9.448 15.1141 8.984 14.3461 8.984C13.4661 8.984 12.8581 9.496 12.8581 10.632V15H10.4581V7H12.8581V7.752C13.2901 7.16 14.0901 6.776 15.1461 6.776Z" fill="black"/>
<path d="M4.61375 12.536H9.09375V15H2.05375V3.8H9.01375V6.264H4.61375V8.12H8.61375V10.552H4.61375V12.536ZM15.1461 6.776C16.7621 6.776 18.1381 7.928 18.1381 10.088V15H15.7381V10.44C15.7381 9.448 15.1141 8.984 14.3461 8.984C13.4661 8.984 12.8581 9.496 12.8581 10.632V15H10.4581V7H12.8581V7.752C13.2901 7.16 14.0901 6.776 15.1461 6.776Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 453 B

After

Width:  |  Height:  |  Size: 460 B

View File

@@ -0,0 +1,6 @@
<svg t="1716545040041" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="2664" width="18" height="18">
<path d="M349 838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V642H349v196z m531.1-684H143.9c-24.5 0-39.8 26.7-27.5 48l221.3 376h348.8l221.3-376c12.1-21.3-3.2-48-27.7-48z"
p-id="2665" fill="currentColor">
</path>
</svg>

After

Width:  |  Height:  |  Size: 375 B

View File

@@ -0,0 +1,9 @@
import React, { forwardRef } from "react";
import { ReactComponent as Filter } from "./Filter.svg";
export const FilterIcon = forwardRef<
SVGSVGElement & { className: any },
React.PropsWithChildren<{ className?: string }>
>((props, ref) => {
return <Filter ref={ref} {...props} />;
});

View File

@@ -0,0 +1,40 @@
export { AddToIcon } from './addTo';
export { ApplicationIcon } from './menu/application';
export { AssistantIcon } from './assistant';
export { AvatarIcon } from './avatar';
export { BookOpenIcon } from './bookOpen';
export { ClearIcon } from './clear';
export { DelIcon } from './del';
export { EnIcon } from './en';
export { FilterIcon } from './filter';
export { FormIcon } from './form';
export { GithubIcon } from './github';
export { GoIcon } from './go';
export { KnowledgeIcon } from './knowledge';
export { LoadIcon } from './loading';
export { ModelIcon } from './menu/model';
export { MoonIcon } from './moon';
export { MoveOneIcon } from './moveOne';
export { NewApplicationIcon } from './newApplication';
export { WordIcon } from './office';
export { PlusIcon } from './plus';
export { PlusBoxIcon } from './plusBox';
export { QuestionMarkIcon } from './questionMark';
export { QuitIcon } from './quit';
export { SaveIcon } from './save';
export { SearchIcon } from './search';
export { SendIcon } from './send';
export { SettingIcon } from './setting';
export { SkillIcon } from './skill';
export { SystemIcon } from './menu/system';
export { TabIcon } from './tab';
export { TechnologyIcon } from './menu/technology';
export { ThunmbIcon } from './thumbs';
export { TipIcon } from './tip';
export { ToastIcon } from './toast';
export { ToolIcon } from './tool';
export { UploadIcon } from './upload';
export { UserIcon } from './user';
export { LogIcon } from './menu/log';
export { EvaluatingIcon } from './menu/evaluation';
export { DropDownIcon } from './down'

View File

Before

Width:  |  Height:  |  Size: 821 B

After

Width:  |  Height:  |  Size: 821 B

View File

@@ -0,0 +1,6 @@
<svg t="1719471279077" class="icon" viewBox="-160 -160 1344 1344" version="1.1" xmlns="http://www.w3.org/2000/svg" width="24"
height="24">
<path
d="M887.994182 46.545455H146.245818C95.976727 46.545455 46.545455 88.110545 46.545455 138.612364V512h183.761454L298.821818 446.370909c7.68-7.68 18.618182-9.448727 29.230546-7.447273a33.512727 33.512727 0 0 1 23.738181 20.014546l83.409455 196.096 129.117091-389.259637a33.186909 33.186909 0 0 1 30.72-22.202181c15.266909 0.325818 27.508364 6.656 31.464727 20.573091L697.809455 512h92.625454a31.650909 31.650909 0 1 1 0 63.488h-117.201454c-14.522182 0-27.275636-5.585455-31.278546-19.549091l-49.198545-171.054545-118.784 371.712c-4.282182 12.8-25.460364 22.248727-25.460364 22.807272v0.279273c-21.131636 0-30.068364-7.586909-35.281455-19.549091l-100.258909-230.4-45.102545 40.308364c-6.050909 6.097455-15.406545 5.445818-24.064 5.445818H46.545455v309.248C46.545455 935.284364 96.023273 977.454545 146.245818 977.454545h741.748364c50.269091 0 89.460364-42.170182 89.460363-92.718545V138.612364C977.454545 88.110545 938.216727 46.545455 887.994182 46.545455z"
fill="currentColor"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,9 @@
import React, { forwardRef } from "react";
import { ReactComponent as Icon } from "./Evaluation.svg";
export const EvaluatingIcon = forwardRef<
SVGSVGElement & { className: any },
React.PropsWithChildren<{ className?: string }>
>(({ className, ...props }, ref) => {
return <Icon ref={ref} {...props} className={className || ''} />;
});

View File

@@ -0,0 +1,6 @@
<svg t="1717680812187" class="icon" viewBox="-100 -100 1224 1224" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7890"
width="24" height="24">
<path
d="M511.999269 0c4.608 0 9.289143 1.755429 13.165714 5.046857 42.422857 36.644571 185.051429 144.237714 405.650286 150.454857 11.117714 0.438857 20.187429 9.508571 20.041142 21.065143V605.622857C950.856411 797.622857 668.232411 1024 511.999269 1024c-160.621714 0-438.857143-226.377143-438.857143-418.377143V176.347429c0-11.483429 9.069714-20.626286 20.187428-20.918858C314.001554 149.284571 456.703269 41.691429 498.833554 4.900571A20.626286 20.626286 0 0 1 511.999269 0z m-24.356572 283.209143l-130.194286 270.336h204.214858L487.496411 712.704l75.044572 34.962286 129.024-277.065143H489.324983l72.996571-151.552-74.678857-35.84z"
fill="currentColor"></path>
</svg>

After

Width:  |  Height:  |  Size: 846 B

View File

@@ -0,0 +1,9 @@
import React, { forwardRef } from "react";
import { ReactComponent as Log } from "./Log.svg";
export const LogIcon = forwardRef<
SVGSVGElement & { className: any },
React.PropsWithChildren<{ className?: string }>
>(({ className, ...props }, ref) => {
return <Log ref={ref} {...props} className={className || ''} />;
});

View File

Before

Width:  |  Height:  |  Size: 750 B

After

Width:  |  Height:  |  Size: 750 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 562 B

After

Width:  |  Height:  |  Size: 562 B

View File

@@ -5,6 +5,6 @@ export const WordIcon = forwardRef<
SVGSVGElement & { className: any },
React.PropsWithChildren<{ className?: string }>
>(({ className, ...props }, ref) => {
const _className = 'transition text-[#43AFD2] ' + (className || '')
const _className = 'transition text-gray-950 ' + (className || '')
return <Word ref={ref} {...props} className={_className} />;
});

View File

@@ -1,10 +1,13 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 541">
<path id="Rectangle 247" d="M0 4C0 3.44772 0.447715 3 1 3H18C21.3137 3 24 5.68629 24 9V15C24 18.3137 21.3137 21 18 21H6C2.68629 21 0 18.3137 0 15V4Z" fill="#111111"/>
<g id="Group 540">
<g id="Group 414">
<path id="Union" fill-rule="evenodd" clip-rule="evenodd" d="M13 11V8H11L11 11H8V13H11L11 16H13V13H16V11H13Z" fill="white"/>
</g>
</g>
</g>
</svg>
<g id="Group 541">
<path id="Rectangle 247"
d="M0 4C0 3.44772 0.447715 3 1 3H18C21.3137 3 24 5.68629 24 9V15C24 18.3137 21.3137 21 18 21H6C2.68629 21 0 18.3137 0 15V4Z"
fill="#111111" />
<g id="Group 540">
<g id="Group 414">
<path id="Union" fill-rule="evenodd" clip-rule="evenodd"
d="M13 11V8H11L11 11H8V13H11L11 16H13V13H16V11H13Z" fill="white" />
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 466 B

After

Width:  |  Height:  |  Size: 583 B

View File

@@ -5,6 +5,6 @@ export const QuestionMarkIcon = forwardRef<
SVGSVGElement & { className: any },
React.PropsWithChildren<{ className?: string }>
>(({ className, ...props }, ref) => {
const _className = 'transition text-gray-950 ' + (className || '')
const _className = 'transition text-[#999] ' + (className || '')
return <QuestionMark ref={ref} {...props} className={_className} />;
});

View File

@@ -1,8 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 542">
<g id="Group 417">
<path id="Rectangle 186" d="M10 5H7.2C6.0799 5 5.51984 5 5.09202 5.21799C4.71569 5.40973 4.40973 5.71569 4.21799 6.09202C4 6.51984 4 7.07989 4 8.2V15.8C4 16.9201 4 17.4802 4.21799 17.908C4.40973 18.2843 4.71569 18.5903 5.09202 18.782C5.51984 19 6.07989 19 7.2 19H10" stroke="white" stroke-width="2"/>
<path id="Vector 1" d="M10 12H17.5M15 8L19 12L15 16" stroke="white" stroke-width="2" stroke-linejoin="round"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 563 B

View File

@@ -1,8 +1,11 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 542">
<g id="Group 417">
<path id="Rectangle 186" d="M10 5H7.2C6.0799 5 5.51984 5 5.09202 5.21799C4.71569 5.40973 4.40973 5.71569 4.21799 6.09202C4 6.51984 4 7.07989 4 8.2V15.8C4 16.9201 4 17.4802 4.21799 17.908C4.40973 18.2843 4.71569 18.5903 5.09202 18.782C5.51984 19 6.07989 19 7.2 19H10" stroke="black" stroke-width="2"/>
<path id="Vector 1" d="M10 12H17.5M15 8L19 12L15 16" stroke="black" stroke-width="2" stroke-linejoin="round"/>
</g>
</g>
</svg>
<g id="Group 542">
<g id="Group 417">
<path id="Rectangle 186"
d="M10 5H7.2C6.0799 5 5.51984 5 5.09202 5.21799C4.71569 5.40973 4.40973 5.71569 4.21799 6.09202C4 6.51984 4 7.07989 4 8.2V15.8C4 16.9201 4 17.4802 4.21799 17.908C4.40973 18.2843 4.71569 18.5903 5.09202 18.782C5.51984 19 6.07989 19 7.2 19H10"
stroke="currentColor" stroke-width="2" />
<path id="Vector 1" d="M10 12H17.5M15 8L19 12L15 16" stroke="currentColor" stroke-width="2"
stroke-linejoin="round" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 674 B

View File

@@ -1,17 +1,9 @@
import React, { forwardRef } from "react";
import { ReactComponent as Quit } from "./Quit.svg";
import { ReactComponent as QuitDark } from "./Quit-dark.svg";
export const QuitIcon = forwardRef<
SVGSVGElement & { className: any },
React.PropsWithChildren<{ className?: string }>
>(({className,...props}, ref) => {
return <Quit ref={ref} {...props} className={className || ''}/>;
});
export const QuitIconDark = forwardRef<
SVGSVGElement & { className: any },
React.PropsWithChildren<{ className?: string }>
>(({className,...props}, ref) => {
return <QuitDark ref={ref} {...props} className={className || ''}/>;
>(({ className, ...props }, ref) => {
return <Quit ref={ref} {...props} className={className || ''} />;
});

View File

@@ -1,8 +1,8 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 459">
<g id="Group 458">
<circle id="Ellipse 10" cx="9" cy="9" r="6" stroke="black" stroke-width="2" />
<path id="Vector 4" d="M13 13L17 17" stroke="black" stroke-width="2" stroke-linejoin="round" />
<circle id="Ellipse 10" cx="9" cy="9" r="6" stroke="currentColor" stroke-width="2" />
<path id="Vector 4" d="M13 13L17 17" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 373 B

After

Width:  |  Height:  |  Size: 387 B

View File

@@ -1,8 +1,8 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 488">
<rect id="Rectangle 231" x="5.75" y="5.75" width="12.5" height="13.5" rx="2.25" fill="white"
<rect id="Rectangle 231" x="5.75" y="5.75" width="12.5" height="13.5" rx="2.25" fill="transparent"
stroke="currentColor" stroke-width="1.5" />
<rect id="Rectangle 232" x="8.75" y="4.75" width="6.5" height="3.5" rx="1.25" fill="transparent"
stroke="currentColor" stroke-width="1.5" />
<rect id="Rectangle 232" x="8.75" y="4.75" width="6.5" height="3.5" rx="1.25" fill="white" stroke="currentColor"
stroke-width="1.5" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 446 B

After

Width:  |  Height:  |  Size: 458 B

View File

@@ -1,6 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 488">
<rect id="Rectangle 231" x="5.75" y="5.75" width="12.5" height="13.5" rx="2.25" fill="#1B1B1B" stroke="#898C97" stroke-width="1.5"/>
<rect id="Rectangle 232" x="8.75" y="4.75" width="6.5" height="3.5" rx="1.25" fill="#1B1B1B" stroke="#898C97" stroke-width="1.5"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 391 B

View File

@@ -1,11 +1,8 @@
import React, { forwardRef } from "react";
import { ReactComponent as copy } from "./copy.svg";
import { ReactComponent as copyDark } from "./copyDark.svg";
import { ReactComponent as like } from "./like.svg";
import { ReactComponent as likeDark } from "./likeDark.svg";
import { ReactComponent as unLike } from "./unLike.svg";
import { ReactComponent as unLikeDark } from "./unLikeDark.svg";
import { cname } from "@/components/bs-ui/utils";
type ThunmbIconType = 'copy' | 'like' | 'unLike' | 'copyDark' | 'likeDark' | 'unLikeDark';
@@ -15,13 +12,10 @@ export const ThunmbIcon = forwardRef<
>((props, ref) => {
const comps = {
'copy': copy,
'copyDark': copyDark,
'like': like,
'likeDark': likeDark,
'unLike': unLike,
'unLikeDark': unLikeDark,
}
const Comp = comps[props.type];
const _className = 'transition text-gray-400 ' + (props.className || '')
const _className = cname('transition text-gray-400 hover:text-gray-500', props.className)
return <Comp ref={ref} {...props} className={_className} />;
});

View File

@@ -1,15 +1,15 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 489">
<rect id="Rectangle 231" x="4.75" y="9.75" width="3.5" height="8.5" rx="1.75" fill="white" stroke="currentColor"
stroke-width="1.5" />
<rect id="Rectangle 231" x="4.75" y="9.75" width="3.5" height="8.5" rx="1.75" fill="transparent"
stroke="currentColor" stroke-width="1.5" />
<g id="Union">
<mask id="path-2-inside-1_399_44" fill="white">
<mask id="path-2-inside-1_399_44" fill="#fff">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M13.2231 4C12.1561 4 11.1694 4.56673 10.6318 5.48839L8.89567 8.46456C8.05682 8.99647 7.5 9.93321 7.5 11V16C7.5 17.6569 8.84315 19 10.5 19H14.6983C16.3803 19 17.8826 17.9477 18.4575 16.367L20.2802 11.3544C20.8731 9.7239 19.6657 8 17.9307 8H14.5V5C14.5 4.44772 14.0523 4 13.5 4H13.2231Z" />
</mask>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M13.2231 4C12.1561 4 11.1694 4.56673 10.6318 5.48839L8.89567 8.46456C8.05682 8.99647 7.5 9.93321 7.5 11V16C7.5 17.6569 8.84315 19 10.5 19H14.6983C16.3803 19 17.8826 17.9477 18.4575 16.367L20.2802 11.3544C20.8731 9.7239 19.6657 8 17.9307 8H14.5V5C14.5 4.44772 14.0523 4 13.5 4H13.2231Z"
fill="white" />
fill="transparent" />
<path
d="M10.6318 5.48839L9.33611 4.73258V4.73258L10.6318 5.48839ZM8.89567 8.46456L9.69893 9.73136L10.0073 9.5358L10.1913 9.22037L8.89567 8.46456ZM18.4575 16.367L19.8672 16.8796V16.8796L18.4575 16.367ZM20.2802 11.3544L21.6899 11.867L20.2802 11.3544ZM14.5 8H13V9.5H14.5V8ZM11.9274 6.24419C12.1963 5.78337 12.6896 5.5 13.2231 5.5V2.5C11.6226 2.5 10.1426 3.3501 9.33611 4.73258L11.9274 6.24419ZM10.1913 9.22037L11.9274 6.24419L9.33611 4.73258L7.6 7.70876L10.1913 9.22037ZM9 11C9 10.4682 9.27563 9.99977 9.69893 9.73136L8.09241 7.19777C6.83801 7.99317 6 9.3982 6 11H9ZM9 16V11H6V16H9ZM10.5 17.5C9.67157 17.5 9 16.8284 9 16H6C6 18.4853 8.01472 20.5 10.5 20.5V17.5ZM14.6983 17.5H10.5V20.5H14.6983V17.5ZM17.0478 15.8544C16.6885 16.8423 15.7496 17.5 14.6983 17.5V20.5C17.0111 20.5 19.0768 19.0531 19.8672 16.8796L17.0478 15.8544ZM18.8705 10.8417L17.0478 15.8544L19.8672 16.8796L21.6899 11.867L18.8705 10.8417ZM17.9307 9.5C18.6247 9.5 19.1077 10.1896 18.8705 10.8417L21.6899 11.867C22.6386 9.25824 20.7066 6.5 17.9307 6.5V9.5ZM14.5 9.5H17.9307V6.5H14.5V9.5ZM13 5V8H16V5H13ZM13.5 5.5C13.2239 5.5 13 5.27614 13 5H16C16 3.61929 14.8807 2.5 13.5 2.5V5.5ZM13.2231 5.5H13.5V2.5H13.2231V5.5Z"
fill="currentColor" mask="url(#path-2-inside-1_399_44)" />

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -1,12 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 489">
<rect id="Rectangle 231" x="4.75" y="9.75" width="3.5" height="8.5" rx="1.75" fill="#1B1B1B" stroke="#898C97" stroke-width="1.5"/>
<g id="Union">
<mask id="path-2-inside-1_387_497" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.2231 4C12.1561 4 11.1694 4.56673 10.6318 5.48839L8.89567 8.46456C8.05682 8.99647 7.5 9.93321 7.5 11V16C7.5 17.6569 8.84315 19 10.5 19H14.6983C16.3803 19 17.8826 17.9477 18.4575 16.367L20.2802 11.3544C20.8731 9.7239 19.6657 8 17.9307 8H14.5V5C14.5 4.44772 14.0523 4 13.5 4H13.2231Z"/>
</mask>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.2231 4C12.1561 4 11.1694 4.56673 10.6318 5.48839L8.89567 8.46456C8.05682 8.99647 7.5 9.93321 7.5 11V16C7.5 17.6569 8.84315 19 10.5 19H14.6983C16.3803 19 17.8826 17.9477 18.4575 16.367L20.2802 11.3544C20.8731 9.7239 19.6657 8 17.9307 8H14.5V5C14.5 4.44772 14.0523 4 13.5 4H13.2231Z" fill="#1B1B1B"/>
<path d="M10.6318 5.48839L9.33611 4.73258V4.73258L10.6318 5.48839ZM8.89567 8.46456L9.69893 9.73136L10.0073 9.5358L10.1913 9.22037L8.89567 8.46456ZM18.4575 16.367L19.8672 16.8796V16.8796L18.4575 16.367ZM20.2802 11.3544L21.6899 11.867L20.2802 11.3544ZM14.5 8H13V9.5H14.5V8ZM11.9274 6.24419C12.1963 5.78337 12.6896 5.5 13.2231 5.5V2.5C11.6226 2.5 10.1426 3.3501 9.33611 4.73258L11.9274 6.24419ZM10.1913 9.22037L11.9274 6.24419L9.33611 4.73258L7.6 7.70876L10.1913 9.22037ZM9 11C9 10.4682 9.27563 9.99977 9.69893 9.73136L8.09241 7.19777C6.83801 7.99317 6 9.3982 6 11H9ZM9 16V11H6V16H9ZM10.5 17.5C9.67157 17.5 9 16.8284 9 16H6C6 18.4853 8.01472 20.5 10.5 20.5V17.5ZM14.6983 17.5H10.5V20.5H14.6983V17.5ZM17.0478 15.8544C16.6885 16.8423 15.7496 17.5 14.6983 17.5V20.5C17.0111 20.5 19.0768 19.0531 19.8672 16.8796L17.0478 15.8544ZM18.8705 10.8417L17.0478 15.8544L19.8672 16.8796L21.6899 11.867L18.8705 10.8417ZM17.9307 9.5C18.6247 9.5 19.1077 10.1896 18.8705 10.8417L21.6899 11.867C22.6386 9.25824 20.7066 6.5 17.9307 6.5V9.5ZM14.5 9.5H17.9307V6.5H14.5V9.5ZM13 5V8H16V5H13ZM13.5 5.5C13.2239 5.5 13 5.27614 13 5H16C16 3.61929 14.8807 2.5 13.5 2.5V5.5ZM13.2231 5.5H13.5V2.5H13.2231V5.5Z" fill="#898C97" mask="url(#path-2-inside-1_387_497)"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -2,15 +2,15 @@
<g id="Group 490">
<g id="Group 491">
<rect id="Rectangle 231" x="19.25" y="14.25" width="3.5" height="8.5" rx="1.75"
transform="rotate(-180 19.25 14.25)" fill="white" stroke="currentColor" stroke-width="1.5" />
transform="rotate(-180 19.25 14.25)" fill="transparent" stroke="currentColor" stroke-width="1.5" />
<g id="Union">
<mask id="path-2-inside-1_399_50" fill="white">
<mask id="path-2-inside-1_399_50" fill="#fff">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M10.0061 20C10.9504 20 11.8395 19.5554 12.4061 18.8L14.6872 15.7586C15.7568 15.3 16.5061 14.2375 16.5061 13L16.5061 8C16.5061 6.34315 15.163 5 13.5061 5L9.30781 5C7.62579 5 6.12346 6.05227 5.54864 7.63302L3.72587 12.6456C3.13298 14.2761 4.34044 16 6.07535 16L9.17277 16L8.70017 18.8356C8.59858 19.4451 9.06862 20 9.68656 20L10.0061 20Z" />
</mask>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M10.0061 20C10.9504 20 11.8395 19.5554 12.4061 18.8L14.6872 15.7586C15.7568 15.3 16.5061 14.2375 16.5061 13L16.5061 8C16.5061 6.34315 15.163 5 13.5061 5L9.30781 5C7.62579 5 6.12346 6.05227 5.54864 7.63302L3.72587 12.6456C3.13298 14.2761 4.34044 16 6.07535 16L9.17277 16L8.70017 18.8356C8.59858 19.4451 9.06862 20 9.68656 20L10.0061 20Z"
fill="white" />
fill="transparent" />
<path
d="M12.4061 18.8L13.6061 19.7L13.6061 19.7L12.4061 18.8ZM14.6872 15.7586L14.0961 14.3799L13.7277 14.5379L13.4872 14.8586L14.6872 15.7586ZM5.54864 7.63302L4.13895 7.12041L4.13895 7.12041L5.54864 7.63302ZM3.72587 12.6456L2.31618 12.133L3.72587 12.6456ZM9.17277 16L10.6524 16.2466L10.9435 14.5L9.17277 14.5L9.17277 16ZM8.70017 18.8356L10.1798 19.0822L10.1798 19.0822L8.70017 18.8356ZM11.2061 17.9C10.9228 18.2777 10.4782 18.5 10.0061 18.5L10.0061 21.5C11.4225 21.5 12.7563 20.8331 13.6061 19.7L11.2061 17.9ZM13.4872 14.8586L11.2061 17.9L13.6061 19.7L15.8872 16.6586L13.4872 14.8586ZM15.0061 13C15.0061 13.6164 14.634 14.1493 14.0961 14.3799L15.2782 17.1372C16.8796 16.4507 18.0061 14.8586 18.0061 13L15.0061 13ZM15.0061 8L15.0061 13L18.0061 13L18.0061 8L15.0061 8ZM13.5061 6.5C14.3345 6.5 15.0061 7.17157 15.0061 8L18.0061 8C18.0061 5.51472 15.9914 3.5 13.5061 3.5L13.5061 6.5ZM9.30781 6.5L13.5061 6.5L13.5061 3.5L9.30781 3.5L9.30781 6.5ZM6.95833 8.14564C7.31759 7.15767 8.25655 6.5 9.30781 6.5L9.30781 3.5C6.99503 3.5 4.92933 4.94687 4.13895 7.12041L6.95833 8.14564ZM5.13556 13.1583L6.95833 8.14564L4.13895 7.12041L2.31618 12.133L5.13556 13.1583ZM6.07535 14.5C5.38139 14.5 4.8984 13.8104 5.13556 13.1583L2.31618 12.133C1.36755 14.7418 3.29949 17.5 6.07535 17.5L6.07535 14.5ZM9.17277 14.5L6.07535 14.5L6.07535 17.5L9.17277 17.5L9.17277 14.5ZM10.1798 19.0822L10.6524 16.2466L7.69318 15.7534L7.22058 18.589L10.1798 19.0822ZM9.68656 18.5C9.99553 18.5 10.2306 18.7774 10.1798 19.0822L7.22058 18.589C6.96661 20.1128 8.14171 21.5 9.68656 21.5L9.68656 18.5ZM10.0061 18.5L9.68656 18.5L9.68656 21.5L10.0061 21.5L10.0061 18.5Z"
fill="currentColor" mask="url(#path-2-inside-1_399_50)" />

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,14 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 490">
<g id="Group 491">
<rect id="Rectangle 231" x="19.25" y="14.25" width="3.5" height="8.5" rx="1.75" transform="rotate(-180 19.25 14.25)" fill="#1B1B1B" stroke="#898C97" stroke-width="1.5"/>
<g id="Union">
<mask id="path-2-inside-1_387_503" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.0061 20C10.9504 20 11.8395 19.5554 12.4061 18.8L14.6872 15.7586C15.7568 15.3 16.5061 14.2375 16.5061 13L16.5061 8C16.5061 6.34315 15.163 5 13.5061 5L9.30781 5C7.62579 5 6.12346 6.05227 5.54864 7.63302L3.72587 12.6456C3.13298 14.2761 4.34044 16 6.07535 16L9.17277 16L8.70017 18.8356C8.59858 19.4451 9.06862 20 9.68656 20L10.0061 20Z"/>
</mask>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.0061 20C10.9504 20 11.8395 19.5554 12.4061 18.8L14.6872 15.7586C15.7568 15.3 16.5061 14.2375 16.5061 13L16.5061 8C16.5061 6.34315 15.163 5 13.5061 5L9.30781 5C7.62579 5 6.12346 6.05227 5.54864 7.63302L3.72587 12.6456C3.13298 14.2761 4.34044 16 6.07535 16L9.17277 16L8.70017 18.8356C8.59858 19.4451 9.06862 20 9.68656 20L10.0061 20Z" fill="#1B1B1B"/>
<path d="M12.4061 18.8L13.6061 19.7L13.6061 19.7L12.4061 18.8ZM14.6872 15.7586L14.0961 14.3799L13.7277 14.5379L13.4872 14.8586L14.6872 15.7586ZM5.54864 7.63302L4.13895 7.12041L4.13895 7.12041L5.54864 7.63302ZM3.72587 12.6456L2.31618 12.133L3.72587 12.6456ZM9.17277 16L10.6524 16.2466L10.9435 14.5L9.17277 14.5L9.17277 16ZM8.70017 18.8356L10.1798 19.0822L10.1798 19.0822L8.70017 18.8356ZM11.2061 17.9C10.9228 18.2777 10.4782 18.5 10.0061 18.5L10.0061 21.5C11.4225 21.5 12.7563 20.8331 13.6061 19.7L11.2061 17.9ZM13.4872 14.8586L11.2061 17.9L13.6061 19.7L15.8872 16.6586L13.4872 14.8586ZM15.0061 13C15.0061 13.6164 14.634 14.1493 14.0961 14.3799L15.2782 17.1372C16.8796 16.4507 18.0061 14.8586 18.0061 13L15.0061 13ZM15.0061 8L15.0061 13L18.0061 13L18.0061 8L15.0061 8ZM13.5061 6.5C14.3345 6.5 15.0061 7.17157 15.0061 8L18.0061 8C18.0061 5.51472 15.9914 3.5 13.5061 3.5L13.5061 6.5ZM9.30781 6.5L13.5061 6.5L13.5061 3.5L9.30781 3.5L9.30781 6.5ZM6.95833 8.14564C7.31759 7.15767 8.25655 6.5 9.30781 6.5L9.30781 3.5C6.99503 3.5 4.92933 4.94687 4.13895 7.12041L6.95833 8.14564ZM5.13556 13.1583L6.95833 8.14564L4.13895 7.12041L2.31618 12.133L5.13556 13.1583ZM6.07535 14.5C5.38139 14.5 4.8984 13.8104 5.13556 13.1583L2.31618 12.133C1.36755 14.7418 3.29949 17.5 6.07535 17.5L6.07535 14.5ZM9.17277 14.5L6.07535 14.5L6.07535 17.5L9.17277 17.5L9.17277 14.5ZM10.1798 19.0822L10.6524 16.2466L7.69318 15.7534L7.22058 18.589L10.1798 19.0822ZM9.68656 18.5C9.99553 18.5 10.2306 18.7774 10.1798 19.0822L7.22058 18.589C6.96661 20.1128 8.14171 21.5 9.68656 21.5L9.68656 18.5ZM10.0061 18.5L9.68656 18.5L9.68656 21.5L10.0061 21.5L10.0061 18.5Z" fill="#898C97" mask="url(#path-2-inside-1_387_503)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -5,6 +5,6 @@ export const UploadIcon = forwardRef<
SVGSVGElement & { className: any },
React.PropsWithChildren<{ className?: string }>
>(({ className, ...props }, ref) => {
const _className = 'transition text-gray-950 ' + (className || '')
const _className = 'transition text-[#ffd025] ' + (className || '')
return <Upload ref={ref} {...props} className={_className} />;
});

Binary file not shown.

View File

@@ -0,0 +1,58 @@
"use client"
import * as React from "react"
import { CalendarIcon } from "@radix-ui/react-icons"
import { Button } from "../button"
import { Calendar } from "../calendar"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { cname } from "../utils"
import { useMemo } from "react"
import { formatDate } from "@/util/utils"
export function DatePicker({
value,
placeholder = '',
onChange
}) {
const [date, setDate] = React.useState<Date>(value)
const dateStr = useMemo(() => {
return date ? formatDate(date, 'yyyy-MM-dd') : ''
}, [date])
React.useEffect(() => {
setDate(value)
},[value])
return (
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cname(
"w-full justify-start text-left font-normal bg-[#1a1a1a]",
!date && "text-muted-foreground border-[#666] text-[#999]"
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{dateStr || <span>{placeholder}</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={date}
onSelect={(d) => {
setDate(d)
onChange?.(d)
}}
initialFocus
/>
</PopoverContent>
</Popover>
)
}

View File

@@ -0,0 +1,72 @@
"use client"
import * as React from "react"
import { ChevronLeftIcon, ChevronRightIcon } from "@radix-ui/react-icons"
import { DayPicker } from "react-day-picker"
import { buttonVariants } from "@/components/bs-ui/button"
import { cname } from "../utils"
export type CalendarProps = React.ComponentProps<typeof DayPicker>
function Calendar({
className,
classNames,
showOutsideDays = true,
...props
}: CalendarProps) {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cname("p-3", className)}
classNames={{
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
month: "space-y-4",
caption: "flex justify-center pt-1 relative items-center",
caption_label: "text-sm font-medium",
nav: "space-x-1 flex items-center",
nav_button: cname(
buttonVariants({ variant: "outline" }),
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
),
nav_button_previous: "absolute left-1",
nav_button_next: "absolute right-1",
table: "w-full border-collapse space-y-1",
head_row: "flex",
head_cell:
"text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
row: "flex w-full mt-2",
cell: cname(
"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected].day-range-end)]:rounded-r-md",
props.mode === "range"
? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md"
: "[&:has([aria-selected])]:rounded-md"
),
day: cname(
buttonVariants({ variant: "ghost" }),
"h-8 w-8 p-0 font-normal aria-selected:opacity-100"
),
day_range_start: "day-range-start",
day_range_end: "day-range-end",
day_selected:
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
day_today: "bg-accent text-accent-foreground",
day_outside:
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
day_disabled: "text-muted-foreground opacity-50",
day_range_middle:
"aria-selected:bg-accent aria-selected:text-accent-foreground",
day_hidden: "invisible",
...classNames,
}}
components={{
IconLeft: ({ ...props }) => <ChevronLeftIcon className="h-4 w-4" />,
IconRight: ({ ...props }) => <ChevronRightIcon className="h-4 w-4" />,
}}
{...props}
/>
)
}
Calendar.displayName = "Calendar"
export { Calendar }

View File

@@ -42,7 +42,7 @@ const DialogContent = React.forwardRef<
{...props}
>
{children}
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground text-[#fff]">
<Cross2Icon className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>

View File

@@ -0,0 +1,46 @@
import { Button } from "../button";
import { useToast } from "../toast/use-toast";
import { cname } from "../utils";
// 头像
export default function Avator({
size = 5 * 1024 * 1024,
accept = "image/jpeg,image/png",
value,
className,
buttonName = '上传头像',
onChange,
children
}) {
const { message } = useToast();
const handleFileChange = (event) => {
const file = event.target.files[0];
if (file) {
const isValidSize = file.size <= size;
const isValidType = accept.split(',').some(type => file.type === type);
const errormgs = []
if (!isValidSize) errormgs.push(`文件大小不能超过 ${size / 1024 / 1024}MB`)
if (!isValidType) errormgs.push(`文件类型不符合要求:${accept}`)
errormgs.length ? message({
variant: 'error',
description: errormgs
}) : onChange(file)
}
};
return <div className={cname("flex w-full rounded-md gap-4", className)}>
{value ? <img src={value} className="max-w-24 max-h-24 rounded-md object-cover" alt="" /> : children}
<Button variant="outline" className="relative">
{buttonName}
<input
className=" absolute top-0 left-0 inset-0 w-full h-full opacity-0 cursor-pointer"
type="file"
accept={accept}
onChange={handleFileChange}
/>
</Button>
</div>
};

View File

@@ -3,6 +3,9 @@ import { cname } from "../utils"
import { SearchIcon } from "../../bs-icons/search"
import { generateUUID } from "../utils"
import { MinusCircledIcon } from "@radix-ui/react-icons"
import { EyeOpenIcon, EyeNoneIcon } from "@radix-ui/react-icons"
import { useState } from "react"
import sousuo from "../../../assets/npc/sousuo1.png"
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> { }
@@ -13,7 +16,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input
type={type}
className={cname(
"flex h-9 w-full rounded-md border border-input bg-[#FAFBFC] px-3 py-1 text-sm text-[#111] shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 ",
"flex h-9 w-full rounded-md border-input bg-[#FAFBFC] px-3 py-1 text-sm text-[#111] shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-[#666] focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 ",
className
)}
ref={ref}
@@ -29,15 +32,34 @@ const SearchInput = React.forwardRef<HTMLInputElement, InputProps & { inputClass
({ className, inputClassName, iconClassName, ...props }, ref) => {
return <div className={cname("relative", className)}>
{/* <SearchIcon className={cname("h-5 w-5 absolute left-2 top-2 text-[#666666]", iconClassName)} /> */}
<img src={sousuo} alt="" className="w-[14px] absolute left-[14px] top-[10px]" />
<Input type="text" ref={ref} className={cname("w-[244px] h-[34px] pl-[40px] npcInput3", inputClassName)} {...props}></Input>
<div className="absolute w-[40px] h-[100%] flex items-center">
<img src={sousuo} alt="" className="w-[14px] absolute left-[14px]" />
</div>
<Input type="text" ref={ref} className={cname("w-[244px] h-[34px] pl-[40px] npcInput2", inputClassName)} {...props}></Input>
</div>
}
)
SearchInput.displayName = "SearchInput"
const PasswordInput = React.forwardRef<HTMLInputElement, InputProps & { inputClassName?: string, iconClassName?: string }>(
({ className, inputClassName, iconClassName, ...props }, ref) => {
const [type, setType] = useState('password')
const handleShowPwd = () => {
type === 'password' ? setType('text') : setType('password')
}
return <div className={cname("relative flex place-items-center", className)}>
<Input type={type} ref={ref} autocomplete="new-password" className={cname("pr-8 bg-[#1a1a1a] text-[#fff] ", inputClassName)} {...props}></Input>
{
type === 'password'
? <EyeNoneIcon onClick={handleShowPwd} className={cname("absolute right-2 text-[#fff] dark:text-[#fff] cursor-pointer", iconClassName)}/>
: <EyeOpenIcon onClick={handleShowPwd} className={cname("absolute right-2 text-[#fff] dark:text-[#fff] cursor-pointer", iconClassName)}/>
}
</div>
}
)
PasswordInput.displayName = 'PasswordInput'
/**
* 多行文本
@@ -146,4 +168,4 @@ const InputList = React.forwardRef<HTMLDivElement, InputProps & {
}
)
export { Input, SearchInput, Textarea, InputList }
export { Input, SearchInput, PasswordInput, Textarea, InputList }

View File

@@ -22,7 +22,7 @@ const PopoverContent = React.forwardRef<
align={align}
sideOffset={sideOffset}
className={cname(
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
"z-50 w-[280px] rounded-md bg-[#000000] p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 box-shadow",
className
)}
{...props}

View File

@@ -0,0 +1,57 @@
import React from 'react';
import { Button } from "@/components/bs-ui/button";
import { Checkbox } from "@/components/bs-ui/checkBox";
import { useTranslation } from "react-i18next";
import { SearchInput } from "../../../components/bs-ui/input";
// 定义组件的 props 类型
interface FilterUserGroupProps {
value: string[];
options: { id: string;[key: string]: any }[];
nameKey?: string;
placeholder: string;
onChecked: (id: string) => void;
search: (event: React.ChangeEvent<HTMLInputElement>) => void;
onClearChecked: () => void;
onOk: () => void;
}
const FilterUserGroup: React.FC<FilterUserGroupProps> = ({
value = [],
options,
nameKey = 'name',
placeholder,
onChecked,
search,
onClearChecked,
onOk
}) => {
const { t } = useTranslation();
return (
<div className="h-full">
<div>
<SearchInput placeholder={placeholder} className="w-[240px]" onChange={search}></SearchInput>
</div>
<div className="mt-2 max-h-[260px] min-h-20 overflow-y-auto">
{options.map((i) => (
<div className="flex items-center space-x-2 text-gray-500 mb-1 xiala" key={i.id}>
<Checkbox id={i.id} checked={value.includes(i.id)} onCheckedChange={() => onChecked(i.id)} />
<label htmlFor={i.id} className="cursor-pointer text-sm text-[#999]">{i[nameKey]}</label>
</div>
))}
{options.length === 0 && (
<div className="flex items-center justify-center h-[70px]">
<Button variant="ghost">{t('build.empty')}</Button>
</div>
)}
</div>
<div className="flex justify-end mt-4">
<Button variant="ghost" className="px-8 h-8 bg-[#333333] hover:bg-[#333333]" onClick={onClearChecked}>{t('system.reset')}</Button>
<Button className="px-8 h-8 bg-[#ffd025] hover:bg-[#ffd025] ml-[20px]" onClick={onOk}>{t('system.confirm')}</Button>
</div>
</div>
);
}
export default React.memo(FilterUserGroup);

View File

@@ -0,0 +1,23 @@
import { Button } from "../button";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../tooltip";
export function SelectHoverItem({ children, ...props }) {
return <div {...props} className="relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none hover:bg-[#EBF0FF] dark:text-gray-50 dark:hover:bg-[#26231B]" style={{borderRadius:"5px"}}>
{children}
</div>
}
export function SelectHover({ triagger, children }) {
return <TooltipProvider delayDuration={100}>
<Tooltip>
<TooltipTrigger asChild>
{triagger}
</TooltipTrigger>
<TooltipContent className="text-popover-foreground bg-popover dark:bg-[#1A1A1A] shadow-md">
{children}
</TooltipContent>
</Tooltip>
</TooltipProvider>
};

View File

@@ -23,7 +23,7 @@ const SelectTrigger = React.forwardRef<
<SelectPrimitive.Trigger
ref={ref}
className={cname(
"group flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-[#1a1a1a] px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 data-[placeholder]:text-gray-400",
"group flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border-input bg-[#1a1a1a] px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 data-[placeholder]:text-gray-400 border-[#666] text-[#999]",
className
)}
{...props}
@@ -79,7 +79,7 @@ const SelectContent = React.forwardRef<
<SelectPrimitive.Content
ref={ref}
className={cname(
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md box-shadow border-[#DEE3EF] bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md box-shadow border-[#0d0d0d] bg-[#0d0d0d] text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
@@ -124,7 +124,7 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.Item
ref={ref}
className={cname(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-[#1a1a1a] focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-[#2e2406] focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}

View File

@@ -1,15 +1,19 @@
import { CheckIcon, Cross1Icon } from "@radix-ui/react-icons"
import React, { useEffect, useRef } from "react"
import React, { useEffect, useMemo, useRef, useState } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger } from "."
import { Badge } from "../badge"
import { SearchInput } from "../input"
import { useDebounce } from "../utils"
const MultiItem = ({ active, children, value, onClick }) => {
const MultiItem: React.FC<
{ active: boolean; children: React.ReactNode; value: string; onClick: (value: string, label: string) => void }
> = ({ active, children, value, onClick }) => {
return <div key={value}
className={`relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 mb-1 text-sm outline-none hover:bg-[#1a1a1a] hover:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 break-all
${active && 'bg-[#1a1a1a]'}`}
onClick={() => { onClick(value) }}
return <div
key={value}
className={`relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 mb-1 text-sm outline-none hover:bg-[] dark:hover:bg-[#2e2406] hover:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 break-all
${active && 'bg-[#EBF0FF] dark:bg-[#2e2406]'}`}
onClick={() => { onClick(value, children as string) }}
>
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
{active && <CheckIcon className="h-4 w-4"></CheckIcon>}
@@ -17,21 +21,45 @@ const MultiItem = ({ active, children, value, onClick }) => {
{children}
</div>
}
interface IProps {
className?: string,
options: { label: string, value: string }[],
value?: string[],
defaultValue?: string[],
children?: React.ReactNode,
placeholder?: string,
searchPlaceholder?: string,
lockedValues?: string[],
onChange?: (value: string[]) => void
interface Option {
label: string;
value: string;
}
interface BaseProps<T> {
/** 多选 */
multiple?: boolean;
disabled?: boolean;
className?: string;
options: Option[];
children?: React.ReactNode;
placeholder?: string;
searchPlaceholder?: string;
/** 锁定不可修改的值 */
lockedValues?: string[];
onLoad?: () => void;
onSearch?: (name: string) => void;
onChange?: (value: T) => void;
}
// onScrollLoad有值表示开启分页、异步检索
interface ScrollLoadProps extends BaseProps<Option[]> {
onScrollLoad: (name: string) => void;
value?: Option[];
defaultValue?: Option[];
}
interface NonScrollLoadProps extends BaseProps<string[]> {
onScrollLoad?: undefined;
value?: string[];
defaultValue?: string[];
}
type IProps = ScrollLoadProps | NonScrollLoadProps;
// 临时用 andt 设计方案封装组件
const MultiSelect = ({
multiple = false,
className,
value = [],
defaultValue = [],
@@ -40,13 +68,15 @@ const MultiSelect = ({
placeholder = '',
searchPlaceholder = '',
lockedValues = [],
onSearch,
onLoad,
onScrollLoad,
onChange, ...props
}: IProps) => {
const [values, setValues] = React.useState(defaultValue)
const [optionFilter, setOptionFilter] = React.useState(options)
const [created, creatInput] = useState(false)
const inputRef = useRef(null)
useEffect(() => {
@@ -54,75 +84,145 @@ const MultiSelect = ({
}, [value])
useEffect(() => {
setOptionFilter(options)
if (inputRef.current) {
inputRef.current.value = ''
}
}, [options])
// delete
// if (onScrollLoad) {
setOptionFilter(options);
// }
}, [options]);
// delete
const handleDelete = (value: string) => {
const newValues = values.filter((item) => {
return item !== value
const newValues = (values as any[]).filter((item) => {
const _value = onScrollLoad ? (item as Option).value : item;
return _value !== value
})
setValues(newValues)
onChange?.(newValues)
}
// add
const handleSwitch = (value: string) => {
const handleSwitch = (value: string, label: string) => {
if (lockedValues.includes(value)) {
return
}
if (values.includes(value)) {
const newValues = values.filter((item) => {
return item !== value
})
setValues(newValues)
onChange?.(newValues)
const updateValues = (newValues: any) => {
setValues(newValues);
onChange?.(newValues);
};
// 单选
if (!multiple) {
const newValues = onScrollLoad ? [{ label, value }] : [value]
updateValues(newValues);
return
}
if (onScrollLoad) {
const newValues = (values as Option[]).some(item => item.value === value)
? (values as Option[]).filter(item => item.value !== value)
: [...(values as Option[]), { label, value }];
updateValues(newValues);
} else {
const _newValues = [...values, value]
setValues(_newValues)
onChange?.(_newValues)
const newValues = (values as string[]).includes(value)
? (values as string[]).filter(item => item !== value)
: [...(values as string[]), value];
updateValues(newValues);
}
}
// search
const handleSearch = (e) => {
const handleSearch = useDebounce((e) => {
const newValues = options.filter((item) => {
return item.label.toLowerCase().indexOf(e.target.value.toLowerCase()) !== -1
})
setOptionFilter(newValues)
}
return <Select {...props} required onOpenChange={(e) => !e && setOptionFilter(options)}>
<SelectTrigger className="mt-2 h-auto bg-[#1a1a1a]">
onSearch?.(inputRef.current?.value || '')
}, 500, false)
// scroll laod
const footerRef = useRef(null)
useEffect(function () {
if (!created) return
if (!footerRef.current) return
if (!onScrollLoad) return // 不绑定滚动事件
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// console.log('div is in the viewport!');
onScrollLoad?.(inputRef.current?.value || '')
}
});
}, {
// root: null, // 视口
rootMargin: '0px', // 视口的边距
threshold: 0.1 // 目标元素超过视口的10%即触发回调
});
// 开始观察目标元素
observer.observe(footerRef.current);
return () => observer.unobserve(footerRef.current);
}, [created])
return <Select
{...props}
required
onOpenChange={(e) => {
creatInput(e);
if (!e) {
onLoad?.();
setOptionFilter(options);
}
}}
>
<SelectTrigger className="h-auto">
{
values.length
? <div className="flex flex-wrap">
!multiple && (values.length ? <span>{onScrollLoad ? (values[0] as Option).label : options.find(op => op.value === values[0])?.label}</span> : placeholder)
}
{
multiple && (values.length ? (
onScrollLoad ? <div className="flex flex-wrap">
{
options.filter(option => values.includes(option.value)).map(option =>
<Badge onPointerDown={(e) => e.stopPropagation()} key={option.value} className="flex whitespace-normal items-center gap-1 select-none bg-primary/20 text-primary hover:bg-primary/15 m-[2px]">
values.map(item =>
<Badge onPointerDown={(e) => e.stopPropagation()} key={item.value} className="flex whitespace-normal items-center gap-1 select-none bg-[#261F08] text-[#CCA831] hover:bg-[#261F08] m-[2px]">
{item.label}
{lockedValues.includes(item.value) || <Cross1Icon className="h-3 w-3" onClick={() => handleDelete(item.value)}></Cross1Icon>}
</Badge>
)
}
</div> : <div className="flex flex-wrap">
{
options.filter(option => (values as string[]).includes(option.value)).map(option =>
<Badge onPointerDown={(e) => e.stopPropagation()} key={option.value} className="flex whitespace-normal items-center gap-1 select-none bg-[#261F08] text-[#CCA831] hover:bg-[#261F08] m-[2px] break-all">
{option.label}
{lockedValues.includes(option.value) || <Cross1Icon className="h-3 w-3" onClick={() => handleDelete(option.value)}></Cross1Icon>}
</Badge>
)
}
</div>
: placeholder
</div>)
: placeholder)
}
</SelectTrigger>
<SelectContent className={className}
<SelectContent
className={className}
headNode={
<div className="p-2">
<SearchInput ref={inputRef} inputClassName="h-8" placeholder={searchPlaceholder} onChange={handleSearch} iconClassName="w-4 h-4" />
<SearchInput ref={inputRef} inputClassName="w-[98%] h-8 dark:border-gray-700" placeholder={searchPlaceholder} onChange={handleSearch} iconClassName="w-4 h-4" />
</div>
}
footerNode={children}
>
<div className="mt-2">
{
optionFilter.map((item, index) => (
<MultiItem active={values.includes(item.value)} value={item.value} onClick={handleSwitch}>{item.label}</MultiItem>
optionFilter.map((item) => (
<MultiItem
active={values.some(val => val === item.value || val.value === item.value)}
value={item.value}
onClick={handleSwitch}
>{item.label}</MultiItem>
))
}
<div ref={footerRef} style={{ height: 20 }}></div>
</div>
</SelectContent>
</Select>

Some files were not shown because too many files have changed in this diff Show More