diff --git a/nx-dev/nx-dev/app/powerpack/page.tsx b/nx-dev/nx-dev/app/powerpack/page.tsx index b27a8bb67b1b0..fd51e9e3ee619 100644 --- a/nx-dev/nx-dev/app/powerpack/page.tsx +++ b/nx-dev/nx-dev/app/powerpack/page.tsx @@ -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 = { @@ -39,21 +37,15 @@ export default function NxPowerPackPage(): JSX.Element {
- -
-
- +
-
- + +
+
- - {/* */} +
); diff --git a/nx-dev/ui-animations/src/index.ts b/nx-dev/ui-animations/src/index.ts index eaa9db921885a..9cd2a0fbed3be 100644 --- a/nx-dev/ui-animations/src/index.ts +++ b/nx-dev/ui-animations/src/index.ts @@ -1,3 +1,4 @@ +export * from './lib/animated-beam'; export * from './lib/animate-value'; export * from './lib/blur-fade'; export * from './lib/fit-text'; diff --git a/nx-dev/ui-animations/src/lib/animated-beam.tsx b/nx-dev/ui-animations/src/lib/animated-beam.tsx new file mode 100644 index 0000000000000..1b2250ce65aab --- /dev/null +++ b/nx-dev/ui-animations/src/lib/animated-beam.tsx @@ -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; // Container ref + fromRef: RefObject; + toRef: RefObject; + 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 = ({ + 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 ( + + + + + + + + + + + + + ); +}; diff --git a/nx-dev/ui-icons/src/index.ts b/nx-dev/ui-icons/src/index.ts index cda98713ae493..c626dcfe9ae04 100644 --- a/nx-dev/ui-icons/src/index.ts +++ b/nx-dev/ui-icons/src/index.ts @@ -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'; diff --git a/nx-dev/ui-icons/src/lib/others/amazon-s3.tsx b/nx-dev/ui-icons/src/lib/others/amazon-s3.tsx new file mode 100644 index 0000000000000..5e2b803207ebc --- /dev/null +++ b/nx-dev/ui-icons/src/lib/others/amazon-s3.tsx @@ -0,0 +1,17 @@ +import { FC, SVGProps } from 'react'; + +/** + * Use `#569A31` for a colored version. + */ +export const AmazonS3Icon: FC> = (props) => ( + + Amazon S3 + + +); diff --git a/nx-dev/ui-powerpack/src/index.ts b/nx-dev/ui-powerpack/src/index.ts index 586c70b3e0693..7dfdd8321a597 100644 --- a/nx-dev/ui-powerpack/src/index.ts +++ b/nx-dev/ui-powerpack/src/index.ts @@ -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'; diff --git a/nx-dev/ui-powerpack/src/lib/call-to-action.tsx b/nx-dev/ui-powerpack/src/lib/call-to-action.tsx new file mode 100644 index 0000000000000..cf5fc845f5c6c --- /dev/null +++ b/nx-dev/ui-powerpack/src/lib/call-to-action.tsx @@ -0,0 +1,87 @@ +import Link from 'next/link'; +import { ReactElement } from 'react'; + +export function CallToAction(): ReactElement { + return ( +
+ +
+ ); +} diff --git a/nx-dev/ui-powerpack/src/lib/code-owners.tsx b/nx-dev/ui-powerpack/src/lib/code-owners.tsx deleted file mode 100644 index e7ef8b649aeb5..0000000000000 --- a/nx-dev/ui-powerpack/src/lib/code-owners.tsx +++ /dev/null @@ -1,47 +0,0 @@ -'use client'; - -import { - ButtonLink, - SectionHeading, - Strong, - TextLink, -} from '@nx/nx-dev/ui-common'; - -export function CodeOwners(): JSX.Element { - return ( -
-
- - CodeOwners for monorepos - - - Define and manage ownership where it matters— - at the project level. Common VCS providers require - folder-based ownership definitions, though. Nx Powerpack CodeOwners - bridges this gap by{' '} - - automatically tracking changes and syncing ownership data - {' '} - with GitHub, GitLab, or Bitbucket-specific CODEOWNERS files. This - ensures clear responsibilities and enables efficient collaboration - across large-scale projects. - -
- - Learn more about CodeOwners - -
-
-
- ); -} diff --git a/nx-dev/ui-powerpack/src/lib/conformance.tsx b/nx-dev/ui-powerpack/src/lib/conformance.tsx deleted file mode 100644 index 4ee8d8dbe0ee6..0000000000000 --- a/nx-dev/ui-powerpack/src/lib/conformance.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { - ButtonLink, - SectionHeading, - Strong, - TextLink, -} from '@nx/nx-dev/ui-common'; - -export function Conformance(): JSX.Element { - return ( -
-
- - Scale more confidently with workspace conformance - - - Ensuring consistent code quality and long-term maintainability across - large teams is critical. Nx Powerpack allows you to{' '} - - define and run conformance rules throughout your workspace - - , leveraging built-in rules or{' '} - - creating your own to ensure compliance with organizational - standards. - {' '} - With Nx Cloud Enterprise Edition, you can{' '} - - upload your custom rules to your Nx Cloud organization - {' '} - and automatically enforce them across multiple repositories and - workspaces, regardless of the tech stack. - -
- - Learn how to use conformance rules - -
-
-
- ); -} diff --git a/nx-dev/ui-powerpack/src/lib/custom-cache-storage.tsx b/nx-dev/ui-powerpack/src/lib/custom-cache-storage.tsx deleted file mode 100644 index 3af537243138e..0000000000000 --- a/nx-dev/ui-powerpack/src/lib/custom-cache-storage.tsx +++ /dev/null @@ -1,38 +0,0 @@ -'use client'; - -import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common'; - -export function CustomCacheStorage(): JSX.Element { - return ( -
-
- - Custom Remote Cache Storage - - - Enjoy the{' '} - flexibility of managing your remote cache location on - S3 or custom network drives. With Nx Powerpack's custom remote caching - feature, you can configure Nx to write cache data directly to your own - AWS S3 buckets or network drives, whether your infrastructure is - already in place or you need more control over your caching location. - -
- - Learn more about Custom Cache Storage - -
-
-
- ); -} diff --git a/nx-dev/ui-powerpack/src/lib/get-started.tsx b/nx-dev/ui-powerpack/src/lib/get-started.tsx new file mode 100644 index 0000000000000..3ed69dd12eef5 --- /dev/null +++ b/nx-dev/ui-powerpack/src/lib/get-started.tsx @@ -0,0 +1,154 @@ +import { SectionHeading } from '@nx/nx-dev/ui-common'; +import { ReactElement } from 'react'; +import { TerminalOutput } from '@nx/nx-dev/ui-fence'; +import { PowerpackPricing } from './powerpack-pricing'; + +export function GetStarted(): ReactElement { + return ( +
+
+
+ + Premium features,
carefully crafted DX +
+ + Expand you capabilities with Nx Powerpack,
a suite of + advanced tools designed for enterprises. +
+
+ +
+ + +
+
+
+ + 1 + +
+
+

+ Buy an Nx Powerpack license +

+

+ Select with type of license to subscribe to for your own needs + with monthly payments or pay once for the whole year. +

+
+ +
+
+
+
+
+ + 2 + +
+
+

+ Activate Nx Powerpack right from your terminal +

+

+ The setup is simple and straightforward. Run one command to + activate your license and start adding unique capabilities to + your workspace. +

+
+ +
+
+
+
+
+ + 3 + +
+
+

+ Enjoy your enhanced setup +

+

+ Use Nx Powerpack to enhance your development experience with + custom remote caching, Conformance, Workspace wide code + ownership and more premium official Nx Plugins. +

+
+
+
+
+
+
+ ); +} diff --git a/nx-dev/ui-powerpack/src/lib/hero.tsx b/nx-dev/ui-powerpack/src/lib/hero.tsx index 3dcaf7ba6b13a..4fc71c6eb917b 100644 --- a/nx-dev/ui-powerpack/src/lib/hero.tsx +++ b/nx-dev/ui-powerpack/src/lib/hero.tsx @@ -1,40 +1,30 @@ 'use client'; -import { SectionHeading } from '@nx/nx-dev/ui-common'; +import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common'; import { PowerpackPricing } from './powerpack-pricing'; +import { ReactElement } from 'react'; -export function Hero(): JSX.Element { +export function Hero(): ReactElement { return ( -
-
-
-
- - Nx Powerpack - -
- - Enterprise-grade features for your Nx workspace - - +
+ + Nx Powerpack + + + A suite of paid extensions for Nx specifically designed for + enterprises, built and supported by the Nx core team. + +
+ - Nx Powerpack is a suite of paid extensions for Nx specifically - designed for enterprises. Built and supported by the Nx core team, - Powerpack provides flexibility of choice with custom cache locations - and features designed to enhance maintainability and scale - development, ensuring your teams can operate efficiently at scale. - -
-
- + Buy an Nx Powerpack license +
-
+
); } diff --git a/nx-dev/ui-powerpack/src/lib/layout.tsx b/nx-dev/ui-powerpack/src/lib/layout.tsx deleted file mode 100644 index ce102b8346695..0000000000000 --- a/nx-dev/ui-powerpack/src/lib/layout.tsx +++ /dev/null @@ -1,25 +0,0 @@ -export function Layout({ - children, -}: { - children: React.ReactNode; -}): JSX.Element { - return ( -
-
- -
- ); -} diff --git a/nx-dev/ui-powerpack/src/lib/powerpack-features.tsx b/nx-dev/ui-powerpack/src/lib/powerpack-features.tsx new file mode 100644 index 0000000000000..04552c196e6ce --- /dev/null +++ b/nx-dev/ui-powerpack/src/lib/powerpack-features.tsx @@ -0,0 +1,256 @@ +'use client'; +import { forwardRef, ReactElement, ReactNode, useRef } from 'react'; +import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common'; +import { cx } from '@nx/nx-dev/ui-primitives'; +import { AnimatedBeam } from '@nx/nx-dev/ui-animations'; +import { ComputerDesktopIcon } from '@heroicons/react/24/outline'; +import { AmazonS3Icon, GitHubIcon, GitlabIcon } from '@nx/nx-dev/ui-icons'; + +export function PowerpackFeatures(): ReactElement { + return ( +
+
+
+
+
+ + Custom remote cache storage + +

