mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-27 12:51:26 +08:00
feat(ui): add new spinner component and update lucide-react
- Add new general-purpose spinner component with multiple variants - Rename old Spinner component to SearchSpinner to clarify its purpose - Update lucide-react dependency to v0.546.0
This commit is contained in:
parent
a0445a307a
commit
578cf38072
@ -291,7 +291,7 @@
|
||||
"lint-staged": "^15.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lru-cache": "^11.1.0",
|
||||
"lucide-react": "^0.525.0",
|
||||
"lucide-react": "^0.546.0",
|
||||
"macos-release": "^3.4.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"mermaid": "^11.10.1",
|
||||
|
||||
@ -17,6 +17,7 @@ const spinnerVariants = {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: This is not a general spinner. It's just for searching.
|
||||
export default function Spinner({ text, className = '' }: Props) {
|
||||
return (
|
||||
<motion.div
|
||||
|
||||
@ -9,7 +9,7 @@ export { default as EmojiIcon } from './base/EmojiIcon'
|
||||
export type { CustomFallbackProps, ErrorBoundaryCustomizedProps } from './base/ErrorBoundary'
|
||||
export { ErrorBoundary } from './base/ErrorBoundary'
|
||||
export { default as IndicatorLight } from './base/IndicatorLight'
|
||||
export { default as Spinner } from './base/Spinner'
|
||||
export { default as SearchSpinner } from './base/Spinner'
|
||||
export type { StatusTagProps, StatusType } from './base/StatusTag'
|
||||
export { ErrorTag, InfoTag, StatusTag, SuccessTag, WarnTag } from './base/StatusTag'
|
||||
export { DescriptionSwitch, Switch } from './base/Switch'
|
||||
@ -97,3 +97,4 @@ export * from './ui/command'
|
||||
export * from './ui/dialog'
|
||||
export * from './ui/popover'
|
||||
export * from './ui/shadcn-io/dropzone'
|
||||
export * from './ui/shadcn-io/spinner'
|
||||
|
||||
215
packages/ui/src/components/ui/shadcn-io/spinner/index.tsx
Normal file
215
packages/ui/src/components/ui/shadcn-io/spinner/index.tsx
Normal file
@ -0,0 +1,215 @@
|
||||
import { cn } from '@cherrystudio/ui/utils/index'
|
||||
import { LoaderCircleIcon, LoaderIcon, LoaderPinwheelIcon, type LucideProps } from 'lucide-react'
|
||||
|
||||
type SpinnerVariantProps = Omit<SpinnerProps, 'variant'>
|
||||
|
||||
const Default = ({ className, ...props }: SpinnerVariantProps) => (
|
||||
<LoaderIcon className={cn('animate-spin', className)} {...props} />
|
||||
)
|
||||
|
||||
const Circle = ({ className, ...props }: SpinnerVariantProps) => (
|
||||
<LoaderCircleIcon className={cn('animate-spin', className)} {...props} />
|
||||
)
|
||||
|
||||
const Pinwheel = ({ className, ...props }: SpinnerVariantProps) => (
|
||||
<LoaderPinwheelIcon className={cn('animate-spin', className)} {...props} />
|
||||
)
|
||||
|
||||
const CircleFilled = ({ className, size = 24, ...props }: SpinnerVariantProps) => (
|
||||
<div className="relative" style={{ width: size, height: size }}>
|
||||
<div className="absolute inset-0 rotate-180">
|
||||
<LoaderCircleIcon
|
||||
className={cn('animate-spin', className, 'text-foreground opacity-20')}
|
||||
size={size}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
<LoaderCircleIcon className={cn('relative animate-spin', className)} size={size} {...props} />
|
||||
</div>
|
||||
)
|
||||
|
||||
const Ellipsis = ({ size = 24, ...props }: SpinnerVariantProps) => {
|
||||
return (
|
||||
<svg height={size} viewBox="0 0 24 24" width={size} xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<title>Loading...</title>
|
||||
<circle cx="4" cy="12" fill="currentColor" r="2">
|
||||
<animate
|
||||
attributeName="cy"
|
||||
begin="0;ellipsis3.end+0.25s"
|
||||
calcMode="spline"
|
||||
dur="0.6s"
|
||||
id="ellipsis1"
|
||||
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
||||
values="12;6;12"
|
||||
/>
|
||||
</circle>
|
||||
<circle cx="12" cy="12" fill="currentColor" r="2">
|
||||
<animate
|
||||
attributeName="cy"
|
||||
begin="ellipsis1.begin+0.1s"
|
||||
calcMode="spline"
|
||||
dur="0.6s"
|
||||
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
||||
values="12;6;12"
|
||||
/>
|
||||
</circle>
|
||||
<circle cx="20" cy="12" fill="currentColor" r="2">
|
||||
<animate
|
||||
attributeName="cy"
|
||||
begin="ellipsis1.begin+0.2s"
|
||||
calcMode="spline"
|
||||
dur="0.6s"
|
||||
id="ellipsis3"
|
||||
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
||||
values="12;6;12"
|
||||
/>
|
||||
</circle>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
const Ring = ({ size = 24, ...props }: SpinnerVariantProps) => (
|
||||
<svg
|
||||
height={size}
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 44 44"
|
||||
width={size}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}>
|
||||
<title>Loading...</title>
|
||||
<g fill="none" fillRule="evenodd" strokeWidth="2">
|
||||
<circle cx="22" cy="22" r="1">
|
||||
<animate
|
||||
attributeName="r"
|
||||
begin="0s"
|
||||
calcMode="spline"
|
||||
dur="1.8s"
|
||||
keySplines="0.165, 0.84, 0.44, 1"
|
||||
keyTimes="0; 1"
|
||||
repeatCount="indefinite"
|
||||
values="1; 20"
|
||||
/>
|
||||
<animate
|
||||
attributeName="stroke-opacity"
|
||||
begin="0s"
|
||||
calcMode="spline"
|
||||
dur="1.8s"
|
||||
keySplines="0.3, 0.61, 0.355, 1"
|
||||
keyTimes="0; 1"
|
||||
repeatCount="indefinite"
|
||||
values="1; 0"
|
||||
/>
|
||||
</circle>
|
||||
<circle cx="22" cy="22" r="1">
|
||||
<animate
|
||||
attributeName="r"
|
||||
begin="-0.9s"
|
||||
calcMode="spline"
|
||||
dur="1.8s"
|
||||
keySplines="0.165, 0.84, 0.44, 1"
|
||||
keyTimes="0; 1"
|
||||
repeatCount="indefinite"
|
||||
values="1; 20"
|
||||
/>
|
||||
<animate
|
||||
attributeName="stroke-opacity"
|
||||
begin="-0.9s"
|
||||
calcMode="spline"
|
||||
dur="1.8s"
|
||||
keySplines="0.3, 0.61, 0.355, 1"
|
||||
keyTimes="0; 1"
|
||||
repeatCount="indefinite"
|
||||
values="1; 0"
|
||||
/>
|
||||
</circle>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
|
||||
const Bars = ({ size = 24, ...props }: SpinnerVariantProps) => (
|
||||
<svg height={size} viewBox="0 0 24 24" width={size} xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<title>Loading...</title>
|
||||
<style>{`
|
||||
.spinner-bar {
|
||||
animation: spinner-bars-animation .8s linear infinite;
|
||||
animation-delay: -.8s;
|
||||
}
|
||||
.spinner-bars-2 {
|
||||
animation-delay: -.65s;
|
||||
}
|
||||
.spinner-bars-3 {
|
||||
animation-delay: -0.5s;
|
||||
}
|
||||
@keyframes spinner-bars-animation {
|
||||
0% {
|
||||
y: 1px;
|
||||
height: 22px;
|
||||
}
|
||||
93.75% {
|
||||
y: 5px;
|
||||
height: 14px;
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
<rect className="spinner-bar" fill="currentColor" height="22" width="6" x="1" y="1" />
|
||||
<rect className="spinner-bar spinner-bars-2" fill="currentColor" height="22" width="6" x="9" y="1" />
|
||||
<rect className="spinner-bar spinner-bars-3" fill="currentColor" height="22" width="6" x="17" y="1" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
const Infinite = ({ size = 24, ...props }: SpinnerVariantProps) => (
|
||||
<svg
|
||||
height={size}
|
||||
preserveAspectRatio="xMidYMid"
|
||||
viewBox="0 0 100 100"
|
||||
width={size}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}>
|
||||
<title>Loading...</title>
|
||||
<path
|
||||
d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40 C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeDasharray="205.271142578125 51.317785644531256"
|
||||
strokeLinecap="round"
|
||||
strokeWidth="10"
|
||||
style={{
|
||||
transform: 'scale(0.8)',
|
||||
transformOrigin: '50px 50px'
|
||||
}}>
|
||||
<animate
|
||||
attributeName="stroke-dashoffset"
|
||||
dur="2s"
|
||||
keyTimes="0;1"
|
||||
repeatCount="indefinite"
|
||||
values="0;256.58892822265625"
|
||||
/>
|
||||
</path>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export type SpinnerProps = LucideProps & {
|
||||
variant?: 'default' | 'circle' | 'pinwheel' | 'circle-filled' | 'ellipsis' | 'ring' | 'bars' | 'infinite'
|
||||
}
|
||||
|
||||
export const Spinner = ({ variant, ...props }: SpinnerProps) => {
|
||||
switch (variant) {
|
||||
case 'circle':
|
||||
return <Circle {...props} />
|
||||
case 'pinwheel':
|
||||
return <Pinwheel {...props} />
|
||||
case 'circle-filled':
|
||||
return <CircleFilled {...props} />
|
||||
case 'ellipsis':
|
||||
return <Ellipsis {...props} />
|
||||
case 'ring':
|
||||
return <Ring {...props} />
|
||||
case 'bars':
|
||||
return <Bars {...props} />
|
||||
case 'infinite':
|
||||
return <Infinite {...props} />
|
||||
default:
|
||||
return <Default {...props} />
|
||||
}
|
||||
}
|
||||
20
yarn.lock
20
yarn.lock
@ -17318,7 +17318,7 @@ __metadata:
|
||||
lint-staged: "npm:^15.5.0"
|
||||
lodash: "npm:^4.17.21"
|
||||
lru-cache: "npm:^11.1.0"
|
||||
lucide-react: "npm:^0.525.0"
|
||||
lucide-react: "npm:^0.546.0"
|
||||
macos-release: "npm:^3.4.0"
|
||||
markdown-it: "npm:^14.1.0"
|
||||
mermaid: "npm:^11.10.1"
|
||||
@ -25322,15 +25322,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lucide-react@npm:^0.525.0":
|
||||
version: 0.525.0
|
||||
resolution: "lucide-react@npm:0.525.0"
|
||||
peerDependencies:
|
||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
checksum: 10c0/81c4438e2cf1c86ea2ebe0a97b378201512450894283cccce766a89bc6a4e47c8df1d9115d845d98f582bb0a10be31c454aa232520fea35018dac1cd8466ea9b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lucide-react@npm:^0.545.0":
|
||||
version: 0.545.0
|
||||
resolution: "lucide-react@npm:0.545.0"
|
||||
@ -25340,6 +25331,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lucide-react@npm:^0.546.0":
|
||||
version: 0.546.0
|
||||
resolution: "lucide-react@npm:0.546.0"
|
||||
peerDependencies:
|
||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
checksum: 10c0/42ee0bd358517f012297aefb69b54da0b3c62f1ac8485ffa24141b63f05c9f4a682eacc2637c4b13f597aed11f9a8c79627af0c17717400bebb25581daeaad80
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lz-string@npm:^1.5.0":
|
||||
version: 1.5.0
|
||||
resolution: "lz-string@npm:1.5.0"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user