enzostvs's picture
enzostvs HF Staff
Upload 172 files
9cd6ddb verified
import { forwardRef, useEffect, useRef, useState } from "react";
import { BadgeType } from "@/types/badge";
import { FONT_FAMILY } from "@/components/font-family/font-family.constants";
import { RATIONAL_BADGE_WIDTH } from "../badge-editor.constants";
import { Icons } from "@/components/svg/icons";
import { IconItem } from "@/types/editor";
import { BADGE_COMPONENTS } from "@/components/svg/badges";
import classNames from "classnames";
import { ShineEffect } from "./shine_effect";
export const Badge = forwardRef(
(
{
badge,
size = "medium",
}: {
badge: BadgeType;
size?: "medium" | "small";
},
ref
) => {
const textRef = useRef<any>(null);
const svgRef = useRef<any>(null);
const badgeContentRef = useRef<any>(null);
const [viewBox, setViewBox] = useState<string>("0 0 24 24");
useEffect(() => {
if (!textRef.current) return;
if (!badgeContentRef.current) return;
const textWidth = textRef.current.getBoundingClientRect().width;
let newBadgeWidth = RATIONAL_BADGE_WIDTH;
if (textWidth > RATIONAL_BADGE_WIDTH) {
newBadgeWidth = Math.ceil(textWidth / 32) * 32;
}
if (
(findShape?.autoResize || badge.type === "circle") &&
newBadgeWidth - textWidth < (badge.type === "circle" ? 6 : 3)
)
newBadgeWidth += 32;
badgeContentRef.current.style.width = `${newBadgeWidth}px`;
}, [
badge.text,
badge.fontFamily,
badge.letterSpacing,
badge.fontWeight,
badge.type,
badge?.icon?.component,
badge?.icon?.enabled,
badge?.icon?.position,
]);
const fontFamily = FONT_FAMILY?.find((f) => f.label === badge?.fontFamily);
const defaultStyle = {
letterSpacing: badge?.letterSpacing,
fontWeight: badge?.fontWeight,
};
const findIcon = Icons?.find(
(i: IconItem) => badge?.icon?.component === i.name
);
const findShape = BADGE_COMPONENTS?.find(
(b: any) => b.name === badge?.type
);
useEffect(() => {
return setViewBox(
svgRef?.current?.getAttribute("viewBox") ?? "0 0 200 200"
);
}, [badge?.icon]);
const IconComponent = findIcon?.component as any;
const ShapeComponent = findShape?.component as any;
return (
<div
id={size === "medium" ? "discotools-selected-badge" : ""}
ref={ref as any}
className="max-w-max flex items-center h-[32px] justify-center relative"
>
{findShape?.component && (
<ShapeComponent.left color={badge?.stringColor ?? badge?.colour} />
)}
{badge?.shinyEffect && (
<>
<ShineEffect className="absolute left-[6px] -bottom-[0px] z-1" />
<ShineEffect className="absolute right-[6px] -top-[0px] z-1" />
</>
)}
<div
className="whitespace-nowrap text-white font-bold flex text-[18px] h-[28px] items-center justify-center text-center transition-all duration-200 relative"
ref={badgeContentRef}
style={{
background: badge?.stringColor ?? badge?.colour,
borderRadius: badge.type !== "circle" ? 0 : badge?.radius ?? 0,
}}
>
<div
ref={textRef as any}
className="flex items-center justify-center gap-2"
>
{badge?.icon?.enabled &&
badge?.icon?.position?.includes("left") &&
findIcon?.component &&
badge?.icon?.component && (
<svg
width={16}
height={16}
fill={badge?.icon?.colour}
viewBox={viewBox}
style={{ minWidth: 16, minHeight: 16 }}
>
<IconComponent ref={svgRef as any} />
</svg>
)}
{badge?.text?.value && (
<p
className={`!bg-clip-text text-transparent ${fontFamily?.value}`}
style={
badge?.text?.gradient?.enabled
? {
backgroundImage:
badge?.text?.stringColor ?? badge?.text?.colour,
...defaultStyle,
}
: {
backgroundColor:
badge?.text?.stringColor ?? badge?.text?.colour,
...defaultStyle,
}
}
>
{badge?.text?.value}
</p>
)}
{badge?.icon?.enabled &&
badge?.icon?.position?.includes("right") &&
findIcon?.component &&
badge?.icon?.component && (
<svg
width={16}
height={16}
fill={badge?.icon?.colour}
viewBox={viewBox}
style={{ minWidth: 16, minHeight: 16 }}
>
<IconComponent ref={svgRef as any} />
</svg>
)}
</div>
</div>
{findShape?.component && (
<ShapeComponent.right color={badge?.stringColor ?? badge?.colour} />
)}
</div>
);
}
);