feat(nx-dev): update home page (#26893)

Add new sections and update information about Nx.

---------

Co-authored-by: Juri <juri.strumpflohner@gmail.com>
This commit is contained in:
Benjamin Cabanes 2024-07-16 15:43:41 -04:00 committed by GitHub
parent facfc147f8
commit 85d310a8c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
244 changed files with 8438 additions and 4613 deletions

View File

@ -183,6 +183,14 @@ To display a terminal command, use:
```
````
You can also add a title to the shell as follows:
````
```shell {% title="Build the app" %}
npx nx build
```
````
#### Terminal Output
You can display your terminal output with a dedicated component the same way you would show code.

View File

@ -17,10 +17,32 @@ Find out more about [why you should use Nx](/getting-started/why-nx) or browse o
## Try Nx Yourself!
```shell
npx create-nx-workspace@latest
{% side-by-side %}
```shell {% title="Create a new workspace" %}
npx create-nx-workspace
```
```shell {% title="Add Nx to an existing workspace" %}
npx nx init
```
{% /side-by-side %}
Also, here are some recipes that give you more details based on the technology stack you're using:
{% cards cols="2" mdCols="4" smCols="2" moreLink="/recipes/adopting-nx" %}
{% link-card title="Add to Existing Monorepo" appearance="small" url="/recipes/adopting-nx/adding-to-monorepo" icon="pnpm" /%}
{% link-card title="Add to Any Project" appearance="small" url="/recipes/adopting-nx/adding-to-existing-project" icon="nx" /%}
{% link-card title="Migrate from Angular CLI" appearance="small" url="/recipes/angular/migration/angular" icon="angular" /%}
{% /cards %}
{% /tab %}
{% /tabs %}
## Learn Nx
{% cards cols="2" lgCols="4" mdCols="4" smCols="2" %}
@ -57,26 +79,6 @@ npx create-nx-workspace@latest
{% /cards %}
## Have an Existing Project? Add Nx to it!
If you have an existing project and want to adopt Nx or migrate to Nx just run the following command which guides you through the migration process:
```shell
npx nx@latest init
```
Alternatively, here are some recipes that give you more details based on the technology stack you're using:
{% cards cols="2" mdCols="4" smCols="2" moreLink="/recipes/adopting-nx" %}
{% link-card title="Add to Existing Monorepo" appearance="small" url="/recipes/adopting-nx/adding-to-monorepo" icon="pnpm" /%}
{% link-card title="Add to Any Project" appearance="small" url="/recipes/adopting-nx/adding-to-existing-project" icon="nx" /%}
{% link-card title="Migrate from Angular CLI" appearance="small" url="/recipes/angular/migration/angular" icon="angular" /%}
{% /cards %}
## Pick Your Stack!
{% cards cols="3" lgCols="8" mdCols="6" smCols="5" moreLink="/showcase/example-repos" %}

View File

@ -49,12 +49,12 @@ export default function Community(): JSX.Element {
<div className="mx-auto max-w-7xl items-stretch px-4 py-12 sm:grid sm:grid-cols-1 sm:gap-8 sm:px-6 md:grid-cols-3 lg:px-8 lg:py-16">
<div className="md:col-span-2">
<header>
<SectionHeading as="h1" variant="title" id="champions">
<SectionHeading as="h1" variant="subtitle" id="champions">
Get to know our
</SectionHeading>
<SectionHeading
as="p"
variant="display"
variant="title"
id="nx-champions"
className="mt-4"
>
@ -81,7 +81,7 @@ export default function Community(): JSX.Element {
</div>
</div>
</div>
<div className="mt-6 flex h-full w-full flex-col items-start items-stretch gap-6 md:mt-0">
<div className="mt-6 flex h-full w-full flex-col items-stretch gap-6 md:mt-0">
{champions3.map((data) => (
<ChampionCard key={data.name} data={data} />
))}

View File

@ -1,4 +1,4 @@
import { DefaultLayout } from '@nx/nx-dev/ui-common';
import { CallToAction, DefaultLayout } from '@nx/nx-dev/ui-common';
import { NextSeo } from 'next-seo';
import { useRouter } from 'next/router';
@ -44,6 +44,9 @@ export function Customers(): JSX.Element {
<div className="mt-16 lg:mt-32">
<OssProjects />
</div>
<div className="mt-32 lg:mt-56">
<CallToAction />
</div>
</DefaultLayout>
</>
);

View File

@ -1,18 +1,14 @@
import { AnnouncementBanner, Footer, Header } from '@nx/nx-dev/ui-common';
import {
ExtensibleAndIntegrated,
GettingStarted,
Hero,
ImproveWorstCiCase,
Migrate,
MigrationsAndCodeGeneration,
MonorepoStyles,
Newsletter,
NxStatistics,
NxWithCi,
Testimonials,
} from '@nx/nx-dev/ui-home';
import { CallToAction, DefaultLayout } from '@nx/nx-dev/ui-common';
import { NextSeo } from 'next-seo';
import {
CiForMonorepos,
Hero,
SmarterToolsForMonorepos,
Statistics,
TeamAndCommunity,
TrustedBy,
WorkBetterAchieveMoreShipQuicker,
} from '@nx/nx-dev/ui-home';
export default function Index(): JSX.Element {
return (
@ -39,35 +35,31 @@ export default function Index(): JSX.Element {
}}
/>
<h1 className="sr-only">Next generation monorepo tool</h1>
<AnnouncementBanner />
<Header />
<main id="main" role="main">
<div className="w-full">
{/*HERO COMPONENT*/}
{/*<AnnouncementBanner />*/}
<DefaultLayout isHome>
<Hero />
{/*NX CI*/}
<NxWithCi />
{/*NX STATISTICS*/}
<NxStatistics />
{/*MONOREPO STYLES*/}
<MonorepoStyles />
{/*WORST CASE CI TIMES*/}
<ImproveWorstCiCase />
{/*EXTENSIBLE & INTEGRATED*/}
<ExtensibleAndIntegrated />
{/*MIGRATE*/}
<Migrate />
{/*AFFECTED & CODE GENERATION*/}
<MigrationsAndCodeGeneration />
{/*GETTING STARTED*/}
<GettingStarted />
{/*TESTIMONIALS*/}
<Testimonials />
{/*NEWSLETTER*/}
<Newsletter />
<div className="mt-16 lg:-mt-32">
<Statistics />
</div>
</main>
<Footer />
<div className="mt-32 lg:mt-56">
<TrustedBy />
</div>
<div className="mt-32 lg:mt-56">
<CiForMonorepos />
</div>
<div className="mt-32 lg:mt-56">
<WorkBetterAchieveMoreShipQuicker />
</div>
<div className="mt-32 lg:mt-56">
<SmarterToolsForMonorepos />
</div>
<div className="mt-32 lg:mt-56">
<TeamAndCommunity />
</div>
<div className="mt-32 lg:mt-56">
<CallToAction />
</div>
</DefaultLayout>
</>
);
}

View File

@ -0,0 +1,87 @@
import { ShaderGradient, ShaderGradientCanvas } from 'shadergradient';
export default function Shader(): JSX.Element {
return (
<>
<div className="absolute left-0 top-0 z-10 h-screen w-screen overflow-hidden bg-white text-gray-50">
{/*COTTON CANDY*/}
{/*<ShaderGradientCanvas
pointerEvents="none"
eventPrefix="client"
fov={45}
pixelDensity={1}
className="pointer-events-none"
>
<ShaderGradient
brightness={4}
cDistance={5}
color1="#ebedff"
color2="#f3f2f8"
color3="#dbf8ff"
frameRate={10}
grain="off"
lightType="3d"
positionX={0}
positionY={1.8}
positionZ={0}
range="enabled"
rangeEnd={40}
rangeStart={0}
reflection={0.1}
rotationX={0}
rotationY={0}
rotationZ={-90}
shader="defaults"
type="waterPlane"
uDensity={1}
uFrequency={5.5}
uSpeed={0.3}
uStrength={3}
uTime={0.2}
/>
</ShaderGradientCanvas>*/}
{/*UNIVERSE*/}
<ShaderGradientCanvas
pointerEvents="none"
eventPrefix="client"
fov={45}
pixelDensity={1}
className="pointer-events-none"
>
<ShaderGradient
brightness={4}
cAzimuthAngle={180}
cameraZoom={1}
cDistance={4}
cPolarAngle={115}
color1="#5606FF"
color2="#FE8989"
color3="#000000"
frameRate={10}
grain="off"
lightType="3d"
positionX={-0.5}
positionY={0.1}
positionZ={0}
range="enabled"
rangeEnd={40}
rangeStart={0}
reflection={0.1}
rotationX={0}
rotationY={0}
rotationZ={235}
shader="defaults"
type="waterPlane"
uAmplitude={0}
uDensity={1.1}
uFrequency={5.5}
uSpeed={0.1}
uStrength={2.4}
uTime={0.2}
/>
</ShaderGradientCanvas>
</div>
</>
);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

View File

@ -3,6 +3,9 @@ const path = require('path');
// nx-ignore-next-line
const { createGlobPatternsForDependencies } = require('@nx/next/tailwind');
const plugin = require('tailwindcss/plugin');
const {
default: flattenColorPalette,
} = require('tailwindcss/lib/util/flattenColorPalette');
if (!createGlobPatternsForDependencies(__dirname).length)
throw Error('GRAPH ISSUE: No dependency found when many are expected.');
@ -24,6 +27,18 @@ const FlipAnimation = plugin(function ({ addUtilities }) {
});
});
// This plugin adds each Tailwind color as a global CSS variable, e.g. var(--gray-200).
function addVariablesForColors({ addBase, theme }) {
let allColors = flattenColorPalette(theme('colors'));
let newVars = Object.fromEntries(
Object.entries(allColors).map(([key, val]) => [`--${key}`, val])
);
addBase({
':root': newVars,
});
}
module.exports = {
experimental: {
optimizeUniversalDefaults: true,
@ -36,6 +51,20 @@ module.exports = {
],
theme: {
extend: {
animation: {
marquee: 'marquee var(--duration) linear infinite',
'marquee-vertical': 'marquee-vertical var(--duration) linear infinite',
},
keyframes: {
marquee: {
from: { transform: 'translateX(0)' },
to: { transform: 'translateX(calc(-100% - var(--gap)))' },
},
'marquee-vertical': {
from: { transform: 'translateY(0)' },
to: { transform: 'translateY(calc(-100% - var(--gap)))' },
},
},
typography: {
DEFAULT: {
css: {
@ -61,5 +90,6 @@ module.exports = {
require('@tailwindcss/typography'),
require('@tailwindcss/forms'),
FlipAnimation,
addVariablesForColors,
],
};

View File

@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}

View File

@ -0,0 +1,18 @@
{
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

View File

@ -0,0 +1,7 @@
# nx-dev-ui-animations
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test nx-dev-ui-animations` to execute the unit tests via [Jest](https://jestjs.io).

View File

@ -0,0 +1,10 @@
/* eslint-disable */
export default {
displayName: 'nx-dev-ui-animations',
preset: '../../jest.preset.js',
transform: {
'^.+\\.[tj]sx?$': 'babel-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/nx-dev/ui-animations',
};

View File

@ -0,0 +1,8 @@
{
"name": "nx-dev-ui-animations",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "nx-dev/ui-animations/src",
"projectType": "library",
"tags": [],
"targets": {}
}

View File

@ -0,0 +1,6 @@
export * from './lib/animate-value';
export * from './lib/blur-fade';
export * from './lib/fit-text';
export * from './lib/marquee';
export * from './lib/moving-border';
export * from './lib/shine-border';

View File

@ -0,0 +1,51 @@
import { animate, useInView } from 'framer-motion';
import { useEffect, useRef, useState } from 'react';
/**
* Animates a value and renders it with a specified suffix.
*
* @param {Object} params - The parameters for animating the value.
* @param {number} params.num - The number to animate.
* @param {boolean} [params.once=false] - Flag indicating if the animation should only run once.
* @param {string} params.suffix - The suffix to append to the animated value.
* @param {number} [params.decimals=0] - The number of decimal places to display for the animated value.
*
* @return {JSX.Element} - The JSX element representing the animated value with suffix.
*/
export function AnimateValue({
num,
once = false,
suffix,
decimals = 0,
}: {
num: number;
once?: boolean;
suffix: string;
decimals?: number;
}) {
const ref = useRef<HTMLSpanElement | null>(null);
const [isComplete, setIsComplete] = useState<boolean>(false);
const isInView = useInView(ref);
useEffect(() => {
if (!isInView) return;
if (isComplete && once) return;
animate(0, num, {
duration: 2.5,
onUpdate(value) {
if (!ref.current) return;
ref.current.textContent = value.toFixed(decimals);
},
});
setIsComplete(true);
}, [num, decimals, isInView, once]);
return (
<span>
<span ref={ref}></span>
<span>{suffix}</span>
</span>
);
}

View File

@ -0,0 +1,85 @@
'use client';
import {
AnimatePresence,
motion,
useInView,
useWillChange,
Variants,
} from 'framer-motion';
import { ReactNode, useRef } from 'react';
interface BlurFadeProps {
children: ReactNode;
className?: string;
variant?: {
hidden: { y: number };
visible: { y: number };
};
duration?: number;
delay?: number;
yOffset?: number;
inView?: boolean;
inViewMargin?: string;
blur?: string;
once?: boolean;
}
/**
* Applies a blur fade effect to its children based on the scroll position.
*
* @param {Object} props - The component props.
* @param {React.ReactNode} props.children - The child elements to apply the effect to.
* @param {string} [props.className] - The CSS class to apply to the component.
* @param {Object} [props.variant] - The animation variants to apply.
* @param {number} [props.duration=0.4] - The duration of the animation in seconds.
* @param {number} [props.delay=0] - The delay before starting the animation in seconds.
* @param {number} [props.yOffset=6] - The distance the element moves on the Y-axis during the animation.
* @param {boolean} [props.inView=false] - Specifies whether the animation should trigger when the element is in view.
* @param {string} [props.inViewMargin='-50px'] - The margin to consider when checking if the element is in view.
* @param {string} [props.blur='5px'] - The amount of blur to apply to the element during the animation.
* @param {boolean} [props.once=false] - Specifies whether the animation should only trigger once.
*
* @return {React.ReactNode} The component with the blur fade effect applied.
*/
export function BlurFade({
children,
className,
variant,
duration = 0.4,
delay = 0,
yOffset = 6,
inView = false,
inViewMargin = '-50px',
blur = '5px',
once = false,
}: BlurFadeProps) {
const willChange = useWillChange();
const ref = useRef(null);
const inViewResult = useInView(ref, { once, margin: inViewMargin });
const isInView = !inView || inViewResult;
const defaultVariants: Variants = {
hidden: { y: yOffset, opacity: 0, filter: `blur(${blur})` },
visible: { y: -yOffset, opacity: 1, filter: `blur(0px)` },
};
const combinedVariants = variant || defaultVariants;
return (
<AnimatePresence>
<motion.div
ref={ref}
initial="hidden"
animate={isInView ? 'visible' : 'hidden'}
exit="hidden"
variants={combinedVariants}
style={{ willChange }}
transition={{
delay: 0.04 + delay,
duration,
ease: 'easeOut',
}}
className={className}
>
{children}
</motion.div>
</AnimatePresence>
);
}

View File

@ -0,0 +1,76 @@
import { useInView } from 'framer-motion';
import { ComponentRef, ReactNode, useEffect, useRef } from 'react';
import { cx } from '@nx/nx-dev/ui-primitives';
/**
* Resizes the text to fit within its container.
*
* @param {Object} props - The component's properties.
* @param {ReactNode} props.children - The content to be displayed within the component.
* @param {string} [props.className=''] - The additional className to be applied to the component.
*
* @return {JSX.Element} - The rendered component.
*/
export function FitText({
children,
className = '',
}: {
children: ReactNode;
className?: string;
}): JSX.Element {
const containerRef = useRef<ComponentRef<'div'>>(null);
const textRef = useRef<ComponentRef<'span'>>(null);
const isInView = useInView(containerRef);
useEffect(() => {
if (!isInView) return;
resizeText();
window.addEventListener('resize', resizeText);
return () => {
window.removeEventListener('resize', resizeText);
};
}, [isInView, children]);
const resizeText = () => {
const container = containerRef.current;
const text = textRef.current;
if (!container || !text) {
return;
}
const containerWidth = container.offsetWidth;
let min = 1;
let max = 2500;
while (min <= max) {
const mid = Math.floor((min + max) / 2);
text.style.fontSize = mid + 'px';
if (text.offsetWidth <= containerWidth) {
min = mid + 1;
} else {
max = mid - 1;
}
}
text.style.fontSize = max + 'px';
};
return (
<span
className="relative grid h-full w-full grid-cols-1 place-items-center"
ref={containerRef}
>
<span
className={cx(
'transform whitespace-nowrap text-center font-bold',
className
)}
ref={textRef}
>
{children}
</span>
</span>
);
}

View File

@ -0,0 +1,65 @@
import { cx } from '@nx/nx-dev/ui-primitives';
interface MarqueeProps {
className?: string;
reverse?: boolean;
pauseOnHover?: boolean;
children?: React.ReactNode;
vertical?: boolean;
repeat?: number;
[key: string]: any;
}
/**
* Creates a marquee component that animates its children horizontally or vertically.
*
* @param {Object} props - The props for the marquee component.
* @param {string} [props.className] - Additional class name(s) to be added to the component.
* @param {boolean} [props.reverse=false] - Whether to reverse the marquee animation.
* @param {boolean} [props.pauseOnHover=false] - Whether to pause the marquee animation on hover.
* @param {ReactNode} props.children - The content to be displayed within the marquee.
* @param {boolean} [props.vertical=false] - Whether to animate the marquee vertically.
* @param {number} [props.repeat=4] - The number of times to repeat the marquee animation.
* @param {any} props... - Additional props to be passed to the underlying div element.
*
* @return {ReactElement} The marquee component.
*/
export function Marquee({
className,
reverse,
pauseOnHover = false,
children,
vertical = false,
repeat = 4,
...props
}: MarqueeProps) {
return (
<div
{...props}
className={cx(
'group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] [gap:var(--gap)]',
{
'flex-row': !vertical,
'flex-col': vertical,
},
className
)}
>
{Array(repeat)
.fill(0)
.map((_, i) => (
<div
key={i}
className={cx('flex shrink-0 justify-around [gap:var(--gap)]', {
'animate-marquee flex-row': !vertical,
'animate-marquee-vertical flex-col': vertical,
'group-hover:[animation-play-state:paused]': pauseOnHover,
'[animation-direction:reverse]': reverse,
})}
>
{children}
</div>
))}
</div>
);
}

View File

@ -0,0 +1,89 @@
import {
motion,
useAnimationFrame,
useMotionTemplate,
useMotionValue,
useTransform,
} from 'framer-motion';
import { ReactNode, useRef } from 'react';
/**
* Creates a moving border effect around the specified component by animating a rectangular SVG element.
*
* @param {object} options - The options for the MovingBorder effect.
* @param {ReactNode} options.children - The content to be displayed within the moving border.
* @param {number} [options.duration=2000] - The duration of the animation in milliseconds.
* @param {string} [options.rx] - The x-axis radius of the border corners.
* @param {string} [options.ry] - The y-axis radius of the border corners.
* @param {any} [options.otherProps] - Additional properties to be applied to the SVG element.
*
* @return {ReactNode} - The MovingBorder component.
*/
export function MovingBorder({
children,
duration = 2000,
rx,
ry,
...otherProps
}: {
children: ReactNode;
duration?: number;
rx?: string;
ry?: string;
[key: string]: any;
}) {
const pathRef = useRef<any>();
const progress = useMotionValue<number>(0);
useAnimationFrame((time) => {
const length = pathRef.current?.getTotalLength();
if (length) {
const pxPerMillisecond = length / duration;
progress.set((time * pxPerMillisecond) % length);
}
});
const x = useTransform(
progress,
(val) => pathRef.current?.getPointAtLength(val).x
);
const y = useTransform(
progress,
(val) => pathRef.current?.getPointAtLength(val).y
);
const transform = useMotionTemplate`translateX(${x}px) translateY(${y}px) translateX(-50%) translateY(-50%)`;
return (
<>
<svg
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="none"
className="absolute h-full w-full"
width="100%"
height="100%"
{...otherProps}
>
<rect
fill="none"
width="100%"
height="100%"
rx={rx}
ry={ry}
ref={pathRef}
/>
</svg>
<motion.div
style={{
position: 'absolute',
top: 0,
left: 0,
display: 'inline-block',
transform,
}}
>
{children}
</motion.div>
</>
);
}

View File

@ -0,0 +1,67 @@
'use client';
import { cx } from '@nx/nx-dev/ui-primitives';
import { CSSProperties, ReactNode } from 'react';
type TColorProp = `#${string}` | `#${string}`[];
interface ShineBorderProps {
borderRadius?: number;
borderWidth?: number;
duration?: number;
color?: TColorProp;
className?: string;
children: ReactNode;
}
/**
* Shines a border around a container element.
*
* @param borderRadius - The radius of the border corners in pixels. Defaults to 8.
* @param borderWidth - The width of the border in pixels. Defaults to 1.
* @param duration - The duration of the shine animation in seconds. Defaults to 14.
* @param color - The color of the shine. Can be a single color (string) or an array of colors. Defaults to '#fff'.
* @param className - Additional CSS classes to apply to the container element.
* @param children - The content to display inside the container element.
*
* @return The container element with a shining border.
*/
export function ShineBorder({
borderRadius = 8,
borderWidth = 1,
duration = 14,
color = '#fff',
className,
children,
}: ShineBorderProps) {
return (
<div
style={
{
'--border-radius': `${borderRadius}px`,
} as CSSProperties
}
className={cx(
'relative grid min-h-[60px] w-fit min-w-[300px] place-items-center rounded-[--border-radius] bg-white p-3 text-black dark:bg-black dark:text-white',
className
)}
>
<div
style={
{
'--border-width': `${borderWidth}px`,
'--border-radius': `${borderRadius}px`,
'--border-radius-child': `${borderRadius * 0.2}px`,
'--shine-pulse-duration': `${duration}s`,
'--mask-linear-gradient': `linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)`,
'--background-radial-gradient': `radial-gradient(transparent,transparent, ${
!(color instanceof Array) ? color : color.join(',')
},transparent,transparent)`,
} as CSSProperties
}
className={`before:bg-shine-size before:absolute before:inset-[0] before:aspect-square before:h-full before:w-full before:rounded-[--border-radius] before:p-[--border-width] before:will-change-[background-position] before:content-[""] before:![-webkit-mask-composite:xor] before:[background-image:var(--background-radial-gradient)] before:[background-size:300%_300%] before:![mask-composite:exclude] before:[mask:var(--mask-linear-gradient)] motion-safe:before:animate-[shine-pulse_var(--shine-pulse-duration)_infinite_linear]`}
></div>
<div className={'z-[1] h-full w-full rounded-[--border-radius-child]'}>
{children}
</div>
</div>
);
}

View File

@ -0,0 +1,25 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@ -0,0 +1,24 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"],
"lib": ["dom"]
},
"files": [
"../../node_modules/@nx/react/typings/cssmodule.d.ts",
"../../node_modules/@nx/react/typings/image.d.ts"
],
"exclude": [
"jest.config.ts",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

View File

@ -0,0 +1,20 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"jest.config.ts",
"**/*.test.ts",
"**/*.spec.ts",
"**/*.test.tsx",
"**/*.spec.tsx",
"**/*.test.js",
"**/*.spec.js",
"**/*.test.jsx",
"**/*.spec.jsx",
"**/*.d.ts"
]
}

View File

@ -2,14 +2,12 @@ export * from './lib/announcement-banner';
export * from './lib/headers/documentation-header';
export * from './lib/breadcrumbs';
export * from './lib/button';
export * from './lib/call-to-action';
export * from './lib/champion-card';
export * from './lib/champion-perks';
export * from './lib/default-layout';
export * from './lib/headers/header';
export * from './lib/flip-card';
export * from './lib/nx-agents-icon';
export * from './lib/nx-cloud-icon';
export * from './lib/nx-replay-icon';
export * from './lib/footer';
export * from './lib/sidebar-container';
export * from './lib/sidebar';
@ -21,7 +19,6 @@ export * from './lib/github-star-widget';
export * from './lib/youtube.component';
export * from './lib/x-icon';
export * from './lib/discord-icon';
export * from './lib/logos';
export { resourceMenuItems } from './lib/headers/menu-items';
export { solutionsMenuItems } from './lib/headers/menu-items';

View File

@ -7,7 +7,7 @@ import {
ReactNode,
} from 'react';
type AllowedVariants = 'primary' | 'secondary';
type AllowedVariants = 'primary' | 'secondary' | 'contrast';
type AllowedSizes = 'large' | 'default' | 'small';
interface ButtonProps {
@ -22,6 +22,8 @@ const variantStyles: Record<AllowedVariants, string> = {
'bg-blue-500 dark:bg-sky-500 text-white group-hover:bg-blue-600 dark:group-hover:bg-sky-600 group-focus:ring-2 group-focus:ring-blue-500 dark:group-focus:ring-sky-500 focus:group-ring-offset-2',
secondary:
'border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200 group-hover:bg-slate-50 dark:group-hover:bg-slate-700 group-focus:ring-2 group-focus:ring-blue-500 dark:group-focus:ring-sky-500 focus:ring-offset-2',
contrast:
'bg-slate-950 dark:bg-white text-slate-100 dark:text-slate-950 group-hover:bg-slate-800 dark:group-hover:bg-slate-100 group-focus:ring-2 group-focus:ring-blue-500 dark:group-focus:ring-sky-500 focus:ring-offset-2',
};
const sizes: Record<AllowedSizes, string> = {
large: 'space-x-4 px-4 py-2 text-lg',

View File

@ -0,0 +1,87 @@
import Link from 'next/link';
export function CallToAction(): JSX.Element {
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="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"
>
Ready to
<br />
build smarter and ship faster?
</h2>
<div className="mt-10 flex items-center justify-center gap-x-6">
<Link
href="/getting-started/intro"
title="Get started with Nx"
prefetch={false}
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"
>
Get started
</Link>
<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>
);
}

View File

@ -33,12 +33,12 @@ export function ChampionPerks(): JSX.Element {
<div className="mx-auto max-w-7xl px-4 sm:grid sm:grid-cols-2 sm:gap-8 sm:px-6 lg:px-8">
<div>
<header>
<SectionHeading as="h1" variant="title" id="nx-is-fast">
<SectionHeading as="h1" variant="subtitle" id="nx-is-fast">
Interested in joining the Nx Champions program yourself?
</SectionHeading>
<SectionHeading
as="p"
variant="display"
variant="title"
id="nx-is-fast"
className="mt-4"
>

View File

@ -1,12 +1,16 @@
import { Footer } from './footer';
import { Header } from './headers/header';
import { PropsWithChildren } from 'react';
import cx from 'classnames';
export function DefaultLayout({ children }: PropsWithChildren): JSX.Element {
export function DefaultLayout({
isHome = false,
children,
}: { isHome?: boolean } & PropsWithChildren): JSX.Element {
return (
<div className="dark:bg-slate-950">
<Header />
<div className="relative isolate pt-14">
<div className="relative isolate">
<div
className="absolute inset-x-0 -top-40 -z-10 h-full transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true"
@ -19,7 +23,7 @@ export function DefaultLayout({ children }: PropsWithChildren): JSX.Element {
}}
/>
</div>
<main className="py-24 sm:py-32">{children}</main>
<main className={isHome ? '' : 'py-24 sm:py-32'}>{children}</main>
</div>
<Footer />
</div>

View File

@ -138,7 +138,7 @@ export function Footer(): JSX.Element {
};
return (
<footer
className="bg-slate-50 dark:bg-slate-900"
className="bg-white dark:bg-slate-950"
aria-labelledby="footer-heading"
>
<h2 id="footer-heading" className="sr-only">
@ -164,8 +164,8 @@ export function Footer(): JSX.Element {
key={item.name}
href={item.href}
title={item.label}
className="text-sm text-slate-500 hover:text-slate-600 dark:hover:text-slate-400"
prefetch={false}
className="text-sm text-slate-500 hover:text-slate-600 dark:hover:text-slate-400"
>
<span className="sr-only">{item.name}</span>
<item.icon className="h-6 w-6" aria-hidden="true" />
@ -187,8 +187,8 @@ export function Footer(): JSX.Element {
<li key={item.name}>
<Link
href={item.href}
className="text-sm text-slate-500 hover:text-slate-600 dark:hover:text-slate-400"
prefetch={false}
className="text-sm text-slate-500 hover:text-slate-600 dark:hover:text-slate-400"
>
{item.name}
</Link>
@ -205,8 +205,8 @@ export function Footer(): JSX.Element {
<li key={item.name}>
<Link
href={item.href}
className="text-sm text-slate-500 hover:text-slate-600 dark:hover:text-slate-400"
prefetch={false}
className="text-sm text-slate-500 hover:text-slate-600 dark:hover:text-slate-400"
>
{item.name}
</Link>
@ -225,8 +225,8 @@ export function Footer(): JSX.Element {
<li key={item.name}>
<Link
href={item.href}
className="text-sm text-slate-500 hover:text-slate-600 dark:hover:text-slate-400"
prefetch={false}
className="text-sm text-slate-500 hover:text-slate-600 dark:hover:text-slate-400"
>
{item.name}
</Link>
@ -243,8 +243,8 @@ export function Footer(): JSX.Element {
<li key={item.name}>
<Link
href={item.href}
className="text-sm text-slate-500 hover:text-slate-600 dark:hover:text-slate-400"
prefetch={false}
className="text-sm text-slate-500 hover:text-slate-600 dark:hover:text-slate-400"
>
{item.name}
</Link>
@ -259,7 +259,7 @@ export function Footer(): JSX.Element {
<p className="text-sm text-slate-400 xl:text-center">
&copy; 2024 made with{' '}
<HeartIcon className="-mt-0.5 inline h-4 w-4" /> by{' '}
<Link
<a
href="https://nx.app/company/?utm_source=nx.dev"
target="_blank"
rel="noreferrer"
@ -273,7 +273,7 @@ export function Footer(): JSX.Element {
>
<path d="m12 14.1-3.1 5-5.2-8.5v8.9H0v-15h3.7l5.2 8.9v-4l3 4.7zm.6-5.7V4.5H8.9v3.9h3.7zm5.6 4.1a2 2 0 0 0-2 1.3 2 2 0 0 1 2.4-.7c.4.2 1 .4 1.3.3a2.1 2.1 0 0 0-1.7-.9zm3.4 1c-.4 0-.8-.2-1.1-.6l-.2-.3a2.1 2.1 0 0 0-.5-.6 2 2 0 0 0-1.2-.3 2.5 2.5 0 0 0-2.3 1.5 2.3 2.3 0 0 1 4 .4.8.8 0 0 0 .9.3c.5 0 .4.4 1.2.5v-.1c0-.4-.3-.5-.8-.7zm2 1.3a.7.7 0 0 0 .4-.6c0-3-2.4-5.5-5.4-5.5a5.4 5.4 0 0 0-4.5 2.4l-1.5-2.4H8.9l3.5 5.4L9 19.5h3.6L14 17l1.6 2.4h3.5l-3.1-5a.7.7 0 0 1 0-.3 2.7 2.7 0 0 1 2.6-2.7c1.5 0 1.7.9 2 1.3.7.8 2 .5 2 1.5a.7.7 0 0 0 1 .6zm.4.2c-.2.3-.6.3-.8.6-.1.3.1.4.1.4s.4.2.6-.3V15z" />
</svg>
</Link>
</a>
</p>
</div>
</div>

View File

@ -11,7 +11,6 @@ import cx from 'classnames';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { ButtonLink } from '../button';
import { NxIcon } from '../nx-icon';
import { Popover, Transition } from '@headlessui/react';
import { TwoColumnsMenu } from './two-columns-menu';
import {
@ -20,9 +19,9 @@ import {
solutionsMenuItems,
} from './menu-items';
import { SectionsMenu } from './sections-menu';
import { NxCloudIcon } from '../nx-cloud-icon';
import { AnnouncementBanner } from '../announcement-banner';
import { DiscordIcon } from '../discord-icon';
import { NxCloudIcon, NxIcon } from '@nx/nx-dev/ui-icons';
function Menu({ tabs }: { tabs: any[] }): JSX.Element {
return (

View File

@ -19,13 +19,11 @@ import {
resourceMenuItems,
solutionsMenuItems,
} from './menu-items';
import { NxIcon } from '../nx-icon';
import { GitHubIcon } from '../github-icon';
import { MobileMenuItem } from './mobile-menu-item';
import { SectionsMenu } from './sections-menu';
import { TwoColumnsMenu } from './two-columns-menu';
import { AlgoliaSearch } from '@nx/nx-dev/feature-search';
import { NxCloudIcon } from '../nx-cloud-icon';
import { GitHubIcon, NxCloudIcon, NxIcon } from '@nx/nx-dev/ui-icons';
export function Header(): JSX.Element {
let [isOpen, setIsOpen] = useState(false);
@ -46,9 +44,16 @@ export function Header(): JSX.Element {
}, []);
return (
<div className="relative inset-x-0 top-0 z-[5] flex print:hidden">
<div className="fixed inset-x-0 top-0 isolate z-[5] flex px-4 print:hidden">
<div
className="absolute inset-x-0 top-0 mx-auto h-20 max-w-7xl backdrop-blur"
style={{
maskImage:
'linear-gradient(to bottom, #000000 20%, transparent calc(100% - 20%))',
}}
/>
{/*DESKTOP*/}
<div className="mx-auto hidden w-full max-w-7xl items-center justify-between space-x-10 p-4 px-8 lg:flex">
<div className="mx-auto mt-2 hidden w-full max-w-7xl items-center justify-between space-x-10 rounded-xl border border-slate-200/40 bg-white/70 px-4 py-2 shadow-lg backdrop-blur-xl backdrop-saturate-150 lg:flex dark:border-slate-800/60 dark:bg-slate-950/40">
{/*PRIMARY NAVIGATION*/}
<div className="flex flex-shrink-0 text-sm">
{/*LOGO*/}
@ -243,7 +248,7 @@ export function Header(): JSX.Element {
title="Log in to your Nx Cloud Account"
>
<NxCloudIcon className="h-4 w-4" aria-hidden="true" />
<span>Go to App</span>
<span>Go to app</span>
</ButtonLink>
<a
title="Nx is open source, check the code on GitHub"
@ -363,7 +368,7 @@ export function Header(): JSX.Element {
title="Log in to your Nx Cloud Account"
className="w-full"
>
Go to App
Go to app
</ButtonLink>
<div className="mt-4 divide-y divide-slate-200 border-b border-slate-200 dark:divide-slate-800 dark:border-slate-800">

View File

@ -15,10 +15,9 @@ import {
GlobeAltIcon,
} from '@heroicons/react/24/outline';
import { FC, SVGProps } from 'react';
import { NxAgentsIcon } from '../nx-agents-icon';
import { NxReplayIcon } from '../nx-replay-icon';
import { DiscordIcon } from '../discord-icon';
import { BuildingOfficeIcon } from '@heroicons/react/24/solid';
import { NxAgentsIcon, NxReplayIcon } from '@nx/nx-dev/ui-icons';
export interface MenuItem {
name: string;

View File

@ -1,64 +0,0 @@
export * from './tanstack';
export * from './lerna';
export * from './angular';
export * from './epic-web';
export * from './7eleven';
export * from './american-airlines';
export * from './aws-amplify';
export * from './bill';
export * from './capital-one';
export * from './caterpillar';
export * from './cisco';
export * from './fico';
export * from './hilton';
export * from './man';
export * from './react-query';
export * from './redwood-js';
export * from './royal-bank-of-canada';
export * from './shopify';
export * from './storybook';
export * from './vmware';
export * from './wallmart';
export * from './fedex';
export * from './rxjs';
export * from './sentry';
export * from './mui';
export * from './tide';
export * from './adobe';
export * from './intel';
export * from './addidas';
export * from './ikea';
export * from './paramount';
export * from './deloitte';
export * from './vodafone';
export * from './t-mobile';
export * from './mail-chimp';
export * from './moderna';
export * from './click-up';
export * from './sharp';
export * from './red-bull';
export * from './lego';
export * from './philips';
export * from './bloomberg';
export * from './sainsburys';
export * from './ukg';
export * from './splice';
export * from './dnb';
export * from './hetzner-cloud';
export * from './ghost';
export * from './hasura';
export * from './paylocity';
export * from './varian';
export * from './payfit';
export * from './caseware';
export * from './three-kit';
export * from './cais-group';
export * from './milliennium';
export * from './entain';
export * from './microsoft';
export * from './strapi';
export * from './cypress';
export * from './builder-mitosis';
export * from './electron';
export * from './typescript-eslint';
export * from './zipari';

View File

@ -1,17 +0,0 @@
import { FC, SVGProps } from 'react';
export const NxAgentsIcon: FC<SVGProps<SVGSVGElement>> = (props) => (
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
fill="none"
{...props}
>
<path
strokeLinejoin="round"
d="M21 12.5h-4m4 0a1 1 0 1 0 2 0 1 1 0 0 0-2 0Zm-2 8h-5v-3m5 3a1 1 0 1 0 2 0 1 1 0 0 0-2 0Zm-16-8h4m-4 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm2 8h5v-3m-5 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm0-17h5v4m-5-4a1 1 0 1 0-2 0 1 1 0 0 0 2 0Zm14 0h-5v4m5-4a1 1 0 1 1 2 0 1 1 0 0 1-2 0Zm-3 14H8a1 1 0 0 1-1-1v-8a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1Zm-5-8h2l-.667 1.875L14 11.346 11.333 15.5l.334-2.77H10l1-3.23Z"
/>
</svg>
);

View File

@ -1,17 +0,0 @@
import { FC, SVGProps } from 'react';
export const NxCloudIcon: FC<SVGProps<SVGSVGElement>> = (props) => (
<svg
role="img"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
fill="transparent"
viewBox="0 0 24 24"
{...props}
>
<path
d="M22.167 7.167v-2.5a2.5 2.5 0 0 0-2.5-2.5h-15a2.5 2.5 0 0 0-2.5 2.5v15a2.5 2.5 0 0 0 2.5 2.5h2.5m15-15c-2.76 0-5 2.24-5 5s-2.24 5-5 5-5 2.24-5 5m15-15V19.59a2.577 2.577 0 0 1-2.576 2.576H7.167"
strokeWidth="2"
/>
</svg>
);

View File

@ -1,14 +0,0 @@
import { FC, SVGProps } from 'react';
export const NxIcon: FC<SVGProps<SVGSVGElement>> = (props) => (
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
{...props}
>
<title>Nx</title>
<path d="m12 14.1-3.1 5-5.2-8.5v8.9H0v-15h3.7l5.2 8.9v-4l3 4.7zm.6-5.7V4.5H8.9v3.9h3.7zm5.6 4.1a2 2 0 0 0-2 1.3 2 2 0 0 1 2.4-.7c.4.2 1 .4 1.3.3a2.1 2.1 0 0 0-1.7-.9zm3.4 1c-.4 0-.8-.2-1.1-.6l-.2-.3a2.1 2.1 0 0 0-.5-.6 2 2 0 0 0-1.2-.3 2.5 2.5 0 0 0-2.3 1.5 2.3 2.3 0 0 1 4 .4.8.8 0 0 0 .9.3c.5 0 .4.4 1.2.5v-.1c0-.4-.3-.5-.8-.7zm2 1.3a.7.7 0 0 0 .4-.6c0-3-2.4-5.5-5.4-5.5a5.4 5.4 0 0 0-4.5 2.4l-1.5-2.4H8.9l3.5 5.4L9 19.5h3.6L14 17l1.6 2.4h3.5l-3.1-5a.7.7 0 0 1 0-.3 2.7 2.7 0 0 1 2.6-2.7c1.5 0 1.7.9 2 1.3.7.8 2 .5 2 1.5a.7.7 0 0 0 1 .6zm.4.2c-.2.3-.6.3-.8.6-.1.3.1.4.1.4s.4.2.6-.3V15z" />
</svg>
);

View File

@ -1,17 +0,0 @@
import { FC, SVGProps } from 'react';
export const NxReplayIcon: FC<SVGProps<SVGSVGElement>> = (props) => (
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
fill="none"
{...props}
>
<path
strokeLinecap="round"
d="m8.625 2.621-.014.004c-.317.09-.622.22-.907.387m4.796-.965-.014-.002a3.958 3.958 0 0 0-.986.002m3.875.574.014.004c.317.09.622.22.907.387m-.92 18.367.013-.004c.317-.09.622-.22.907-.387m-4.796.965.014.002c.328.04.659.04.986-.002m-3.875-.574-.014-.004a3.96 3.96 0 0 1-.907-.387M21.38 8.625l-.004-.014a3.96 3.96 0 0 0-.387-.907m.965 4.796.002-.014c.04-.328.04-.659-.002-.986m-.574 3.875-.004.014a3.96 3.96 0 0 1-.387.907m-18.367-.92.004.013c.09.317.22.622.387.907M2.047 11.5l-.002.014c-.04.328-.04.659.002.986m.574-3.875.004-.014c.09-.317.22-.622.387-.907M7.5 10.516h9m-9 0a1.5 1.5 0 0 1 0-3h9a1.5 1.5 0 0 1 0 3m-9 0a1.5 1.5 0 0 0 0 3m9-3a1.5 1.5 0 0 1 0 3m-6.412-4.5h.01m-1.883 0h.01m-.725 4.5h9m-9 0a1.5 1.5 0 0 0 0 3h9a1.5 1.5 0 0 0 0-3m-6.412-1.5h.01m-1.883 0h.01m1.863 3h.01m-1.883 0h.01M3 4.516a1.5 1.5 0 1 0 3 0 1.5 1.5 0 0 0-3 0Zm15 0a1.5 1.5 0 1 0 3 0 1.5 1.5 0 0 0-3 0Zm-15 15a1.5 1.5 0 1 0 3 0 1.5 1.5 0 0 0-3 0Zm15 0a1.5 1.5 0 1 0 3 0 1.5 1.5 0 0 0-3 0Z"
/>
</svg>
);

View File

@ -1,61 +0,0 @@
import { cx } from '@nx/nx-dev/ui-primitives';
import { ElementType, ReactNode } from 'react';
type AllowedVariants = 'title' | 'display' | 'subtitle';
type Headings = {
as: ElementType;
className?: string;
children: ReactNode | ReactNode[];
id?: string;
variant: AllowedVariants;
};
type Description = {
as: ElementType;
className?: string;
children: ReactNode | ReactNode[];
id?: string;
};
const variants: Record<AllowedVariants, string> = {
title:
'text-3xl font-medium tracking-tight text-slate-950 dark:text-white sm:text-5xl',
display:
'text-4xl font-medium tracking-tight text-slate-950 dark:text-white sm:text-7xl',
subtitle: 'text-lg leading-8 text-slate-700 dark:text-slate-300 sm:text-2xl',
};
// TODO(nicholas): Replace `typography.tsx` with this file after ensuring all components are using the new `SectionHeading` and `SectionDescription` components.
// Also remove the entry from tsconfig.base.json for this file.
export function SectionHeading({
as = 'div',
children,
className,
variant,
...rest
}: Headings): JSX.Element {
const Tag = as;
return (
<Tag className={cx(variants[variant], className)} {...rest}>
{children}
</Tag>
);
}
export function SectionDescription({
as = 'div',
children,
className,
...rest
}: Description): JSX.Element {
const Tag = as;
return (
<Tag
className={cx('text-slate-700 dark:text-slate-400', className)}
{...rest}
>
{children}
</Tag>
);
}

View File

@ -7,7 +7,7 @@ import cx from 'classnames';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { createRef, Fragment, useCallback, useEffect, useState } from 'react';
import { NxIcon } from './nx-icon';
import { NxIcon } from '@nx/nx-dev/ui-icons';
export interface SidebarProps {
menu: Menu;

View File

@ -1,20 +1,30 @@
import cx from 'classnames';
import { ElementType, ReactNode } from 'react';
import { cx } from '@nx/nx-dev/ui-primitives';
import Link from 'next/link';
import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';
type AllowedVariants = 'title' | 'display';
type AllowedVariants = 'title' | 'display' | 'subtitle';
type Headings = {
as: ElementType;
className?: string;
children: ReactNode | ReactNode[];
id?: string;
variant: 'title' | 'display';
variant: AllowedVariants;
};
type Description = {
as: ElementType;
className?: string;
children: ReactNode | ReactNode[];
id?: string;
};
const variants: Record<AllowedVariants, string> = {
title: 'text-lg font-semibold tracking-tight text-blue-500 dark:text-sky-500',
title:
'text-3xl font-bold tracking-tight text-slate-950 dark:text-white sm:text-5xl',
display:
'text-3xl font-semibold tracking-tight text-slate-900 dark:text-slate-100 sm:text-5xl',
'text-4xl font-medium tracking-tight text-slate-950 dark:text-white sm:text-8xl',
subtitle: 'text-lg leading-8 text-slate-700 dark:text-slate-300 sm:text-2xl',
};
export function SectionHeading({
@ -31,3 +41,84 @@ export function SectionHeading({
</Tag>
);
}
export function SectionDescription({
as = 'div',
children,
className,
...rest
}: Description): JSX.Element {
const Tag = as;
return (
<Tag
className={cx('text-slate-700 dark:text-slate-400', className)}
{...rest}
>
{children}
</Tag>
);
}
// TODO: add external link support with `<a>` only.
/**
* Use `<Link>` from NextJs to create an internal link between screens.
* Set `prefetch` to `false` by default.
* @param className
* @param props
*/
export function TextLink({
className,
...props
}: ComponentPropsWithoutRef<typeof Link>) {
return (
<Link
prefetch={false}
{...props}
className={cx(
className,
'font-bold text-blue-600 underline decoration-blue-600/50 transition hover:text-black hover:decoration-blue-600 dark:text-sky-500 dark:decoration-sky-500/50 dark:hover:text-white dark:hover:decoration-sky-500'
)}
/>
);
}
export function TextLinkHighlight({
className,
...props
}: ComponentPropsWithoutRef<typeof Link>) {
return (
<Link
{...props}
className={cx(
className,
'rounded bg-black px-1 py-0.5 font-bold text-white transition hover:bg-blue-600 dark:bg-white dark:text-black dark:hover:bg-sky-500'
)}
/>
);
}
export function Strong({
className,
...props
}: ComponentPropsWithoutRef<'strong'>) {
return (
<strong
{...props}
className={cx(className, 'font-bold text-slate-950 dark:text-slate-100')}
/>
);
}
export function Code({
className,
...props
}: React.ComponentPropsWithoutRef<'code'>) {
return (
<code
{...props}
className={cx(
className,
'rounded border border-slate-950/10 bg-slate-950/[2.5%] px-0.5 text-sm font-medium text-slate-950 sm:text-[0.8125rem] dark:border-white/20 dark:bg-white/5 dark:text-white'
)}
/>
);
}

View File

@ -10,7 +10,7 @@ export function ConnectWithUs(): JSX.Element {
>
<header className="space-y-10 md:py-12 lg:w-5/12 xl:w-5/12">
<div>
<SectionHeading as="h1" variant="display" id="connect-with-us">
<SectionHeading as="h1" variant="title" id="connect-with-us">
Let's connect together!
</SectionHeading>
<p className="mt-4">

View File

@ -1,4 +1,4 @@
import { SectionHeading } from '@nx/nx-dev/ui-common/src/lib/section-tags';
import { SectionHeading } from '@nx/nx-dev/ui-common';
import { XIcon } from '@nx/nx-dev/ui-common';
const coFounders = [

View File

@ -1,4 +1,4 @@
import { SectionHeading } from '@nx/nx-dev/ui-common/src/lib/section-tags';
import { SectionHeading } from '@nx/nx-dev/ui-common';
import {
GlobeAltIcon,
TrophyIcon,

View File

@ -1,4 +1,4 @@
import { SectionHeading } from '@nx/nx-dev/ui-common/src/lib/section-tags';
import { SectionHeading } from '@nx/nx-dev/ui-common';
const teamMembers = [
{

View File

@ -1,52 +1,49 @@
import {
ManIcon,
VmwareIcon,
SevenElevenIcon,
AwsAmplifyIcon,
CapitalOneIcon,
ShopifyIcon,
AmericanAirlinesIcon,
CiscoIcon,
CaterpillarIcon,
FicoIcon,
HiltonIcon,
FedExIcon,
ParamountIcon,
AdidasIcon,
AdobeIcon,
AddidasIcon,
IntelIcon,
IkeaIcon,
DeloitteIcon,
VodafoneIcon,
TMobileIcon,
MailChimpIcon,
ModernaIcon,
ClickUpIcon,
SharpIcon,
RedBullIcon,
LegoIcon,
PhilipsIcon,
BloombergIcon,
SainsburysIcon,
TideIcon,
UkgIcon,
SpliceIcon,
DnbIcon,
HetznerCloudIcon,
GhostIcon,
HasuraIcon,
PaylocityIcon,
VarianIcon,
PayfitIcon,
CasewareIcon,
ThreeKitIcon,
CaisGroupIcon,
MillienniumIcon,
EntainIcon,
ZipariIcon,
AmericanAirlinesIcon,
BillIcon,
BloombergIcon,
CaisGroupIcon,
CapitalOneIcon,
CasewareIcon,
CaterpillarIcon,
CiscoIcon,
ClickUpIcon,
DeloitteIcon,
DnbIcon,
EntainIcon,
FedExIcon,
FicoIcon,
HasuraIcon,
HetznerCloudIcon,
HiltonIcon,
IkeaIcon,
IntelIcon,
LegoIcon,
MailChimpIcon,
ManIcon,
MillienniumIcon,
ModernaIcon,
ParamountIcon,
PayfitIcon,
PaylocityIcon,
PhilipsIcon,
RedBullIcon,
RoyalBankOfCanadaIcon,
} from '@nx/nx-dev/ui-common';
SainsburysIcon,
SevenElevenIcon,
SharpIcon,
SpliceIcon,
ThreeKitIcon,
TideIcon,
TMobileIcon,
UkgIcon,
VarianIcon,
VmwareIcon,
VodafoneIcon,
ZipariIcon,
} from '@nx/nx-dev/ui-icons';
export function EnterpriseCustomers(): JSX.Element {
return (
@ -173,7 +170,7 @@ export function EnterpriseCustomers(): JSX.Element {
target="_blank"
className="flex items-center justify-center border-x border-b border-slate-200/20 p-12 transition hover:bg-slate-100/20 hover:text-slate-950 dark:border-slate-800/20 dark:hover:border-slate-600/20 dark:hover:bg-slate-600/10 dark:hover:text-white"
>
<AddidasIcon aria-hidden="true" className="h-14 w-14" />
<AdidasIcon aria-hidden="true" className="h-14 w-14" />
</a>
<a
href="https://www.intel.com"

View File

@ -1,5 +1,4 @@
import { SectionHeading } from '@nx/nx-dev/ui-common/src/lib/section-tags';
import { ButtonLink } from '@nx/nx-dev/ui-common';
import { ButtonLink, SectionHeading } from '@nx/nx-dev/ui-common';
export function Hero(): JSX.Element {
return (
@ -19,8 +18,8 @@ export function Hero(): JSX.Element {
<div className="mt-16 flex items-center justify-center gap-x-6">
<ButtonLink
href="/contact"
variant="primary"
size="large"
variant="contrast"
size="default"
title="Join us"
>
Reach out
@ -29,7 +28,7 @@ export function Hero(): JSX.Element {
<a
title="Live demo"
href="https://staging.nx.app/orgs/62d013d4d26f260059f7765e/workspaces/62d013ea0852fe0a2df74438/overview"
className="group text-sm font-semibold leading-6 text-slate-950 dark:text-white"
className="group font-semibold leading-6 text-slate-950 dark:text-white"
>
Live demo{' '}
<span

View File

@ -1,28 +1,28 @@
import { SectionHeading } from '@nx/nx-dev/ui-common/src/lib/section-tags';
import { SectionHeading } from '@nx/nx-dev/ui-common';
import {
TanstackIcon,
LernaIcon,
AwsAmplifyIcon,
CypressIcon,
ElectronIcon,
EpicWebIcon,
GhostIcon,
LernaIcon,
MicrosoftIcon,
MuiIcon,
RedwoodJsIcon,
StorybookIcon,
RxJSIcon,
SentryIcon,
MuiIcon,
AwsAmplifyIcon,
ShopifyIcon,
GhostIcon,
TypescriptEslintIcon,
CypressIcon,
MicrosoftIcon,
ElectronIcon,
StorybookIcon,
StrapiIcon,
} from '@nx/nx-dev/ui-common';
TanstackIcon,
TypescriptEslintIcon,
} from '@nx/nx-dev/ui-icons';
export function OssProjects(): JSX.Element {
return (
<section>
<div className="mx-auto max-w-7xl text-center">
<SectionHeading as="h2" variant="subtitle">
<SectionHeading as="h2" variant="subtitle" id="popular-oss">
Popular OSS projects using Nx
</SectionHeading>
@ -74,7 +74,6 @@ export function OssProjects(): JSX.Element {
target="_blank"
className="flex items-center justify-center border-b border-slate-200/20 p-12 transition hover:bg-slate-100/25 hover:text-slate-950 dark:border-slate-800/20 dark:hover:border-slate-600/20 dark:hover:bg-slate-600/10 dark:hover:text-white"
>
{' '}
<RxJSIcon aria-hidden="true" className="h-12 w-12" />
</a>
<a
@ -110,7 +109,6 @@ export function OssProjects(): JSX.Element {
>
<ShopifyIcon aria-hidden="true" className="h-12 w-12" />
</a>
<a
href="https://github.com/electron/forge"
rel="noreferrer"

View File

@ -13,7 +13,7 @@ import {
ShopifyIcon,
StorybookIcon,
VmwareIcon,
} from '@nx/nx-dev/ui-common';
} from '@nx/nx-dev/ui-icons';
export function MetricsAndCustomers(): JSX.Element {
const downloadElement: Variants = {

View File

@ -1,9 +1,6 @@
import { BoltIcon, UserGroupIcon } from '@heroicons/react/24/outline';
import {
NxAgentsIcon,
NxReplayIcon,
SectionHeading,
} from '@nx/nx-dev/ui-common';
import { BoltIcon } from '@heroicons/react/24/outline';
import { SectionHeading } from '@nx/nx-dev/ui-common';
import { NxAgentsIcon, NxReplayIcon } from '@nx/nx-dev/ui-icons';
const features = [
{

View File

@ -14,7 +14,7 @@ import {
ShopifyIcon,
StorybookIcon,
VmwareIcon,
} from '@nx/nx-dev/ui-common';
} from '@nx/nx-dev/ui-icons';
import { motion } from 'framer-motion';
export function TrustedBy(): JSX.Element {

View File

@ -28,18 +28,25 @@ function resolveLanguage(lang: string) {
function CodeWrapper(options: {
fileName: string;
command: string;
title: string;
path: string;
language: string;
children: string; // intentionally typed as such
}): ({ children }: { children: ReactNode }) => JSX.Element {
return ({ children }: { children: ReactNode }) =>
options.language === 'shell' ? (
<TerminalOutput command={options.children} path="" content={null} />
<TerminalOutput
command={options.children}
path=""
title={options.title}
content={null}
/>
) : options.command ? (
<TerminalOutput
content={children}
command={options.command}
path={options.path}
title={options.title}
/>
) : (
<CodeOutput content={children} fileName={options.fileName} />
@ -75,6 +82,7 @@ function processHighlightLines(highlightLines: any): number[] {
export interface FenceProps {
children: string;
command: string;
title: string;
path: string;
fileName: string;
highlightLines: number[];
@ -89,6 +97,7 @@ export interface FenceProps {
export function Fence({
children,
command,
title,
path,
fileName,
lineGroups,
@ -206,6 +215,7 @@ export function Fence({
PreTag={CodeWrapper({
fileName,
command,
title,
path,
language,
children,

View File

@ -4,17 +4,19 @@ import { TerminalShellWrapper } from './terminal-shell';
export function TerminalOutput({
content,
command,
title,
path,
actionElement,
}: {
content: ReactNode;
command: string;
title?: string;
path: string;
actionElement?: ReactNode;
}): JSX.Element {
const commandLines = command.split('\n').filter(Boolean);
return (
<TerminalShellWrapper>
<TerminalShellWrapper title={title}>
<div className="overflow-x-auto p-4 pt-2">
<div className="items-left relative flex flex-col">
{commandLines.map((line, index) => {

View File

@ -1,8 +1,10 @@
import { JSX, ReactNode } from 'react';
export function TerminalShellWrapper({
title,
children,
}: {
title?: string;
children: ReactNode;
}): JSX.Element {
return (
@ -13,7 +15,7 @@ export function TerminalShellWrapper({
<span className="h-2 w-2 rounded-full bg-yellow-400 dark:bg-yellow-600" />
<span className="h-2 w-2 rounded-full bg-green-400 dark:bg-green-600" />
</div>
<span className="h-5"></span>
<span className="h-5">{title}</span>
</div>
{children}
</div>

View File

@ -1,13 +1,7 @@
export * from './lib/extensible-and-integrated';
export * from './lib/getting-started';
export * from './lib/ci-for-monorepos';
export * from './lib/hero';
export * from './lib/improve-worst-ci-case';
export * from './lib/logo-cloud';
export * from './lib/migrate';
export * from './lib/migrations-and-code-generation';
export * from './lib/monorepo-styles';
export * from './lib/newsletter';
export * from './lib/nx-statistics';
export * from './lib/nx-with-ci';
export * from './lib/testimonials';
export * from './lib/why-is-nx-fast';
export * from './lib/smarter-tools-for-monorepos';
export * from './lib/statistics';
export * from './lib/team-and-community';
export * from './lib/trusted-by';
export * from './lib/work-better-achieve-more-ship-quicker';

View File

@ -0,0 +1,464 @@
import { Dialog, Transition } from '@headlessui/react';
import { PlayIcon } from '@heroicons/react/24/outline';
import { cx } from '@nx/nx-dev/ui-primitives';
import { motion } from 'framer-motion';
import Image from 'next/image';
import Link from 'next/link';
import { ComponentProps, Fragment, ReactNode, useState } from 'react';
import {
ButtonLink,
SectionHeading,
Strong,
TextLink,
} from '@nx/nx-dev/ui-common';
import { AnimateValue, Marquee } from '@nx/nx-dev/ui-animations';
import {
AzureDevOpsIcon,
BitbucketIcon,
GitHubIcon,
GitlabIcon,
JenkinsIcon,
TravisCiIcon,
} from '@nx/nx-dev/ui-icons';
export function CiForMonorepos(): JSX.Element {
return (
<section className="bg-slate-50 py-32 shadow-inner sm:py-40 dark:bg-slate-900">
<article className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="max-w-5xl">
<SectionHeading
as="h2"
variant="title"
id="ci-for-monorepos"
className="scroll-mt-24"
>
Finally! CI that works for monorepos.
</SectionHeading>
<SectionHeading as="p" variant="subtitle" className="mt-6">
Current CI systems are <Strong>slow</Strong>,{' '}
<Strong>hard to maintain and unreliable</Strong>. With Nx Cloud, we
introduce an{' '}
<TextLink
href="/blog/reliable-ci-a-new-execution-model-fixing-both-flakiness-and-slowness?utm_source=homepage&utm_medium=website&utm_campaign=homepage_links&utm_content=cta_ci_for_monorepos"
title="Task-based CI by Nx"
>
innovative task-based approach
</TextLink>{' '}
to making CI for monorepos not just <Strong>fast</Strong>, but also{' '}
<Strong>cost-efficient</Strong>. It plugs right into your existing
CI setup, enabling features such as{' '}
<TextLink
href="/ci/features/remote-cache?utm_source=homepage&utm_medium=website&utm_campaign=homepage_links&utm_content=cta_ci_for_monorepos"
title="Remote caching with Nx Replay"
>
remote caching
</TextLink>
,{' '}
<TextLink
href="/ci/features/distribute-task-execution?utm_source=homepage&utm_medium=website&utm_campaign=homepage_links&utm_content=cta_ci_for_monorepos"
title="Distribute task execution with Nx Agents "
>
dynamically allocating machines to distribute tasks
</TextLink>
, providing{' '}
<TextLink
href="/ci/features/split-e2e-tasks?utm_source=homepage&utm_medium=website&utm_campaign=homepage_links&utm_content=cta_ci_for_monorepos"
title="E2E test splitting with Atomizer"
>
fine-grained e2e test splitting
</TextLink>{' '}
and{' '}
<TextLink
href="/ci/features/flaky-tasks?utm_source=homepage&utm_medium=website&utm_campaign=homepage_links&utm_content=cta_ci_for_monorepos"
title="Flakiness detection with Nx"
>
automated flakiness detection
</TextLink>
. <Strong>All with a single line of code!</Strong>
</SectionHeading>
</div>
<div className="mt-24 grid grid-cols-1 gap-4 lg:grid-cols-12">
<ApplicationCard />
<div className="col-span-1 grid grid-cols-2 gap-4 lg:col-span-8 lg:grid-cols-2">
<ProjectsCreatedEveryMonth />
<HalveYouBill />
<IntegratesToYouCurrentCiProvider />
</div>
</div>
</article>
</section>
);
}
export const Card = ({
className,
children,
}: {
className?: string;
children?: ReactNode;
}) => {
return (
<div
className={cx(
'relative h-full w-full overflow-hidden rounded-2xl border border-slate-100 bg-white p-6 dark:border-slate-800/60 dark:bg-slate-950',
className
)}
>
{children}
</div>
);
};
export const PulseLine = () => {
return (
<span className="absolute left-0 top-1/2 h-48 w-[1px] -translate-y-1/2 animate-pulse bg-gradient-to-b from-blue-500/0 via-blue-400 to-blue-500/0" />
);
};
export const CornerBlur = () => (
<div className="absolute bottom-0 left-0 z-0 size-72 -translate-x-1/2 translate-y-1/2 rounded-full bg-slate-50 blur-2xl dark:bg-slate-900" />
);
export const ApplicationCard = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="col-span-1 h-[600px] lg:col-span-4 lg:h-[600px]">
<Card>
<PulseLine />
<CornerBlur />
<p className="text-2xl text-slate-900 dark:text-slate-100">
Powerful and elegant UI
</p>
<p className="mt-2 text-slate-600 dark:text-slate-400">
CI application build for monorepos, so you can quickly find what
failed, debug and move on.
</p>
<div className="mt-10 flex items-center justify-center gap-x-6">
<a
href="https://staging.nx.app/orgs/62d013d4d26f260059f7765e/workspaces/62d013ea0852fe0a2df74438/overview??utm_source=homepage&utm_medium=website&utm_campaign=homepage_links&utm_content=cta_ci_for_monorepos_live_demo"
target="_blank"
rel="noopener"
title="See Nx Cloud live demo"
className="group font-semibold leading-6 text-slate-950 dark:text-white"
>
View a live demo{' '}
<span
aria-hidden="true"
className="inline-block transition group-hover:translate-x-1"
>
</span>
</a>
</div>
<picture className="absolute bottom-0 left-4 h-[345px] w-full overflow-hidden rounded-xl border border-slate-200 dark:bg-slate-800">
<Image
src="/images/home/nx-app-dashboard.avif"
alt="App screenshot: overview"
width={534}
height={370}
loading={'eager'}
priority={true}
unoptimized
className="h-full w-full object-cover object-left-top"
/>
<div className="absolute inset-0 z-10 grid h-full w-full items-center justify-center">
<PlayButton onClick={() => setIsOpen(true)} />
</div>
</picture>
</Card>
{/*MODAL*/}
<Transition appear show={isOpen} as={Fragment}>
<Dialog
as="div"
open={isOpen}
onClose={() => setIsOpen(false)}
className="relative z-10"
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black/25 backdrop-blur-sm" />
</Transition.Child>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="relative w-auto transform overflow-hidden rounded-2xl border border-slate-600 text-left align-middle shadow-xl transition-all focus:outline-none dark:border-slate-800">
<iframe
width="812"
height="468"
src="https://www.youtube.com/embed/4VI-q943J3o?si=3tR-EkCKLfLvHYzL"
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowFullScreen
className="max-w-full"
/>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
</div>
);
};
//
function PlayButton({
className,
...props
}: ComponentProps<'div'>): JSX.Element {
const parent = {
initial: {
width: 82,
transition: {
when: 'afterChildren',
},
},
hover: {
width: 296,
transition: {
duration: 0.125,
type: 'tween',
ease: 'easeOut',
},
},
};
const child = {
initial: {
opacity: 0,
x: -6,
},
hover: {
x: 0,
opacity: 1,
transition: {
duration: 0.015,
type: 'tween',
ease: 'easeOut',
},
},
};
return (
<div
className={cx(
'group relative overflow-hidden rounded-full bg-transparent p-[1px] shadow-md',
className
)}
{...props}
>
<div className="absolute inset-0">
<span className="absolute inset-[-1000%] animate-[spin_2s_linear_infinite] bg-[conic-gradient(from_90deg_at_50%_50%,#FFFFFF_0%,#3B82F6_50%,#FFFFFF_100%)] dark:bg-[conic-gradient(from_90deg_at_50%_50%,#FFFFFF_0%,#0EA5E9_50%,#FFFFFF_100%)]" />
</div>
<motion.div
initial="initial"
whileHover="hover"
variants={parent}
className="relative isolate flex h-20 w-20 cursor-pointer items-center justify-center gap-6 rounded-full border border-slate-100 bg-white/70 p-6 text-sm text-slate-950 antialiased backdrop-blur-xl"
>
<PlayIcon
aria-hidden="true"
className="absolute left-6 top-6 h-8 w-8"
/>
<motion.div variants={child} className="absolute left-20 top-4 w-48">
<p className="text-base font-medium">See how Nx Cloud works</p>
<p className="text-slate-700">In under 9 minutes</p>
</motion.div>
</motion.div>
</div>
);
}
//
export const ProjectsCreatedEveryMonth = () => {
return (
<div className="relative col-span-2 h-[360px] md:col-span-1">
<Card className="relative">
<div className="flex flex-col justify-between text-center drop-shadow">
<div>
<span className="text-9xl font-bold text-slate-950 dark:text-white">
<AnimateValue num={10} suffix="k" once />
</span>
<br />
<span className="text-4xl font-semibold text-slate-950 dark:text-white">
new projects
</span>
</div>
<span className="text-2xl font-semibold text-slate-600 dark:text-slate-400">
every month
</span>
</div>
<div className="mt-8 text-center">
<ButtonLink
href="https://cloud.nx.app?utm_source=homepage&utm_medium=website&utm_campaign=homepage_links&utm_content=cta_ci_for_monorepos_connect_now"
title="Get started"
variant="primary"
size="large"
target="_blank"
rel="nofollow"
>
Connect your Nx repository now!
</ButtonLink>
</div>
</Card>
</div>
);
};
//
//
export const HalveYouBill = () => {
return (
<div className="col-span-2 h-[415px] sm:h-[360px] md:col-span-1">
<Card>
<p className="text-2xl text-slate-900 dark:text-slate-100">
Halve your CI bill
</p>
<p className="mt-2 text-slate-600 dark:text-slate-400">
Nx Cloud doesn't only makes your runs{' '}
<span className="font-semibold text-slate-800 dark:text-slate-200">
30% to 70% faster
</span>
, but also significantly cheaper.
</p>
<div className="mt-6">
<div className="flex items-center">
<div className="w-28 shrink-0 border-r-2 border-slate-200 py-3 pr-2 text-right text-slate-700 transition duration-200 dark:border-slate-800 dark:text-slate-300">
CI
</div>
<div className="flex-grow py-1.5 font-semibold">
<div className="w-full flex-grow items-center justify-end rounded-r-lg border border-l-0 border-slate-200 bg-slate-100 px-4 py-2 text-right text-slate-900 transition duration-200 dark:border-slate-800 dark:bg-slate-700 dark:text-white">
<span className="drop-shadow-sm">$6k</span>
</div>
</div>
</div>
<div className="flex items-center">
<div className="w-28 shrink-0 border-r-2 border-slate-200 py-3 pr-2 text-right font-medium text-slate-700 transition duration-200 dark:border-slate-800 dark:text-slate-300">
CI + Nx Cloud
</div>
<div className="flex-grow py-1.5 font-semibold">
<div className="w-1/2 rounded-r-lg border border-l-0 border-slate-200 bg-gradient-to-r from-emerald-500 to-green-500 px-4 py-2 text-right text-white transition duration-200 dark:border-slate-800">
<span className="drop-shadow-sm">$3.2k</span>
</div>
</div>
</div>
</div>
<p className="z-10 mt-6 text-xs text-slate-400 transition duration-200 dark:text-slate-600">
<span className="underline">Cost per month for CI compute.</span> Data
collected based on a typical month of CI runs measured on the Nx OSS
monorepo.
</p>
</Card>
</div>
);
};
//
//
export const IntegratesToYouCurrentCiProvider = () => {
return (
<div className="col-span-2 h-fit sm:h-[225px]">
<Card>
<div className="relative z-20">
<p className="text-2xl text-slate-900 dark:text-slate-100">
Works with your current CI
</p>
<p className="mt-2 max-w-md text-slate-600 dark:text-slate-400">
Use your current CI provider, export your compute and slash your CI
bill by using Nx engines to save time, better performance and proper
developer experience.
</p>
<div className="mt-4 flex items-center">
<Link
href="/ci/intro/connect-to-cloud?utm_source=homepage&utm_medium=website&utm_campaign=homepage_links&utm_content=cta_ci_for_monorepos"
title="Add Nx Cloud to your CI workflow"
prefetch={false}
className="group font-semibold leading-6 text-slate-950 dark:text-white"
>
Enable speed with a single line{' '}
<span
aria-hidden="true"
className="inline-block transition group-hover:translate-x-1"
>
</span>
</Link>
</div>
</div>
<div className="hidden sm:block">
<CiProviderVerticalMarquees />
</div>
</Card>
</div>
);
};
export function CiProviderVerticalMarquees() {
const ICON_DATA = [
{
Icon: GitHubIcon,
},
{
Icon: JenkinsIcon,
},
{
Icon: BitbucketIcon,
},
{
Icon: AzureDevOpsIcon,
},
{
Icon: TravisCiIcon,
},
{
Icon: GitlabIcon,
},
];
const ICON_DATA_REVERSED = ICON_DATA.reverse();
return (
<div className="bg-background absolute inset-y-0 right-0 flex h-full w-40 flex-col items-center justify-center gap-4 overflow-hidden">
<div className="flex flex-row gap-6 [perspective:300px]">
<Marquee
className="h-96 justify-center overflow-hidden [--duration:60s] [--gap:1rem]"
vertical
>
{ICON_DATA.map((data, idx) => (
<data.Icon
key={'ci-provider-icon-1-' + idx}
aria-hidden="true"
className="mx-auto size-8"
/>
))}
</Marquee>
<Marquee
className="hidden h-96 justify-center overflow-hidden [--duration:60s] [--gap:1rem] md:flex"
vertical
reverse
>
{ICON_DATA_REVERSED.map((data, idx) => (
<data.Icon
key={'ci-provider-icon-2-' + idx}
aria-hidden="true"
className="mx-auto size-8"
/>
))}
</Marquee>
</div>
</div>
);
}

View File

@ -1,114 +0,0 @@
import { Tab } from '@headlessui/react';
import { Button, SectionHeading } from '@nx/nx-dev/ui-common';
import Link from 'next/link';
import { Fragment } from 'react';
import { tabs } from './extensible-and-integrated/tabs';
export function ExtensibleAndIntegrated(): JSX.Element {
return (
<article
id="extensible-and-integrated"
className="overflow-hidden bg-slate-50 pt-28 dark:bg-slate-800/40"
>
<div className="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8 lg:py-16">
<header className="max-w-2xl">
<SectionHeading
as="h1"
variant="title"
id="extensible-and-integrated"
>
Integrated developer experience
</SectionHeading>
<SectionHeading
as="p"
variant="display"
id="nx-is-fast"
className="mt-4"
>
Everything is just a click away
</SectionHeading>
</header>
<div className="mt-8 flex flex-col gap-16 font-normal md:flex-row">
<p className="max-w-xl text-lg text-slate-700 dark:text-slate-400">
No need to browse the docs to find the right commands to run.{' '}
<span className="font-medium">Stay in the flow!</span> Augment your
editor with Nx Console, a dedicated extension available for{' '}
<Link
href="/getting-started/editor-setup"
title="Install VSCode's native extension for Nx"
className="font-medium text-blue-500 dark:text-sky-500"
prefetch={false}
>
VSCode
</Link>{' '}
,{' '}
<Link
href="/getting-started/editor-setup"
className="font-medium text-blue-500 dark:text-sky-500"
title="Install JetBrains' native plugin for Nx"
prefetch={false}
>
JetBrains
</Link>{' '}
and{' '}
<Link
href="/getting-started/editor-setup#neovim"
className="font-medium text-blue-500 dark:text-sky-500"
prefetch={false}
>
Neovim
</Link>
. Generating a new library, running e2e tests, building your app -
everything just a click away.
</p>
<p className="max-w-xl text-lg text-slate-700 dark:text-slate-400">
Debug and understand your workspace with the built-in{' '}
<code>nx graph</code> capabilities! Also,{' '}
<span className="font-medium">
give yourself a treat by enabling the Nx Cloud GitHub integration
</span>
. Most CI interfaces are a struggle to work with and they are not
made for monorepos. The{' '}
<Link
href="https://nx.app/?utm_source=nx.dev"
title="Nx Cloud: Distributed Task execution & Caching"
className="font-medium text-blue-500 dark:text-sky-500"
prefetch={false}
target="_blank"
rel="noreferrer"
>
Nx Cloud
</Link>{' '}
integration takes care of that, presenting what matters most in an
awesome visual way.
</p>
</div>
</div>
<div className="relative mx-auto max-w-7xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pb-4 lg:pt-6">
<Tab.Group>
<Tab.List>
<div className="flex justify-between space-x-4 md:justify-start">
{tabs.map((tab) => (
<Tab as={Fragment} key={'tab-' + tab.title}>
{({ selected }) => (
<Button
variant={selected ? 'primary' : 'secondary'}
size="small"
>
{tab.title}
</Button>
)}
</Tab>
))}
</div>
</Tab.List>
<Tab.Panels>
{tabs.map((tab) => (
<Tab.Panel key={'panel-' + tab.title}>{tab.panel}</Tab.Panel>
))}
</Tab.Panels>
</Tab.Group>
</div>
</article>
);
}

View File

@ -1,172 +0,0 @@
import { BuildingStorefrontIcon } from '@heroicons/react/24/solid';
import { motion } from 'framer-motion';
import Image from 'next/image';
import { transition, variants } from './motion.helpers';
export function GitHubIntegrationTab(): JSX.Element {
return (
<motion.div
initial="hidden"
variants={variants}
animate="visible"
transition={transition}
exit="hidden"
className="wrapper my-8 grid h-full gap-12 md:grid-cols-2 lg:grid-cols-3"
>
<div className="relative flex flex-col space-y-12 md:space-y-0">
<div
className="coding z-10 rounded-lg border border-slate-200 bg-slate-50 p-4 font-mono
text-xs leading-normal text-slate-800 subpixel-antialiased shadow-lg dark:border-slate-700 dark:bg-slate-800 dark:text-slate-200"
>
<div className="flex items-center">
<p>
<span className="text-base text-purple-600 dark:text-fuchsia-500">
</span>{' '}
<span className="mx-1 text-green-600 dark:text-green-400">
~/workspace
</span>{' '}
<span>$</span>
</p>
<p className="typing mt-0.5 flex-1 pl-2">nx connect-to-nx-cloud</p>
</div>
<div className="mt-2 flex">
<p className="typing flex-1 animate-pulse items-center space-x-0.5">
<span className="inline-flex h-5 w-2 bg-slate-300 dark:bg-slate-700" />
<span className="inline-flex h-5 w-2 bg-slate-300 dark:bg-slate-700" />
<span className="inline-flex h-5 w-2 bg-slate-300 dark:bg-slate-700" />
<span className="inline-flex h-5 w-2 bg-slate-300 dark:bg-slate-700" />
<span className="inline-flex h-5 w-2 bg-slate-200 dark:bg-slate-700" />
<span className="inline-flex h-5 w-2 bg-slate-200 dark:bg-slate-700" />
<span className="inline-flex h-5 w-2 bg-slate-200 dark:bg-slate-700" />
<span className="inline-flex h-5 w-2 bg-slate-200 dark:bg-slate-700" />
</p>
</div>
</div>
{/*HORIZONTAL LINK*/}
<div className="absolute right-0 hidden w-48 translate-x-full translate-y-12 items-center md:flex">
<span className="absolute left-0 top-0 -ml-1 -mt-1 flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-500 opacity-75 dark:bg-sky-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-slate-200 dark:bg-slate-700" />
</span>
<span className="absolute right-0 top-0 -mr-1 -mt-1 flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-500 opacity-75 dark:bg-sky-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-slate-200 dark:bg-slate-700" />
</span>
<div className="-m-0.5 h-0.5 w-full bg-slate-200 dark:bg-slate-700" />
</div>
{/*VERTICAL LINK*/}
<div className="relative hidden grow flex-col justify-center md:flex">
<span className="relative m-auto flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-500 opacity-75 dark:bg-sky-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-slate-200 dark:bg-slate-700" />
</span>
<div className="m-auto h-32 w-0.5 bg-slate-200 dark:bg-slate-700" />
<span className="relative m-auto flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-500 opacity-75 dark:bg-sky-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-slate-200 dark:bg-slate-700" />
</span>
<div className="absolute inset-x-0 bottom-0 flex items-center justify-between px-2 text-slate-500 opacity-80">
<div className="flex">
<BuildingStorefrontIcon className="h-4 w-4" />
<span className="ml-2 text-xs font-medium">
GitHub Marketplace
</span>
</div>
<svg
className="h-10 w-10 translate-x-6 translate-y-2 rotate-12 text-slate-400"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
>
<title>GitHub</title>
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
</svg>
</div>
</div>
<div className="relative z-10 flex space-x-4 overflow-hidden rounded-lg rounded-t-none border border-slate-200 bg-white py-5 shadow-sm focus-within:ring-2 focus-within:ring-indigo-500 focus-within:ring-offset-2 hover:shadow-md dark:border-slate-700 dark:bg-slate-800">
<div className="absolute inset-x-0 top-0 h-1 w-full bg-blue-500 dark:bg-sky-500"></div>
<div className="flex-shrink-0">
<svg
id="nx-cloud-header-logo"
role="img"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
fill="transparent"
viewBox="0 0 24 24"
className="h-10 w-10"
>
<path
strokeWidth="2"
d="M23 3.75V6.5c-3.036 0-5.5 2.464-5.5 5.5s-2.464 5.5-5.5 5.5-5.5 2.464-5.5 5.5H3.75C2.232 23 1 21.768 1 20.25V3.75C1 2.232 2.232 1 3.75 1h16.5C21.768 1 23 2.232 23 3.75Z"
id="nx-cloud-header-logo-stroke-1"
/>
<path
strokeWidth="2"
d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z"
id="nx-cloud-header-logo-stroke-2"
/>
</svg>
</div>
<div className="min-w-0 flex-1">
<a
href="https://github.com/marketplace/official-nx-cloud-app"
target="_blank"
rel="noreferrer"
className="focus:outline-none"
>
<span className="absolute inset-0" aria-hidden="true"></span>
<p className="text-sm font-medium text-slate-900 dark:text-slate-300">
Official Nx Cloud App
</p>
<p className="text-sm text-slate-700 dark:text-slate-400">
By nrwl
</p>
<p className="mt-2 text-sm text-slate-700 dark:text-slate-400">
The Nx Cloud GitHub App lets you access the result of every run
with all its logs and build insights straight from your PR.
</p>
</a>
</div>
</div>
{/*HORIZONTAL LINK*/}
<div className="absolute bottom-80 right-0 hidden w-24 translate-x-full translate-y-12 items-center md:flex">
<span className="absolute left-0 top-0 -ml-1 -mt-1 flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-500 opacity-75 dark:bg-sky-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-slate-200 dark:bg-slate-700" />
</span>
<span className="absolute right-0 top-0 -mr-1 -mt-1 flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-500 opacity-75 dark:bg-sky-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-slate-200 dark:bg-slate-700" />
</span>
<div className="-m-0.5 h-0.5 w-full bg-slate-200 dark:bg-slate-700" />
</div>
<div className="spacer h-56" />
</div>
<div
aria-hidden="true"
className="relative hidden px-4 pr-6 md:flex lg:col-span-2 lg:h-full lg:px-0"
>
<div className="absolute -top-28 left-36 mx-auto h-[510px] w-auto w-full max-w-none overflow-hidden rounded-xl border border-slate-200 shadow-xl dark:border-slate-700">
<Image
src="/images/nx-cloud.webp"
alt="Nx Cloud app"
loading="lazy"
width={715}
height={510}
/>
</div>
<div className="absolute -bottom-2 left-12 mx-auto flex w-auto w-full max-w-none overflow-hidden rounded-xl border border-slate-200 shadow-xl">
<Image
src="/images/github-nxcloud.webp"
alt="Nx Cloud GitHub app"
loading="lazy"
width={715}
height={510}
/>
</div>
</div>
</motion.div>
);
}

View File

@ -1,73 +0,0 @@
import { motion } from 'framer-motion';
import { transition, variants } from './motion.helpers';
export function GraphTab(): JSX.Element {
return (
<motion.div
initial="hidden"
variants={variants}
animate="visible"
transition={transition}
exit="hidden"
className="wrapper relative my-8 flex h-full flex-col items-center space-y-12 overflow-hidden lg:flex-row"
>
<div
className="coding z-10 w-96 shrink-0 grow-0 overflow-hidden rounded-lg border border-slate-200 bg-slate-50 p-4 font-mono
text-xs leading-normal text-slate-800 subpixel-antialiased shadow-lg dark:border-slate-700 dark:bg-slate-800 dark:text-slate-200"
>
<div className="flex items-center">
<p>
<span className="text-base text-purple-600 dark:text-fuchsia-500">
</span>{' '}
<span className="mx-1 text-green-600 dark:text-green-400">
~/workspace
</span>{' '}
<span>$</span>
</p>
<p className="typing mt-0.5 flex-1 pl-2">nx graph</p>
</div>
<div className="mt-2 flex">
<p className="typing flex-1 items-center">
<span className="bg-yellow-300 px-1 py-0.5 dark:bg-yellow-600">
Nx
</span>{' '}
Project graph started at{' '}
<span className="underline">http://127.0.0.1:4211</span>
<br />
</p>
</div>
</div>
<div className="relative -top-5 mr-0.5 hidden grow items-center lg:flex">
<span className="absolute left-0 top-0 -ml-1 -mt-1 flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-500 opacity-75 dark:bg-sky-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-slate-200 dark:bg-slate-700" />
</span>
<span className="absolute right-0 top-0 -mr-1 -mt-1 flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-500 opacity-75 dark:bg-sky-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-slate-200 dark:bg-slate-700" />
</span>
<div className="-m-0.5 h-0.5 w-full bg-slate-200 dark:bg-slate-700" />
</div>
<div className="z-10 h-auto overflow-hidden rounded-lg border border-slate-200 shadow lg:min-h-[485px] lg:w-[690px] dark:border-slate-700">
<div className="flex h-7 w-full items-center justify-start space-x-1.5 bg-slate-200 px-3 dark:bg-slate-700">
<span className="h-2 w-2 rounded-full bg-red-400"></span>
<span className="h-2 w-2 rounded-full bg-yellow-400"></span>
<span className="h-2 w-2 rounded-full bg-green-400"></span>
</div>
<div className="w-full bg-transparent dark:hidden">
<video preload="true" autoPlay={true} loop muted playsInline={true}>
<source src="/videos/light.webm" type="video/webm" />
<source src="/videos/light.mp4" type="video/mp4" />
</video>
</div>
<div className="hidden w-full bg-slate-700 dark:flex">
<video preload="true" autoPlay={true} loop muted playsInline={true}>
<source src="/videos/dark.webm" type="video/webm" />
<source src="/videos/dark.mp4" type="video/mp4" />
</video>
</div>
</div>
</motion.div>
);
}

View File

@ -1,107 +0,0 @@
import {
CogIcon,
CommandLineIcon,
SparklesIcon,
} from '@heroicons/react/24/outline';
import cx from 'classnames';
import { motion } from 'framer-motion';
import Image from 'next/image';
import Link from 'next/link';
import { transition, variants } from './motion.helpers';
export function IdeIntegrationTab(): JSX.Element {
const features = [
{
connectionWidth: 'w-96',
name: 'Generate anything',
icon: <CogIcon className="h-5 w-5" />,
description:
'No need to remember the commands and options available. See everything at a glance. Great for exploring.',
link: '/recipes/nx-console/console-generate-command',
},
{
connectionWidth: 'w-[668px]',
name: 'Run anything',
icon: <CommandLineIcon className="h-5 w-5" />,
description:
'Easy access to your projects and scripts from the context menu, command palette and augmented config files. Perfectly integrated into your flow.',
link: '/recipes/nx-console/console-run-command',
},
{
connectionWidth: 'w-48',
name: 'The best companion for Nx',
icon: <SparklesIcon className="h-5 w-5" />,
description:
'The Nx team is obsessed with providing the best possible DX. Nx Console is the culmination of that. Carefully crafted, in constant evolution, always in search of making the life of developers easier.',
link: '/getting-started/editor-setup',
},
];
return (
<motion.div
initial="hidden"
variants={variants}
animate="visible"
transition={transition}
exit="hidden"
className="wrapper my-8 grid h-full items-center gap-16 md:grid-cols-2 lg:grid-cols-3"
>
<div className="lg:col-span-2">
<div className="w-full overflow-hidden overflow-hidden rounded-lg rounded-lg border border-slate-200 shadow shadow-lg dark:hidden dark:border-slate-700">
<Image
src="/images/nx-console/vscode-light.webp"
alt="Nx Console app screenshot"
loading="lazy"
width={800}
height={800}
/>
</div>
<div className="hidden w-full overflow-hidden overflow-hidden rounded-lg rounded-lg border border-slate-200 shadow shadow-lg dark:block dark:border-slate-700">
<Image
src="/images/nx-console/vscode-dark.webp"
alt="Nx Console app screenshot"
loading="lazy"
width={800}
height={800}
/>
</div>
</div>
<div className="relative flex flex-col gap-8">
{features.map((feature) => (
<div
key={feature.name}
className="group relative rounded-lg px-4 py-2 transition hover:bg-slate-100 sm:flex dark:hover:bg-slate-800/40"
>
<div
className={cx(
'absolute -left-4 hidden -translate-x-full translate-y-12 items-center xl:flex',
feature.connectionWidth
)}
>
<span className="absolute left-0 top-0 -ml-1 -mt-1 flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-500 opacity-75 transition dark:bg-sky-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-slate-200 transition group-hover:bg-blue-600 group-hover:bg-sky-600 dark:bg-slate-700" />
</span>
<span className="absolute right-0 top-0 -mr-1 -mt-1 flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-500 opacity-75 transition dark:bg-sky-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-slate-200 transition group-hover:bg-blue-600 group-hover:bg-sky-600 dark:bg-slate-700" />
</span>
<div className="-m-0.5 h-0.5 w-full bg-slate-200 transition group-hover:bg-blue-500 dark:bg-slate-700 dark:group-hover:bg-sky-500" />
</div>
<div className="sm:flex-shrink-0">
<div className="flow-root">{feature.icon}</div>
</div>
<div className="mt-3 sm:ml-3 sm:mt-0">
<h3 className="text-sm font-medium">{feature.name}</h3>
<Link href={feature.link} prefetch={false}>
<span className="absolute inset-0" aria-hidden="true" />
<p className="mt-2 text-sm text-slate-500">
{feature.description}
</p>
</Link>
</div>
</div>
))}
</div>
</motion.div>
);
}

View File

@ -1,20 +0,0 @@
export const variants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
when: 'beforeChildren',
staggerChildren: 0.12,
ease: 'linear',
duration: 0.24,
type: 'tween',
},
},
};
export const transition = {
when: 'beforeChildren',
staggerChildren: 0.12,
ease: 'linear',
duration: 0.24,
type: 'tween',
};

View File

@ -1,364 +0,0 @@
import { motion } from 'framer-motion';
const pluginList = [
{
logo: (
<svg
className="mr-3 h-8 w-8 text-[#17202C] dark:text-slate-200"
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Cypress</title>
<path d="M11.998 0C5.366 0 0 5.367 0 12a11.992 11.992 0 0 0 12 12c6.633 0 12-5.367 12-12-.001-6.633-5.412-12-12.002-12zM6.37 14.575c.392.523.916.742 1.657.742.35 0 .699-.044 1.004-.175.306-.13.655-.306 1.09-.567l1.223 1.745c-1.003.83-2.138 1.222-3.447 1.222-1.048 0-1.92-.218-2.705-.654a4.393 4.393 0 0 1-1.746-1.92c-.392-.83-.611-1.79-.611-2.925 0-1.09.219-2.094.61-2.923a4.623 4.623 0 0 1 1.748-2.007c.741-.48 1.657-.698 2.661-.698.699 0 1.353.087 1.877.305a5.64 5.64 0 0 1 1.614.96l-1.222 1.658A4.786 4.786 0 0 0 9.12 8.77c-.305-.13-.698-.174-1.048-.174-1.483 0-2.225 1.134-2.225 3.446-.043 1.18.175 2.008.524 2.532H6.37zm12 2.705c-.436 1.353-1.091 2.357-2.008 3.098-.916.743-2.138 1.135-3.665 1.266l-.305-2.05c1.003-.132 1.745-.35 2.225-.7.174-.13.524-.523.524-.523L11.519 6.764h3.01l2.095 8.683 2.226-8.683h2.923L18.37 17.28z" />
</svg>
),
name: '@nx/cypress',
url: '/nx-api/cypress',
description: 'Cypress is an e2e test runner built for modern web.',
isOfficial: true,
},
{
logo: (
<svg
className="mr-3 h-8 w-8 text-[#646CFF]"
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Vite</title>
<path d="m8.286 10.578.512-8.657a.306.306 0 0 1 .247-.282L17.377.006a.306.306 0 0 1 .353.385l-1.558 5.403a.306.306 0 0 0 .352.385l2.388-.46a.306.306 0 0 1 .332.438l-6.79 13.55-.123.19a.294.294 0 0 1-.252.14c-.177 0-.35-.152-.305-.369l1.095-5.301a.306.306 0 0 0-.388-.355l-1.433.435a.306.306 0 0 1-.389-.354l.69-3.375a.306.306 0 0 0-.37-.36l-2.32.536a.306.306 0 0 1-.374-.316zm14.976-7.926L17.284 3.74l-.544 1.887 2.077-.4a.8.8 0 0 1 .84.369.8.8 0 0 1 .034.783L12.9 19.93l-.013.025-.015.023-.122.19a.801.801 0 0 1-.672.37.826.826 0 0 1-.634-.302.8.8 0 0 1-.16-.67l1.029-4.981-1.12.34a.81.81 0 0 1-.86-.262.802.802 0 0 1-.165-.67l.63-3.08-2.027.468a.808.808 0 0 1-.768-.233.81.81 0 0 1-.217-.6l.389-6.57-7.44-1.33a.612.612 0 0 0-.64.906L11.58 23.691a.612.612 0 0 0 1.066-.004l11.26-20.135a.612.612 0 0 0-.644-.9z" />
</svg>
),
name: '@nx/vite',
url: '/nx-api/vite',
description:
'The Nx Plugin for building and testing applications using Vite.',
isOfficial: true,
},
{
logo: (
<svg
className="mr-3 h-8 w-8 text-[#61DAFB]"
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>React</title>
<path d="M14.23 12.004a2.236 2.236 0 0 1-2.235 2.236 2.236 2.236 0 0 1-2.236-2.236 2.236 2.236 0 0 1 2.235-2.236 2.236 2.236 0 0 1 2.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38-.318-.184-.688-.277-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44-.96-.236-2.006-.417-3.107-.534-.66-.905-1.345-1.727-2.035-2.447 1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442-1.107.117-2.154.298-3.113.538-.112-.49-.195-.964-.254-1.42-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87-.728.063-1.466.098-2.21.098-.74 0-1.477-.035-2.202-.093-.406-.582-.802-1.204-1.183-1.86-.372-.64-.71-1.29-1.018-1.946.303-.657.646-1.313 1.013-1.954.38-.66.773-1.286 1.18-1.868.728-.064 1.466-.098 2.21-.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933-.2-.39-.41-.783-.64-1.174-.225-.392-.465-.774-.705-1.146zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493-.28-.958-.646-1.956-1.1-2.98.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98-.45 1.017-.812 2.01-1.086 2.964-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39.24-.375.48-.762.705-1.158.225-.39.435-.788.636-1.18zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143-.695-.102-1.365-.23-2.006-.386.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295-.22-.005-.406-.05-.553-.132-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z" />
</svg>
),
name: '@nx/react',
url: '/nx-api/react',
description:
'Contains executors and generators for managing React applications and libraries within an Nx workspace.',
isOfficial: true,
},
{
logo: (
<svg
className="mr-3 h-8 w-8 text-[#00ADD8]"
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Go</title>
<path d="M1.811 10.231c-.047 0-.058-.023-.035-.059l.246-.315c.023-.035.081-.058.128-.058h4.172c.046 0 .058.035.035.07l-.199.303c-.023.036-.082.07-.117.07zM.047 11.306c-.047 0-.059-.023-.035-.058l.245-.316c.023-.035.082-.058.129-.058h5.328c.047 0 .07.035.058.07l-.093.28c-.012.047-.058.07-.105.07zm2.828 1.075c-.047 0-.059-.035-.035-.07l.163-.292c.023-.035.07-.07.117-.07h2.337c.047 0 .07.035.07.082l-.023.28c0 .047-.047.082-.082.082zm12.129-2.36c-.736.187-1.239.327-1.963.514-.176.046-.187.058-.34-.117-.174-.199-.303-.327-.548-.444-.737-.362-1.45-.257-2.115.175-.795.514-1.204 1.274-1.192 2.22.011.935.654 1.706 1.577 1.835.795.105 1.46-.175 1.987-.77.105-.13.198-.27.315-.434H10.47c-.245 0-.304-.152-.222-.35.152-.362.432-.97.596-1.274a.315.315 0 01.292-.187h4.253c-.023.316-.023.631-.07.947a4.983 4.983 0 01-.958 2.29c-.841 1.11-1.94 1.8-3.33 1.986-1.145.152-2.209-.07-3.143-.77-.865-.655-1.356-1.52-1.484-2.595-.152-1.274.222-2.419.993-3.424.83-1.086 1.928-1.776 3.272-2.02 1.098-.2 2.15-.07 3.096.571.62.41 1.063.97 1.356 1.648.07.105.023.164-.117.2m3.868 6.461c-1.064-.024-2.034-.328-2.852-1.029a3.665 3.665 0 01-1.262-2.255c-.21-1.32.152-2.489.947-3.529.853-1.122 1.881-1.706 3.272-1.95 1.192-.21 2.314-.095 3.33.595.923.63 1.496 1.484 1.648 2.605.198 1.578-.257 2.863-1.344 3.962-.771.783-1.718 1.273-2.805 1.495-.315.06-.63.07-.934.106zm2.78-4.72c-.011-.153-.011-.27-.034-.387-.21-1.157-1.274-1.81-2.384-1.554-1.087.245-1.788.935-2.045 2.033-.21.912.234 1.835 1.075 2.21.643.28 1.285.244 1.905-.07.923-.48 1.425-1.228 1.484-2.233z" />
</svg>
),
name: '@nx-go/nx-go',
url: 'https://github.com/nx-go/nx-go',
description: 'Nx plugin to use Go in a Nx workspace',
isOfficial: false,
},
{
logo: (
<svg
className="mr-3 h-8 w-8 text-[#FF4785]"
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Svelte</title>
<path d="M10.354 21.125a4.44 4.44 0 0 1-4.765-1.767 4.109 4.109 0 0 1-.703-3.107 3.898 3.898 0 0 1 .134-.522l.105-.321.287.21a7.21 7.21 0 0 0 2.186 1.092l.208.063-.02.208a1.253 1.253 0 0 0 .226.83 1.337 1.337 0 0 0 1.435.533 1.231 1.231 0 0 0 .343-.15l5.59-3.562a1.164 1.164 0 0 0 .524-.778 1.242 1.242 0 0 0-.211-.937 1.338 1.338 0 0 0-1.435-.533 1.23 1.23 0 0 0-.343.15l-2.133 1.36a4.078 4.078 0 0 1-1.135.499 4.44 4.44 0 0 1-4.765-1.766 4.108 4.108 0 0 1-.702-3.108 3.855 3.855 0 0 1 1.742-2.582l5.589-3.563a4.072 4.072 0 0 1 1.135-.499 4.44 4.44 0 0 1 4.765 1.767 4.109 4.109 0 0 1 .703 3.107 3.943 3.943 0 0 1-.134.522l-.105.321-.286-.21a7.204 7.204 0 0 0-2.187-1.093l-.208-.063.02-.207a1.255 1.255 0 0 0-.226-.831 1.337 1.337 0 0 0-1.435-.532 1.231 1.231 0 0 0-.343.15L8.62 9.368a1.162 1.162 0 0 0-.524.778 1.24 1.24 0 0 0 .211.937 1.338 1.338 0 0 0 1.435.533 1.235 1.235 0 0 0 .344-.151l2.132-1.36a4.067 4.067 0 0 1 1.135-.498 4.44 4.44 0 0 1 4.765 1.766 4.108 4.108 0 0 1 .702 3.108 3.857 3.857 0 0 1-1.742 2.583l-5.589 3.562a4.072 4.072 0 0 1-1.135.499m10.358-17.95C18.484-.015 14.082-.96 10.9 1.068L5.31 4.63a6.412 6.412 0 0 0-2.896 4.295 6.753 6.753 0 0 0 .666 4.336 6.43 6.43 0 0 0-.96 2.396 6.833 6.833 0 0 0 1.168 5.167c2.229 3.19 6.63 4.135 9.812 2.108l5.59-3.562a6.41 6.41 0 0 0 2.896-4.295 6.756 6.756 0 0 0-.665-4.336 6.429 6.429 0 0 0 .958-2.396 6.831 6.831 0 0 0-1.167-5.168Z" />
</svg>
),
name: '@nxext/svelte',
url: 'https://nxext.dev/docs/svelte/overview.html',
description: 'Nx plugin to use Svelte within nx workspaces.',
isOfficial: false,
},
{
logo: (
<svg
className="mr-3 h-8 w-8 text-[#FF4785]"
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Storybook</title>
<path d="M16.71.243l-.12 2.71a.18.18 0 00.29.15l1.06-.8.9.7a.18.18 0 00.28-.14l-.1-2.76 1.33-.1a1.2 1.2 0 011.279 1.2v21.596a1.2 1.2 0 01-1.26 1.2l-16.096-.72a1.2 1.2 0 01-1.15-1.16l-.75-19.797a1.2 1.2 0 011.13-1.27L16.7.222zM13.64 9.3c0 .47 3.16.24 3.59-.08 0-3.2-1.72-4.89-4.859-4.89-3.15 0-4.899 1.72-4.899 4.29 0 4.45 5.999 4.53 5.999 6.959 0 .7-.32 1.1-1.05 1.1-.96 0-1.35-.49-1.3-2.16 0-.36-3.649-.48-3.769 0-.27 4.03 2.23 5.2 5.099 5.2 2.79 0 4.969-1.49 4.969-4.18 0-4.77-6.099-4.64-6.099-6.999 0-.97.72-1.1 1.13-1.1.45 0 1.25.07 1.19 1.87z" />
</svg>
),
name: '@nx/storybook',
url: '/nx-api/storybook',
description: 'Storybook is a development environment for UI components.',
isOfficial: true,
},
{
logo: (
<svg
className="mr-3 h-8 w-8 text-[#C21325]"
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Jest</title>
<path d="M22.251 11.82a3.117 3.117 0 0 0-2.328-3.01L22.911 0H8.104L11.1 8.838a3.116 3.116 0 0 0-2.244 2.988c0 1.043.52 1.967 1.313 2.536a8.279 8.279 0 0 1-1.084 1.244 8.14 8.14 0 0 1-2.55 1.647c-.834-.563-1.195-1.556-.869-2.446a3.11 3.11 0 0 0-.91-6.08 3.117 3.117 0 0 0-3.113 3.113c0 .848.347 1.626.903 2.182-.048.097-.097.195-.146.299-.465.959-.993 2.043-1.195 3.259-.403 2.432.257 4.384 1.849 5.489A5.093 5.093 0 0 0 5.999 24c1.827 0 3.682-.917 5.475-1.807 1.279-.632 2.599-1.292 3.898-1.612.48-.118.98-.187 1.508-.264 1.07-.153 2.175-.312 3.168-.89a4.482 4.482 0 0 0 2.182-3.091c.174-.994 0-1.994-.444-2.87.298-.48.465-1.042.465-1.647zm-1.355 0c0 .965-.785 1.75-1.75 1.75a1.753 1.753 0 0 1-1.085-3.126l.007-.007c.056-.042.118-.084.18-.125 0 0 .008 0 .008-.007.028-.014.055-.035.083-.05.007 0 .014-.006.021-.006.028-.014.063-.028.097-.042.035-.014.07-.027.098-.041.007 0 .013-.007.02-.007.028-.007.056-.021.084-.028.007 0 .02-.007.028-.007.034-.007.062-.014.097-.02h.007l.104-.022c.007 0 .02 0 .028-.007.028 0 .055-.007.083-.007h.035c.035 0 .07-.007.111-.007h.09c.028 0 .05 0 .077.007h.014c.055.007.111.014.167.028a1.766 1.766 0 0 1 1.396 1.723zM10.043 1.39h10.93l-2.509 7.4c-.104.02-.208.055-.312.09l-2.64-5.385-2.648 5.35c-.104-.034-.216-.055-.327-.076l-2.494-7.38zm4.968 9.825a3.083 3.083 0 0 0-.938-1.668l1.438-2.904 1.452 2.967c-.43.43-.743.98-.868 1.605H15.01zm-3.481-1.098c.034-.007.062-.014.097-.02h.02c.029-.008.056-.008.084-.015h.028c.028 0 .049-.007.076-.007h.271c.028 0 .049.007.07.007.014 0 .02 0 .035.007.027.007.048.007.076.014.007 0 .014 0 .028.007l.097.02h.007c.028.008.056.015.083.029.007 0 .014.007.028.007.021.007.049.014.07.027.007 0 .014.007.02.007.028.014.056.021.084.035h.007a.374.374 0 0 1 .09.049h.007c.028.014.056.034.084.048.007 0 .007.007.013.007.028.014.05.035.077.049l.007.007c.083.062.16.132.236.201l.007.007a1.747 1.747 0 0 1 .48 1.209 1.752 1.752 0 0 1-3.502 0 1.742 1.742 0 0 1 1.32-1.695zm-6.838-.049c.966 0 1.751.786 1.751 1.751s-.785 1.751-1.75 1.751-1.752-.785-1.752-1.75.786-1.752 1.751-1.752zm16.163 6.025a3.07 3.07 0 0 1-1.508 2.133c-.758.438-1.689.577-2.669.716a17.29 17.29 0 0 0-1.64.291c-1.445.355-2.834 1.05-4.182 1.717-1.724.854-3.35 1.66-4.857 1.66a3.645 3.645 0 0 1-2.154-.688c-1.529-1.056-1.453-3.036-1.272-4.12.167-1.015.632-1.966 1.077-2.877.028-.055.049-.104.077-.16.152.056.312.098.479.126-.264 1.473.486 2.994 1.946 3.745l.264.139.284-.104c1.216-.431 2.342-1.133 3.336-2.071a9.334 9.334 0 0 0 1.445-1.716c.16.027.32.034.48.034a3.117 3.117 0 0 0 3.008-2.327h1.167a3.109 3.109 0 0 0 3.01 2.327c.576 0 1.11-.16 1.57-.43.18.52.236 1.063.139 1.605z" />
</svg>
),
name: '@nx/jest',
url: '/nx-api/jest',
description: 'Jest is an open source test runner created by Facebook.',
isOfficial: true,
},
{
logo: (
<svg
className="mr-3 h-8 w-8 text-[#512BD4]"
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>.NET</title>
<path d="M24 8.77h-2.468v7.565h-1.425V8.77h-2.462V7.53H24zm-6.852 7.565h-4.821V7.53h4.63v1.24h-3.205v2.494h2.953v1.234h-2.953v2.604h3.396zm-6.708 0H8.882L4.78 9.863a2.896 2.896 0 0 1-.258-.51h-.036c.032.189.048.592.048 1.21v5.772H3.157V7.53h1.659l3.965 6.32c.167.261.275.442.323.54h.024c-.04-.233-.06-.629-.06-1.185V7.529h1.372zm-8.703-.693a.868.829 0 0 1-.869.829.868.829 0 0 1-.868-.83.868.829 0 0 1 .868-.828.868.829 0 0 1 .869.829Z" />
</svg>
),
name: 'nx-dotnet',
url: 'https://www.nx-dotnet.com/docs/core/',
description:
'Nx plugin for developing and housing .NET projects within an Nx workspace.',
isOfficial: false,
},
{
logo: (
<svg
className="mr-3 h-8 w-8"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Angular</title>
<path
fill="url(#a)"
d="m23.9 3.986-.862 12.805L14.786 0l9.115 3.986Zm-5.715 16.558-6.235 3.362-6.235-3.362 1.268-2.904h9.934l1.268 2.904ZM11.95 6.374l3.268 7.505H8.682l3.267-7.505ZM.854 16.79 0 3.986 9.115 0 .855 16.791Z"
/>
<path
fill="url(#b)"
d="m23.9 3.986-.862 12.805L14.786 0l9.115 3.986Zm-5.715 16.558-6.235 3.362-6.235-3.362 1.268-2.904h9.934l1.268 2.904ZM11.95 6.374l3.268 7.505H8.682l3.267-7.505ZM.854 16.79 0 3.986 9.115 0 .855 16.791Z"
/>
<defs>
<linearGradient id="a" x1="21%" x2="100%" y1="87.5%" y2="50%">
<stop stopColor="#E40035" />
<stop offset=".24" stopColor="#F60A48" />
<stop offset=".352" stopColor="#F20755" />
<stop offset=".494" stopColor="#DC087D" />
<stop offset=".745" stopColor="#9717E7" />
<stop offset="1" stopColor="#6C00F5" />
</linearGradient>
<linearGradient id="b" x1="16%" x2="67%" y1="12.5%" y2="71%">
<stop stopColor="#FF31D9" />
<stop offset="1" stopColor="#FF5BE1" stopOpacity="0" />
</linearGradient>
</defs>
</svg>
),
name: '@nx/angular',
url: '/nx-api/angular',
description:
'Integration with libraries such as Storybook, Jest, Cypress, NgRx, Micro-frontend...',
isOfficial: true,
},
{
logo: (
<svg
className="mr-3 h-8 w-8 text-[#2496ED]"
fill="currentColor"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Docker</title>
<path d="M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z" />
</svg>
),
name: '@nx-tools/nx-docker',
url: 'https://github.com/gperdomor/nx-tools',
description: 'Nx plugin to build docker images of your affected apps.',
isOfficial: false,
},
];
export function PluginsTab(): JSX.Element {
return (
<motion.div className="wrapper my-8 grid h-full gap-12 md:grid-cols-2 lg:grid-cols-3">
<div className="flex flex-col">
<div className="mb-8">
<h3 className="text-xl font-medium leading-6 text-blue-500 dark:text-sky-500">
Plugins available for all stacks
</h3>
<p className="mt-4 text-slate-900 dark:text-slate-400">
Official Nx plugins are created and maintained by the Nx team. You
can see all the available plugins when you run the{' '}
<code className="break-normal rounded-md border border-slate-200 bg-slate-50 px-2 py-1 font-mono text-xs text-slate-800 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-200">
nx list
</code>{' '}
command in your workspace.
</p>
</div>
<div
className="coding rounded-lg border border-slate-200 bg-slate-50 p-4 font-mono
text-xs leading-normal text-slate-800 subpixel-antialiased shadow-lg dark:border-slate-700 dark:bg-slate-800 dark:text-slate-200"
>
<div className="flex items-center">
<p>
<span className="text-base text-purple-600 dark:text-fuchsia-500">
</span>{' '}
<span className="mx-1 text-green-600 dark:text-green-400">
~/workspace
</span>{' '}
<span>$</span>
</p>
<p className="typing mt-0.5 flex-1 pl-2">nx list</p>
</div>
<div className="mt-2 flex">
<p className="typing flex-1 items-center">
<span className="bg-yellow-300 px-1 py-0.5 dark:bg-yellow-600">
NX
</span>{' '}
Local workspace plugins: <br />
<br />
@nx/react-native (executors,generators) <br />
@nx/jest (executors,generators) <br />
@nx/storybook (executors,generators)
<br />
<br />
<span className="bg-yellow-300 px-1 py-0.5 dark:bg-yellow-600">
NX
</span>{' '}
Installed plugins: <br />
<br />
@nx/js (executors,generators) <br />
@nx/eslint (executors,generators) <br />
@nx/next (executors,generators)
<br />
<br />
<span className="bg-yellow-300 px-1 py-0.5 dark:bg-yellow-600">
NX
</span>{' '}
Also available: <br />
<br />
@nx/nest (executors,generators) <br />
@nx/node (executors,generators) <br />
@nx/express (executors,generators)
<br />
<br />
<span className="bg-yellow-300 px-1 py-0.5 dark:bg-yellow-600">
NX
</span>{' '}
Community plugins: <br />
<br />
@nxext/svelte <br />
@nx-tools/nx-docker <br />
@nx-plus/docusaurus <br />
</p>
</div>
</div>
</div>
<div className="flex flex-col space-y-4">
{pluginList.slice(0, 5).map((plugin) => (
<div className="relative flex w-full overflow-hidden rounded-lg border border-slate-200 bg-white shadow-sm transition focus-within:ring-2 focus-within:ring-blue-500 focus-within:ring-offset-2 hover:shadow-md dark:border-slate-700 dark:bg-slate-800 dark:focus-within:ring-sky-500">
<div className="flex w-full flex-col px-4 py-3">
<h3 className="mb-4 flex text-lg font-semibold leading-tight dark:text-slate-300">
{plugin.logo}
{plugin.name}
</h3>
<a
href={plugin.url}
target="_blank"
rel="noreferrer"
title={plugin.name}
className="focus:outline-none"
>
<span className="absolute inset-0" aria-hidden="true"></span>
<p className="mb-8 sm:text-sm">{plugin.description}</p>
{plugin.isOfficial ? (
<span
title="Official plugins are maintained by the Nx Team"
className="absolute bottom-3 right-4 rounded-full border border-slate-200 bg-slate-50 px-3 py-0.5 text-xs font-medium capitalize dark:border-slate-700 dark:bg-slate-800"
>
Nx Team
</span>
) : (
<span
title="Community plugins are maintained by their community members"
className="absolute bottom-3 right-4 rounded-full border border-slate-200 bg-slate-50 px-3 py-0.5 text-xs font-medium capitalize dark:border-slate-700 dark:bg-slate-800"
>
Community
</span>
)}
</a>
</div>
</div>
))}
</div>
<div className="hidden flex-col space-y-4 lg:flex">
{pluginList.slice(5).map((plugin) => (
<div className="relative flex w-full overflow-hidden rounded-lg border border-slate-200 bg-white shadow-sm transition focus-within:ring-2 focus-within:ring-blue-500 focus-within:ring-offset-2 hover:shadow-md dark:border-slate-700 dark:bg-slate-800 dark:focus-within:ring-sky-500">
<div className="flex w-full flex-col px-4 py-3">
<h3 className="mb-4 flex text-lg font-semibold leading-tight dark:text-slate-300">
{plugin.logo}
{plugin.name}
</h3>
<a
href={plugin.url}
target="_blank"
rel="noreferrer"
title={plugin.name}
className="focus:outline-none"
>
<span className="absolute inset-0" aria-hidden="true"></span>
<p className="mb-8 sm:text-sm">{plugin.description}</p>
{plugin.isOfficial ? (
<span
title="Official plugins are maintained by the Nx Team"
className="absolute bottom-3 right-4 rounded-full border border-slate-200 bg-slate-50 px-3 py-0.5 text-xs font-medium capitalize dark:border-slate-700 dark:bg-slate-800"
>
Nx Team
</span>
) : (
<span
title="Community plugins are maintained by their community members"
className="absolute bottom-3 right-4 rounded-full border border-slate-200 bg-slate-50 px-3 py-0.5 text-xs font-medium capitalize dark:border-slate-700 dark:bg-slate-800"
>
Community
</span>
)}
</a>
</div>
</div>
))}
</div>
</motion.div>
);
}

View File

@ -1,11 +0,0 @@
import { GitHubIntegrationTab } from './github-intergration-tab';
import { GraphTab } from './graph-tab';
import { PluginsTab } from './plugins-tab';
import { IdeIntegrationTab } from './ide-integration-tab';
export const tabs = [
{ title: 'IDE integrations', panel: IdeIntegrationTab },
{ title: 'Interactive graph', panel: GraphTab },
{ title: 'GitHub integration', panel: GitHubIntegrationTab },
{ title: 'Plugins', panel: PluginsTab },
];

View File

@ -1,33 +0,0 @@
import { ButtonLink } from '@nx/nx-dev/ui-common';
export function GettingStarted(): JSX.Element {
return (
<article
id="getting-started"
className="border-b border-t border-slate-200 bg-gradient-to-r from-cyan-500 to-blue-500 shadow-inner dark:border-slate-700"
>
<div className="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:flex lg:items-center lg:justify-between lg:px-8 lg:py-24">
<div>
<h2 className="text-3xl font-bold tracking-tight text-slate-900 md:text-4xl">
<span className="block">Ready to dive in?</span>
<span className="block text-white">
Start your monorepo now with Nx.
</span>
</h2>
</div>
<div className="mt-8 flex lg:mt-0 lg:flex-shrink-0">
<div className="inline-flex rounded-md">
<ButtonLink
href="/getting-started/intro"
title="Start using Nx by creating a workspace"
variant="secondary"
size="large"
>
Get started now!
</ButtonLink>
</div>
</div>
</div>
</article>
);
}

View File

@ -1,50 +1,27 @@
import { ButtonLink } from '@nx/nx-dev/ui-common';
import { Fragment, useEffect, useState } from 'react';
import { Transition } from '@headlessui/react';
import { cx } from '@nx/nx-dev/ui-primitives';
'use client';
import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common';
import { ShaderGradient, ShaderGradientCanvas } from 'shadergradient';
import { BlurFade } from '@nx/nx-dev/ui-animations';
import { Theme, useTheme } from '@nx/nx-dev/ui-theme';
import { useEffect, useState } from 'react';
import Link from 'next/link';
import { useIsomorphicLayoutEffect } from '@nx/nx-dev/ui-primitives';
export function Hero(): JSX.Element {
const [copied, setCopied] = useState(false);
const [displayBuildSystem, setDisplayBuildSystem] = useState(false);
const [displayTools, setDisplayTools] = useState(false);
const [displayCi, setDisplayCi] = useState(false);
useEffect(() => {
let t: NodeJS.Timeout;
if (copied) {
t = setTimeout(() => {
setCopied(false);
}, 3000);
}
return () => {
t && clearTimeout(t);
};
}, [copied]);
return (
<header className="bg-contain bg-fixed bg-clip-border bg-center bg-no-repeat bg-origin-border lg:bg-local">
<div className="mx-auto max-w-3xl px-4 pt-20">
<div className="hidden sm:mb-8 sm:flex sm:justify-center">
<div className="relative rounded-full px-3 py-1 text-sm leading-6 ring-1 ring-slate-900/10 transition-all hover:ring-slate-900/20 dark:ring-slate-100/10 dark:hover:ring-slate-100/20">
Introducing{' '}
<span className="text-blue-500 dark:text-sky-500">Nx Agents</span>,
the next leap in CI.{' '}
<Link
href="/ci/features/distribute-task-execution"
title="Discover Nx Agents"
className="font-semibold text-blue-500 dark:text-sky-500"
prefetch={false}
>
<span className="absolute inset-0" aria-hidden="true"></span>Read
more <span aria-hidden="true"></span>
</Link>
<div className="mx-auto h-screen w-full max-w-7xl px-6 lg:px-8">
<ShaderGradientElement />
<div className="absolute left-0 right-0 -z-10 mx-auto flex h-full max-h-screen w-full flex-row justify-between border-b border-dashed border-slate-200/30 px-6 lg:h-full lg:max-w-7xl lg:px-0 dark:border-slate-800/40">
<div className="h-full w-full border-x border-dashed border-slate-200/20 dark:border-slate-800/40" />
<div className="h-full w-full border-x border-dashed border-slate-200/20 dark:border-slate-800/40" />
<div className="h-full w-full border-x border-dashed border-slate-200/20 dark:border-slate-800/40" />
<div className="h-full w-full border-x border-dashed border-slate-200/20 dark:border-slate-800/40" />
<div className="h-full w-full border-x border-dashed border-slate-200/20 dark:border-slate-800/40" />
<div className="h-full w-full border-x border-dashed border-slate-200/20 dark:border-slate-800/40" />
</div>
</div>
<div className="text-center">
<h1
className="text-3xl font-bold leading-none tracking-tight text-black sm:mt-6 sm:text-5xl md:text-6xl dark:text-white"
data-cy="primary-heading"
>
<div className="z-20 mx-auto grid h-screen max-w-6xl grid-cols-1 place-items-center text-center">
<div className="container">
<SectionHeading as="h1" variant="display" data-cy="primary-heading">
<span className="rounded-lg bg-gradient-to-r from-cyan-500 to-blue-500 bg-clip-text text-transparent">
Smart
</span>{' '}
@ -60,150 +37,168 @@ export function Hero(): JSX.Element {
Fast
</span>{' '}
CI
</h1>
<h2 className="mt-6 text-lg font-medium leading-8 dark:text-slate-100">
Nx is a{' '}
<span
onClick={() => setDisplayBuildSystem(!displayBuildSystem)}
className={cx(
'text-md my-0.5 inline-flex cursor-pointer items-center rounded-md px-1.5 py-0.5 font-medium ring-1 ring-inset ring-slate-500/10 transition hover:bg-slate-50 hover:underline dark:ring-slate-400/20 hover:dark:bg-slate-400/10',
displayBuildSystem && 'bg-yellow-500/10 dark:bg-yellow-500/20'
)}
</SectionHeading>
<SectionHeading
as="p"
variant="subtitle"
className="mx-auto mt-6 max-w-4xl"
>
build system
</span>{' '}
<Transition
as={Fragment}
show={displayBuildSystem}
enter="transform transition duration-[400ms]"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transform duration-200 transition ease-in-out"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<span className="rounded-md bg-gradient-to-r from-orange-500 to-yellow-500 bg-clip-text text-transparent">
optimized for monorepos
</span>
</Transition>{' '}
with{' '}
<span
onClick={() => setDisplayTools(!displayTools)}
className={cx(
'text-md my-0.5 inline-flex cursor-pointer items-center rounded-md px-1.5 py-0.5 font-medium ring-1 ring-inset ring-slate-500/10 transition hover:bg-slate-50 hover:underline dark:ring-slate-400/20 hover:dark:bg-slate-400/10',
displayTools && 'bg-cyan-500/10 dark:bg-cyan-500/20'
)}
>
built-in tooling
</span>{' '}
<Transition
as={Fragment}
show={displayTools}
enter="transform transition duration-[400ms]"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transform duration-200 transition ease-in-out"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<span className="rounded-md bg-gradient-to-r from-cyan-500 to-blue-500 bg-clip-text text-transparent">
for code scaffolding, module boundary enforcement, automated
updates
</span>
</Transition>{' '}
and{' '}
<span
onClick={() => setDisplayCi(!displayCi)}
className={cx(
'text-md my-0.5 inline-flex cursor-pointer items-center rounded-md px-1.5 py-0.5 font-medium ring-1 ring-inset ring-slate-500/10 transition hover:bg-slate-50 hover:underline dark:ring-slate-400/20 hover:dark:bg-slate-400/10',
displayCi && 'bg-fuchsia-500/10 dark:bg-fuchsia-500/20'
)}
>
advanced CI capabilities
</span>{' '}
<Transition
as={Fragment}
show={displayCi}
enter="transform transition duration-[400ms]"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transform duration-200 transition ease-in-out"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<span className="rounded-md bg-gradient-to-r from-pink-500 to-fuchsia-500 bg-clip-text text-transparent">
with caching and distribution
</span>
</Transition>{' '}
. It helps you maintain and scale monorepos, both locally and on CI.
</h2>
<div className="mt-4 flex items-center justify-center gap-x-6">
{/*Structured, maintainable and efficient monorepos. Locally and on CI, easy as that.*/}
<Strong>Build system</Strong>, optimized for monorepos, with plugins
for popular frameworks and tools and{' '}
<Strong>advanced CI capabilities</Strong> including caching and
distribution.
</SectionHeading>
<div className="mt-10 flex items-center justify-center gap-x-6">
<ButtonLink
href="/getting-started/intro"
href="/getting-started/intro?utm_medium=website&utm_campaign=homepage_links&utm_content=cta_hero_get_started#try-nx-yourself"
title="Get started"
variant="primary"
size="large"
title="Start using Nx by creating a workspace"
size="default"
>
Get started
</ButtonLink>
<ButtonLink
href="/contact"
variant="secondary"
size="large"
title="Contact us"
<Link
href="ci/intro/ci-with-nx?utm_medium=website&utm_campaign=homepage_links&utm_content=cta_hero_get_started&utm_source=nxdev"
target="blank"
title="Start with Nx"
prefetch={false}
className="group font-semibold leading-6 text-slate-950 dark:text-white"
>
Contact us
</ButtonLink>
</div>
<div className="text-md mt-4 flex items-center justify-center gap-2 italic">
Built with
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
fill="currentColor"
Connect your Nx repository{' '}
<span
aria-hidden="true"
className="inline-block transition group-hover:translate-x-1"
>
<title>Rust</title>
<path d="M23.8346 11.7033l-1.0073-.6236a13.7268 13.7268 0 00-.0283-.2936l.8656-.8069a.3483.3483 0 00-.1154-.578l-1.1066-.414a8.4958 8.4958 0 00-.087-.2856l.6904-.9587a.3462.3462 0 00-.2257-.5446l-1.1663-.1894a9.3574 9.3574 0 00-.1407-.2622l.49-1.0761a.3437.3437 0 00-.0274-.3361.3486.3486 0 00-.3006-.154l-1.1845.0416a6.7444 6.7444 0 00-.1873-.2268l.2723-1.153a.3472.3472 0 00-.417-.4172l-1.1532.2724a14.0183 14.0183 0 00-.2278-.1873l.0415-1.1845a.3442.3442 0 00-.49-.328l-1.076.491c-.0872-.0476-.1742-.0952-.2623-.1407l-.1903-1.1673A.3483.3483 0 0016.256.955l-.9597.6905a8.4867 8.4867 0 00-.2855-.086l-.414-1.1066a.3483.3483 0 00-.5781-.1154l-.8069.8666a9.2936 9.2936 0 00-.2936-.0284L12.2946.1683a.3462.3462 0 00-.5892 0l-.6236 1.0073a13.7383 13.7383 0 00-.2936.0284L9.9803.3374a.3462.3462 0 00-.578.1154l-.4141 1.1065c-.0962.0274-.1903.0567-.2855.086L7.744.955a.3483.3483 0 00-.5447.2258L7.009 2.348a9.3574 9.3574 0 00-.2622.1407l-1.0762-.491a.3462.3462 0 00-.49.328l.0416 1.1845a7.9826 7.9826 0 00-.2278.1873L3.8413 3.425a.3472.3472 0 00-.4171.4171l.2713 1.1531c-.0628.075-.1255.1509-.1863.2268l-1.1845-.0415a.3462.3462 0 00-.328.49l.491 1.0761a9.167 9.167 0 00-.1407.2622l-1.1662.1894a.3483.3483 0 00-.2258.5446l.6904.9587a13.303 13.303 0 00-.087.2855l-1.1065.414a.3483.3483 0 00-.1155.5781l.8656.807a9.2936 9.2936 0 00-.0283.2935l-1.0073.6236a.3442.3442 0 000 .5892l1.0073.6236c.008.0982.0182.1964.0283.2936l-.8656.8079a.3462.3462 0 00.1155.578l1.1065.4141c.0273.0962.0567.1914.087.2855l-.6904.9587a.3452.3452 0 00.2268.5447l1.1662.1893c.0456.088.0922.1751.1408.2622l-.491 1.0762a.3462.3462 0 00.328.49l1.1834-.0415c.0618.0769.1235.1528.1873.2277l-.2713 1.1541a.3462.3462 0 00.4171.4161l1.153-.2713c.075.0638.151.1255.2279.1863l-.0415 1.1845a.3442.3442 0 00.49.327l1.0761-.49c.087.0486.1741.0951.2622.1407l.1903 1.1662a.3483.3483 0 00.5447.2268l.9587-.6904a9.299 9.299 0 00.2855.087l.414 1.1066a.3452.3452 0 00.5781.1154l.8079-.8656c.0972.0111.1954.0203.2936.0294l.6236 1.0073a.3472.3472 0 00.5892 0l.6236-1.0073c.0982-.0091.1964-.0183.2936-.0294l.8069.8656a.3483.3483 0 00.578-.1154l.4141-1.1066a8.4626 8.4626 0 00.2855-.087l.9587.6904a.3452.3452 0 00.5447-.2268l.1903-1.1662c.088-.0456.1751-.0931.2622-.1407l1.0762.49a.3472.3472 0 00.49-.327l-.0415-1.1845a6.7267 6.7267 0 00.2267-.1863l1.1531.2713a.3472.3472 0 00.4171-.416l-.2713-1.1542c.0628-.0749.1255-.1508.1863-.2278l1.1845.0415a.3442.3442 0 00.328-.49l-.49-1.076c.0475-.0872.0951-.1742.1407-.2623l1.1662-.1893a.3483.3483 0 00.2258-.5447l-.6904-.9587.087-.2855 1.1066-.414a.3462.3462 0 00.1154-.5781l-.8656-.8079c.0101-.0972.0202-.1954.0283-.2936l1.0073-.6236a.3442.3442 0 000-.5892zm-6.7413 8.3551a.7138.7138 0 01.2986-1.396.714.714 0 11-.2997 1.396zm-.3422-2.3142a.649.649 0 00-.7715.5l-.3573 1.6685c-1.1035.501-2.3285.7795-3.6193.7795a8.7368 8.7368 0 01-3.6951-.814l-.3574-1.6684a.648.648 0 00-.7714-.499l-1.473.3158a8.7216 8.7216 0 01-.7613-.898h7.1676c.081 0 .1356-.0141.1356-.088v-2.536c0-.074-.0536-.0881-.1356-.0881h-2.0966v-1.6077h2.2677c.2065 0 1.1065.0587 1.394 1.2088.0901.3533.2875 1.5044.4232 1.8729.1346.413.6833 1.2381 1.2685 1.2381h3.5716a.7492.7492 0 00.1296-.0131 8.7874 8.7874 0 01-.8119.9526zM6.8369 20.024a.714.714 0 11-.2997-1.396.714.714 0 01.2997 1.396zM4.1177 8.9972a.7137.7137 0 11-1.304.5791.7137.7137 0 011.304-.579zm-.8352 1.9813l1.5347-.6824a.65.65 0 00.33-.8585l-.3158-.7147h1.2432v5.6025H3.5669a8.7753 8.7753 0 01-.2834-3.348zm6.7343-.5437V8.7836h2.9601c.153 0 1.0792.1772 1.0792.8697 0 .575-.7107.7815-1.2948.7815zm10.7574 1.4862c0 .2187-.008.4363-.0243.651h-.9c-.09 0-.1265.0586-.1265.1477v.413c0 .973-.5487 1.1846-1.0296 1.2382-.4576.0517-.9648-.1913-1.0275-.4717-.2704-1.5186-.7198-1.8436-1.4305-2.4034.8817-.5599 1.799-1.386 1.799-2.4915 0-1.1936-.819-1.9458-1.3769-2.3153-.7825-.5163-1.6491-.6195-1.883-.6195H5.4682a8.7651 8.7651 0 014.907-2.7699l1.0974 1.151a.648.648 0 00.9182.0213l1.227-1.1743a8.7753 8.7753 0 016.0044 4.2762l-.8403 1.8982a.652.652 0 00.33.8585l1.6178.7188c.0283.2875.0425.577.0425.8717zm-9.3006-9.5993a.7128.7128 0 11.984 1.0316.7137.7137 0 01-.984-1.0316zm8.3389 6.71a.7107.7107 0 01.9395-.3625.7137.7137 0 11-.9405.3635z" />
</svg>
<span className="sr-only">Rust</span> for speed &
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4"
fill="currentColor"
aria-hidden="true"
>
<title>TypeScript</title>
<path d="M1.125 0C.502 0 0 .502 0 1.125v21.75C0 23.498.502 24 1.125 24h21.75c.623 0 1.125-.502 1.125-1.125V1.125C24 .502 23.498 0 22.875 0zm17.363 9.75c.612 0 1.154.037 1.627.111a6.38 6.38 0 0 1 1.306.34v2.458a3.95 3.95 0 0 0-.643-.361 5.093 5.093 0 0 0-.717-.26 5.453 5.453 0 0 0-1.426-.2c-.3 0-.573.028-.819.086a2.1 2.1 0 0 0-.623.242c-.17.104-.3.229-.393.374a.888.888 0 0 0-.14.49c0 .196.053.373.156.529.104.156.252.304.443.444s.423.276.696.41c.273.135.582.274.926.416.47.197.892.407 1.266.628.374.222.695.473.963.753.268.279.472.598.614.957.142.359.214.776.214 1.253 0 .657-.125 1.21-.373 1.656a3.033 3.033 0 0 1-1.012 1.085 4.38 4.38 0 0 1-1.487.596c-.566.12-1.163.18-1.79.18a9.916 9.916 0 0 1-1.84-.164 5.544 5.544 0 0 1-1.512-.493v-2.63a5.033 5.033 0 0 0 3.237 1.2c.333 0 .624-.03.872-.09.249-.06.456-.144.623-.25.166-.108.29-.234.373-.38a1.023 1.023 0 0 0-.074-1.089 2.12 2.12 0 0 0-.537-.5 5.597 5.597 0 0 0-.807-.444 27.72 27.72 0 0 0-1.007-.436c-.918-.383-1.602-.852-2.053-1.405-.45-.553-.676-1.222-.676-2.005 0-.614.123-1.141.369-1.582.246-.441.58-.804 1.004-1.089a4.494 4.494 0 0 1 1.47-.629 7.536 7.536 0 0 1 1.77-.201zm-15.113.188h9.563v2.166H9.506v9.646H6.789v-9.646H3.375z" />
</svg>
<span className="sr-only">TypeScript</span> for extensibility
</span>
</Link>
</div>
</div>
</div>
<div className="relative overflow-hidden pt-16">
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<img
src="/images/illustrations/nxdev-light.webp"
alt="light"
aria-hidden="true"
className="block dark:hidden"
/>
<img
src="/images/illustrations/nxdev-dark.webp"
alt="dark"
aria-hidden="true"
className="hidden dark:block"
/>
<div className="relative" aria-hidden="true">
<div className="absolute -inset-x-20 bottom-0 bg-gradient-to-t from-white pt-[7%] dark:from-slate-900"></div>
</div>
</div>
</div>
</header>
);
}
function ShaderGradientElement() {
const [theme] = useTheme();
const [displayTheme, setDisplayTheme] = useState<Theme>('system');
useIsomorphicLayoutEffect(() => {
const matchMedia: any = window.matchMedia('(prefers-color-scheme: dark)');
function handleChange(): void {
if (theme === 'system') {
setDisplayTheme(matchMedia.matches ? 'dark' : 'light');
} else {
setDisplayTheme(theme === 'dark' ? 'dark' : 'light');
}
}
handleChange();
// Use deprecated `addListener` and `removeListener` to support Safari < 14 (#135)
if (matchMedia.addListener) {
matchMedia.addListener(handleChange);
} else {
matchMedia.addEventListener('change', handleChange);
}
return () => {
if (matchMedia.removeListener) {
matchMedia.removeListener(handleChange);
} else {
matchMedia.removeEventListener('change', handleChange);
}
};
}, [theme]);
if (displayTheme === 'dark')
return (
<BlurFade
delay={1}
duration={1.8}
className="absolute left-0 -z-10 w-full"
>
<div className="h-screen w-full overflow-hidden">
<ShaderGradientCanvas
pointerEvents="none"
eventPrefix="client"
fov={45}
pixelDensity={1}
className="pointer-events-none"
>
<ShaderGradient
brightness={4}
cDistance={5}
color1="#251B36"
color2="#020617"
color3="#1F1C3A"
frameRate={10}
grain="off"
lightType="3d"
positionX={0}
positionY={1.8}
positionZ={0}
range="enabled"
rangeEnd={40}
rangeStart={0}
reflection={0.1}
rotationX={0}
rotationY={0}
rotationZ={-90}
shader="defaults"
type="waterPlane"
uDensity={1}
uFrequency={5.5}
uSpeed={0.1}
uStrength={3}
uTime={0.2}
/>
</ShaderGradientCanvas>
<div className="absolute inset-x-0 bottom-0 h-96 bg-gradient-to-b from-transparent to-white dark:to-slate-950" />
</div>
</BlurFade>
);
return (
<BlurFade delay={1} duration={1.8} className="absolute left-0 -z-10 w-full">
<div className="h-screen w-full overflow-hidden">
<ShaderGradientCanvas
pointerEvents="none"
eventPrefix="client"
fov={45}
pixelDensity={1}
className="pointer-events-none"
>
<ShaderGradient
brightness={4}
cDistance={5}
color1="#F4F2FE"
color2="#F7F7FF"
color3="#FFFFFF"
frameRate={10}
grain="off"
lightType="3d"
positionX={0}
positionY={1.8}
positionZ={0}
range="enabled"
rangeEnd={40}
rangeStart={0}
reflection={0.1}
rotationX={0}
rotationY={0}
rotationZ={-90}
shader="defaults"
type="waterPlane"
uDensity={1}
uFrequency={5.5}
uSpeed={0.1}
uStrength={3}
uTime={0.2}
/>
</ShaderGradientCanvas>
<div className="absolute inset-x-0 bottom-0 h-96 bg-gradient-to-b from-transparent to-white dark:to-slate-950" />
</div>
</BlurFade>
);
}

View File

@ -0,0 +1,903 @@
import { FC, SVGProps } from 'react';
export const AutomatedMigrationIllustration: FC<SVGProps<SVGSVGElement>> = (
props
) => (
<svg
role="img"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 336 336"
{...props}
>
<mask
id="b"
width={336}
height={336}
x={0}
y={0}
maskUnits="userSpaceOnUse"
style={{
maskType: 'alpha',
}}
>
<path fill="url(#a)" d="M0 0h336v336H0z" />
</mask>
<g mask="url(#b)">
<circle
cx={167.5}
cy={388.5}
r={252.5}
stroke="#F8F8F8"
strokeDasharray="1 32"
strokeWidth={1.5}
/>
<circle
cx={167.5}
cy={388.5}
r={180.5}
stroke="#F8F8F8"
strokeDasharray="1 24"
strokeWidth={4}
opacity={0.1}
/>
<circle
cx={167.5}
cy={388.5}
r={326.5}
stroke="#F8F8F8"
strokeDasharray="1 24"
strokeWidth={4}
opacity={0.1}
/>
<mask
id="d"
width={337}
height={326}
x={-2}
y={21}
maskUnits="userSpaceOnUse"
style={{
maskType: 'alpha',
}}
>
<path fill="url(#c)" d="M-1 21h336v326H-1z" />
</mask>
<g mask="url(#d)">
<g
filter="url(#e)"
shapeRendering="crispEdges"
transform="rotate(-60 -51.173 262.25)"
>
<circle
cx={-51.173}
cy={262.25}
r={24}
fill="#F8F8F8"
fillOpacity={0.05}
style={{
mixBlendMode: 'luminosity',
}}
/>
<circle
cx={-51.173}
cy={262.25}
r={23.25}
stroke="url(#f)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<g
filter="url(#g)"
shapeRendering="crispEdges"
transform="rotate(-45 -11.046 209.956)"
>
<circle
cx={-11.046}
cy={209.956}
r={24}
fill="#F8F8F8"
fillOpacity={0.05}
style={{
mixBlendMode: 'luminosity',
}}
/>
<circle
cx={-11.046}
cy={209.956}
r={23.25}
stroke="url(#h)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<g
filter="url(#i)"
shapeRendering="crispEdges"
transform="rotate(-30 41.249 169.829)"
>
<circle
cx={41.249}
cy={169.829}
r={24}
fill="#F8F8F8"
fillOpacity={0.05}
style={{
mixBlendMode: 'luminosity',
}}
/>
<circle
cx={41.249}
cy={169.829}
r={23.25}
stroke="url(#j)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<path
fill="#F8F8F8"
fillOpacity={0.7}
d="M44.254 174.029a5.406 5.406 0 0 1-1.396.579 3.671 3.671 0 0 1-1.3.072 2.793 2.793 0 0 1-1.112-.441 2.782 2.782 0 0 1-.846-.934c-.285-.493-.413-.985-.383-1.476.037-.496.2-.951.488-1.366a2.382 2.382 0 0 1-1.16-.3c-.35-.197-.644-.501-.882-.913-.28-.485-.398-.961-.355-1.428.046-.479.23-.936.551-1.369.33-.438.78-.822 1.355-1.154.565-.326 1.116-.52 1.652-.582.539-.074 1.024-.009 1.454.195.439.2.796.538 1.07 1.015.239.412.358.823.357 1.233a2.41 2.41 0 0 1-.307 1.147c.503-.042.975.046 1.414.267.448.215.814.57 1.1 1.063.302.525.433 1.059.39 1.601-.047.534-.249 1.043-.604 1.529-.36.477-.856.898-1.486 1.262Zm-.56-.97c.371-.215.67-.473.894-.775.224-.302.358-.622.4-.959a1.61 1.61 0 0 0-.223-1.002c-.191-.332-.441-.559-.75-.683a1.904 1.904 0 0 0-1.023-.12 2.888 2.888 0 0 0-1.118.387 2.988 2.988 0 0 0-.907.782 1.912 1.912 0 0 0-.407.946c-.047.329.025.659.216.991.187.323.439.555.757.694.313.132.656.176 1.03.133a2.995 2.995 0 0 0 1.13-.394Zm-2.373-4.11c.307-.178.557-.397.75-.66.202-.267.323-.542.365-.825a1.227 1.227 0 0 0-.164-.843 1.322 1.322 0 0 0-.643-.582 1.554 1.554 0 0 0-.884-.104 2.498 2.498 0 0 0-.971.334 2.599 2.599 0 0 0-.787.681 1.656 1.656 0 0 0-.353.818c-.037.291.024.573.183.848.163.283.38.481.65.595.266.105.558.135.877.091a2.78 2.78 0 0 0 .977-.353Z"
/>
<g
filter="url(#k)"
shapeRendering="crispEdges"
transform="rotate(-15 102.147 144.603)"
>
<circle
cx={102.147}
cy={144.603}
r={24}
fill="#F8F8F8"
fillOpacity={0.05}
style={{
mixBlendMode: 'luminosity',
}}
/>
<circle
cx={102.147}
cy={144.603}
r={23.25}
stroke="url(#l)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<path
fill="#F8F8F8"
fillOpacity={0.7}
d="M101.99 149.822a.284.284 0 0 1-.225-.027.37.37 0 0 1-.125-.198.433.433 0 0 1-.006-.129l1.258-8.773-4.435 1.189a.35.35 0 0 1-.252-.02.352.352 0 0 1-.143-.208l-.144-.541c-.027-.099-.02-.183.02-.251a.328.328 0 0 1 .204-.157l5.544-1.485a.293.293 0 0 1 .255.033c.078.037.13.105.157.204l.134.501c.031.117.047.214.049.291a2.02 2.02 0 0 1-.016.265l-1.257 8.671a.919.919 0 0 1-.074.266c-.034.087-.106.144-.214.173l-.73.196Z"
/>
<g filter="url(#m)">
<g clipPath="url(#n)">
<rect
width={52}
height={92}
x={142}
y={90}
fill="url(#o)"
fillOpacity={0.05}
rx={26}
/>
<g filter="url(#p)">
<rect
width={44}
height={84}
x={146}
y={94}
fill="#F8F8F8"
fillOpacity={0.05}
rx={22}
shapeRendering="crispEdges"
style={{
mixBlendMode: 'luminosity',
}}
/>
<rect
width={42.5}
height={82.5}
x={146.75}
y={94.75}
stroke="url(#q)"
strokeOpacity={0.25}
strokeWidth={1.5}
rx={21.25}
shapeRendering="crispEdges"
/>
<path
fill="#F8F8F8"
fillOpacity={0.95}
d="M168.002 141.16c-.619 0-1.19-.075-1.712-.224a4.201 4.201 0 0 1-1.328-.672 3.169 3.169 0 0 1-.848-1.072 3.168 3.168 0 0 1-.304-1.408c0-.651.154-1.211.464-1.68.32-.469.741-.827 1.264-1.072a2.707 2.707 0 0 1-.976-.96c-.235-.395-.352-.864-.352-1.408 0-.64.154-1.179.464-1.616.32-.448.762-.795 1.328-1.04.576-.245 1.242-.368 2-.368.746 0 1.402.123 1.968.368.576.235 1.018.576 1.328 1.024.32.448.48.987.48 1.616 0 .544-.118 1.019-.352 1.424a2.758 2.758 0 0 1-.96.96c.522.245.938.603 1.248 1.072.32.469.48 1.029.48 1.68 0 .693-.176 1.296-.528 1.808-.352.501-.843.891-1.472 1.168-.63.267-1.36.4-2.192.4Zm0-1.28c.49 0 .933-.085 1.328-.256.394-.171.709-.411.944-.72.234-.32.352-.693.352-1.12 0-.437-.118-.805-.352-1.104a2.194 2.194 0 0 0-.944-.704 3.311 3.311 0 0 0-1.328-.256c-.491 0-.939.085-1.344.256-.395.16-.71.395-.944.704-.235.299-.352.667-.352 1.104 0 .427.117.8.352 1.12.234.309.549.549.944.72.405.171.853.256 1.344.256Zm0-5.424c.405 0 .778-.075 1.12-.224a2.06 2.06 0 0 0 .832-.608c.213-.256.32-.565.32-.928a1.52 1.52 0 0 0-.304-.944 1.776 1.776 0 0 0-.816-.608 2.856 2.856 0 0 0-1.152-.224c-.427 0-.816.075-1.168.224a1.887 1.887 0 0 0-.816.608 1.514 1.514 0 0 0-.304.944c0 .373.101.693.304.96.202.256.474.453.816.592.352.139.741.208 1.168.208Z"
/>
</g>
</g>
<rect
width={50.5}
height={90.5}
x={142.75}
y={90.75}
stroke="#fff"
strokeOpacity={0.4}
strokeWidth={1.5}
rx={25.25}
/>
</g>
<g
filter="url(#r)"
shapeRendering="crispEdges"
transform="rotate(15 232.851 144.603)"
>
<circle
cx={232.851}
cy={144.603}
r={24}
fill="#F8F8F8"
fillOpacity={0.05}
style={{
mixBlendMode: 'luminosity',
}}
/>
<circle
cx={232.851}
cy={144.603}
r={23.25}
stroke="url(#s)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<path
fill="#F8F8F8"
fillOpacity={0.7}
d="M230.642 149.188a.284.284 0 0 1-.181-.136.367.367 0 0 1-.01-.234.35.35 0 0 1 .043-.105.82.82 0 0 0 .058-.056l2.841-2.326a3.272 3.272 0 0 1-.752-.115 3.663 3.663 0 0 1-1.28-.633 3.208 3.208 0 0 1-.829-.961 3.22 3.22 0 0 1-.272-2.392c.106-.397.277-.766.514-1.109.246-.34.549-.626.911-.857a3.244 3.244 0 0 1 1.264-.444c.474-.076 1-.037 1.577.118.568.152 1.04.375 1.415.669.387.287.684.623.89 1.007.218.377.344.773.377 1.188.043.417.01.829-.099 1.234-.099.37-.243.694-.434.971-.19.278-.394.518-.613.72-.209.205-.414.391-.614.56l-3.571 2.942a5.303 5.303 0 0 1-.196.136c-.08.046-.183.052-.309.019l-.73-.196Zm2.482-4.017a2.31 2.31 0 0 0 1.106.036c.371-.084.691-.25.96-.497.271-.255.464-.595.577-1.019.114-.424.116-.81.006-1.158a1.943 1.943 0 0 0-.582-.91 2.227 2.227 0 0 0-.973-.535 2.179 2.179 0 0 0-1.096-.019 1.968 1.968 0 0 0-.946.5c-.269.247-.46.582-.574 1.006-.114.424-.117.814-.01 1.172.11.348.3.65.569.906.272.246.593.419.963.518Z"
/>
<g
filter="url(#t)"
shapeRendering="crispEdges"
transform="rotate(30 293.749 169.829)"
>
<circle
cx={293.749}
cy={169.829}
r={24}
fill="#F8F8F8"
fillOpacity={0.05}
style={{
mixBlendMode: 'luminosity',
}}
/>
<circle
cx={293.749}
cy={169.829}
r={23.25}
stroke="url(#u)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<path
fill="#F8F8F8"
fillOpacity={0.7}
d="M288.587 172.622a.356.356 0 0 1-.164-.192.356.356 0 0 1 .046-.248l3.92-6.79-2.908.39c-.093.011-.173-.008-.241-.058s-.108-.122-.119-.214l-.084-.582a.374.374 0 0 1 .065-.254.354.354 0 0 1 .226-.111l3.819-.511a.446.446 0 0 1 .2.018c.053.02.108.046.165.079l.618.357a.278.278 0 0 1 .145.197.308.308 0 0 1-.039.236l-4.578 7.929a.352.352 0 0 1-.192.164.299.299 0 0 1-.236-.039l-.643-.371Zm5.613 3.402c-.557-.322-.981-.68-1.271-1.073a2.94 2.94 0 0 1-.514-1.267 3.486 3.486 0 0 1 .076-1.363c.123-.456.305-.912.546-1.366l.375-.705.42-.727c.152-.246.298-.48.437-.701.265-.44.568-.826.91-1.156a3.619 3.619 0 0 1 1.142-.747 2.79 2.79 0 0 1 1.359-.17c.491.047 1.011.228 1.56.546.558.322.976.681 1.253 1.078.29.394.467.815.533 1.262.069.439.044.893-.076 1.363a5.26 5.26 0 0 1-.534 1.373c-.123.231-.256.471-.401.722-.132.247-.272.489-.42.727-.14.243-.277.471-.411.684a5.28 5.28 0 0 1-.922 1.149c-.342.331-.723.58-1.142.747a2.787 2.787 0 0 1-1.354.189c-.478-.05-1-.238-1.566-.565Zm.595-1.03c.631.364 1.215.426 1.752.186.549-.243 1.036-.722 1.46-1.436.151-.225.29-.447.416-.665l.385-.667c.13-.226.251-.453.361-.681.397-.708.564-1.361.5-1.958-.052-.601-.393-1.084-1.024-1.448-.622-.359-1.21-.413-1.765-.162-.542.247-1.024.718-1.446 1.412-.126.218-.258.438-.397.66l-.385.667c-.118.223-.244.451-.38.686-.399.728-.566 1.392-.502 1.989.069.59.411 1.062 1.025 1.417Z"
/>
<g
filter="url(#v)"
shapeRendering="crispEdges"
transform="rotate(45 346.044 209.956)"
>
<circle
cx={346.044}
cy={209.956}
r={24}
fill="#F8F8F8"
fillOpacity={0.05}
style={{
mixBlendMode: 'luminosity',
}}
/>
<circle
cx={346.044}
cy={209.956}
r={23.25}
stroke="url(#w)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<g
filter="url(#x)"
shapeRendering="crispEdges"
transform="rotate(60 386.172 262.25)"
>
<circle
cx={386.172}
cy={262.25}
r={24}
fill="#F8F8F8"
fillOpacity={0.05}
style={{
mixBlendMode: 'luminosity',
}}
/>
<circle
cx={386.172}
cy={262.25}
r={23.25}
stroke="url(#y)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
</g>
<g filter="url(#z)">
<rect
width={136}
height={48}
x={100}
y={248}
fill="#F8F8F8"
fillOpacity={0.05}
rx={8}
shapeRendering="crispEdges"
style={{
mixBlendMode: 'luminosity',
}}
/>
<rect
width={135}
height={47}
x={100.5}
y={248.5}
stroke="url(#A)"
strokeOpacity={0.25}
rx={7.5}
shapeRendering="crispEdges"
/>
<rect
width={44}
height={4}
x={146}
y={270}
fill="#F8F8F8"
fillOpacity={0.95}
rx={1}
/>
</g>
<path
fill="#F8F8F8"
d="M143 21c-1.105 0-2 .759-2 1.695s.895 1.696 2 1.696h17.323a4 4 0 0 1 2.853 1.195l3.056 3.109c.4.407 1.136.407 1.536 0l3.056-3.109a4 4 0 0 1 2.853-1.195H191c1.105 0 2-.76 2-1.696S192.105 21 191 21h-48Z"
opacity={0.2}
/>
</g>
<defs>
<linearGradient
id="c"
x1={335}
x2={-1}
y1={184}
y2={184}
gradientUnits="userSpaceOnUse"
>
<stop stopOpacity={0} />
<stop offset={0.15} />
<stop offset={0.85} />
<stop offset={1} stopOpacity={0} />
</linearGradient>
<linearGradient
id="f"
x1={-51.173}
x2={-30.292}
y1={238.25}
y2={290.96}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="h"
x1={-11.046}
x2={9.835}
y1={185.956}
y2={238.665}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="j"
x1={41.249}
x2={62.13}
y1={145.829}
y2={198.538}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="l"
x1={102.147}
x2={123.028}
y1={120.603}
y2={173.313}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="o"
x1={168}
x2={168}
y1={90}
y2={182}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0} />
<stop offset={1} stopColor="#fff" stopOpacity={0.05} />
</linearGradient>
<linearGradient
id="q"
x1={168}
x2={219.342}
y1={94}
y2={161.888}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="s"
x1={232.851}
x2={253.732}
y1={120.603}
y2={173.313}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="u"
x1={293.749}
x2={314.63}
y1={145.829}
y2={198.538}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="w"
x1={346.045}
x2={366.925}
y1={185.956}
y2={238.666}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="y"
x1={386.172}
x2={407.053}
y1={238.25}
y2={290.96}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="A"
x1={168}
x2={176.363}
y1={248}
y2={307.813}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<filter
id="e"
width={112.008}
height={112.008}
x={-107.177}
y={206.246}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={16} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect1_backgroundBlur_282_13442"
result="shape"
/>
</filter>
<filter
id="g"
width={112}
height={128}
x={-67.046}
y={153.956}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={16} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13442"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="effect1_backgroundBlur_282_13442"
mode="multiply"
result="effect2_dropShadow_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13442"
result="shape"
/>
</filter>
<filter
id="i"
width={112.008}
height={128.008}
x={-14.755}
y={113.824}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={16} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13442"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="effect1_backgroundBlur_282_13442"
mode="multiply"
result="effect2_dropShadow_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13442"
result="shape"
/>
</filter>
<filter
id="k"
width={112.012}
height={128.012}
x={46.141}
y={88.597}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={16} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13442"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="effect1_backgroundBlur_282_13442"
mode="multiply"
result="effect2_dropShadow_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13442"
result="shape"
/>
</filter>
<filter
id="m"
width={252}
height={292}
x={42}
y={-10}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={50} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect1_backgroundBlur_282_13442"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dx={2} dy={4} />
<feGaussianBlur stdDeviation={8} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.06 0" />
<feBlend in2="shape" result="effect2_innerShadow_282_13442" />
</filter>
<filter
id="p"
width={108}
height={164}
x={114}
y={62}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={16} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13442"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="effect1_backgroundBlur_282_13442"
mode="multiply"
result="effect2_dropShadow_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13442"
result="shape"
/>
</filter>
<filter
id="r"
width={112.012}
height={128.012}
x={176.845}
y={88.597}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={16} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13442"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="effect1_backgroundBlur_282_13442"
mode="multiply"
result="effect2_dropShadow_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13442"
result="shape"
/>
</filter>
<filter
id="t"
width={112.008}
height={128.008}
x={237.745}
y={113.824}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={16} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13442"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="effect1_backgroundBlur_282_13442"
mode="multiply"
result="effect2_dropShadow_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13442"
result="shape"
/>
</filter>
<filter
id="v"
width={112}
height={128}
x={290.044}
y={153.956}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={16} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13442"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="effect1_backgroundBlur_282_13442"
mode="multiply"
result="effect2_dropShadow_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13442"
result="shape"
/>
</filter>
<filter
id="x"
width={112.008}
height={112.008}
x={330.168}
y={206.246}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={16} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect1_backgroundBlur_282_13442"
result="shape"
/>
</filter>
<filter
id="z"
width={184}
height={96}
x={76}
y={248}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13442"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13442"
result="shape"
/>
</filter>
<radialGradient
id="a"
cx={0}
cy={0}
r={1}
gradientTransform="rotate(90 0 168) scale(226)"
gradientUnits="userSpaceOnUse"
>
<stop offset={0.344} stopColor="#D9D9D9" />
<stop offset={1} stopColor="#737373" stopOpacity={0} />
</radialGradient>
<clipPath id="n">
<rect width={52} height={92} x={142} y={90} fill="#fff" rx={26} />
</clipPath>
</defs>
</svg>
);

View File

@ -0,0 +1,295 @@
import { FC, SVGProps } from 'react';
export const DistributedTaskExecutionIllustration: FC<
SVGProps<SVGSVGElement>
> = (props) => (
<svg
role="img"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 336 336"
{...props}
>
<mask
id="b"
width={336}
height={336}
x={0}
y={0}
maskUnits="userSpaceOnUse"
style={{
maskType: 'alpha',
}}
>
<path fill="url(#a)" d="M0 0h336v336H0z" />
</mask>
<g mask="url(#b)">
<rect
width={62.5}
height={62.5}
x={0.75}
y={0.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<rect
width={198.5}
height={62.5}
x={68.75}
y={0.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<rect
width={62.5}
height={62.5}
x={272.75}
y={0.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<g filter="url(#c)">
<g clipPath="url(#d)">
<rect
width={62.5}
height={62.5}
x={136.75}
y={136.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.4}
rx={15.25}
/>
<g filter="url(#e)">
<rect
width={52}
height={52}
x={142}
y={142}
fill="#F8F8F8"
fillOpacity={0.01}
rx={10}
/>
<g filter="url(#f)" opacity={0.25}>
<path
fill="#F8F8F8"
fillRule="evenodd"
d="M170 162a2 2 0 1 0-4 0v1a3 3 0 0 1-3 3h-1a2 2 0 1 0 0 4h1a3 3 0 0 1 3 3v1a2 2 0 1 0 4 0v-1a3 3 0 0 1 3-3h1a2 2 0 1 0 0-4h-1a3 3 0 0 1-3-3v-1Z"
clipRule="evenodd"
/>
</g>
</g>
</g>
</g>
<mask
id="g"
width={207}
height={207}
x={12}
y={65}
maskUnits="userSpaceOnUse"
style={{
maskType: 'alpha',
}}
>
<circle cx={115.5} cy={168.5} r={103.5} fill="#D9D9D9" />
</mask>
<g stroke="#F8F8F8" strokeWidth={1.5} mask="url(#g)">
<rect width={130.5} height={62.5} x={-67.25} y={68.75} rx={15.25} />
<rect width={130.5} height={62.5} x={-67.25} y={136.75} rx={15.25} />
<rect width={130.5} height={62.5} x={-67.25} y={204.75} rx={15.25} />
</g>
<mask
id="h"
width={207}
height={207}
x={117}
y={65}
maskUnits="userSpaceOnUse"
style={{
maskType: 'alpha',
}}
>
<circle cx={220.5} cy={168.5} r={103.5} fill="#D9D9D9" />
</mask>
<g stroke="#F8F8F8" strokeWidth={1.5} mask="url(#h)">
<rect width={62.5} height={62.5} x={272.75} y={68.75} rx={15.25} />
<rect width={62.5} height={62.5} x={272.75} y={136.75} rx={15.25} />
<rect width={62.5} height={62.5} x={272.75} y={204.75} rx={15.25} />
</g>
<rect
width={62.5}
height={62.5}
x={0.75}
y={272.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<rect
width={198.5}
height={62.5}
x={68.75}
y={272.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<rect
width={62.5}
height={62.5}
x={272.75}
y={272.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<g opacity={0.25}>
<path
fill="#F8F8F8"
d="M73 99.25a.75.75 0 0 0 0 1.5v-1.5Zm0 1.5h11.505v-1.5H73v1.5Zm25.746 9.796 18.169 47.444 1.401-.536-18.169-47.444-1.401.536Zm33.811 58.204H137v-1.5h-4.443v1.5Zm-15.642-10.76a16.75 16.75 0 0 0 15.642 10.76v-1.5a15.25 15.25 0 0 1-14.241-9.796l-1.401.536Zm-32.41-57.24a15.25 15.25 0 0 1 14.241 9.796l1.401-.536a16.75 16.75 0 0 0-15.642-10.76v1.5Z"
/>
<path
fill="#F8F8F8"
d="M73 238.75a.75.75 0 0 1 0-1.5v1.5Zm26.387-11.171-.703-.262.703.262ZM73 237.25h11.391v1.5H73v-1.5Zm25.684-9.933 18.288-49.157 1.406.523-18.288 49.157-1.406-.523Zm33.987-60.067H137v1.5h-4.329v-1.5Zm-15.699 10.91a16.75 16.75 0 0 1 15.699-10.91v1.5a15.249 15.249 0 0 0-14.293 9.933l-1.406-.523Zm-32.58 59.09a15.25 15.25 0 0 0 14.292-9.933l1.406.523a16.75 16.75 0 0 1-15.699 10.91v-1.5Z"
/>
<path
stroke="#F8F8F8"
strokeLinecap="round"
strokeWidth={1.5}
d="M73 168h44"
/>
</g>
<g opacity={0.25}>
<path
fill="#F8F8F8"
d="M263 99.25a.75.75 0 0 1 0 1.5v-1.5Zm0 1.5h-11.505v-1.5H263v1.5Zm-25.746 9.796-18.169 47.444-1.401-.536 18.169-47.444 1.401.536Zm-33.811 58.204H199v-1.5h4.443v1.5Zm15.642-10.76a16.75 16.75 0 0 1-15.642 10.76v-1.5a15.25 15.25 0 0 0 14.241-9.796l1.401.536Zm32.41-57.24a15.25 15.25 0 0 0-14.241 9.796l-1.401-.536a16.75 16.75 0 0 1 15.642-10.76v1.5Z"
/>
<path
fill="#F8F8F8"
d="M263 238.75a.75.75 0 0 0 0-1.5v1.5Zm-26.387-11.171.703-.262-.703.262ZM263 237.25h-11.391v1.5H263v-1.5Zm-25.684-9.933-18.288-49.157-1.406.523 18.288 49.157 1.406-.523Zm-33.987-60.067H199v1.5h4.329v-1.5Zm15.699 10.91a16.75 16.75 0 0 0-15.699-10.91v1.5a15.249 15.249 0 0 1 14.293 9.933l1.406-.523Zm32.581 59.09a15.249 15.249 0 0 1-14.293-9.933l-1.406.523a16.75 16.75 0 0 0 15.699 10.91v-1.5Z"
/>
<path
stroke="#F8F8F8"
strokeLinecap="round"
strokeWidth={1.5}
d="M263 168h-44"
/>
</g>
</g>
<defs>
<filter
id="c"
width={80}
height={104}
x={128}
y={136}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feMorphology
in="SourceAlpha"
radius={16}
result="effect1_dropShadow_282_13464"
/>
<feOffset dy={32} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13464"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13464"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={4} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect2_innerShadow_282_13464" />
</filter>
<filter
id="e"
width={52}
height={52}
x={142}
y={142}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={4} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect1_innerShadow_282_13464" />
</filter>
<filter
id="f"
width={16}
height={16}
x={160}
y={160}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={4} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect1_innerShadow_282_13464" />
</filter>
<radialGradient
id="a"
cx={0}
cy={0}
r={1}
gradientTransform="rotate(90 0 168) scale(168)"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D9D9D9" />
<stop offset={1} stopColor="#737373" stopOpacity={0} />
</radialGradient>
<clipPath id="d">
<rect width={64} height={64} x={136} y={136} fill="#fff" rx={16} />
</clipPath>
</defs>
</svg>
);

View File

@ -0,0 +1,728 @@
import { FC, SVGProps } from 'react';
export const InferredTasksIllustration: FC<SVGProps<SVGSVGElement>> = (
props
) => (
<svg
role="img"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 336 336"
{...props}
>
<mask
id="b"
width={336}
height={336}
x={0}
y={0}
maskUnits="userSpaceOnUse"
style={{
maskType: 'alpha',
}}
>
<circle cx={168} cy={168} r={168} fill="url(#a)" />
</mask>
<g mask="url(#b)">
<g clipPath="url(#c)">
<rect
width={58.5}
height={58.5}
x={-21.25}
y={10.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={42.75}
y={10.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={106.75}
y={10.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<rect
width={122.5}
height={58.5}
x={170.75}
y={10.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={298.75}
y={10.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={-21.25}
y={74.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={298.75}
y={74.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<rect
width={58.5}
height={122.5}
x={-21.25}
y={138.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={298.75}
y={138.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={298.75}
y={202.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<mask
id="e"
width={193}
height={193}
x={72}
y={72}
maskUnits="userSpaceOnUse"
style={{
maskType: 'alpha',
}}
>
<circle cx={168.5} cy={168.5} r={96.5} fill="url(#d)" />
</mask>
<g mask="url(#e)">
<path
stroke="#F8F8F8"
strokeWidth={1.5}
d="M170.5 104H150c-6.627 0-12 5.373-12 12v80"
/>
<rect
width={58.5}
height={58.5}
x={170.75}
y={202.75}
stroke="#F8F8F8"
strokeWidth={1.5}
rx={15.25}
/>
<rect
width={58.5}
height={122.5}
x={234.75}
y={138.75}
stroke="#F8F8F8"
strokeWidth={1.5}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={170.75}
y={138.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<path
fill="#D9D9D9"
d="M129 198a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v4h-14v-4Z"
/>
</g>
<rect
width={58.5}
height={58.5}
x={-21.25}
y={266.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={42.75}
y={266.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<rect
width={122.5}
height={58.5}
x={106.75}
y={266.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={234.75}
y={266.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.1}
rx={15.25}
/>
<rect
width={58.5}
height={58.5}
x={298.75}
y={266.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.5}
rx={15.25}
/>
<path
stroke="#F8F8F8"
strokeWidth={1.5}
d="M102 104h20c6.627 0 12 5.373 12 12v80"
opacity={0.5}
/>
<g filter="url(#f)" shapeRendering="crispEdges">
<circle cx={102} cy={104} r={6} fill="#F8F8F8" fillOpacity={0.01} />
<circle cx={102} cy={104} r={6} fill="#121212" fillOpacity={0.3} />
<circle
cx={102}
cy={104}
r={5.25}
stroke="url(#g)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<circle cx={102} cy={104} r={3} fill="#F8F8F8" />
<g filter="url(#h)" shapeRendering="crispEdges">
<circle cx={171} cy={104} r={6} fill="#F8F8F8" fillOpacity={0.01} />
<circle cx={171} cy={104} r={6} fill="#121212" fillOpacity={0.3} />
<circle
cx={171}
cy={104}
r={5.25}
stroke="url(#i)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<circle cx={171} cy={104} r={3} fill="#F8F8F8" />
</g>
<g filter="url(#j)" shapeRendering="crispEdges">
<g clipPath="url(#k)" filter="url(#l)">
<rect
width={52}
height={52}
x={110}
y={206}
fill="#F8F8F8"
fillOpacity={0.01}
rx={12}
/>
<rect
width={52}
height={52}
x={110}
y={206}
fill="#121212"
fillOpacity={0.3}
rx={12}
/>
<rect
width={50.5}
height={50.5}
x={110.75}
y={206.75}
stroke="url(#m)"
strokeOpacity={0.25}
strokeWidth={1.5}
rx={11.25}
/>
</g>
<rect
width={58.5}
height={58.5}
x={106.75}
y={202.75}
stroke="#F8F8F8"
strokeOpacity={0.4}
strokeWidth={1.5}
rx={15.25}
/>
</g>
<g filter="url(#n)">
<g clipPath="url(#o)">
<g filter="url(#p)">
<rect
width={60}
height={60}
x={42}
y={74}
fill="#282828"
fillOpacity={0.1}
rx={16}
/>
<rect
width={60}
height={60}
x={42}
y={74}
fill="#121212"
fillOpacity={0.2}
rx={16}
/>
</g>
<rect
width={59}
height={59}
x={42.5}
y={74.5}
stroke="#F8F8F8"
strokeOpacity={0.1}
rx={15.5}
/>
</g>
</g>
<g filter="url(#q)">
<rect
width={60}
height={60}
x={170}
y={74}
fill="#282828"
fillOpacity={0.1}
rx={16}
/>
<rect
width={60}
height={60}
x={170}
y={74}
fill="#121212"
fillOpacity={0.2}
rx={16}
/>
</g>
<rect
width={59}
height={59}
x={170.5}
y={74.5}
stroke="#F8F8F8"
strokeOpacity={0.1}
rx={15.5}
/>
</g>
<defs>
<filter
id="f"
width={28}
height={46.667}
x={88}
y={90}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={4} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13447"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feMorphology
in="SourceAlpha"
radius={10.667}
result="effect2_dropShadow_282_13447"
/>
<feOffset dy={21.333} />
<feGaussianBlur stdDeviation={8} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0" />
<feBlend
in2="effect1_backgroundBlur_282_13447"
mode="multiply"
result="effect2_dropShadow_282_13447"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13447"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={2.667} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect3_innerShadow_282_13447" />
</filter>
<filter
id="h"
width={28}
height={46.667}
x={157}
y={90}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={4} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13447"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feMorphology
in="SourceAlpha"
radius={10.667}
result="effect2_dropShadow_282_13447"
/>
<feOffset dy={21.333} />
<feGaussianBlur stdDeviation={8} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0" />
<feBlend
in2="effect1_backgroundBlur_282_13447"
mode="multiply"
result="effect2_dropShadow_282_13447"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13447"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={2.667} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect3_innerShadow_282_13447" />
</filter>
<filter
id="j"
width={76}
height={100}
x={98}
y={202}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feMorphology
in="SourceAlpha"
radius={16}
result="effect1_dropShadow_282_13447"
/>
<feOffset dy={32} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13447"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13447"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={4} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect2_innerShadow_282_13447" />
</filter>
<filter
id="l"
width={76}
height={104}
x={98}
y={194}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={6} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13447"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feMorphology
in="SourceAlpha"
radius={16}
result="effect2_dropShadow_282_13447"
/>
<feOffset dy={32} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0" />
<feBlend
in2="effect1_backgroundBlur_282_13447"
mode="multiply"
result="effect2_dropShadow_282_13447"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13447"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={4} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect3_innerShadow_282_13447" />
</filter>
<filter
id="n"
width={76}
height={100}
x={34}
y={74}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feMorphology
in="SourceAlpha"
radius={16}
result="effect1_dropShadow_282_13447"
/>
<feOffset dy={32} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13447"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13447"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={4} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect2_innerShadow_282_13447" />
</filter>
<filter
id="p"
width={60}
height={60}
x={42}
y={74}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={4} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect1_innerShadow_282_13447" />
</filter>
<filter
id="q"
width={60}
height={60}
x={170}
y={74}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={4} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect1_innerShadow_282_13447" />
</filter>
<linearGradient
id="g"
x1={102}
x2={107.22}
y1={98}
y2={111.177}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="i"
x1={171}
x2={176.22}
y1={98}
y2={111.177}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="m"
x1={136}
x2={158.621}
y1={206}
y2={263.102}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<clipPath id="c">
<path fill="#fff" d="M0 0h336v336H0z" />
</clipPath>
<clipPath id="k">
<rect width={60} height={60} x={106} y={202} fill="#fff" rx={16} />
</clipPath>
<clipPath id="o">
<rect width={60} height={60} x={42} y={74} fill="#fff" rx={16} />
</clipPath>
<radialGradient
id="a"
cx={0}
cy={0}
r={1}
gradientTransform="rotate(90 0 168) scale(168)"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D9D9D9" />
<stop offset={1} stopColor="#737373" stopOpacity={0} />
</radialGradient>
<radialGradient
id="d"
cx={0}
cy={0}
r={1}
gradientTransform="rotate(90 0 168.5) scale(96.5)"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D9D9D9" />
<stop offset={1} stopColor="#737373" stopOpacity={0} />
</radialGradient>
</defs>
</svg>
);

View File

@ -0,0 +1,856 @@
import { FC, SVGProps } from 'react';
export const RemoteCachingIllustration: FC<SVGProps<SVGSVGElement>> = (
props
) => (
<svg
role="img"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 336 336"
{...props}
>
<g clipPath="url(#a)">
<mask
id="c"
width={336}
height={336}
x={0}
y={0}
maskUnits="userSpaceOnUse"
style={{
maskType: 'alpha',
}}
>
<circle cx={168} cy={168} r={168} fill="url(#b)" />
</mask>
<g mask="url(#c)">
<g clipPath="url(#d)">
<rect
width={58.5}
height={58.5}
x={-21.25}
y={92.75}
stroke="#F8F8F8"
strokeOpacity={0.1}
strokeWidth={1.5}
rx={15.25}
/>
</g>
<g clipPath="url(#e)">
<rect
width={250.5}
height={58.5}
x={42.75}
y={220.75}
stroke="#F8F8F8"
strokeOpacity={0.1}
strokeWidth={1.5}
rx={15.25}
/>
</g>
<g clipPath="url(#f)">
<rect
width={58.5}
height={58.5}
x={42.75}
y={92.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.3}
rx={15.25}
/>
<g filter="url(#g)" opacity={0.05} shapeRendering="crispEdges">
<circle cx={72} cy={122} r={6} fill="url(#h)" />
<circle
cx={72}
cy={122}
r={5.5}
stroke="#F8F8F8"
strokeOpacity={0.1}
/>
</g>
</g>
<g clipPath="url(#i)">
<rect
width={58.5}
height={58.5}
x={106.75}
y={156.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.3}
rx={15.25}
/>
<g filter="url(#j)" opacity={0.05} shapeRendering="crispEdges">
<circle cx={136} cy={186} r={6} fill="url(#k)" />
<circle
cx={136}
cy={186}
r={5.5}
stroke="#F8F8F8"
strokeOpacity={0.1}
/>
</g>
</g>
<g clipPath="url(#l)">
<rect
width={58.5}
height={58.5}
x={170.75}
y={92.75}
stroke="#F8F8F8"
strokeWidth={1.5}
opacity={0.3}
rx={15.25}
/>
<g filter="url(#m)" opacity={0.05} shapeRendering="crispEdges">
<circle cx={200} cy={122} r={6} fill="url(#n)" />
<circle
cx={200}
cy={122}
r={5.5}
stroke="#F8F8F8"
strokeOpacity={0.1}
/>
</g>
</g>
<g clipPath="url(#o)">
<rect
width={122.5}
height={58.5}
x={-21.25}
y={156.75}
stroke="#F8F8F8"
strokeOpacity={0.1}
strokeWidth={1.5}
rx={15.25}
/>
</g>
<g clipPath="url(#p)">
<rect
width={58.5}
height={58.5}
x={170.75}
y={156.75}
stroke="#F8F8F8"
strokeOpacity={0.1}
strokeWidth={1.5}
rx={15.25}
/>
<g filter="url(#q)" opacity={0.05} shapeRendering="crispEdges">
<circle cx={200} cy={186} r={6} fill="url(#r)" />
<circle
cx={200}
cy={186}
r={5.5}
stroke="#F8F8F8"
strokeOpacity={0.1}
/>
</g>
</g>
<g filter="url(#s)">
<g clipPath="url(#t)" filter="url(#u)">
<rect
width={52}
height={52}
x={110}
y={96}
fill="#F8F8F8"
fillOpacity={0.01}
rx={12}
shapeRendering="crispEdges"
/>
<rect
width={52}
height={52}
x={110}
y={96}
fill="#121212"
fillOpacity={0.3}
rx={12}
shapeRendering="crispEdges"
/>
<rect
width={50.5}
height={50.5}
x={110.75}
y={96.75}
stroke="url(#v)"
strokeOpacity={0.25}
strokeWidth={1.5}
rx={11.25}
shapeRendering="crispEdges"
/>
<path
fill="#F8F8F8"
fillRule="evenodd"
d="M136 115.76a1.76 1.76 0 0 0-1.76-1.76h-4.48a1.76 1.76 0 0 0-1.76 1.76v4.538c0 .972.788 1.76 1.76 1.76h4.48c.972 0 1.76.788 1.76 1.76v4.422c0 .972.788 1.76 1.76 1.76h4.48a1.76 1.76 0 0 0 1.76-1.76v-4.538a1.76 1.76 0 0 0-1.76-1.76h-4.48a1.76 1.76 0 0 1-1.76-1.76v-4.422Z"
clipRule="evenodd"
/>
</g>
<rect
width={58.5}
height={58.5}
x={106.75}
y={92.75}
stroke="#F8F8F8"
strokeOpacity={0.4}
strokeWidth={1.5}
rx={15.25}
shapeRendering="crispEdges"
/>
</g>
<g clipPath="url(#w)">
<rect
width={58.5}
height={58.5}
x={298.75}
y={156.75}
stroke="#F8F8F8"
strokeOpacity={0.1}
strokeWidth={1.5}
rx={15.25}
/>
<g filter="url(#x)" opacity={0.05} shapeRendering="crispEdges">
<circle cx={328} cy={186} r={6} fill="url(#y)" />
<circle
cx={328}
cy={186}
r={5.5}
stroke="#F8F8F8"
strokeOpacity={0.1}
/>
</g>
</g>
<g clipPath="url(#z)">
<rect
width={58.5}
height={58.5}
x={-21.25}
y={220.75}
stroke="#F8F8F8"
strokeOpacity={0.1}
strokeWidth={1.5}
rx={15.25}
/>
</g>
<g clipPath="url(#A)">
<rect
width={58.5}
height={58.5}
x={234.75}
y={156.75}
stroke="#F8F8F8"
strokeOpacity={0.1}
strokeWidth={1.5}
rx={15.25}
/>
<g filter="url(#B)" opacity={0.05} shapeRendering="crispEdges">
<circle cx={264} cy={186} r={6} fill="url(#C)" />
<circle
cx={264}
cy={186}
r={5.5}
stroke="#F8F8F8"
strokeOpacity={0.1}
/>
</g>
</g>
<g clipPath="url(#D)">
<rect
width={58.5}
height={58.5}
x={298.75}
y={220.75}
stroke="#F8F8F8"
strokeOpacity={0.1}
strokeWidth={1.5}
rx={15.25}
/>
</g>
<g clipPath="url(#E)">
<rect
width={122.5}
height={58.5}
x={234.75}
y={92.75}
stroke="#F8F8F8"
strokeOpacity={0.1}
strokeWidth={1.5}
rx={15.25}
/>
</g>
<path
stroke="#F8F8F8"
strokeWidth={1.5}
d="M77-81V45.5c0 6.627 5.373 12 12 12h36c6.627 0 12 5.373 12 12V93m0 186.5v29.086c0 6.628 5.373 12 12 12h102c6.627 0 12 5.373 12 12V354"
/>
<g filter="url(#F)" shapeRendering="crispEdges">
<circle cx={137} cy={93} r={6} fill="#F8F8F8" fillOpacity={0.01} />
<circle cx={137} cy={93} r={6} fill="#121212" fillOpacity={0.3} />
<circle
cx={137}
cy={93}
r={5.25}
stroke="url(#G)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<circle cx={137} cy={93} r={3} fill="#F8F8F8" />
<g filter="url(#H)" shapeRendering="crispEdges">
<circle cx={137} cy={279} r={6} fill="#F8F8F8" fillOpacity={0.01} />
<circle cx={137} cy={279} r={6} fill="#121212" fillOpacity={0.3} />
<circle
cx={137}
cy={279}
r={5.25}
stroke="url(#I)"
strokeOpacity={0.25}
strokeWidth={1.5}
/>
</g>
<circle cx={137} cy={279} r={3} fill="#F8F8F8" />
</g>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h336v336H0z" />
</clipPath>
<clipPath id="d">
<path fill="#fff" d="M-22 92h60v60h-60z" />
</clipPath>
<clipPath id="e">
<path fill="#fff" d="M42 220h252v60H42z" />
</clipPath>
<clipPath id="f">
<path fill="#fff" d="M42 92h60v60H42z" />
</clipPath>
<clipPath id="i">
<path fill="#fff" d="M106 156h60v60h-60z" />
</clipPath>
<clipPath id="l">
<path fill="#fff" d="M170 92h60v60h-60z" />
</clipPath>
<clipPath id="o">
<path fill="#fff" d="M-22 156h124v60H-22z" />
</clipPath>
<clipPath id="p">
<path fill="#fff" d="M170 156h60v60h-60z" />
</clipPath>
<clipPath id="t">
<rect width={60} height={60} x={106} y={92} fill="#fff" rx={16} />
</clipPath>
<clipPath id="w">
<path fill="#fff" d="M298 156h60v60h-60z" />
</clipPath>
<clipPath id="z">
<path fill="#fff" d="M-22 220h60v60h-60z" />
</clipPath>
<clipPath id="A">
<path fill="#fff" d="M234 156h60v60h-60z" />
</clipPath>
<clipPath id="D">
<path fill="#fff" d="M298 220h60v60h-60z" />
</clipPath>
<clipPath id="E">
<path fill="#fff" d="M234 92h124v60H234z" />
</clipPath>
<filter
id="g"
width={60}
height={60}
x={42}
y={116}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13448"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13448"
result="shape"
/>
</filter>
<filter
id="j"
width={60}
height={60}
x={106}
y={180}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13448"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13448"
result="shape"
/>
</filter>
<filter
id="m"
width={60}
height={60}
x={170}
y={116}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13448"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13448"
result="shape"
/>
</filter>
<filter
id="q"
width={60}
height={60}
x={170}
y={180}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13448"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13448"
result="shape"
/>
</filter>
<filter
id="s"
width={76}
height={100}
x={98}
y={92}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feMorphology
in="SourceAlpha"
radius={16}
result="effect1_dropShadow_282_13448"
/>
<feOffset dy={32} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13448"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13448"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={4} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect2_innerShadow_282_13448" />
</filter>
<filter
id="u"
width={76}
height={104}
x={98}
y={84}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={6} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13448"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feMorphology
in="SourceAlpha"
radius={16}
result="effect2_dropShadow_282_13448"
/>
<feOffset dy={32} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0" />
<feBlend
in2="effect1_backgroundBlur_282_13448"
mode="multiply"
result="effect2_dropShadow_282_13448"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13448"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={4} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect3_innerShadow_282_13448" />
</filter>
<filter
id="x"
width={60}
height={60}
x={298}
y={180}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13448"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13448"
result="shape"
/>
</filter>
<filter
id="B"
width={60}
height={60}
x={234}
y={180}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset dy={24} />
<feGaussianBlur stdDeviation={12} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0" />
<feBlend
in2="BackgroundImageFix"
mode="multiply"
result="effect1_dropShadow_282_13448"
/>
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow_282_13448"
result="shape"
/>
</filter>
<filter
id="F"
width={28}
height={46.667}
x={123}
y={79}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={4} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13448"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feMorphology
in="SourceAlpha"
radius={10.667}
result="effect2_dropShadow_282_13448"
/>
<feOffset dy={21.333} />
<feGaussianBlur stdDeviation={8} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0" />
<feBlend
in2="effect1_backgroundBlur_282_13448"
mode="multiply"
result="effect2_dropShadow_282_13448"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13448"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={2.667} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect3_innerShadow_282_13448" />
</filter>
<filter
id="H"
width={28}
height={46.667}
x={123}
y={265}
colorInterpolationFilters="sRGB"
filterUnits="userSpaceOnUse"
>
<feFlood floodOpacity={0} result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation={4} />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_282_13448"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feMorphology
in="SourceAlpha"
radius={10.667}
result="effect2_dropShadow_282_13448"
/>
<feOffset dy={21.333} />
<feGaussianBlur stdDeviation={8} />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0" />
<feBlend
in2="effect1_backgroundBlur_282_13448"
mode="multiply"
result="effect2_dropShadow_282_13448"
/>
<feBlend
in="SourceGraphic"
in2="effect2_dropShadow_282_13448"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
result="hardAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
/>
<feOffset />
<feGaussianBlur stdDeviation={2.667} />
<feComposite in2="hardAlpha" k2={-1} k3={1} operator="arithmetic" />
<feColorMatrix values="0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0 0.972549 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect3_innerShadow_282_13448" />
</filter>
<linearGradient
id="h"
x1={72}
x2={72}
y1={116}
y2={128}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F8F8F8" stopOpacity={0.9} />
<stop offset={1} stopColor="#F8F8F8" stopOpacity={0.3} />
</linearGradient>
<linearGradient
id="k"
x1={136}
x2={136}
y1={180}
y2={192}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F8F8F8" stopOpacity={0.9} />
<stop offset={1} stopColor="#F8F8F8" stopOpacity={0.3} />
</linearGradient>
<linearGradient
id="n"
x1={200}
x2={200}
y1={116}
y2={128}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F8F8F8" stopOpacity={0.9} />
<stop offset={1} stopColor="#F8F8F8" stopOpacity={0.3} />
</linearGradient>
<linearGradient
id="r"
x1={200}
x2={200}
y1={180}
y2={192}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F8F8F8" stopOpacity={0.9} />
<stop offset={1} stopColor="#F8F8F8" stopOpacity={0.3} />
</linearGradient>
<linearGradient
id="v"
x1={136}
x2={158.621}
y1={96}
y2={153.102}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="y"
x1={328}
x2={328}
y1={180}
y2={192}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F8F8F8" stopOpacity={0.9} />
<stop offset={1} stopColor="#F8F8F8" stopOpacity={0.3} />
</linearGradient>
<linearGradient
id="C"
x1={264}
x2={264}
y1={180}
y2={192}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F8F8F8" stopOpacity={0.9} />
<stop offset={1} stopColor="#F8F8F8" stopOpacity={0.3} />
</linearGradient>
<linearGradient
id="G"
x1={137}
x2={142.22}
y1={87}
y2={100.177}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<linearGradient
id="I"
x1={137}
x2={142.22}
y1={273}
y2={286.177}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#fff" stopOpacity={0.4} />
<stop offset={0.4} stopColor="#fff" stopOpacity={0.01} />
<stop offset={0.6} stopColor="#fff" stopOpacity={0.01} />
<stop offset={1} stopColor="#fff" stopOpacity={0.1} />
</linearGradient>
<radialGradient
id="b"
cx={0}
cy={0}
r={1}
gradientTransform="rotate(90 0 168) scale(168)"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D9D9D9" />
<stop offset={1} stopColor="#737373" stopOpacity={0} />
</radialGradient>
</defs>
</svg>
);

Some files were not shown because too many files have changed in this diff Show More