+ Enjoy the{' '} + + flexibility of managing your remote cache location + {' '} + on S3 or custom network drives. With Nx Powerpack's custom + remote caching feature, you can configure Nx to write cache data + directly to your own AWS S3 buckets or network drives, whether + your infrastructure is already in place or you need more control + over your caching location. +

+
+ + Learn more about Custom Cache Storage + +
+
+
+ +
+
+
+
+ + CodeOwners: for monorepos + +

+ Define and manage ownership where it matters— + at the project level. Common VCS providers + require folder-based ownership definitions, though. +

+

+ Nx Powerpack CodeOwners bridges this gap by{' '} + + automatically tracking changes and syncing ownership data + {' '} + with GitHub, GitLab, or Bitbucket-specific CODEOWNERS files. + This ensures clear responsibilities and enables efficient + collaboration across large-scale projects. +

+
+
+ + Learn more about CodeOwners + +
+
+
+
+ + Workspace conformance + +

+ Ensuring consistent code quality and long-term maintainability + across large teams is critical. Nx Powerpack allows you to{' '} + + define and run conformance rules throughout your workspace + + , leveraging built-in rules or{' '} + + creating your own to ensure compliance with organizational + standards. + +

+

+ With Nx Cloud Enterprise Edition, you can{' '} + + upload your custom rules to your Nx Cloud organization + {' '} + and automatically enforce them across multiple repositories and + workspaces, regardless of the tech stack. +

