967 lines
24 KiB
TypeScript
967 lines
24 KiB
TypeScript
"use client";
|
|
|
|
import type { Transition, Variants } from "framer-motion";
|
|
import { motion, useAnimation } from "framer-motion";
|
|
import { useCallback, useEffect } from "react";
|
|
|
|
const playIconVariants: Variants = {
|
|
normal: {
|
|
x: 0,
|
|
rotate: 0,
|
|
},
|
|
animate: {
|
|
x: [0, -1, 2, 0],
|
|
rotate: [0, -10, 0, 0],
|
|
transition: {
|
|
duration: 0.5,
|
|
times: [0, 0.2, 0.5, 1],
|
|
stiffness: 260,
|
|
damping: 20,
|
|
},
|
|
},
|
|
};
|
|
|
|
const defaultTransition: Transition = {
|
|
duration: 0.6,
|
|
opacity: { duration: 0.2 },
|
|
};
|
|
|
|
const pathVariants: Variants = {
|
|
normal: {
|
|
pathLength: 1,
|
|
opacity: 1,
|
|
},
|
|
animate: {
|
|
opacity: [0, 1],
|
|
pathLength: [0.5, 1],
|
|
},
|
|
};
|
|
|
|
// Higher-order component for icon animation
|
|
const withIconAnimation = (IconComponent: React.ComponentType<any>) => {
|
|
const AnimatedIcon = ({
|
|
isHovered = false,
|
|
className,
|
|
...props
|
|
}: {
|
|
isHovered?: boolean;
|
|
className?: string;
|
|
}) => {
|
|
const controls = useAnimation();
|
|
|
|
useEffect(() => {
|
|
if (isHovered) {
|
|
controls.start("animate");
|
|
} else {
|
|
controls.start("normal");
|
|
}
|
|
}, [isHovered, controls]);
|
|
|
|
return (
|
|
<div className={className}>
|
|
<IconComponent controls={controls} {...props} />
|
|
</div>
|
|
);
|
|
};
|
|
AnimatedIcon.displayName = `Animated${IconComponent.displayName || IconComponent.name || 'Icon'}`;
|
|
return AnimatedIcon;
|
|
};
|
|
|
|
// Higher-order component for icon animation
|
|
const withChartIconAnimation = (IconComponent: React.ComponentType<any>) => {
|
|
const AnimatedChartIcon = ({
|
|
isHovered = false,
|
|
className,
|
|
...props
|
|
}: {
|
|
isHovered?: boolean;
|
|
className?: string;
|
|
}) => {
|
|
const controls = useAnimation();
|
|
|
|
const handleHoverStart = useCallback(async () => {
|
|
await controls.start((i) => ({
|
|
pathLength: 0,
|
|
opacity: 0,
|
|
transition: { delay: i * 0.1, duration: 0.3 },
|
|
}));
|
|
await controls.start((i) => ({
|
|
pathLength: 1,
|
|
opacity: 1,
|
|
transition: { delay: i * 0.1, duration: 0.3 },
|
|
}));
|
|
}, [controls]);
|
|
|
|
const handleHoverEnd = useCallback(() => {
|
|
controls.start("normal");
|
|
}, [controls]);
|
|
|
|
useEffect(() => {
|
|
if (isHovered) {
|
|
handleHoverStart();
|
|
} else {
|
|
handleHoverEnd();
|
|
}
|
|
}, [isHovered, handleHoverStart, handleHoverEnd]);
|
|
|
|
return (
|
|
<div className={className}>
|
|
<IconComponent
|
|
onMouseEnter={handleHoverStart}
|
|
onMouseLeave={handleHoverEnd}
|
|
controls={controls}
|
|
{...props}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
AnimatedChartIcon.displayName = `AnimatedChart${IconComponent.displayName || IconComponent.name || 'Icon'}`;
|
|
return AnimatedChartIcon;
|
|
};
|
|
|
|
// Base icon components
|
|
const HomeIconBase = ({ controls }: { controls: any }) => (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
|
<motion.path
|
|
d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"
|
|
variants={pathVariants}
|
|
transition={defaultTransition}
|
|
animate={controls}
|
|
/>
|
|
</svg>
|
|
);
|
|
|
|
// Example of another icon with animation
|
|
const PlayIconBase = ({ controls }: { controls: any }) => (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<motion.path
|
|
d="M5 3l14 9-14 9V3z"
|
|
variants={playIconVariants}
|
|
transition={defaultTransition}
|
|
animate={controls}
|
|
/>
|
|
</svg>
|
|
);
|
|
|
|
const SettingsGearIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<motion.svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
transition={{ type: "spring", stiffness: 50, damping: 10 }}
|
|
variants={{
|
|
normal: {
|
|
rotate: 0,
|
|
},
|
|
animate: {
|
|
rotate: 90,
|
|
},
|
|
}}
|
|
animate={controls}
|
|
>
|
|
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" />
|
|
<circle cx="12" cy="12" r="3" />
|
|
</motion.svg>
|
|
);
|
|
};
|
|
|
|
const lineChartVariants2: Variants = {
|
|
visible: { pathLength: 1, opacity: 1 },
|
|
hidden: { pathLength: 0, opacity: 0 },
|
|
};
|
|
const ChartColumnIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<motion.path
|
|
d="M13 17V9"
|
|
variants={lineChartVariants2}
|
|
transition={defaultTransition}
|
|
animate={controls}
|
|
initial="visible"
|
|
custom={1}
|
|
/>
|
|
<motion.path
|
|
d="M18 17V5"
|
|
variants={lineChartVariants2}
|
|
transition={defaultTransition}
|
|
animate={controls}
|
|
initial="visible"
|
|
custom={2}
|
|
/>
|
|
<path d="M3 3v16a2 2 0 0 0 2 2h16" />
|
|
<motion.path
|
|
d="M8 17v-3"
|
|
variants={lineChartVariants2}
|
|
transition={defaultTransition}
|
|
animate={controls}
|
|
initial="visible"
|
|
custom={0}
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
// const defaultTransition: Transition = {
|
|
// duration: 0.9,
|
|
// ease: 'easeInOut',
|
|
// };
|
|
|
|
// const pathVariants: Variants = {
|
|
// normal: {
|
|
// rotate: 0,
|
|
// x: 0,
|
|
// y: 0,
|
|
// },
|
|
// hover: {
|
|
// rotate: [0, 4, 2, -3, 1, 0],
|
|
// x: [0, 0.7, -0.3, 0.5, 0.2, 0],
|
|
// y: [0, -0.2, 0.3, -0.2, 0.4, 0],
|
|
// },
|
|
// };
|
|
|
|
const transition = (custom: number): Transition => ({
|
|
duration: 0.25,
|
|
delay: custom * 0.1,
|
|
});
|
|
|
|
const variants: Variants = {
|
|
default: {
|
|
pathLength: 1,
|
|
opacity: 1,
|
|
},
|
|
normal: (custom: number) => ({
|
|
pathLength: 1,
|
|
opacity: 1,
|
|
transition: transition(custom),
|
|
}),
|
|
animate: (custom: number) => ({
|
|
pathLength: 0.5,
|
|
opacity: 1,
|
|
transition: transition(custom),
|
|
}),
|
|
};
|
|
|
|
const ActivityLogsIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<motion.rect
|
|
variants={variants}
|
|
initial="normal"
|
|
animate={controls}
|
|
custom={0}
|
|
x="3"
|
|
y="3"
|
|
width="3"
|
|
height="3"
|
|
fill="currentColor"
|
|
stroke="none"
|
|
/>
|
|
<motion.path
|
|
variants={variants}
|
|
initial="normal"
|
|
animate={controls}
|
|
custom={0}
|
|
d="M8 4.5 L21 4.5"
|
|
strokeWidth="2"
|
|
/>
|
|
|
|
<motion.rect
|
|
variants={variants}
|
|
initial="normal"
|
|
animate={controls}
|
|
custom={1}
|
|
x="3"
|
|
y="10"
|
|
width="3"
|
|
height="3"
|
|
fill="currentColor"
|
|
stroke="none"
|
|
/>
|
|
<motion.path
|
|
variants={variants}
|
|
initial="normal"
|
|
animate={controls}
|
|
custom={1}
|
|
d="M8 11.5 L21 11.5"
|
|
strokeWidth="2"
|
|
/>
|
|
|
|
<motion.rect
|
|
variants={variants}
|
|
initial="normal"
|
|
animate={controls}
|
|
custom={2}
|
|
x="3"
|
|
y="17"
|
|
width="3"
|
|
height="3"
|
|
fill="currentColor"
|
|
stroke="none"
|
|
/>
|
|
<motion.path
|
|
variants={variants}
|
|
initial="normal"
|
|
animate={controls}
|
|
custom={2}
|
|
d="M8 18.5 L21 18.5"
|
|
strokeWidth="2"
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
const defaultTransition2: Transition = {
|
|
type: "spring",
|
|
stiffness: 200,
|
|
damping: 10,
|
|
};
|
|
|
|
const pathVariants2: Variants = {
|
|
normal: {
|
|
rotate: 0,
|
|
},
|
|
animate: {
|
|
rotate: -20,
|
|
},
|
|
};
|
|
|
|
const KeyOneBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<motion.svg
|
|
viewBox="0 0 24 24"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
fill="currentColor"
|
|
aria-hidden="true"
|
|
animate={controls}
|
|
initial="normal"
|
|
variants={pathVariants2}
|
|
transition={defaultTransition2}
|
|
>
|
|
<path d="M10.7577 11.8281L18.6066 3.97919L20.0208 5.3934L18.6066 6.80761L21.0815 9.28249L19.6673 10.6967L17.1924 8.22183L15.7782 9.63604L17.8995 11.7574L16.4853 13.1716L14.364 11.0503L12.1719 13.2423C13.4581 15.1837 13.246 17.8251 11.5355 19.5355C9.58291 21.4882 6.41709 21.4882 4.46447 19.5355C2.51184 17.5829 2.51184 14.4171 4.46447 12.4645C6.17493 10.754 8.81633 10.5419 10.7577 11.8281ZM10.1213 18.1213C11.2929 16.9497 11.2929 15.0503 10.1213 13.8787C8.94975 12.7071 7.05025 12.7071 5.87868 13.8787C4.70711 15.0503 4.70711 16.9497 5.87868 18.1213C7.05025 19.2929 8.94975 19.2929 10.1213 18.1213Z" />
|
|
</motion.svg>
|
|
);
|
|
};
|
|
|
|
const frameVariants: Variants = {
|
|
normal: { opacity: 1 },
|
|
animate: { opacity: 1 },
|
|
};
|
|
|
|
const lineVariants: Variants = {
|
|
normal: { pathLength: 1, opacity: 1 },
|
|
animate: { pathLength: 0, opacity: 0 },
|
|
};
|
|
|
|
const ScanTextIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<motion.path
|
|
d="M3 7V5a2 2 0 0 1 2-2h2"
|
|
variants={frameVariants}
|
|
animate={controls}
|
|
/>
|
|
<motion.path
|
|
d="M17 3h2a2 2 0 0 1 2 2v2"
|
|
variants={frameVariants}
|
|
animate={controls}
|
|
/>
|
|
<motion.path
|
|
d="M21 17v2a2 2 0 0 1-2 2h-2"
|
|
variants={frameVariants}
|
|
animate={controls}
|
|
/>
|
|
<motion.path
|
|
d="M7 21H5a2 2 0 0 1-2-2v-2"
|
|
variants={frameVariants}
|
|
animate={controls}
|
|
/>
|
|
<motion.path
|
|
d="M7 8h8"
|
|
variants={lineVariants}
|
|
initial="animate"
|
|
animate={controls}
|
|
custom={0}
|
|
/>
|
|
<motion.path
|
|
d="M7 12h10"
|
|
variants={lineVariants}
|
|
initial="animate"
|
|
animate={controls}
|
|
custom={1}
|
|
/>
|
|
<motion.path
|
|
d="M7 16h6"
|
|
variants={lineVariants}
|
|
initial="animate"
|
|
animate={controls}
|
|
custom={2}
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
// Create animated versions of icons
|
|
const HomeIcon = withIconAnimation(HomeIconBase);
|
|
const PlayIcon = withIconAnimation(PlayIconBase);
|
|
const SettingsGearIcon = withIconAnimation(SettingsGearIconBase);
|
|
const ChartColumnIcon = withChartIconAnimation(ChartColumnIconBase);
|
|
const ActivityLogsIcon = withIconAnimation(ActivityLogsIconBase);
|
|
const ScanTextIcon = withIconAnimation(ScanTextIconBase);
|
|
const KeyIcon = withIconAnimation(KeyOneBase);
|
|
|
|
// Logout icon with animation
|
|
const LogOutIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<motion.svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
|
|
<motion.polyline
|
|
points="16 17 21 12 16 7"
|
|
variants={{
|
|
normal: { x: 0 },
|
|
animate: { x: [0, 3, 0] },
|
|
}}
|
|
transition={{ duration: 0.5, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
<motion.line
|
|
x1="21"
|
|
y1="12"
|
|
x2="9"
|
|
y2="12"
|
|
variants={{
|
|
normal: { x1: 21, x2: 9 },
|
|
animate: { x1: [21, 24, 21], x2: [9, 12, 9] },
|
|
}}
|
|
transition={{ duration: 0.5, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
</motion.svg>
|
|
);
|
|
};
|
|
|
|
// External link icon with animation
|
|
const ExternalLinkIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
|
|
<motion.polyline
|
|
points="15 3 21 3 21 9"
|
|
variants={{
|
|
normal: { rotate: 0, scale: 1 },
|
|
animate: { rotate: [0, -10, 0], scale: [1, 1.1, 1] },
|
|
}}
|
|
transition={{ duration: 0.4, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
<motion.line
|
|
x1="10"
|
|
y1="14"
|
|
x2="21"
|
|
y2="3"
|
|
variants={pathVariants}
|
|
transition={defaultTransition}
|
|
animate={controls}
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
// File text icon with animation
|
|
const FileTextIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
|
<motion.polyline
|
|
points="14 2 14 8 20 8"
|
|
variants={{
|
|
normal: { pathLength: 1, opacity: 1 },
|
|
animate: { pathLength: [1, 0, 1], opacity: [1, 0.5, 1] },
|
|
}}
|
|
transition={{ duration: 0.6, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
<motion.line
|
|
x1="16"
|
|
y1="13"
|
|
x2="8"
|
|
y2="13"
|
|
variants={lineVariants}
|
|
initial="animate"
|
|
animate={controls}
|
|
custom={0}
|
|
/>
|
|
<motion.line
|
|
x1="16"
|
|
y1="17"
|
|
x2="8"
|
|
y2="17"
|
|
variants={lineVariants}
|
|
initial="animate"
|
|
animate={controls}
|
|
custom={1}
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
// Book open icon with animation
|
|
const BookOpenIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<motion.path
|
|
d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"
|
|
variants={{
|
|
normal: { rotate: 0 },
|
|
animate: { rotate: [-2, 2, -2] },
|
|
}}
|
|
transition={{ duration: 0.6, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
<motion.path
|
|
d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"
|
|
variants={{
|
|
normal: { rotate: 0 },
|
|
animate: { rotate: [2, -2, 2] },
|
|
}}
|
|
transition={{ duration: 0.6, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
// Message square icon with animation
|
|
const MessageSquareIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
<motion.circle
|
|
cx="8"
|
|
cy="10"
|
|
r="1"
|
|
fill="currentColor"
|
|
variants={{
|
|
normal: { scale: 1, opacity: 1 },
|
|
animate: { scale: [1, 1.5, 1], opacity: [1, 0.5, 1] },
|
|
}}
|
|
transition={{ duration: 0.4, delay: 0 }}
|
|
animate={controls}
|
|
/>
|
|
<motion.circle
|
|
cx="12"
|
|
cy="10"
|
|
r="1"
|
|
fill="currentColor"
|
|
variants={{
|
|
normal: { scale: 1, opacity: 1 },
|
|
animate: { scale: [1, 1.5, 1], opacity: [1, 0.5, 1] },
|
|
}}
|
|
transition={{ duration: 0.4, delay: 0.1 }}
|
|
animate={controls}
|
|
/>
|
|
<motion.circle
|
|
cx="16"
|
|
cy="10"
|
|
r="1"
|
|
fill="currentColor"
|
|
variants={{
|
|
normal: { scale: 1, opacity: 1 },
|
|
animate: { scale: [1, 1.5, 1], opacity: [1, 0.5, 1] },
|
|
}}
|
|
transition={{ duration: 0.4, delay: 0.2 }}
|
|
animate={controls}
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
const LogOutIcon = withIconAnimation(LogOutIconBase);
|
|
const ExternalLinkIcon = withIconAnimation(ExternalLinkIconBase);
|
|
const FileTextIcon = withIconAnimation(FileTextIconBase);
|
|
const BookOpenIcon = withIconAnimation(BookOpenIconBase);
|
|
const MessageSquareIcon = withIconAnimation(MessageSquareIconBase);
|
|
|
|
// Bell icon with animation
|
|
const BellIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<motion.svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<motion.path
|
|
d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"
|
|
variants={{
|
|
normal: { rotate: 0 },
|
|
animate: { rotate: [-10, 10, -10, 10, 0] },
|
|
}}
|
|
transition={{ duration: 0.5, ease: "easeInOut" }}
|
|
animate={controls}
|
|
style={{ transformOrigin: "50% 20%" }}
|
|
/>
|
|
<motion.path
|
|
d="M10.3 21a1.94 1.94 0 0 0 3.4 0"
|
|
variants={{
|
|
normal: { scale: 1 },
|
|
animate: { scale: [1, 1.1, 1] },
|
|
}}
|
|
transition={{ duration: 0.5, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
</motion.svg>
|
|
);
|
|
};
|
|
|
|
// Gift icon with animation
|
|
const GiftIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
{/* Gift box bottom */}
|
|
<polyline points="20 12 20 22 4 22 4 12" />
|
|
<line x1="12" y1="22" x2="12" y2="12" />
|
|
|
|
{/* Gift lid with opening animation */}
|
|
<motion.g
|
|
variants={{
|
|
normal: { y: 0, rotate: 0 },
|
|
animate: { y: -3, rotate: -8 },
|
|
}}
|
|
transition={{ duration: 0.4, ease: "easeOut" }}
|
|
animate={controls}
|
|
style={{ transformOrigin: "2px 9px" }}
|
|
>
|
|
<rect x="2" y="7" width="20" height="5" />
|
|
<line x1="12" y1="7" x2="12" y2="12" />
|
|
|
|
{/* Left bow */}
|
|
<motion.path
|
|
d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"
|
|
variants={{
|
|
normal: { scale: 1 },
|
|
animate: { scale: [1, 1.1, 1] },
|
|
}}
|
|
transition={{ duration: 0.4, ease: "easeInOut" }}
|
|
/>
|
|
|
|
{/* Right bow */}
|
|
<motion.path
|
|
d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"
|
|
variants={{
|
|
normal: { scale: 1 },
|
|
animate: { scale: [1, 1.1, 1] },
|
|
}}
|
|
transition={{ duration: 0.4, ease: "easeInOut" }}
|
|
/>
|
|
</motion.g>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
// HelpCircle icon with animation
|
|
const HelpCircleIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<motion.circle
|
|
cx="12"
|
|
cy="12"
|
|
r="10"
|
|
variants={{
|
|
normal: { rotate: 0 },
|
|
animate: { rotate: 360 },
|
|
}}
|
|
transition={{ duration: 0.6, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
<motion.path
|
|
d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"
|
|
variants={{
|
|
normal: { opacity: 1 },
|
|
animate: { opacity: [1, 0.5, 1] },
|
|
}}
|
|
transition={{ duration: 0.4, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
<motion.line
|
|
x1="12"
|
|
y1="17"
|
|
x2="12.01"
|
|
y2="17"
|
|
variants={{
|
|
normal: { scale: 1 },
|
|
animate: { scale: [1, 1.5, 1] },
|
|
}}
|
|
transition={{ duration: 0.4, ease: "easeInOut", delay: 0.2 }}
|
|
animate={controls}
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
const BellIcon = withIconAnimation(BellIconBase);
|
|
const GiftIcon = withIconAnimation(GiftIconBase);
|
|
const HelpCircleIcon = withIconAnimation(HelpCircleIconBase);
|
|
|
|
// SquareArrowUp icon with animation (for Upgrade button)
|
|
const SquareArrowUpIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<rect width="18" height="18" x="3" y="3" rx="2" />
|
|
<motion.path
|
|
d="m8 12 4-4 4 4"
|
|
variants={{
|
|
normal: { y: 0 },
|
|
animate: { y: [-2, 0] },
|
|
}}
|
|
transition={{ duration: 0.3, ease: "easeOut" }}
|
|
animate={controls}
|
|
/>
|
|
<motion.path
|
|
d="M12 16V8"
|
|
variants={{
|
|
normal: { scaleY: 1 },
|
|
animate: { scaleY: [0.8, 1] },
|
|
}}
|
|
transition={{ duration: 0.3, ease: "easeOut" }}
|
|
animate={controls}
|
|
style={{ transformOrigin: "50% 100%" }}
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
const SquareArrowUpIcon = withIconAnimation(SquareArrowUpIconBase);
|
|
|
|
// Code icon with animation
|
|
const CodeIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<motion.polyline
|
|
points="16 18 22 12 16 6"
|
|
variants={{
|
|
normal: { x: 0 },
|
|
animate: { x: [0, 2, 0] },
|
|
}}
|
|
transition={{ duration: 0.4, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
<motion.polyline
|
|
points="8 6 2 12 8 18"
|
|
variants={{
|
|
normal: { x: 0 },
|
|
animate: { x: [0, -2, 0] },
|
|
}}
|
|
transition={{ duration: 0.4, ease: "easeInOut" }}
|
|
animate={controls}
|
|
/>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
const CodeIcon = withIconAnimation(CodeIconBase);
|
|
|
|
// TestTube icon for Extract Playground (Lucide TestTube2 icon without bubble)
|
|
const BeakerIconBase = ({ controls }: { controls: any }) => {
|
|
return (
|
|
<motion.svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
variants={{
|
|
normal: { rotate: 0 },
|
|
animate: { rotate: [-8, 8, -8] },
|
|
}}
|
|
transition={{
|
|
duration: 0.8,
|
|
ease: "easeInOut",
|
|
times: [0, 0.5, 1],
|
|
}}
|
|
animate={controls}
|
|
>
|
|
<path d="M21 7 6.82 21.18a2.83 2.83 0 0 1-3.99-.01v0a2.83 2.83 0 0 1 0-4L17 3" />
|
|
<path d="m16 2 6 6" />
|
|
</motion.svg>
|
|
);
|
|
};
|
|
|
|
const BeakerIcon = withIconAnimation(BeakerIconBase);
|
|
|
|
export {
|
|
HomeIcon,
|
|
PlayIcon,
|
|
SettingsGearIcon,
|
|
ChartColumnIcon,
|
|
ActivityLogsIcon,
|
|
KeyIcon,
|
|
ScanTextIcon,
|
|
LogOutIcon,
|
|
ExternalLinkIcon,
|
|
FileTextIcon,
|
|
BookOpenIcon,
|
|
MessageSquareIcon,
|
|
BellIcon,
|
|
GiftIcon,
|
|
HelpCircleIcon,
|
|
SquareArrowUpIcon,
|
|
CodeIcon,
|
|
BeakerIcon,
|
|
};
|