|
|
@@ -1,20 +1,27 @@
|
|
|
-import React from 'react'
|
|
|
+import React, { useRef } from 'react'
|
|
|
import DivBtn from '../public/div-btn/div-btn.jsx'
|
|
|
+import './update-btn.scss'
|
|
|
+import { useUpdateBtnAnimation } from './update-btn.js'
|
|
|
|
|
|
/**
|
|
|
* Refresh Button Component
|
|
|
* @param {Object} props
|
|
|
- * @param {Function} props.onClick - Click handler function
|
|
|
+ * @param {Function} props.onClick - Click handler function (can return Promise)
|
|
|
* @param {boolean} props.disabled - Disable button (default: false)
|
|
|
+ * @param {boolean} props.loading - External loading state (optional)
|
|
|
* @param {string} props.title - Tooltip text (default: 'Refresh')
|
|
|
* @param {string} props.className - Additional CSS classes
|
|
|
*/
|
|
|
function UpdateBtn({
|
|
|
onClick,
|
|
|
disabled = false,
|
|
|
+ loading: externalLoading,
|
|
|
title = 'Refresh',
|
|
|
className = ''
|
|
|
}) {
|
|
|
+ const btnRef = useRef(null)
|
|
|
+ const { isLoading, handleClick } = useUpdateBtnAnimation(btnRef, externalLoading, onClick, disabled)
|
|
|
+
|
|
|
// Default refresh icon
|
|
|
const refreshIcon = (
|
|
|
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
@@ -24,21 +31,11 @@ function UpdateBtn({
|
|
|
</svg>
|
|
|
)
|
|
|
|
|
|
- // Hover refresh icon (slightly bolder)
|
|
|
- const refreshIconHover = (
|
|
|
+ // Loading icon (spinning circle)
|
|
|
+ const loadingIcon = (
|
|
|
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
- <path d="M1 4V10H7" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
|
|
|
- <path d="M23 20V14H17" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
|
|
|
- <path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10M23 14L18.36 18.36A9 9 0 0 1 3.51 15" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
|
|
|
- </svg>
|
|
|
- )
|
|
|
-
|
|
|
- // Pressed refresh icon (thicker)
|
|
|
- const refreshIconPressed = (
|
|
|
- <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
- <path d="M1 4V10H7" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"/>
|
|
|
- <path d="M23 20V14H17" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"/>
|
|
|
- <path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10M23 14L18.36 18.36A9 9 0 0 1 3.51 15" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"/>
|
|
|
+ <circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="2" strokeLinecap="round" opacity="0.2"/>
|
|
|
+ <circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeDasharray="47.124" strokeDashoffset="47.124"/>
|
|
|
</svg>
|
|
|
)
|
|
|
|
|
|
@@ -52,18 +49,18 @@ function UpdateBtn({
|
|
|
)
|
|
|
|
|
|
return (
|
|
|
- <DivBtn
|
|
|
- icon={refreshIcon}
|
|
|
- iconHover={refreshIconHover}
|
|
|
- iconPressed={refreshIconPressed}
|
|
|
- iconDisabled={refreshIconDisabled}
|
|
|
- onClick={onClick}
|
|
|
- disabled={disabled}
|
|
|
- title={title}
|
|
|
- className={className}
|
|
|
- rotateOnHover={true}
|
|
|
- rotateDegrees={180}
|
|
|
- />
|
|
|
+ <div ref={btnRef}>
|
|
|
+ <DivBtn
|
|
|
+ icon={isLoading ? loadingIcon : refreshIcon}
|
|
|
+ iconDisabled={refreshIconDisabled}
|
|
|
+ onClick={handleClick}
|
|
|
+ disabled={disabled || isLoading}
|
|
|
+ title={isLoading ? 'Loading...' : title}
|
|
|
+ className={`update-btn ${isLoading ? 'update-btn--loading' : ''} ${className}`}
|
|
|
+ rotateOnHover={!isLoading}
|
|
|
+ rotateDegrees={180}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
)
|
|
|
}
|
|
|
|