Commit 6bf39c02 authored by StyleZhang's avatar StyleZhang

fix: some style

parent 76e0c93b
<svg width="84" height="24" viewBox="0 0 84 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="2" width="80.5714" height="24" fill="url(#pattern0)"/>
<defs>
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
<use xlink:href="#image0_8587_60486" transform="scale(0.0070922 0.0238095)"/>
</pattern>
<image id="image0_8587_60486" width="141" height="42" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI0AAAAqCAYAAACOR9jzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA0NpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDkuMS1jMDAxIDc5LmE4ZDQ3NTM0OSwgMjAyMy8wMy8yMy0xMzowNTo0NSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDI0LjcgKDIwMjMwNzEyLm0uMjIzOSAwZjA3NjhhKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzBFM0JBODMxRkIwMTFFRUFEMzQ5RDE5Nzk4REI4NDAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzBFM0JBODQxRkIwMTFFRUFEMzQ5RDE5Nzk4REI4NDAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozMEUzQkE4MTFGQjAxMUVFQUQzNDlEMTk3OThEQjg0MCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozMEUzQkE4MjFGQjAxMUVFQUQzNDlEMTk3OThEQjg0MCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFj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"/>
</defs>
</svg>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect y="2.06897" width="24" height="19.8621" fill="url(#pattern0)"/>
<defs>
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
<use xlink:href="#image0_8587_60226" transform="scale(0.0197044 0.0238095)"/>
</pattern>
<image id="image0_8587_60226" width="141" height="42" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI0AAAAqCAYAAACOR9jzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA0NpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDkuMS1jMDAxIDc5LmE4ZDQ3NTM0OSwgMjAyMy8wMy8yMy0xMzowNTo0NSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDI0LjcgKDIwMjMwNzEyLm0uMjIzOSAwZjA3NjhhKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzBFM0JBODMxRkIwMTFFRUFEMzQ5RDE5Nzk4REI4NDAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzBFM0JBODQxRkIwMTFFRUFEMzQ5RDE5Nzk4REI4NDAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozMEUzQkE4MTFGQjAxMUVFQUQzNDlEMTk3OThEQjg0MCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozMEUzQkE4MjFGQjAxMUVFQUQzNDlEMTk3OThEQjg0MCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFj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"/>
</defs>
</svg>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Icon">
<g id="Icon_2">
<path d="M6 6.5C6.27614 6.5 6.5 6.27614 6.5 6C6.5 5.72386 6.27614 5.5 6 5.5C5.72386 5.5 5.5 5.72386 5.5 6C5.5 6.27614 5.72386 6.5 6 6.5Z" stroke="#344054" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.5 6.5C9.77614 6.5 10 6.27614 10 6C10 5.72386 9.77614 5.5 9.5 5.5C9.22386 5.5 9 5.72386 9 6C9 6.27614 9.22386 6.5 9.5 6.5Z" stroke="#344054" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2.5 6.5C2.77614 6.5 3 6.27614 3 6C3 5.72386 2.77614 5.5 2.5 5.5C2.22386 5.5 2 5.72386 2 6C2 6.27614 2.22386 6.5 2.5 6.5Z" stroke="#344054" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</g>
</svg>
<svg width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="Icon" d="M5.30246 4.74996C5.4396 4.3601 5.7103 4.03135 6.0666 3.82195C6.4229 3.61255 6.84181 3.53601 7.24915 3.60587C7.65648 3.67574 8.02594 3.88752 8.29209 4.20368C8.55824 4.51985 8.70391 4.92001 8.70329 5.33329C8.70329 6.49996 6.95329 7.08329 6.95329 7.08329M6.99996 9.41663H7.00579M12.8333 6.49996C12.8333 9.72162 10.2216 12.3333 6.99996 12.3333C3.7783 12.3333 1.16663 9.72162 1.16663 6.49996C1.16663 3.2783 3.7783 0.666626 6.99996 0.666626C10.2216 0.666626 12.8333 3.2783 12.8333 6.49996Z" stroke="#98A2B3" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="info-circle" clip-path="url(#clip0_7880_62014)">
<path id="Icon" d="M6 8V6M6 4H6.005M11 6C11 8.76142 8.76142 11 6 11C3.23858 11 1 8.76142 1 6C1 3.23858 3.23858 1 6 1C8.76142 1 11 3.23858 11 6Z" stroke="#98A2B3" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_7880_62014">
<rect width="12" height="12" fill="white"/>
</clipPath>
</defs>
</svg>
......@@ -77,6 +77,54 @@ export { default as <%= svgName %> } from './<%= svgName %>'
await appendFile(path.resolve(currentPath, 'index.ts'), `${indexingRender({ svgName: fileName })}\n`)
}
const generateImageComponent = async (entry, pathList) => {
const currentPath = path.resolve(__dirname, 'src', ...pathList.slice(2))
try {
await access(currentPath)
}
catch {
await generateDir(currentPath)
}
const prefixFileName = camelCase(entry.split('.')[0])
const fileName = prefixFileName.charAt(0).toUpperCase() + prefixFileName.slice(1)
const componentCSSRender = template(`
.wrapper {
display: inline-flex;
background: url(<%= assetPath %>) center center no-repeat;
background-size: contain;
}
`.trim())
await writeFile(path.resolve(currentPath, `${fileName}.module.css`), `${componentCSSRender({ assetPath: path.join('~@/app/components/base/icons/assets', ...pathList.slice(2), entry) })}\n`)
const componentRender = template(`
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import cn from 'classnames'
import s from './<%= fileName %>.module.css'
const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>((
{ className, ...restProps },
ref,
) => <span className={cn(s.wrapper, className)} {...restProps} ref={ref} />)
export default Icon
`.trim())
await writeFile(path.resolve(currentPath, `${fileName}.tsx`), `${componentRender({ fileName })}\n`)
const indexingRender = template(`
export { default as <%= fileName %> } from './<%= fileName %>'
`.trim())
await appendFile(path.resolve(currentPath, 'index.ts'), `${indexingRender({ fileName })}\n`)
}
const walk = async (entry, pathList, replaceFillOrStrokeColor) => {
const currentPath = path.resolve(...pathList, entry)
let fileHandle
......@@ -94,6 +142,9 @@ const walk = async (entry, pathList, replaceFillOrStrokeColor) => {
if (stat.isFile() && /.+\.svg$/g.test(entry))
await generateSvgComponent(fileHandle, entry, pathList, replaceFillOrStrokeColor)
if (stat.isFile() && /.+\.png$/g.test(entry))
await generateImageComponent(entry, pathList)
}
finally {
fileHandle?.close()
......@@ -104,4 +155,5 @@ const walk = async (entry, pathList, replaceFillOrStrokeColor) => {
await rm(path.resolve(__dirname, 'src'), { recursive: true, force: true })
await walk('public', [__dirname, 'assets'])
await walk('vender', [__dirname, 'assets'], true)
await walk('image', [__dirname, 'assets'])
})()
.wrapper {
display: inline-flex;
background: url(~@/app/components/base/icons/assets/image/llm/minimax.png) center center no-repeat;
background-size: contain;
}
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import cn from 'classnames'
import s from './Minimax.module.css'
const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>((
{ className, ...restProps },
ref,
) => <span className={cn(s.wrapper, className)} {...restProps} ref={ref} />)
export default Icon
.wrapper {
display: inline-flex;
background: url(~@/app/components/base/icons/assets/image/llm/minimax-text.png) center center no-repeat;
background-size: contain;
}
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import cn from 'classnames'
import s from './MinimaxText.module.css'
const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>((
{ className, ...restProps },
ref,
) => <span className={cn(s.wrapper, className)} {...restProps} ref={ref} />)
export default Icon
.wrapper {
display: inline-flex;
background: url(~@/app/components/base/icons/assets/image/llm/tongyi.png) center center no-repeat;
background-size: contain;
}
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import cn from 'classnames'
import s from './Tongyi.module.css'
const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>((
{ className, ...restProps },
ref,
) => <span className={cn(s.wrapper, className)} {...restProps} ref={ref} />)
export default Icon
.wrapper {
display: inline-flex;
background: url(~@/app/components/base/icons/assets/image/llm/tongyi-text.png) center center no-repeat;
background-size: contain;
}
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import cn from 'classnames'
import s from './TongyiText.module.css'
const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>((
{ className, ...restProps },
ref,
) => <span className={cn(s.wrapper, className)} {...restProps} ref={ref} />)
export default Icon
.wrapper {
display: inline-flex;
background: url(~@/app/components/base/icons/assets/image/llm/tongyi-text-cn.png) center center no-repeat;
background-size: contain;
}
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import cn from 'classnames'
import s from './TongyiTextCn.module.css'
const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>((
{ className, ...restProps },
ref,
) => <span className={cn(s.wrapper, className)} {...restProps} ref={ref} />)
export default Icon
export { default as MinimaxText } from './MinimaxText'
export { default as Minimax } from './Minimax'
export { default as TongyiTextCn } from './TongyiTextCn'
export { default as TongyiText } from './TongyiText'
export { default as Tongyi } from './Tongyi'
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "24",
"height": "24",
"viewBox": "0 0 24 24",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg",
"xmlns:xlink": "http://www.w3.org/1999/xlink"
},
"children": [
{
"type": "element",
"name": "rect",
"attributes": {
"y": "2.06897",
"width": "24",
"height": "19.8621",
"fill": "url(#pattern0)"
},
"children": []
},
{
"type": "element",
"name": "defs",
"attributes": {},
"children": [
{
"type": "element",
"name": "pattern",
"attributes": {
"id": "pattern0",
"patternContentUnits": "objectBoundingBox",
"width": "1",
"height": "1"
},
"children": [
{
"type": "element",
"name": "use",
"attributes": {
"xlink:href": "#image0_8587_60226",
"transform": "scale(0.0197044 0.0238095)"
},
"children": []
}
]
},
{
"type": "element",
"name": "image",
"attributes": {
"id": "image0_8587_60226",
"width": "141",
"height": "42",
"xlink:href": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI0AAAAqCAYAAACOR9jzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA0NpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDkuMS1jMDAxIDc5LmE4ZDQ3NTM0OSwgMjAyMy8wMy8yMy0xMzowNTo0NSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDI0LjcgKDIwMjMwNzEyLm0uMjIzOSAwZjA3NjhhKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzBFM0JBODMxRkIwMTFFRUFEMzQ5RDE5Nzk4REI4NDAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzBFM0JBODQxRkIwMTFFRUFEMzQ5RDE5Nzk4REI4NDAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozMEUzQkE4MTFGQjAxMUVFQUQzNDlEMTk3OThEQjg0MCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozMEUzQkE4MjFGQjAxMUVFQUQzNDlEMTk3OThEQjg0MCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFj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"
},
"children": []
}
]
}
]
},
"name": "Minimax"
}
\ No newline at end of file
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "84",
"height": "24",
"viewBox": "0 0 84 24",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg",
"xmlns:xlink": "http://www.w3.org/1999/xlink"
},
"children": [
{
"type": "element",
"name": "rect",
"attributes": {
"x": "2",
"width": "80.5714",
"height": "24",
"fill": "url(#pattern0)"
},
"children": []
},
{
"type": "element",
"name": "defs",
"attributes": {},
"children": [
{
"type": "element",
"name": "pattern",
"attributes": {
"id": "pattern0",
"patternContentUnits": "objectBoundingBox",
"width": "1",
"height": "1"
},
"children": [
{
"type": "element",
"name": "use",
"attributes": {
"xlink:href": "#image0_8587_60486",
"transform": "scale(0.0070922 0.0238095)"
},
"children": []
}
]
},
{
"type": "element",
"name": "image",
"attributes": {
"id": "image0_8587_60486",
"width": "141",
"height": "42",
"xlink:href": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI0AAAAqCAYAAACOR9jzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA0NpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDkuMS1jMDAxIDc5LmE4ZDQ3NTM0OSwgMjAyMy8wMy8yMy0xMzowNTo0NSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDI0LjcgKDIwMjMwNzEyLm0uMjIzOSAwZjA3NjhhKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzBFM0JBODMxRkIwMTFFRUFEMzQ5RDE5Nzk4REI4NDAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzBFM0JBODQxRkIwMTFFRUFEMzQ5RDE5Nzk4REI4NDAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozMEUzQkE4MTFGQjAxMUVFQUQzNDlEMTk3OThEQjg0MCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozMEUzQkE4MjFGQjAxMUVFQUQzNDlEMTk3OThEQjg0MCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFj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"
},
"children": []
}
]
}
]
},
"name": "MinimaxText"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './TongyiText.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './TongyiTextCn.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon
......@@ -15,8 +15,6 @@ export { default as IflytekSparkTextCn } from './IflytekSparkTextCn'
export { default as IflytekSparkText } from './IflytekSparkText'
export { default as IflytekSpark } from './IflytekSpark'
export { default as Microsoft } from './Microsoft'
export { default as MinimaxText } from './MinimaxText'
export { default as Minimax } from './Minimax'
export { default as OpenaiBlack } from './OpenaiBlack'
export { default as OpenaiBlue } from './OpenaiBlue'
export { default as OpenaiGreen } from './OpenaiGreen'
......@@ -25,9 +23,6 @@ export { default as OpenaiTransparent } from './OpenaiTransparent'
export { default as OpenaiViolet } from './OpenaiViolet'
export { default as ReplicateText } from './ReplicateText'
export { default as Replicate } from './Replicate'
export { default as TongyiTextCn } from './TongyiTextCn'
export { default as TongyiText } from './TongyiText'
export { default as Tongyi } from './Tongyi'
export { default as WxyyTextCn } from './WxyyTextCn'
export { default as WxyyText } from './WxyyText'
export { default as Wxyy } from './Wxyy'
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "12",
"height": "12",
"viewBox": "0 0 12 12",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Icon"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Icon_2"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M6 6.5C6.27614 6.5 6.5 6.27614 6.5 6C6.5 5.72386 6.27614 5.5 6 5.5C5.72386 5.5 5.5 5.72386 5.5 6C5.5 6.27614 5.72386 6.5 6 6.5Z",
"stroke": "currentColor",
"stroke-width": "1.5",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M9.5 6.5C9.77614 6.5 10 6.27614 10 6C10 5.72386 9.77614 5.5 9.5 5.5C9.22386 5.5 9 5.72386 9 6C9 6.27614 9.22386 6.5 9.5 6.5Z",
"stroke": "currentColor",
"stroke-width": "1.5",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M2.5 6.5C2.77614 6.5 3 6.27614 3 6C3 5.72386 2.77614 5.5 2.5 5.5C2.22386 5.5 2 5.72386 2 6C2 6.27614 2.22386 6.5 2.5 6.5Z",
"stroke": "currentColor",
"stroke-width": "1.5",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
}
]
}
]
},
"name": "DotsHorizontal"
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './MinimaxText.json'
import data from './DotsHorizontal.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
......
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "14",
"height": "13",
"viewBox": "0 0 14 13",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Icon",
"d": "M5.30246 4.74996C5.4396 4.3601 5.7103 4.03135 6.0666 3.82195C6.4229 3.61255 6.84181 3.53601 7.24915 3.60587C7.65648 3.67574 8.02594 3.88752 8.29209 4.20368C8.55824 4.51985 8.70391 4.92001 8.70329 5.33329C8.70329 6.49996 6.95329 7.08329 6.95329 7.08329M6.99996 9.41663H7.00579M12.8333 6.49996C12.8333 9.72162 10.2216 12.3333 6.99996 12.3333C3.7783 12.3333 1.16663 9.72162 1.16663 6.49996C1.16663 3.2783 3.7783 0.666626 6.99996 0.666626C10.2216 0.666626 12.8333 3.2783 12.8333 6.49996Z",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
},
"name": "HelpCircle"
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Minimax.json'
import data from './HelpCircle.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
......
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "12",
"height": "12",
"viewBox": "0 0 12 12",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "info-circle",
"clip-path": "url(#clip0_7880_62014)"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Icon",
"d": "M6 8V6M6 4H6.005M11 6C11 8.76142 8.76142 11 6 11C3.23858 11 1 8.76142 1 6C1 3.23858 3.23858 1 6 1C8.76142 1 11 3.23858 11 6Z",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
},
{
"type": "element",
"name": "defs",
"attributes": {},
"children": [
{
"type": "element",
"name": "clipPath",
"attributes": {
"id": "clip0_7880_62014"
},
"children": [
{
"type": "element",
"name": "rect",
"attributes": {
"width": "12",
"height": "12",
"fill": "white"
},
"children": []
}
]
}
]
}
]
},
"name": "InfoCircle"
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Tongyi.json'
import data from './InfoCircle.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
......
export { default as Check } from './Check'
export { default as DotsHorizontal } from './DotsHorizontal'
export { default as Edit03 } from './Edit03'
export { default as Hash02 } from './Hash02'
export { default as HelpCircle } from './HelpCircle'
export { default as InfoCircle } from './InfoCircle'
export { default as LinkExternal02 } from './LinkExternal02'
export { default as Loading02 } from './Loading02'
export { default as LogOut01 } from './LogOut01'
......
......@@ -22,6 +22,18 @@ export function normalizeAttrs(attrs: Attrs = {}): Attrs {
acc.className = val
delete acc.class
break
case 'style':
(acc.style as any) = val.split(';').reduce((prev, next) => {
const pairs = next?.split(':')
if (pairs[0] && pairs[1]) {
const k = pairs[0].replace(/([-]\w)/g, (g: string) => g[1].toUpperCase())
prev[k] = pairs[1]
}
return prev
}, {} as Attrs)
break
default:
acc[key] = val
}
......
export default {
type: 'provider',
title: {
'en-US': 'Anthropic',
'zh-Hans': 'Anthropic',
},
link: {
href: 'https://docs.dify.ai',
label: {
'en-US': 'Get your API key from Anthropic',
'zh-Hans': '从 Anthropic 获取 API Key',
},
},
fields: [
{
type: 'text',
key: 'anthropic_api_key',
is_required: true,
toggle_enabled: false,
is_obfuscated: true,
label: {
'en-US': 'API Key',
'zh-Hans': 'API Key',
},
place_holder: {
'en-US': 'Enter your API key here',
'zh-Hans': '在此输入您的 API Key',
},
},
{
type: 'text',
key: 'anthropic_api_url',
is_required: false,
toggle_enabled: true,
label: {
'en-US': 'Custom API Domain',
'zh-Hans': '自定义 API 域名',
},
place_holder: {
'en-US': 'Enter your API domain, eg: https://example.com/xxx',
'zh-Hans': '在此输入您的 API 域名,如:https://example.com/xxx',
},
help: {
'en-US': 'Configurable custom Anthropic API server url.',
'zh-Hans': '可配置自定义 Anthropic API 服务器地址。',
},
},
],
}
import anthropicConfig from './anthropic.config'
import openaiConfig from './openai.config'
export default {
anthropic: anthropicConfig,
openai: openaiConfig,
}
export default {
type: 'provider',
title: {
'en-US': 'OpenAI',
'zh-Hans': 'OpenAI',
},
link: {
href: 'https://docs.dify.ai',
label: {
'en-US': 'Get your API key from OpenAI',
'zh-Hans': '从 OpenAI 获取 API Key',
},
},
fields: [
{
type: 'text',
key: 'openai_api_key',
is_required: true,
toggle_enabled: false,
is_obfuscated: true,
label: {
'en-US': 'API Key',
'zh-Hans': 'API Key',
},
place_holder: {
'en-US': 'Enter your API key here',
'zh-Hans': '在此输入您的 API Key',
},
},
{
type: 'text',
key: 'openai_api_base',
is_required: false,
toggle_enabled: true,
label: {
'en-US': 'Custom API Domain',
'zh-Hans': '自定义 API 域名',
},
place_holder: {
'en-US': 'Enter your API domain, eg: https://example.com/xxx',
'zh-Hans': '在此输入您的 API 域名,如:https://example.com/xxx',
},
help: {
'en-US': 'You can configure your server compatible with the OpenAI API specification, or proxy mirror address',
'zh-Hans': '可配置您的兼容 OpenAI API 规范的服务器,或者代理镜像地址',
},
},
{
type: 'text',
key: 'openai_organization',
is_required: false,
toggle_enabled: true,
label: {
'en-US': 'Organization ID',
'zh-Hans': '组织 ID',
},
place_holder: {
'en-US': 'Enter your Organization ID, eg: org-xxxxxxxxxxxxxxxx',
'zh-Hans': '在此输入您的组织 ID,如:org-xxxxxxxxxxxxxxxx',
},
},
],
}
......@@ -5,34 +5,58 @@ import ModelCard from './model-card'
import ModelItem from './model-item'
import ModelModal from './model-modal'
import { ChevronDownDouble } from '@/app/components/base/icons/src/vender/line/arrows'
import { HelpCircle } from '@/app/components/base/icons/src/vender/line/general'
import {
AzureOpenaiServiceText,
ChatglmText,
HuggingfaceText,
ReplicateText,
} from '@/app/components/base/icons/src/public/llm'
import {
MinimaxText,
TongyiText,
} from '@/app/components/base/icons/src/image/llm'
const MODEL_LIST = [
{
key: 'azure_openai',
type: 'add',
icon: <AzureOpenaiServiceText className='h-6' />,
},
{
key: 'replicate',
type: 'add',
icon: <ReplicateText className='h-6' />,
},
{
key: 'huggingface_hub',
type: 'add',
icon: <HuggingfaceText className='h-6' />,
},
{
key: 'tongyi',
type: 'setup',
icon: <TongyiText className='w-[88px] h-6' />,
},
{
key: 'minimax',
type: 'setup',
icon: <MinimaxText className='w-[84px] h-6' />,
},
{
key: 'chatglm',
type: 'setup',
icon: <ChatglmText className='h-6' />,
},
]
const titleClassName = `
flex items-center h-9 text-sm font-medium text-gray-900
`
const tipClassName = `
ml-0.5 w-[14px] h-[14px] text-gray-400
`
const ModelPage = () => {
const { t } = useTranslation()
const [showMoreModel, setShowMoreModel] = useState(false)
......@@ -40,28 +64,46 @@ const ModelPage = () => {
return (
<div className='pt-1'>
<div className='grid grid-cols-2 gap-4 mb-4'>
<div className='grid grid-cols-3 gap-4 mb-5'>
<div className='w-full'>
<div className='py-2 text-sm font-medium text-gray-900'>
<div className={titleClassName}>
{t('common.modelProvider.systemReasoningModel.key')}
<HelpCircle className={tipClassName} />
</div>
<div>
<ModelSelector />
</div>
</div>
<div className='w-full'>
<div className={titleClassName}>
{t('common.modelProvider.embeddingModel.key')}
<HelpCircle className={tipClassName} />
</div>
<div>
<ModelSelector />
</div>
</div>
<div className='w-full'>
<div className={titleClassName}>
{t('common.modelProvider.speechToTextModel.key')}
<HelpCircle className={tipClassName} />
</div>
<div>
<ModelSelector />
</div>
</div>
</div>
<div className='mb-4 h-[0.5px] bg-gray-100' />
<div className='mb-5 h-[0.5px] bg-gray-100' />
<div className='mb-3 text-sm font-medium text-gray-800'>{t('common.modelProvider.models')}</div>
<div className='grid grid-cols-2 gap-4 mb-6'>
<ModelCard />
<ModelCard type='anthropic' />
<ModelCard onOpenModal={() => {}} />
<ModelCard onOpenModal={() => {}} type='anthropic' />
</div>
{
MODEL_LIST.slice(0, showMoreModel ? MODEL_LIST.length : 3).map(model => (
<ModelItem
key={model.key}
provider={model.key}
type={model.type}
provider={model}
onOperate={() => setModelModalShow(true)}
/>
))
......
import { Fragment } from 'react'
import { Popover, Transition } from '@headlessui/react'
import { useTranslation } from 'react-i18next'
import { Check, DotsHorizontal, Trash03 } from '@/app/components/base/icons/src/vender/line/general'
const itemClassName = `
flex items-center px-3 h-9 text-sm text-gray-700 rounded-lg cursor-pointer
`
const PrioritySelector = () => {
const { t } = useTranslation()
return (
<Popover className='relative'>
<Popover.Button>
{
({ open }) => (
<div className={`
flex justify-center items-center w-6 h-6 rounded-md hover:bg-gray-50 cursor-pointer
${open && 'bg-gray-50'}
`}>
<DotsHorizontal className='w-3 h-3 text-gray-700' />
</div>
)
}
</Popover.Button>
<Transition
as={Fragment}
leave='transition ease-in duration-100'
leaveFrom='opacity-100'
leaveTo='opacity-0'
>
<Popover.Panel className='absolute top-7 right-0 w-[192px] bg-white border-[0.5px] border-gray-200 rounded-lg shadow-lg z-10'>
<div className='p-1'>
<div className='px-3 pt-2 pb-1 text-sm font-medium text-gray-700'>{t('common.modelProvider.card.priorityUse')}</div>
<Popover.Button as={Fragment}>
<div className={`${itemClassName} hover:bg-gray-50`}>
<div className='grow'>API</div>
</div>
</Popover.Button>
<Popover.Button as={Fragment}>
<div className={`${itemClassName} hover:bg-gray-50`}>
<div className='grow'>{t('common.modelProvider.quota')}</div>
<Check className='w-4 h-4 text-primary-600' />
</div>
</Popover.Button>
</div>
<div className='h-[1px] bg-gray-100' />
<div className='p-1'>
<Popover.Button as={Fragment}>
<div className={`group ${itemClassName} hover:bg-[#FEF3F2] hover:text-[#D92D20]`}>
<Trash03 className='mr-2 w-4 h-4 text-gray-500 group-hover:text-[#D92D20]' />
{t('common.modelProvider.card.removeKey')}
</div>
</Popover.Button>
</div>
</Popover.Panel>
</Transition>
</Popover>
)
}
export default PrioritySelector
.card {
box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
}
\ No newline at end of file
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
import cn from 'classnames'
import s from './index.module.css'
import Indicator from '../../../indicator'
import PrioritySelector from './PrioritySelector'
import { IS_CE_EDITION } from '@/config'
import Button from '@/app/components/base/button'
import { Plus } from '@/app/components/base/icons/src/vender/line/general'
import { InfoCircle, Plus } from '@/app/components/base/icons/src/vender/line/general'
import { Anthropic, AnthropicText, OpenaiBlack, OpenaiText } from '@/app/components/base/icons/src/public/llm'
const PROVIDER_MAP = {
openai: {
bgColor: 'bg-gray-200',
title: <OpenaiText className='h-5' />,
desc: <OpenaiBlack className='w-6 h-6' />,
},
anthropic: {
bgColor: 'bg-[#F0F0EB]',
title: <AnthropicText className='h-5' />,
desc: <Anthropic className='w-6 h-6' />,
},
}
type ModelCardProps = {
type?: 'openai' | 'anthropic'
onOpenModal: () => void
}
const ModelCard: FC<ModelCardProps> = ({
type = 'openai',
onOpenModal,
}) => {
const { t } = useTranslation()
return (
<div className={cn(
s.card,
'rounded-xl border-[0.5px] border-gray-200',
)}>
<div className='flex px-4 pt-4 pb-3 bg-gray-200 rounded-t-lg'>
<div className='rounded-xl border-[0.5px] border-gray-200 shadow-xs'>
<div className={`flex px-4 pt-4 pb-3 rounded-t-lg ${PROVIDER_MAP[type].bgColor}`}>
<div className='mr-3'>
<div className='mb-1'></div>
<div className='mb-1'>
{PROVIDER_MAP[type].title}
</div>
<div className='text-xs text-black opacity-60'>{t(`common.modelProvider.card.${type}.desc`)}</div>
</div>
<div className='w-6 h-6' />
{PROVIDER_MAP[type].desc}
</div>
<div className='flex justify-between px-4 py-3 border-b-[0.5px] border-b-[rgba(0, 0, 0, 0.5)]'>
<div>
<div className='flex items-center mb-1 h-5'>
<div className='mr-1 text-xs font-medium text-gray-500'>{t('common.modelProvider.card.quota')}</div>
<div className='px-1.5 bg-primary-50 rounded-md text-xs font-semibold text-primary-600'>{t('common.modelProvider.card.onTrial')}</div>
{
!IS_CE_EDITION && (
<div className='flex justify-between px-4 py-3 border-b-[0.5px] border-b-[rgba(0, 0, 0, 0.5)]'>
<div>
<div className='flex items-center mb-1 h-5'>
<div className='mr-1 text-xs font-medium text-gray-500'>{t('common.modelProvider.card.quota')}</div>
<div className='px-1.5 bg-primary-50 rounded-md text-xs font-semibold text-primary-600'>{t('common.modelProvider.card.onTrial')}</div>
</div>
<div className='flex items-center text-gray-700'>
<div className='mr-1 text-sm font-medium'>200</div>
<div className='mr-1 text-sm'>{t('common.modelProvider.card.callTimes')}</div>
<InfoCircle className='w-3 h-3 text-gray-400 hover:text-gray-700' />
</div>
</div>
<Button className='mt-1.5 !px-3 !h-8 !text-[13px] font-medium rounded-lg' type='primary'>{t('common.modelProvider.card.buyQuota')}</Button>
</div>
<div className='flex items-center'>
<div className='mr-1 text-sm font-medium text-gray-700'>200</div>
<div className='mr-1 text-sm text-gray-700'>{t('common.modelProvider.card.callTimes')}</div>
</div>
</div>
<Button className='mt-1.5 !px-3 !h-8 !text-[13px] font-medium rounded-lg' type='primary'>{t('common.modelProvider.card.buyQuota')}</Button>
)
}
<div
className='inline-flex items-center px-4 h-12 text-gray-500 cursor-pointer hover:text-primary-600'
onClick={onOpenModal}
>
<Plus className='mr-1.5 w-4 h-4'/>
<div className='text-xs font-medium'>{t('common.modelProvider.addApiKey')}</div>
</div>
<div className='flex items-center px-4 h-12'>
<Plus className='mr-1.5 w-4 h-4 text-gray-500' />
<div className='text-xs font-medium text-gray-500'>{t('common.modelProvider.addApiKey')}</div>
<Indicator color='green' className='mr-2' />
<div className='grow text-[13px] font-medium text-gray-700'>API key</div>
<div className='mr-1 px-2 leading-6 rounded-md text-xs font-medium text-gray-500 hover:bg-gray-50 cursor-pointer'>{t('common.operation.edit')}</div>
<PrioritySelector />
</div>
</div>
)
......
import { Fragment } from 'react'
import { Popover, Transition } from '@headlessui/react'
import { useTranslation } from 'react-i18next'
import { DotsHorizontal, Trash03 } from '@/app/components/base/icons/src/vender/line/general'
const itemClassName = `
flex items-center px-3 h-9 text-sm text-gray-700 rounded-lg cursor-pointer
`
const Operation = () => {
const { t } = useTranslation()
return (
<Popover className='relative'>
<Popover.Button>
{
({ open }) => (
<div className={`
flex justify-center items-center w-7 h-7 bg-white rounded-md border-[0.5px] border-gray-200 shadow-xs cursor-pointer
${open && 'bg-gray-100 shadow-none'}
`}>
<DotsHorizontal className='w-4 h-4 text-gray-700' />
</div>
)
}
</Popover.Button>
<Transition
as={Fragment}
leave='transition ease-in duration-100'
leaveFrom='opacity-100'
leaveTo='opacity-0'
>
<Popover.Panel className='absolute top-8 right-0 w-[144px] bg-white border-[0.5px] border-gray-200 rounded-lg shadow-lg z-10'>
<div className='p-1'>
<Popover.Button as={Fragment}>
<div className={`group ${itemClassName} hover:bg-[#FEF3F2] hover:text-[#D92D20]`}>
<Trash03 className='mr-2 w-4 h-4 text-gray-500 group-hover:text-[#D92D20]' />
{t('common.operation.remove')}
</div>
</Popover.Button>
</div>
</Popover.Panel>
</Transition>
</Popover>
)
}
export default Operation
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
import Indicator from '../../../indicator'
import Operation from './Operation'
import Button from '@/app/components/base/button'
import {
AzureOpenaiServiceText,
ChatglmText,
HuggingfaceText,
MinimaxText,
ReplicateText,
TongyiText,
} from '@/app/components/base/icons/src/public/llm'
const ICON_MAP = {
azure_openai: <AzureOpenaiServiceText />,
replicate: <ReplicateText />,
huggingface_hub: <HuggingfaceText />,
tongyi: <TongyiText />,
minimax: <MinimaxText />,
chatglm: <ChatglmText />,
}
type ModelItemProps = {
type: string
provider: string
provider: { key: string; type: string; icon: any }
onOperate: () => void
}
const ModelItem: FC<ModelItemProps> = ({
type,
provider,
onOperate,
}) => {
......@@ -34,13 +17,23 @@ const ModelItem: FC<ModelItemProps> = ({
return (
<div className='flex justify-between items-center mb-2 px-4 h-14 bg-gray-50 rounded-xl'>
<div />
{provider.icon}
<Button
className='!px-3 !h-7 rounded-md bg-white !text-xs font-medium text-gray-700'
onClick={onOperate}
>
{t(`common.operation.${type}`)}
{t(`common.operation.${provider.type}`)}
</Button>
<div className='flex items-center'>
<Indicator className='mr-3' />
<Button
className='mr-1 !px-3 !h-7 rounded-md bg-white !text-xs font-medium text-gray-700'
onClick={onOperate}
>
{t('common.operation.edit')}
</Button>
<Operation />
</div>
</div>
)
}
......
.options {
box-shadow: 0px 4px 6px 0px rgba(0, 0, 0, 0.05), 0px 10px 15px -3px rgba(0, 0, 0, 0.10)
}
\ No newline at end of file
import { Fragment, useState } from 'react'
import { Popover, Transition } from '@headlessui/react'
import { useTranslation } from 'react-i18next'
import cn from 'classnames'
import s from './index.module.css'
import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows'
import { Check, SearchLg } from '@/app/components/base/icons/src/vender/line/general'
import { XCircle } from '@/app/components/base/icons/src/vender/solid/general'
import { Anthropic, Gpt3, Gpt4 } from '@/app/components/base/icons/src/public/llm'
const iconClassName = 'mr-2 w-4 h-4'
import {
Anthropic,
Chatglm,
Huggingface,
OpenaiGreen,
OpenaiViolet,
Replicate,
} from '@/app/components/base/icons/src/public/llm'
import {
Minimax,
Tongyi,
} from '@/app/components/base/icons/src/image/llm'
const models = [
{ type: 'provider', name: 'OpenAI' },
{ type: 'model', name: 'GPT-3.5-Turbo-16K', value: 'GPT-3.5-Turbo-16K', icon: <Gpt3 className={iconClassName} />, i: 'Gpt3' },
{ type: 'model', name: 'GPT-4', value: 'GPT-4', icon: <Gpt4 className={iconClassName} />, i: 'Gpt4' },
{ type: 'model', name: 'GPT-3.5-Turbo-16K', value: 'GPT-3.5-Turbo-16K', icon: OpenaiGreen },
{ type: 'model', name: 'GPT-4', value: 'GPT-4', icon: OpenaiViolet },
{ type: 'provider', name: 'Anthropic' },
{ type: 'model', name: 'Claude-2', value: 'Claude-2', icon: <Anthropic className={iconClassName} />, i: 'Anthropic' },
{ type: 'model', name: 'Claude-Instant', value: 'Claude-Instant', icon: <Anthropic className={iconClassName} />, i: 'Anthropic' },
{ type: 'model', name: 'Claude-2', value: 'Claude-2', icon: Anthropic },
{ type: 'model', name: 'Claude-Instant', value: 'Claude-Instant', icon: Anthropic },
{ type: 'provider', name: 'Replicate' },
{ type: 'model', name: 'xxx/xxx-chat', value: 'xxx/xxx-chat', icon: Replicate },
{ type: 'provider', name: 'Hugging Face' },
{ type: 'model', name: 'xxx-chat', value: 'xxx-chat', icon: Huggingface },
{ type: 'provider', name: 'TONGYI QIANWEN' },
{ type: 'model', name: 'TONGYI-GPT', value: 'TONGYI-GPT', icon: Tongyi },
{ type: 'provider', name: 'ChatGLM' },
{ type: 'model', name: 'ChatGLM-3', value: 'ChatGLM-3', icon: Chatglm },
{ type: 'provider', name: 'MINIMAX' },
{ type: 'model', name: 'MINIMAX-GPT', value: 'MINIMAX-GPT', icon: Minimax },
]
const ModelSelector = () => {
const { t } = useTranslation()
const [selected, setSelected] = useState('Claude-2')
const [selected, setSelected] = useState<{ type: string; name: string; value?: string; icon?: any }>()
const [search, setSearch] = useState('')
return (
......@@ -31,8 +48,18 @@ const ModelSelector = () => {
{
({ open }) => (
<>
<div className='mr-1.5 w-5 h-5' />
<div className='mr-1.5 grow text-left text-sm text-gray-900'>{selected}</div>
{
selected
? (
<>
<selected.icon className='mr-1.5 w-5 h-5' />
<div className='mr-1.5 grow text-left text-sm text-gray-900'>{selected?.name}</div>
</>
)
: (
<div className='grow text-left text-sm text-gray-800 opacity-60'>{t('common.modelProvider.selectModel')}</div>
)
}
<ChevronDown className={`w-4 h-4 text-gray-700 ${open ? 'opacity-100' : 'opacity-60'}`} />
</>
)
......@@ -44,10 +71,7 @@ const ModelSelector = () => {
leaveFrom='opacity-100'
leaveTo='opacity-0'
>
<Popover.Panel className={cn(
s.options,
'absolute top-10 p-1 w-full max-h-[366px] bg-white border-[0.5px] border-gray-200 rounded-lg overflow-auto z-10',
)}>
<Popover.Panel className='absolute top-10 p-1 w-full max-h-[366px] bg-white border-[0.5px] border-gray-200 rounded-lg shadow-lg overflow-auto z-10'>
<div className='px-2 pt-2 pb-1'>
<div className='flex items-center px-2 h-8 bg-gray-100 rounded-lg'>
<div className='mr-1.5 p-[1px]'><SearchLg className='w-[14px] h-[14px] text-gray-400' /></div>
......@@ -85,6 +109,7 @@ const ModelSelector = () => {
}
if (model.type === 'model') {
const Icon: any = model.icon
return (
<Popover.Button
key={`${model.type}-${model.name}`}
......@@ -92,8 +117,9 @@ const ModelSelector = () => {
flex items-center px-3 w-full h-8 rounded-lg cursor-pointer hover:bg-gray-50
${selected === model.value && 'bg-gray-50'}
`}
onClick={() => setSelected(model)}
>
{model.icon}
<Icon className='mr-2 w-4 h-4' />
<div className='grow text-left text-sm text-gray-900'>{model.name}</div>
{ selected === model.value && <Check className='w-4 h-4 text-primary-600' /> }
</Popover.Button>
......@@ -103,6 +129,7 @@ const ModelSelector = () => {
return null
})
}
<div className='px-3 pt-1.5 h-[30px] text-center text-xs text-gray-500'>{t('common.modelProvider.noModelFound')}</div>
</Popover.Panel>
</Transition>
</Popover>
......
......@@ -204,6 +204,8 @@ const translation = {
},
},
modelProvider: {
selectModel: 'Select your model',
setupModelFirst: 'Please set up your model first',
systemReasoningModel: {
key: 'System Reasoning Model',
tip: 'System Reasoning Model',
......@@ -212,6 +214,11 @@ const translation = {
key: 'Embedding Model',
tip: 'Embedding Model',
},
speechToTextModel: {
key: 'Speech-to-Text Model',
tip: 'Speech-to-Text Model',
},
quota: 'Quota',
searchModel: 'Search model',
noModelFound: 'No model found for {{model}}',
models: 'Models',
......@@ -229,6 +236,8 @@ const translation = {
callTimes: 'Call times',
tokens: 'Tokens',
buyQuota: 'Buy Quota',
priorityUse: 'Priority use',
removeKey: 'Remove API Key',
},
addApiKey: 'Add your API key',
invalidApiKey: 'Invalid API key',
......
......@@ -204,6 +204,8 @@ const translation = {
},
},
modelProvider: {
selectModel: 'Select your model',
setupModelFirst: 'Please set up your model first',
systemReasoningModel: {
key: 'System Reasoning Model',
tip: 'System Reasoning Model',
......@@ -212,6 +214,7 @@ const translation = {
key: 'Embedding Model',
tip: 'Embedding Model',
},
quota: 'Quota',
searchModel: 'Search model',
noModelFound: 'No model found for {{model}}',
models: 'Models',
......@@ -229,6 +232,8 @@ const translation = {
callTimes: 'Call times',
tokens: 'Tokens',
buyQuota: 'Buy Quota',
priorityUse: 'Priority use',
removeKey: 'Remove API Key',
},
addApiKey: 'Add your API key',
invalidApiKey: 'Invalid API key',
......
......@@ -61,6 +61,15 @@ module.exports = {
pc: '769px',
// => @media (min-width: 769px) { ... }
},
boxShadow: {
'xs': '0px 1px 2px 0px rgba(16, 24, 40, 0.05)',
'sm': '0px 1px 2px 0px rgba(16, 24, 40, 0.06), 0px 1px 3px 0px rgba(16, 24, 40, 0.10)',
'md': '0px 2px 4px -2px rgba(16, 24, 40, 0.06), 0px 4px 8px -2px rgba(16, 24, 40, 0.10)',
'lg': '0px 4px 6px -2px rgba(16, 24, 40, 0.03), 0px 12px 16px -4px rgba(16, 24, 40, 0.08)',
'xl': '0px 8px 8px -4px rgba(16, 24, 40, 0.03), 0px 20px 24px -4px rgba(16, 24, 40, 0.08)',
'2xl': '0px 24px 48px -12px rgba(16, 24, 40, 0.18)',
'3xl': '0px 32px 64px -12px rgba(16, 24, 40, 0.14)',
},
},
},
plugins: [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment