update the plugins page

This commit is contained in:
Yi
2024-09-14 17:09:25 +08:00
parent 6613b8f2e0
commit 21193c2fbf
22 changed files with 609 additions and 46 deletions

View File

@ -0,0 +1,28 @@
@tailwind components;
@layer components {
.badge {
@apply inline-flex justify-center items-center text-text-tertiary border border-divider-deep
}
.badge-l {
@apply rounded-md gap-1 min-w-6
}
/* m is for the regular button */
.badge-m {
@apply rounded-md gap-[3px] min-w-5
}
.badge-s {
@apply rounded-[5px] gap-0.5 min-w-[18px]
}
.badge.badge-warning {
@apply text-text-warning border border-text-warning
}
.badge.badge-accent {
@apply text-text-accent-secondary border border-text-accent-secondary
}
}

View File

@ -0,0 +1,81 @@
import type { CSSProperties, ReactNode } from 'react'
import React from 'react'
import { type VariantProps, cva } from 'class-variance-authority'
import classNames from '@/utils/classnames'
import './index.css'
enum BadgeState {
Warning = 'warning',
Accent = 'accent',
Default = '',
}
const BadgeVariants = cva(
'badge',
{
variants: {
size: {
s: 'badge-s',
m: 'badge-m',
l: 'badge-l',
},
},
defaultVariants: {
size: 'm',
},
},
)
type BadgeProps = {
size?: 's' | 'm' | 'l'
iconOnly?: boolean
uppercase?: boolean
state?: BadgeState
styleCss?: CSSProperties
children?: ReactNode
} & React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof BadgeVariants>
function getBadgeState(state: BadgeState) {
switch (state) {
case BadgeState.Warning:
return 'badge-warning'
case BadgeState.Accent:
return 'badge-accent'
default:
return ''
}
}
const Badge: React.FC<BadgeProps> = ({
className,
size,
state = BadgeState.Default,
iconOnly = false,
uppercase = false,
styleCss,
children,
...props
}) => {
return (
<div
className={classNames(
BadgeVariants({ size, className }),
getBadgeState(state),
size === 's'
? (iconOnly ? 'p-[3px]' : 'px-[5px] py-[3px]')
: size === 'l'
? (iconOnly ? 'p-1.5' : 'px-2 py-1')
: (iconOnly ? 'p-1' : 'px-[5px] py-[2px]'),
uppercase ? 'system-2xs-medium-uppercase' : 'system-2xs-medium',
)}
style={styleCss}
{...props}
>
{children}
</div>
)
}
Badge.displayName = 'Badge'
export default Badge
export { Badge, BadgeState, BadgeVariants }

View File

@ -0,0 +1,8 @@
<svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group">
<path id="Vector" d="M5.6475 8.0115L0.333496 5.05884V11.3335C0.333491 11.4524 0.365258 11.569 0.425506 11.6715C0.485754 11.7739 0.572294 11.8584 0.676163 11.9162L6.3335 15.0588V9.17684C6.33344 8.93907 6.26981 8.70565 6.14919 8.50075C6.02857 8.29586 5.85536 8.12694 5.6475 8.0115Z" fill="#354052"/>
<path id="Vector_2" d="M7.66699 9.17684V15.0588L13.3243 11.9162C13.4282 11.8584 13.5147 11.7739 13.575 11.6715C13.6352 11.569 13.667 11.4524 13.667 11.3335V5.05884L8.35299 8.0115C8.14513 8.12694 7.97192 8.29586 7.8513 8.50075C7.73068 8.70565 7.66705 8.93907 7.66699 9.17684Z" fill="#676F83"/>
<path id="Vector_3" d="M10.1913 2.34351C9.804 3.33351 8.588 4.00017 7 4.00017C5.412 4.00017 4.196 3.33351 3.80867 2.34351L1 3.90417L6.35267 6.87817C6.5507 6.98815 6.77348 7.04586 7 7.04586C7.22652 7.04586 7.4493 6.98815 7.64733 6.87817L13 3.90417L10.1913 2.34351Z" fill="#676F83"/>
<path id="Vector_4" d="M7 2.66675C8.10457 2.66675 9 2.21903 9 1.66675C9 1.11446 8.10457 0.666748 7 0.666748C5.89543 0.666748 5 1.11446 5 1.66675C5 2.21903 5.89543 2.66675 7 2.66675Z" fill="#354052"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Icon">
<path id="Vector" d="M3.99999 1.33325H7.99999V5.33325C7.99999 6.06963 8.59692 6.66659 9.33332 6.66659H13.3333V13.3333C13.3333 14.0697 12.7364 14.6666 12 14.6666H6.66666V13.3333H7.99999V11.9999H6.66666V10.6666H7.99999V9.33325H6.66666V7.99992H5.33332V9.33325H6.66666V10.6666H5.33332V11.9999H6.66666V13.3333H5.33332V14.6666H3.99999C3.26361 14.6666 2.66666 14.0697 2.66666 13.3333V2.66659C2.66666 1.93021 3.26361 1.33325 3.99999 1.33325Z" fill="#676F83"/>
<path id="Vector_2" opacity="0.5" d="M12.9428 4.99993C13.0415 5.09868 13.1232 5.21133 13.1859 5.33327H9.33334V1.48071C9.45528 1.54338 9.56794 1.62504 9.66668 1.72379L12.9428 4.99993Z" fill="#676F83"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 775 B