+
+
+ + Learn how to use conformance rules + +
+
+
+
+ +
+ ); +} + +const Circle = forwardRef< + HTMLDivElement, + { className?: string; children?: ReactNode } +>(({ className, children }, ref) => { + return ( +
+ {children} +
+ ); +}); + +Circle.displayName = 'Circle'; + +export function CustomRemoteCacheAnimation(): ReactElement { + const containerRef = useRef(null); + const gitHubRef = useRef(null); + const computer3Ref = useRef(null); + const computer1Ref = useRef(null); + const amazonBucketRef = useRef(null); + const computer2Ref = useRef(null); + + return ( +
+
+
+ + + + +
+
+ + +
+
+ + + + +
+
+ + + + + +
+ ); +} diff --git a/nx-dev/ui-powerpack/src/lib/powerpack-pricing.tsx b/nx-dev/ui-powerpack/src/lib/powerpack-pricing.tsx index 0c6f2fc590d86..89b30331b5c3b 100644 --- a/nx-dev/ui-powerpack/src/lib/powerpack-pricing.tsx +++ b/nx-dev/ui-powerpack/src/lib/powerpack-pricing.tsx @@ -1,69 +1,81 @@ 'use client'; -import { useState } from 'react'; -import { CheckIcon } from '@heroicons/react/24/outline'; +import { ArrowRightIcon } from '@heroicons/react/24/outline'; import { ButtonLink } from '@nx/nx-dev/ui-common'; -import Link from 'next/link'; export function PowerpackPricing() { - const [isYearly, setIsYearly] = useState(false); - const monthlyPrice = 26; - const yearlyPrice = 250; // 10 months for the price of 12 - return ( -
-

- Get Nx Powerpack -

+
+ ); } diff --git a/nx-dev/ui-powerpack/src/lib/power-pack-process.tsx b/nx-dev/ui-powerpack/src/lib/powerpack-process.tsx similarity index 99% rename from nx-dev/ui-powerpack/src/lib/power-pack-process.tsx rename to nx-dev/ui-powerpack/src/lib/powerpack-process.tsx index 7753a3980995f..6d461950df8ae 100644 --- a/nx-dev/ui-powerpack/src/lib/power-pack-process.tsx +++ b/nx-dev/ui-powerpack/src/lib/powerpack-process.tsx @@ -24,7 +24,7 @@ const ConnectingLine = () => (
); -export function PowerPackProcess() { +export function PowerpackProcess() { return (