support for disable element

This commit is contained in:
SrGooglo 2025-02-18 04:22:43 +00:00
parent 379838d0f7
commit 37ab0184c2
2 changed files with 179 additions and 171 deletions

View File

@ -4,68 +4,73 @@ import classnames from "classnames"
import "./index.less" import "./index.less"
export default (props) => { export default (props) => {
const [liked, setLiked] = React.useState(props.liked) const [liked, setLiked] = React.useState(
const [clicked, setClicked] = React.useState(false) typeof props.liked === "function" ? false : props.liked,
)
const [clicked, setClicked] = React.useState(false)
// TODO: Support handle like change on websocket event // TODO: Support handle like change on websocket event
if (typeof props.watchWs === "object") { if (typeof props.watchWs === "object") {
// useWsEvents({ // useWsEvents({
// [props.watchWs.event]: (data) => { // [props.watchWs.event]: (data) => {
// handleUpdateTrackLike(data.track_id, data.action === "liked") // handleUpdateTrackLike(data.track_id, data.action === "liked")
// } // }
// }, { // }, {
// socketName: props.watchWs.socket, // socketName: props.watchWs.socket,
// }) // })
} }
async function computeLikedState() { async function computeLikedState() {
if (typeof props.liked === "function") { if (props.disabled) {
let result = await props.liked() return false
}
result = result.liked ?? result if (typeof props.liked === "function") {
let result = await props.liked()
return setLiked(result) result = result.liked ?? result
}
return setLiked(props.liked) return setLiked(result)
} }
const handleClick = () => { return setLiked(props.liked)
setClicked(true) }
setTimeout(() => { const handleClick = () => {
setClicked(false) if (props.disabled) {
}, 500) return false
}
if (typeof props.onClick === "function") { setClicked(true)
props.onClick()
}
setLiked(!liked) setTimeout(() => {
} setClicked(false)
}, 500)
React.useEffect(() => { if (typeof props.onClick === "function") {
computeLikedState() props.onClick()
}, [props.liked]) }
return <button setLiked(!liked)
className={classnames( }
"likeButton",
{ React.useEffect(() => {
["liked"]: liked, computeLikedState()
["clicked"]: clicked, }, [props.liked])
}
)} return (
onClick={handleClick} <button
> className={classnames("likeButton", {
{ ["liked"]: liked,
!!props.ripple && <div className="ripple" /> ["clicked"]: clicked,
} ["disabled"]: props.disabled,
<svg })}
className="heart" onClick={handleClick}
viewBox="0 0 24 24" >
> {!!props.ripple && <div className="ripple" />}
<path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"></path> <svg className="heart" viewBox="0 0 24 24">
</svg> <path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"></path>
</button> </svg>
</button>
)
} }

View File

@ -1,158 +1,161 @@
@likeAnimationDuration : .5s; @likeAnimationDuration: 0.5s;
@likeAnimationEasing : cubic-bezier(.7, 0, .3, 1); @likeAnimationEasing: cubic-bezier(0.7, 0, 0.3, 1);
.likeButton { .likeButton {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: var(--text-color); color: var(--text-color);
border: none; border: none;
border-radius: 50%; border-radius: 50%;
width: 1em; width: 1em;
height: 1em; height: 1em;
padding: 0; padding: 0;
margin: 0; margin: 0;
z-index: 2; z-index: 2;
transition: all @likeAnimationDuration @likeAnimationEasing; transition: all @likeAnimationDuration @likeAnimationEasing;
background-color: transparent; background-color: transparent;
&:before { &:before {
z-index: -1; z-index: -1;
content: ''; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 1em; width: 1em;
height: 1em; height: 1em;
border-radius: inherit; border-radius: inherit;
transition: inherit; transition: inherit;
} }
&:after { &:after {
content: ''; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 1em; width: 1em;
height: 1em; height: 1em;
border-radius: inherit; border-radius: inherit;
z-index: -1; z-index: -1;
} }
&.liked { &.liked {
.heart { .heart {
>path { > path {
stroke: var(--colorPrimary); stroke: var(--colorPrimary);
fill: var(--colorPrimary); fill: var(--colorPrimary);
} }
filter: drop-shadow(0px 0px 2px var(--colorPrimary)); filter: drop-shadow(0px 0px 2px var(--colorPrimary));
} }
} }
&.clicked { &.clicked {
.heart { .heart {
animation: heart-bounce @likeAnimationDuration @likeAnimationEasing; animation: heart-bounce @likeAnimationDuration @likeAnimationEasing;
@keyframes heart-bounce { @keyframes heart-bounce {
40% { 40% {
transform: scale(0.7); transform: scale(0.7);
} }
0%, 0%,
80%, 80%,
100% { 100% {
transform: scale(1); transform: scale(1);
} }
} }
} }
} }
.heart { &.disabled {
position: relative; pointer-events: none;
opacity: 0.5;
}
cursor: pointer; .heart {
position: relative;
>path { cursor: pointer;
stroke-width: 2;
transition: fill @likeAnimationDuration @likeAnimationEasing;
stroke: currentColor;
fill: transparent;
}
animation: none; > path {
stroke-width: 2;
transition: fill @likeAnimationDuration @likeAnimationEasing;
stroke: currentColor;
fill: transparent;
}
width: 1em; animation: none;
height: 1em;
margin: 0; width: 1em;
height: 1em;
transition: all @likeAnimationDuration @likeAnimationEasing; margin: 0;
}
.ripple { transition: all @likeAnimationDuration @likeAnimationEasing;
position: absolute; }
height: 1em; .ripple {
width: 1em; position: absolute;
border-radius: 50%; height: 1em;
overflow: hidden; width: 1em;
z-index: 1; border-radius: 50%;
overflow: hidden;
&:before { z-index: 1;
content: '';
position: absolute; &:before {
top: 0; content: "";
left: 0; position: absolute;
width: 100%; top: 0;
height: 100%; left: 0;
border: .4em solid var(--colorPrimary); width: 100%;
border-radius: inherit; height: 100%;
transform: scale(0); border: 0.4em solid var(--colorPrimary);
} border-radius: inherit;
} transform: scale(0);
}
}
} }
@keyframes ripple-out { @keyframes ripple-out {
from { from {
transform: scale(0); transform: scale(0);
} }
to { to {
transform: scale(5); transform: scale(5);
} }
} }
@keyframes depress { @keyframes depress {
from,
to {
transform: none;
}
from, 50% {
to { transform: translateY(5%) scale(0.9);
transform: none; }
}
50% {
transform: translateY(5%) scale(0.9);
}
} }
@keyframes depress-shadow { @keyframes depress-shadow {
from,
to {
transform: none;
}
from, 50% {
to { transform: scale(0.5);
transform: none; }
}
50% {
transform: scale(0.5);
}
} }