mirror of
https://github.com/documenso/documenso.git
synced 2025-11-11 04:52:41 +10:00
Compare commits
1 Commits
v1.9.0-rc.
...
feat/integ
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f22fd48d1 |
@ -36,7 +36,7 @@
|
|||||||
"react-confetti": "^6.1.0",
|
"react-confetti": "^6.1.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-hook-form": "^7.43.9",
|
"react-hook-form": "^7.43.9",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^5.2.1",
|
||||||
"recharts": "^2.7.2",
|
"recharts": "^2.7.2",
|
||||||
"sharp": "^0.33.1",
|
"sharp": "^0.33.1",
|
||||||
"typescript": "5.2.2",
|
"typescript": "5.2.2",
|
||||||
|
|||||||
@ -0,0 +1,83 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import React, { forwardRef, useRef } from 'react';
|
||||||
|
|
||||||
|
import { FileText, Hexagon, Shapes } from 'lucide-react';
|
||||||
|
import { LiaGoogleDrive } from 'react-icons/lia';
|
||||||
|
import { PiMicrosoftTeamsLogo } from 'react-icons/pi';
|
||||||
|
import { TbBrandAirtable, TbBrandZapier } from 'react-icons/tb';
|
||||||
|
|
||||||
|
import { AnimatedDataFlow } from '@documenso/ui/components/animate/animated-data-flow';
|
||||||
|
import { cn } from '@documenso/ui/lib/utils';
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/display-name
|
||||||
|
const Circle = forwardRef<HTMLDivElement, { className?: string; children?: React.ReactNode }>(
|
||||||
|
({ className, children }, ref) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'border-border z-10 flex h-12 w-12 items-center justify-center rounded-full border-2 bg-white p-3 shadow-[0_0_20px_-12px_rgba(0,0,0,0.8)]',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export function DocumensoIntegrationsDataFlow() {
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const div1Ref = useRef<HTMLDivElement>(null);
|
||||||
|
const div2Ref = useRef<HTMLDivElement>(null);
|
||||||
|
const div3Ref = useRef<HTMLDivElement>(null);
|
||||||
|
const div4Ref = useRef<HTMLDivElement>(null);
|
||||||
|
const div5Ref = useRef<HTMLDivElement>(null);
|
||||||
|
const div6Ref = useRef<HTMLDivElement>(null);
|
||||||
|
const div7Ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="bg-background relative z-[-2] flex h-full w-full max-w-[32rem] items-center justify-center overflow-hidden p-10"
|
||||||
|
ref={containerRef}
|
||||||
|
>
|
||||||
|
<div className="flex h-full w-full flex-row items-stretch justify-between gap-10">
|
||||||
|
<div className="flex flex-col justify-center gap-2">
|
||||||
|
<Circle className="bg-background" ref={div1Ref}>
|
||||||
|
<Shapes color="#A2E771" className="h-6 w-6" />
|
||||||
|
</Circle>
|
||||||
|
<Circle className="bg-background" ref={div2Ref}>
|
||||||
|
<Hexagon color="#A2E771" className="h-6 w-6" />
|
||||||
|
</Circle>
|
||||||
|
<Circle className="bg-background" ref={div3Ref}>
|
||||||
|
<FileText color="#A2E771" className="h-6 w-6" />
|
||||||
|
</Circle>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col justify-center">
|
||||||
|
<Circle ref={div4Ref} className="bg-background h-16 w-16">
|
||||||
|
<TbBrandZapier color="#FF4A00" className="h-6 w-6" />
|
||||||
|
</Circle>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col justify-center gap-2">
|
||||||
|
<Circle className="bg-background" ref={div5Ref}>
|
||||||
|
<LiaGoogleDrive color="#A2E771" className="h-6 w-6" />
|
||||||
|
</Circle>
|
||||||
|
<Circle className="bg-background" ref={div6Ref}>
|
||||||
|
<PiMicrosoftTeamsLogo color="#A2E771" className="h-6 w-6" />
|
||||||
|
</Circle>
|
||||||
|
<Circle className="bg-background" ref={div7Ref}>
|
||||||
|
<TbBrandAirtable color="#A2E771" className="h-6 w-6" />
|
||||||
|
</Circle>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<AnimatedDataFlow containerRef={containerRef} fromRef={div1Ref} toRef={div4Ref} />
|
||||||
|
<AnimatedDataFlow containerRef={containerRef} fromRef={div2Ref} toRef={div4Ref} />
|
||||||
|
<AnimatedDataFlow containerRef={containerRef} fromRef={div3Ref} toRef={div4Ref} />
|
||||||
|
<AnimatedDataFlow containerRef={containerRef} fromRef={div4Ref} toRef={div5Ref} />
|
||||||
|
<AnimatedDataFlow containerRef={containerRef} fromRef={div4Ref} toRef={div6Ref} />
|
||||||
|
<AnimatedDataFlow containerRef={containerRef} fromRef={div4Ref} toRef={div7Ref} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -3,13 +3,14 @@ import type { HTMLAttributes } from 'react';
|
|||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
|
||||||
import backgroundPattern from '@documenso/assets/images/background-pattern.png';
|
import backgroundPattern from '@documenso/assets/images/background-pattern.png';
|
||||||
import cardConnectionsFigure from '@documenso/assets/images/card-connections-figure.png';
|
|
||||||
import cardPaidFigure from '@documenso/assets/images/card-paid-figure.png';
|
import cardPaidFigure from '@documenso/assets/images/card-paid-figure.png';
|
||||||
import cardSharingFigure from '@documenso/assets/images/card-sharing-figure.png';
|
import cardSharingFigure from '@documenso/assets/images/card-sharing-figure.png';
|
||||||
import cardWidgetFigure from '@documenso/assets/images/card-widget-figure.png';
|
import cardWidgetFigure from '@documenso/assets/images/card-widget-figure.png';
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
import { cn } from '@documenso/ui/lib/utils';
|
||||||
import { Card, CardContent } from '@documenso/ui/primitives/card';
|
import { Card, CardContent } from '@documenso/ui/primitives/card';
|
||||||
|
|
||||||
|
import { DocumensoIntegrationsDataFlow } from './integrations-data-flow';
|
||||||
|
|
||||||
export type ShareConnectPaidWidgetBentoProps = HTMLAttributes<HTMLDivElement>;
|
export type ShareConnectPaidWidgetBentoProps = HTMLAttributes<HTMLDivElement>;
|
||||||
|
|
||||||
export const ShareConnectPaidWidgetBento = ({
|
export const ShareConnectPaidWidgetBento = ({
|
||||||
@ -56,12 +57,9 @@ export const ShareConnectPaidWidgetBento = ({
|
|||||||
favorite tools.
|
favorite tools.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="flex items-center justify-center p-8">
|
<div className="flex w-full items-center justify-center p-0 md:p-8">
|
||||||
<Image
|
{/* Add Animated Beam */}
|
||||||
src={cardConnectionsFigure}
|
<DocumensoIntegrationsDataFlow />
|
||||||
alt="its fast"
|
|
||||||
className="w-full max-w-sm dark:contrast-[70%] dark:hue-rotate-180 dark:invert"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
"react-hook-form": "^7.43.9",
|
"react-hook-form": "^7.43.9",
|
||||||
"react-hotkeys-hook": "^4.4.1",
|
"react-hotkeys-hook": "^4.4.1",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^5.2.1",
|
||||||
"react-rnd": "^10.4.1",
|
"react-rnd": "^10.4.1",
|
||||||
"remeda": "^1.27.1",
|
"remeda": "^1.27.1",
|
||||||
"sharp": "^0.33.1",
|
"sharp": "^0.33.1",
|
||||||
|
|||||||
37
package-lock.json
generated
37
package-lock.json
generated
@ -60,7 +60,7 @@
|
|||||||
"react-confetti": "^6.1.0",
|
"react-confetti": "^6.1.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-hook-form": "^7.43.9",
|
"react-hook-form": "^7.43.9",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^5.2.1",
|
||||||
"recharts": "^2.7.2",
|
"recharts": "^2.7.2",
|
||||||
"sharp": "^0.33.1",
|
"sharp": "^0.33.1",
|
||||||
"typescript": "5.2.2",
|
"typescript": "5.2.2",
|
||||||
@ -78,6 +78,14 @@
|
|||||||
"integrity": "sha512-O+z53uwx64xY7D6roOi4+jApDGFg0qn6WHcxe5QeqjMaTezBO/mxdfFXIVAVVyNWKx84OmPB3L8kbVYOTeN34A==",
|
"integrity": "sha512-O+z53uwx64xY7D6roOi4+jApDGFg0qn6WHcxe5QeqjMaTezBO/mxdfFXIVAVVyNWKx84OmPB3L8kbVYOTeN34A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"apps/marketing/node_modules/react-icons": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"apps/marketing/node_modules/typescript": {
|
"apps/marketing/node_modules/typescript": {
|
||||||
"version": "5.2.2",
|
"version": "5.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||||
@ -127,7 +135,7 @@
|
|||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
"react-hook-form": "^7.43.9",
|
"react-hook-form": "^7.43.9",
|
||||||
"react-hotkeys-hook": "^4.4.1",
|
"react-hotkeys-hook": "^4.4.1",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^5.2.1",
|
||||||
"react-rnd": "^10.4.1",
|
"react-rnd": "^10.4.1",
|
||||||
"remeda": "^1.27.1",
|
"remeda": "^1.27.1",
|
||||||
"sharp": "^0.33.1",
|
"sharp": "^0.33.1",
|
||||||
@ -155,6 +163,14 @@
|
|||||||
"integrity": "sha512-O+z53uwx64xY7D6roOi4+jApDGFg0qn6WHcxe5QeqjMaTezBO/mxdfFXIVAVVyNWKx84OmPB3L8kbVYOTeN34A==",
|
"integrity": "sha512-O+z53uwx64xY7D6roOi4+jApDGFg0qn6WHcxe5QeqjMaTezBO/mxdfFXIVAVVyNWKx84OmPB3L8kbVYOTeN34A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"apps/web/node_modules/react-icons": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"apps/web/node_modules/typescript": {
|
"apps/web/node_modules/typescript": {
|
||||||
"version": "5.2.2",
|
"version": "5.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||||
@ -5836,6 +5852,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-icons": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.x || ^17.x || ^18.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-id": {
|
"node_modules/@radix-ui/react-id": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz",
|
||||||
@ -20538,14 +20562,6 @@
|
|||||||
"react-dom": ">=16.8.1"
|
"react-dom": ">=16.8.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-icons": {
|
|
||||||
"version": "4.12.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz",
|
|
||||||
"integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-immutable-proptypes": {
|
"node_modules/react-immutable-proptypes": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-immutable-proptypes/-/react-immutable-proptypes-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-immutable-proptypes/-/react-immutable-proptypes-2.2.0.tgz",
|
||||||
@ -27599,6 +27615,7 @@
|
|||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.4",
|
"@radix-ui/react-dropdown-menu": "^2.0.4",
|
||||||
"@radix-ui/react-hover-card": "^1.0.5",
|
"@radix-ui/react-hover-card": "^1.0.5",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.0.1",
|
"@radix-ui/react-label": "^2.0.1",
|
||||||
"@radix-ui/react-menubar": "^1.0.2",
|
"@radix-ui/react-menubar": "^1.0.2",
|
||||||
"@radix-ui/react-navigation-menu": "^1.1.2",
|
"@radix-ui/react-navigation-menu": "^1.1.2",
|
||||||
|
|||||||
@ -7,9 +7,6 @@ module.exports = {
|
|||||||
content: ['src/**/*.{ts,tsx}'],
|
content: ['src/**/*.{ts,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
screens: {
|
|
||||||
print: { raw: 'print' },
|
|
||||||
},
|
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: ['var(--font-sans)', ...fontFamily.sans],
|
sans: ['var(--font-sans)', ...fontFamily.sans],
|
||||||
signature: ['var(--font-signature)'],
|
signature: ['var(--font-signature)'],
|
||||||
@ -138,6 +135,7 @@ module.exports = {
|
|||||||
'3xl': '1920px',
|
'3xl': '1920px',
|
||||||
'4xl': '2560px',
|
'4xl': '2560px',
|
||||||
'5xl': '3840px',
|
'5xl': '3840px',
|
||||||
|
print: { raw: 'print' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
168
packages/ui/components/animate/animated-data-flow.tsx
Normal file
168
packages/ui/components/animate/animated-data-flow.tsx
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { type RefObject, useEffect, useId, useState } from 'react';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
|
import { cn } from '../../lib/utils';
|
||||||
|
|
||||||
|
export interface AnimatedDataFlowProps {
|
||||||
|
className?: string;
|
||||||
|
containerRef: RefObject<HTMLElement>;
|
||||||
|
fromRef: RefObject<HTMLElement>;
|
||||||
|
toRef: RefObject<HTMLElement>;
|
||||||
|
curvature?: number;
|
||||||
|
reverse?: boolean;
|
||||||
|
pathColor?: string;
|
||||||
|
pathWidth?: number;
|
||||||
|
pathOpacity?: number;
|
||||||
|
gradientStartColor?: string;
|
||||||
|
gradientStopColor?: string;
|
||||||
|
delay?: number;
|
||||||
|
duration?: number;
|
||||||
|
startXOffset?: number;
|
||||||
|
startYOffset?: number;
|
||||||
|
endXOffset?: number;
|
||||||
|
endYOffset?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AnimatedDataFlow: React.FC<AnimatedDataFlowProps> = ({
|
||||||
|
className,
|
||||||
|
containerRef,
|
||||||
|
fromRef,
|
||||||
|
toRef,
|
||||||
|
curvature = 0,
|
||||||
|
reverse = false, // Include the reverse prop
|
||||||
|
duration = 5,
|
||||||
|
delay = 0,
|
||||||
|
pathColor = 'gray',
|
||||||
|
pathWidth = 2,
|
||||||
|
pathOpacity = 0.2,
|
||||||
|
gradientStartColor = '#A2E771',
|
||||||
|
gradientStopColor = '#1F5200',
|
||||||
|
startXOffset = 0,
|
||||||
|
startYOffset = 0,
|
||||||
|
endXOffset = 0,
|
||||||
|
endYOffset = 0,
|
||||||
|
}) => {
|
||||||
|
const id = useId();
|
||||||
|
const [pathD, setPathD] = useState('');
|
||||||
|
const [svgDimensions, setSvgDimensions] = useState({ width: 0, height: 0 });
|
||||||
|
|
||||||
|
// Calculate the gradient coordinates based on the reverse prop
|
||||||
|
const gradientCoordinates = reverse
|
||||||
|
? {
|
||||||
|
x1: ['90%', '-10%'],
|
||||||
|
x2: ['100%', '0%'],
|
||||||
|
y1: ['0%', '0%'],
|
||||||
|
y2: ['0%', '0%'],
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
x1: ['10%', '110%'],
|
||||||
|
x2: ['0%', '100%'],
|
||||||
|
y1: ['0%', '0%'],
|
||||||
|
y2: ['0%', '0%'],
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updatePath = () => {
|
||||||
|
if (containerRef.current && fromRef.current && toRef.current) {
|
||||||
|
const containerRect = containerRef.current.getBoundingClientRect();
|
||||||
|
const rectA = fromRef.current.getBoundingClientRect();
|
||||||
|
const rectB = toRef.current.getBoundingClientRect();
|
||||||
|
|
||||||
|
const svgWidth = containerRect.width;
|
||||||
|
const svgHeight = containerRect.height;
|
||||||
|
setSvgDimensions({ width: svgWidth, height: svgHeight });
|
||||||
|
|
||||||
|
const startX = rectA.left - containerRect.left + rectA.width / 2 + startXOffset;
|
||||||
|
const startY = rectA.top - containerRect.top + rectA.height / 2 + startYOffset;
|
||||||
|
const endX = rectB.left - containerRect.left + rectB.width / 2 + endXOffset;
|
||||||
|
const endY = rectB.top - containerRect.top + rectB.height / 2 + endYOffset;
|
||||||
|
|
||||||
|
const controlY = startY - curvature;
|
||||||
|
const d = `M ${startX},${startY} Q ${(startX + endX) / 2},${controlY} ${endX},${endY}`;
|
||||||
|
setPathD(d);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize ResizeObserver
|
||||||
|
const resizeObserver = new ResizeObserver((entries) => {
|
||||||
|
// For all entries, recalculate the path
|
||||||
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||||
|
for (const entry of entries) {
|
||||||
|
updatePath();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Observe the container element
|
||||||
|
if (containerRef.current) {
|
||||||
|
resizeObserver.observe(containerRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the updatePath initially to set the initial path
|
||||||
|
updatePath();
|
||||||
|
|
||||||
|
// Clean up the observer on component unmount
|
||||||
|
return () => {
|
||||||
|
resizeObserver.disconnect();
|
||||||
|
};
|
||||||
|
}, [containerRef, fromRef, toRef, curvature, startXOffset, startYOffset, endXOffset, endYOffset]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
width={svgDimensions.width}
|
||||||
|
height={svgDimensions.height}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className={cn('pointer-events-none absolute left-0 top-0 transform-gpu stroke-2', className)}
|
||||||
|
viewBox={`0 0 ${svgDimensions.width} ${svgDimensions.height}`}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d={pathD}
|
||||||
|
stroke={pathColor}
|
||||||
|
strokeWidth={pathWidth}
|
||||||
|
strokeOpacity={pathOpacity}
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d={pathD}
|
||||||
|
strokeWidth={pathWidth}
|
||||||
|
stroke={`url(#${id})`}
|
||||||
|
strokeOpacity="1"
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
<defs>
|
||||||
|
<motion.linearGradient
|
||||||
|
className="transform-gpu"
|
||||||
|
id={id}
|
||||||
|
gradientUnits={'userSpaceOnUse'}
|
||||||
|
initial={{
|
||||||
|
x1: '0%',
|
||||||
|
x2: '0%',
|
||||||
|
y1: '0%',
|
||||||
|
y2: '0%',
|
||||||
|
}}
|
||||||
|
animate={{
|
||||||
|
x1: gradientCoordinates.x1,
|
||||||
|
x2: gradientCoordinates.x2,
|
||||||
|
y1: gradientCoordinates.y1,
|
||||||
|
y2: gradientCoordinates.y2,
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
delay,
|
||||||
|
duration,
|
||||||
|
ease: [0.16, 1, 0.3, 1],
|
||||||
|
repeat: Infinity,
|
||||||
|
repeatDelay: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<stop stopColor={gradientStartColor} stopOpacity="0"></stop>
|
||||||
|
<stop stopColor={gradientStartColor}></stop>
|
||||||
|
<stop offset="32.5%" stopColor={gradientStopColor}></stop>
|
||||||
|
<stop offset="100%" stopColor={gradientStopColor} stopOpacity="0"></stop>
|
||||||
|
</motion.linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -38,6 +38,7 @@
|
|||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.4",
|
"@radix-ui/react-dropdown-menu": "^2.0.4",
|
||||||
"@radix-ui/react-hover-card": "^1.0.5",
|
"@radix-ui/react-hover-card": "^1.0.5",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.0.1",
|
"@radix-ui/react-label": "^2.0.1",
|
||||||
"@radix-ui/react-menubar": "^1.0.2",
|
"@radix-ui/react-menubar": "^1.0.2",
|
||||||
"@radix-ui/react-navigation-menu": "^1.1.2",
|
"@radix-ui/react-navigation-menu": "^1.1.2",
|
||||||
@ -76,4 +77,4 @@
|
|||||||
"ts-pattern": "^5.0.5",
|
"ts-pattern": "^5.0.5",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user