View File

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Icon">
<path id="Vector" d="M8 1C4.1325 1 1 4.1325 1 8C1 11.0975 3.00375 13.7137 5.78625 14.6413C6.13625 14.7025 6.2675 14.4925 6.2675 14.3088C6.2675 14.1425 6.25875 13.5913 6.25875 13.005C4.5 13.3288 4.045 12.5763 3.905 12.1825C3.82625 11.9812 3.485 11.36 3.1875 11.1937C2.9425 11.0625 2.5925 10.7387 3.17875 10.73C3.73 10.7212 4.12375 11.2375 4.255 11.4475C4.885 12.5062 5.89125 12.2088 6.29375 12.025C6.355 11.57 6.53875 11.2638 6.74 11.0887C5.1825 10.9137 3.555 10.31 3.555 7.6325C3.555 6.87125 3.82625 6.24125 4.2725 5.75125C4.2025 5.57625 3.9575 4.85875 4.3425 3.89625C4.3425 3.89625 4.92875 3.7125 6.2675 4.61375C6.8275 4.45625 7.4225 4.3775 8.0175 4.3775C8.6125 4.3775 9.2075 4.45625 9.7675 4.61375C11.1063 3.70375 11.6925 3.89625 11.6925 3.89625C12.0775 4.85875 11.8325 5.57625 11.7625 5.75125C12.2087 6.24125 12.48 6.8625 12.48 7.6325C12.48 10.3187 10.8438 10.9137 9.28625 11.0887C9.54 11.3075 9.75875 11.7275 9.75875 12.3837C9.75875 13.32 9.75 14.0725 9.75 14.3088C9.75 14.4925 9.88125 14.7113 10.2312 14.6413C11.6209 14.1721 12.8284 13.279 13.6839 12.0877C14.5393 10.8963 14.9996 9.46668 15 8C15 4.1325 11.8675 1 8 1Z" fill="#676F83"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,66 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "14",
"height": "16",
"viewBox": "0 0 14 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Group"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector",
"d": "M5.6475 8.0115L0.333496 5.05884V11.3335C0.333491 11.4524 0.365258 11.569 0.425506 11.6715C0.485754 11.7739 0.572294 11.8584 0.676163 11.9162L6.3335 15.0588V9.17684C6.33344 8.93907 6.26981 8.70565 6.14919 8.50075C6.02857 8.29586 5.85536 8.12694 5.6475 8.0115Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector_2",
"d": "M7.66699 9.17684V15.0588L13.3243 11.9162C13.4282 11.8584 13.5147 11.7739 13.575 11.6715C13.6352 11.569 13.667 11.4524 13.667 11.3335V5.05884L8.35299 8.0115C8.14513 8.12694 7.97192 8.29586 7.8513 8.50075C7.73068 8.70565 7.66705 8.93907 7.66699 9.17684Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector_3",
"d": "M10.1913 2.34351C9.804 3.33351 8.588 4.00017 7 4.00017C5.412 4.00017 4.196 3.33351 3.80867 2.34351L1 3.90417L6.35267 6.87817C6.5507 6.98815 6.77348 7.04586 7 7.04586C7.22652 7.04586 7.4493 6.98815 7.64733 6.87817L13 3.90417L10.1913 2.34351Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector_4",
"d": "M7 2.66675C8.10457 2.66675 9 2.21903 9 1.66675C9 1.11446 8.10457 0.666748 7 0.666748C5.89543 0.666748 5 1.11446 5 1.66675C5 2.21903 5.89543 2.66675 7 2.66675Z",
"fill": "currentColor"
},
"children": []
}
]
}
]
},
"name": "Group"
}

