Skip to content

Commit

Permalink
feat(nx-dev): reorganize powerpack screen
Browse files Browse the repository at this point in the history
  • Loading branch information
bcabanes committed Sep 20, 2024
1 parent 143ad9d commit eee6a28
Show file tree
Hide file tree
Showing 17 changed files with 828 additions and 273 deletions.
26 changes: 9 additions & 17 deletions nx-dev/nx-dev/app/powerpack/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { DefaultLayout } from '@nx/nx-dev/ui-common';
import {
CustomCacheStorage,
CodeOwners,
Conformance,
CallToAction,
GetStarted,
Hero,
PowerPackProcess,
PowerpackFeatures,
} from '@nx/nx-dev/ui-powerpack';

import { CallToAction, DefaultLayout } from '@nx/nx-dev/ui-common';

import type { Metadata } from 'next';

export const metadata: Metadata = {
Expand Down Expand Up @@ -39,21 +37,15 @@ export default function NxPowerPackPage(): JSX.Element {
<Hero />

<div className="mt-32 scroll-mt-32 lg:mt-56" id="features">
<CustomCacheStorage />
</div>
<div className="mt-32 lg:mt-56">
<CodeOwners />
<PowerpackFeatures />
</div>
<div className="mt-32 lg:mt-56">
<Conformance />

<div className="mt-32 scroll-mt-32 lg:mt-56">
<GetStarted />
</div>

<div className="mt-32 lg:mt-56">
<PowerPackProcess />
{/* <CallToAction
mainActionTitle="Get started with Nx PowerPack"
mainActionLink="/docs/powerpack/getting-started"
/> */}
<CallToAction />
</div>
</DefaultLayout>
);
Expand Down
1 change: 1 addition & 0 deletions nx-dev/ui-animations/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './lib/animated-beam';
export * from './lib/animate-value';
export * from './lib/blur-fade';
export * from './lib/fit-text';
Expand Down
209 changes: 209 additions & 0 deletions nx-dev/ui-animations/src/lib/animated-beam.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
'use client';
import { FC, RefObject, useEffect, useId, useState } from 'react';
import { motion, TargetAndTransition } from 'framer-motion';
import { cx } from '@nx/nx-dev/ui-primitives';

export interface AnimatedBeamProps {
className?: string;
containerRef: RefObject<HTMLElement>; // Container ref
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;
bidirectional?: boolean;
}

type BeamAnimation = {
x1: [string, string];
x2: [string, string];
y1: [string, string];
y2: [string, string];
};

export const AnimatedBeam: FC<AnimatedBeamProps> = ({
className,
containerRef,
fromRef,
toRef,
curvature = 0,
reverse = false, // Include the reverse prop
duration = Math.random() * 3 + 8,
delay = 0,
pathColor = 'gray',
pathWidth = 2,
pathOpacity = 0.2,
gradientStartColor = '#ffaa40',
gradientStopColor = '#9c40ff',
startXOffset = 0,
startYOffset = 0,
endXOffset = 0,
endYOffset = 0,
bidirectional = false,
}) => {
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 forwardAnimation: BeamAnimation = {
x1: reverse ? ['90%', '-10%'] : ['10%', '110%'],
x2: reverse ? ['100%', '0%'] : ['0%', '100%'],
y1: ['0%', '0%'],
y2: ['0%', '0%'],
};

const backwardAnimation: BeamAnimation = {
x1: reverse ? ['-10%', '90%'] : ['110%', '10%'],
x2: reverse ? ['0%', '100%'] : ['100%', '0%'],
y1: ['0%', '0%'],
y2: ['0%', '0%'],
};

const animateValue: TargetAndTransition = bidirectional
? {
x1: [
forwardAnimation.x1[0],
forwardAnimation.x1[1],
backwardAnimation.x1[1],
backwardAnimation.x1[0],
],
x2: [
forwardAnimation.x2[0],
forwardAnimation.x2[1],
backwardAnimation.x2[1],
backwardAnimation.x2[0],
],
y1: ['0%', '0%', '0%', '0%'],
y2: ['0%', '0%', '0%', '0%'],
}
: forwardAnimation;

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
for (let 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={cx(
'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={animateValue}
transition={{
delay,
duration,
ease: [0.16, 1, 0.3, 1], // https://easings.net/#easeOutExpo
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>
);
};
1 change: 1 addition & 0 deletions nx-dev/ui-icons/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export * from './lib/editors/visual-studio-code';

// OTHERS
export * from './lib/monorepo-world';
export * from './lib/others/amazon-s3';

// PODCASTS
export * from './lib/podcasts/amazon-music';
Expand Down
17 changes: 17 additions & 0 deletions nx-dev/ui-icons/src/lib/others/amazon-s3.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FC, SVGProps } from 'react';

/**
* Use `#569A31` for a colored version.
*/
export const AmazonS3Icon: FC<SVGProps<SVGSVGElement>> = (props) => (
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
{...props}
>
<title>Amazon S3</title>
<path d="M20.913 13.147l.12-.895c.947.576 1.258.922 1.354 1.071-.16.031-.562.046-1.474-.176zm-2.174 7.988a.547.547 0 0 0-.005.073c0 .084-.207.405-1.124.768a10.28 10.28 0 0 1-1.438.432c-1.405.325-3.128.504-4.853.504-4.612 0-7.412-1.184-7.412-1.704a.547.547 0 0 0-.005-.073L1.81 5.602c.135.078.28.154.432.227.042.02.086.038.128.057.134.062.272.122.417.18l.179.069c.154.058.314.114.478.168.043.013.084.029.13.043.207.065.423.127.646.187l.176.044c.175.044.353.087.534.127a23.414 23.414 0 0 0 .843.17l.121.023c.252.045.508.085.768.122.071.011.144.02.216.03.2.027.4.053.604.077l.24.027c.245.026.49.05.74.07l.081.009c.275.022.552.04.83.056l.233.012c.21.01.422.018.633.025a33.088 33.088 0 0 0 2.795-.026l.232-.011c.278-.016.555-.034.83-.056l.08-.008c.25-.02.497-.045.742-.072l.238-.026c.205-.024.408-.05.609-.077.07-.01.141-.019.211-.03.261-.037.519-.078.772-.122l.111-.02c.215-.04.427-.082.634-.125l.212-.047c.186-.041.368-.085.546-.13l.166-.042c.225-.06.444-.122.654-.189.04-.012.077-.026.115-.038a10.6 10.6 0 0 0 .493-.173c.058-.021.114-.044.17-.066.15-.06.293-.12.43-.185.038-.017.079-.034.116-.052.153-.073.3-.15.436-.228l-.976 7.245c-2.488-.78-5.805-2.292-7.311-3a1.09 1.09 0 0 0-1.088-1.085c-.6 0-1.088.489-1.088 1.088 0 .6.488 1.089 1.088 1.089.196 0 .378-.056.537-.148 1.72.812 5.144 2.367 7.715 3.15zm-7.42-20.047c5.677 0 9.676 1.759 9.75 2.736l-.014.113c-.01.033-.031.067-.048.101-.015.028-.026.057-.047.087-.024.033-.058.068-.09.102-.028.03-.051.06-.084.09-.038.035-.087.07-.133.105-.04.03-.074.06-.119.091-.053.036-.116.071-.177.107-.05.03-.095.06-.15.09-.068.036-.147.073-.222.11-.059.028-.114.057-.177.085-.084.038-.177.074-.268.111-.068.027-.13.054-.203.082-.097.036-.205.072-.31.107-.075.026-.148.053-.228.079-.111.035-.233.069-.35.103-.085.024-.165.05-.253.073-.124.034-.258.065-.389.098-.093.022-.181.046-.278.068-.139.032-.287.061-.433.091-.098.02-.191.041-.293.06-.155.03-.32.057-.482.084-.1.018-.198.036-.302.052-.166.026-.342.048-.515.072-.11.014-.213.03-.325.044-.181.023-.372.041-.56.06-.11.012-.218.025-.332.036-.188.016-.386.029-.58.043-.122.009-.24.02-.364.028-.207.012-.422.02-.635.028-.12.005-.234.012-.354.016a35.605 35.605 0 0 1-2.069 0c-.12-.004-.234-.011-.352-.016-.214-.008-.43-.016-.637-.028-.122-.008-.238-.02-.36-.027-.195-.015-.394-.028-.584-.044-.11-.01-.215-.024-.324-.035-.19-.02-.384-.038-.568-.06l-.315-.044c-.176-.024-.355-.046-.525-.073-.1-.015-.192-.033-.29-.05-.167-.028-.335-.055-.494-.086-.096-.018-.183-.038-.276-.056-.151-.032-.305-.062-.45-.095-.09-.02-.173-.043-.26-.064-.138-.034-.277-.067-.407-.102-.082-.022-.157-.046-.235-.069a11.75 11.75 0 0 1-.368-.108c-.075-.024-.141-.049-.213-.073-.11-.037-.223-.075-.325-.113-.067-.025-.125-.051-.188-.077-.096-.038-.195-.076-.282-.115-.06-.027-.11-.054-.166-.08-.08-.039-.162-.077-.233-.116-.052-.028-.094-.055-.142-.084-.063-.038-.13-.075-.185-.113-.043-.029-.075-.058-.113-.086-.048-.037-.098-.073-.139-.11-.032-.029-.054-.057-.08-.087-.033-.035-.069-.07-.093-.104-.02-.03-.031-.058-.046-.086-.018-.035-.039-.068-.049-.102l-.015-.113c.076-.977 4.074-2.736 9.748-2.736zm12.182 12.124c-.118-.628-.84-1.291-2.31-2.128l.963-7.16a.531.531 0 0 0 .005-.073C22.16 1.581 16.447 0 11.32 0 6.194 0 .482 1.581.482 3.851a.58.58 0 0 0 .005.072L2.819 21.25c.071 2.002 5.236 2.75 8.5 2.75 1.805 0 3.615-.188 5.098-.531.598-.138 1.133-.3 1.592-.48 1.18-.467 1.789-1.053 1.813-1.739l.945-7.018c.557.131 1.016.197 1.389.197.54 0 .902-.137 1.134-.413a.956.956 0 0 0 .21-.804Z" />
</svg>
);
8 changes: 3 additions & 5 deletions nx-dev/ui-powerpack/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// Use this file to export React client components (e.g. those with 'use client' directive) or other non-server utilities

export * from './lib/hero';
export * from './lib/layout';
export * from './lib/custom-cache-storage';
export * from './lib/code-owners';
export * from './lib/conformance';
export * from './lib/power-pack-process';
export * from './lib/powerpack-features';
export * from './lib/get-started';
export * from './lib/powerpack-pricing';
export * from './lib/call-to-action';
87 changes: 87 additions & 0 deletions nx-dev/ui-powerpack/src/lib/call-to-action.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import Link from 'next/link';
import { ReactElement } from 'react';

export function CallToAction(): ReactElement {
return (
<section className="relative isolate px-6 py-32 sm:py-40 lg:px-8">
<svg
className="absolute inset-0 -z-10 h-full w-full stroke-black/10 [mask-image:radial-gradient(100%_100%_at_top_right,white,transparent)] dark:stroke-white/10"
aria-hidden="true"
>
<defs>
<pattern
id="1d4240dd-898f-445f-932d-e2872fd12de3"
width={200}
height={200}
x="50%"
y={0}
patternUnits="userSpaceOnUse"
>
<path d="M.5 200V.5H200" fill="none" />
</pattern>
</defs>
<svg
x="50%"
y={0}
className="overflow-visible fill-slate-200/20 dark:fill-slate-800/20"
>
<path
d="M-200 0h201v201h-201Z M600 0h201v201h-201Z M-400 600h201v201h-201Z M200 800h201v201h-201Z"
strokeWidth={0}
/>
</svg>
<rect
width="100%"
height="100%"
strokeWidth={0}
fill="url(#1d4240dd-898f-445f-932d-e2872fd12de3)"
/>
</svg>
<div
className="pointer-events-none absolute inset-x-0 top-10 -z-10 flex transform-gpu justify-center overflow-hidden blur-3xl"
aria-hidden="true"
>
<div
className="aspect-[1108/632] w-[69.25rem] flex-none bg-gradient-to-r from-[#80caff] to-[#4f46e5] opacity-20"
style={{
clipPath:
'polygon(73.6% 51.7%, 91.7% 11.8%, 100% 46.4%, 97.4% 82.2%, 92.5% 84.9%, 75.7% 64%, 55.3% 47.5%, 46.5% 49.4%, 45% 62.9%, 50.3% 87.2%, 21.3% 64.1%, 0.1% 100%, 5.4% 51.1%, 21.4% 63.9%, 58.9% 0.2%, 73.6% 51.7%)',
}}
/>
</div>
<div className="mx-auto max-w-2xl text-center">
<h2
id="cta"
className="text-3xl font-medium tracking-tight text-slate-950 sm:text-5xl dark:text-white"
>
Get your
<br />
Nx Powerpack license
</h2>
<div className="mt-10 flex items-center justify-center gap-x-6">
<a
href="https://cloud.nx.app/nx-powerpack/purchase"
title="Get your Nx Powerapp license"
className="rounded-md bg-slate-950 px-3.5 py-2.5 text-sm font-semibold text-slate-100 shadow-sm hover:bg-slate-800 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white dark:bg-white dark:text-slate-900 dark:hover:bg-slate-100"
>
Buy now
</a>
<Link
href="/contact"
title="Get in touch"
prefetch={false}
className="group text-sm font-semibold leading-6 text-slate-950 dark:text-white"
>
Contact us{' '}
<span
aria-hidden="true"
className="inline-block transition group-hover:translate-x-1"
>
</span>
</Link>
</div>
</div>
</section>
);
}
Loading

0 comments on commit eee6a28

Please sign in to comment.