View File

@ -0,0 +1,16 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Group.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} />)
Icon.displayName = 'Group'
export default Icon

View File

@ -1 +1,2 @@
export { default as Generator } from './Generator'
export { default as Group } from './Group'

View File

@ -0,0 +1,47 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "16",
"height": "16",
"viewBox": "0 0 16 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Icon"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector",
"d": "M3.99999 1.33325H7.99999V5.33325C7.99999 6.06963 8.59692 6.66659 9.33332 6.66659H13.3333V13.3333C13.3333 14.0697 12.7364 14.6666 12 14.6666H6.66666V13.3333H7.99999V11.9999H6.66666V10.6666H7.99999V9.33325H6.66666V7.99992H5.33332V9.33325H6.66666V10.6666H5.33332V11.9999H6.66666V13.3333H5.33332V14.6666H3.99999C3.26361 14.6666 2.66666 14.0697 2.66666 13.3333V2.66659C2.66666 1.93021 3.26361 1.33325 3.99999 1.33325Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector_2",
"opacity": "0.5",
"d": "M12.9428 4.99993C13.0415 5.09868 13.1232 5.21133 13.1859 5.33327H9.33334V1.48071C9.45528 1.54338 9.56794 1.62504 9.66668 1.72379L12.9428 4.99993Z",
"fill": "currentColor"
},
"children": []
}
]
}
]
},
"name": "FileZip"
}

View File

@ -0,0 +1,16 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './FileZip.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} />)
Icon.displayName = 'FileZip'
export default Icon

View File

@ -1,3 +1,4 @@
export { default as File05 } from './File05'
export { default as FileSearch02 } from './FileSearch02'
export { default as FileZip } from './FileZip'
export { default as Folder } from './Folder'

View File

@ -0,0 +1,36 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "16",
"height": "16",
"viewBox": "0 0 16 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Icon"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector",
"d": "M8 1C4.1325 1 1 4.1325 1 8C1 11.0975 3.00375 13.7137 5.78625 14.6413C6.13625 14.7025 6.2675 14.4925 6.2675 14.3088C6.2675 14.1425 6.25875 13.5913 6.25875 13.005C4.5 13.3288 4.045 12.5763 3.905 12.1825C3.82625 11.9812 3.485 11.36 3.1875 11.1937C2.9425 11.0625 2.5925 10.7387 3.17875 10.73C3.73 10.7212 4.12375 11.2375 4.255 11.4475C4.885 12.5062 5.89125 12.2088 6.29375 12.025C6.355 11.57 6.53875 11.2638 6.74 11.0887C5.1825 10.9137 3.555 10.31 3.555 7.6325C3.555 6.87125 3.82625 6.24125 4.2725 5.75125C4.2025 5.57625 3.9575 4.85875 4.3425 3.89625C4.3425 3.89625 4.92875 3.7125 6.2675 4.61375C6.8275 4.45625 7.4225 4.3775 8.0175 4.3775C8.6125 4.3775 9.2075 4.45625 9.7675 4.61375C11.1063 3.70375 11.6925 3.89625 11.6925 3.89625C12.0775 4.85875 11.8325 5.57625 11.7625 5.75125C12.2087 6.24125 12.48 6.8625 12.48 7.6325C12.48 10.3187 10.8438 10.9137 9.28625 11.0887C9.54 11.3075 9.75875 11.7275 9.75875 12.3837C9.75875 13.32 9.75 14.0725 9.75 14.3088C9.75 14.4925 9.88125 14.7113 10.2312 14.6413C11.6209 14.1721 12.8284 13.279 13.6839 12.0877C14.5393 10.8963 14.9996 9.46668 15 8C15 4.1325 11.8675 1 8 1Z",
"fill": "currentColor"
},
"children": []
}
]
}
]
},
"name": "Github"
}

View File

@ -0,0 +1,16 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Github.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} />)
Icon.displayName = 'Github'
export default Icon

View File

@ -5,6 +5,7 @@ export { default as Download02 } from './Download02'
export { default as Edit03 } from './Edit03'
export { default as Edit04 } from './Edit04'
export { default as Eye } from './Eye'
export { default as Github } from './Github'
export { default as MessageClockCircle } from './MessageClockCircle'
export { default as PlusCircle } from './PlusCircle'
export { default as QuestionTriangle } from './QuestionTriangle'

View File

@ -1,64 +1,81 @@
import type { FC } from 'react'
import { useEffect, useState } from 'react'
import cn from '@/utils/classnames'
import Badge, { BadgeState } from '@/app/components/base/badge/index'
type Option = {
value: string
text: string
}
type TabSliderProps = {
className?: string
itemWidth?: number
value: string
onChange: (v: string) => void
options: Option[]
}
const TabSlider: FC<TabSliderProps> = ({
className,
itemWidth = 118,
value,
onChange,
options,
}) => {
const currentIndex = options.findIndex(option => option.value === value)
const current = options[currentIndex]
const [activeIndex, setActiveIndex] = useState(options.findIndex(option => option.value === value))
const [sliderStyle, setSliderStyle] = useState({})
const updateSliderStyle = (index: number) => {
const tabElement = document.getElementById(`tab-${index}`)
if (tabElement) {
const { offsetLeft, offsetWidth } = tabElement
setSliderStyle({
transform: `translateX(${offsetLeft}px)`,
width: `${offsetWidth}px`,
})
}
}
useEffect(() => {
const newIndex = options.findIndex(option => option.value === value)
setActiveIndex(newIndex)
updateSliderStyle(newIndex)
}, [value, options])
return (
<div className={cn(className, 'relative flex p-0.5 rounded-lg bg-gray-200')}>
{
options.map((option, index) => (
<div
key={option.value}
className={`
flex justify-center items-center h-7 text-[13px]
font-semibold text-gray-600 rounded-[7px] cursor-pointer
hover:bg-gray-50
${index !== options.length - 1 && 'mr-[1px]'}
`}
style={{
width: itemWidth,
}}
onClick={() => onChange(option.value)}
>
{option.text}
</div>
))
}
{
current && (
<div
className={`
absolute flex justify-center items-center h-7 bg-white text-[13px] font-semibold text-primary-600
border-[0.5px] border-gray-200 rounded-[7px] shadow-xs transition-transform
`}
style={{
width: itemWidth,
transform: `translateX(${currentIndex * itemWidth + 1}px)`,
}}
>
{current.text}
</div>
)
}
<div className={cn(className, 'inline-flex p-0.5 rounded-[10px] bg-components-segmented-control-bg-normal relative items-center justify-center')}>
<div
className="absolute top-0.5 bottom-0.5 left-0 right-0 bg-components-panel-bg rounded-[10px] transition-transform duration-300 ease-in-out shadows-shadow-xs"
style={sliderStyle}
/>
{options.map((option, index) => (
<div
id={`tab-${index}`}
key={option.value}
className={cn(
'relative flex justify-center items-center px-2.5 py-1.5 gap-1 rounded-[10px] transition-colors duration-300 ease-in-out cursor-pointer z-10',
'system-md-semibold',
index === activeIndex
? 'text-text-primary'
: 'text-text-tertiary',
)}
onClick={() => {
if (index !== activeIndex) {
onChange(option.value)
updateSliderStyle(index)
}
}}
>
{option.text}
{option.value === 'plugins'
&& <Badge
size='s'
uppercase={true}
state={BadgeState.Default}
>
6
</Badge>
}
</div>
))}
</div>
)
}