nx/nx-dev/ui-common/src/lib/npx-create-nx-workspace.tsx
2022-02-04 15:38:06 -05:00

698 lines
24 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { AnimateSharedLayout, motion, useAnimation } from 'framer-motion';
import { useState } from 'react';
const typing = (line: string, delay: number = 0): any[] =>
Array.from(line).map((char, index) => (
<motion.span
key={[char, index].join('-')}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{
delay: index * 0.04 + delay,
ease: 'linear',
duration: 0.1,
}}
>
{char}
</motion.span>
));
export function NpxCreateNxWorkspaceAnimation({
restartFunction,
}: {
restartFunction: () => void;
}) {
const npxCreateNxWorkspace = useAnimation();
const wrapper = useAnimation();
const firstLoading = useAnimation();
const frameworkSelectionTitle = useAnimation();
const frameworkSelectionAnswerSection = useAnimation();
const frameworkSelectionAnswerSectionArrow = useAnimation();
const frameworkSelectionAnswerSectionPreviousHighlight = useAnimation();
const frameworkSelectionAnswerSectionNextHighlight = useAnimation();
const frameworkSelectionAnswerValidation = useAnimation();
const applicationName = useAnimation();
const stylesheetSelectionTitle = useAnimation();
const stylesheetSelectionAnswerSection = useAnimation();
const stylesheetSelectionAnswerSectionArrow = useAnimation();
const stylesheetSelectionAnswerSectionPreviousHighlight = useAnimation();
const stylesheetSelectionAnswerSectionNextHighlight = useAnimation();
const stylesheetSelectionAnswerValidation = useAnimation();
const nxCloudSelectionTitle = useAnimation();
const nxCloudSelectionAnswerSection = useAnimation();
const nxCloudSelectionAnswerSectionArrow = useAnimation();
const nxCloudSelectionAnswerSectionPreviousHighlight = useAnimation();
const nxCloudSelectionAnswerSectionNextHighlight = useAnimation();
const nxCloudSelectionAnswerValidation = useAnimation();
const creatingNxWorkspace = useAnimation();
const creatingNxWorkspace2 = useAnimation();
const secondLoading = useAnimation();
const workpaceReady = useAnimation();
const restartButton = useAnimation();
const sequence = async () => {
await npxCreateNxWorkspace.start({
opacity: 1,
transition: {
ease: 'easeOut',
duration: 0.12,
},
});
await firstLoading.start({
width: '100%',
transition: { delay: 2.4, ease: 'easeOut', duration: 0.24 },
});
await frameworkSelectionSequence();
await applicationName.start({
opacity: 1,
transition: {
ease: 'easeOut',
duration: 0.2,
},
});
await stylesheetSelectionSequence(1.8);
await nxCloudSelectionSequence();
await creatingNxWorkspace.start({
opacity: 1,
transition: {
ease: 'easeOut',
duration: 0.2,
},
});
await creatingNxWorkspace2.start({
opacity: 1,
transition: {
ease: 'easeOut',
duration: 0.2,
},
});
await secondLoading.start({
width: '100%',
transition: { ease: 'easeOut', duration: 0.24 },
});
workpaceReady.start({
opacity: 1,
transition: { ease: 'easeOut', duration: 0.24 },
});
await wrapper.start({
y: -32,
transition: { ease: 'easeOut', duration: 0.24 },
});
return await restartButton.start({
y: 0,
transition: { ease: 'easeOut', duration: 0.24 },
});
};
const frameworkSelectionSequence = async (delay: number = 0) => {
await frameworkSelectionTitle.start({
opacity: 1,
transition: {
ease: 'easeOut',
delay,
duration: 0.2,
},
});
await frameworkSelectionAnswerSection.start({
opacity: 1,
transition: {
ease: 'easeOut',
duration: 0.12,
},
});
await frameworkSelectionAnswerSectionArrow.start({
y: 54,
transition: { ease: 'easeOut', duration: 0.24 },
});
await frameworkSelectionAnswerSectionPreviousHighlight.start({
color: '#E5E7EB',
transition: { ease: 'easeOut', duration: 0.12 },
});
await frameworkSelectionAnswerSectionNextHighlight.start({
color: '#34D399',
transition: { ease: 'easeOut', duration: 0.12 },
});
await frameworkSelectionAnswerSection.start({
opacity: 0,
transition: {
delay: 2,
ease: 'easeOut',
duration: 0.12,
},
transitionEnd: {
display: 'none',
},
});
return frameworkSelectionAnswerValidation.start({
opacity: 1,
transition: { ease: 'easeOut', duration: 0.24 },
});
};
const stylesheetSelectionSequence = async (delay: number = 0) => {
await stylesheetSelectionTitle.start({
opacity: 1,
transition: {
delay,
ease: 'easeOut',
duration: 0.2,
},
});
await stylesheetSelectionAnswerSection.start({
opacity: 1,
transition: {
ease: 'easeOut',
duration: 0.12,
},
});
await stylesheetSelectionAnswerSectionArrow.start({
y: 72,
transition: { ease: 'easeOut', duration: 0.42 },
});
await stylesheetSelectionAnswerSectionPreviousHighlight.start({
color: '#E5E7EB',
transition: { ease: 'easeOut', duration: 0.12 },
});
await stylesheetSelectionAnswerSectionNextHighlight.start({
color: '#34D399',
transition: { ease: 'easeOut', duration: 0.12 },
});
await stylesheetSelectionAnswerSection.start({
opacity: 0,
transition: {
delay: 2,
ease: 'easeOut',
duration: 0.12,
},
transitionEnd: {
display: 'none',
},
});
return stylesheetSelectionAnswerValidation.start({
opacity: 1,
transition: { ease: 'easeOut', duration: 0.24 },
});
};
const nxCloudSelectionSequence = async (delay: number = 0) => {
await nxCloudSelectionTitle.start({
opacity: 1,
transition: {
delay,
ease: 'easeOut',
duration: 0.2,
},
});
await nxCloudSelectionAnswerSection.start({
opacity: 1,
transition: {
ease: 'easeOut',
duration: 0.12,
},
});
await nxCloudSelectionAnswerSectionArrow.start({
y: 0,
transition: { ease: 'easeOut', duration: 0.24 },
});
await nxCloudSelectionAnswerSectionPreviousHighlight.start({
color: '#E5E7EB',
transition: { ease: 'easeOut', duration: 0.12 },
});
await nxCloudSelectionAnswerSectionNextHighlight.start({
color: '#34D399',
transition: { ease: 'easeOut', duration: 0.12 },
});
await nxCloudSelectionAnswerSection.start({
opacity: 0,
transition: {
delay: 2,
ease: 'easeOut',
duration: 0.12,
},
transitionEnd: {
display: 'none',
},
});
return nxCloudSelectionAnswerValidation.start({
opacity: 1,
transition: { ease: 'easeOut', duration: 0.24 },
});
};
sequence();
return (
<>
<div
key={'npx-create-nx-workspace-animation'}
className="relative h-96 max-w-full overflow-hidden rounded-lg bg-gray-800
pt-4 pb-6 pt-4 font-mono text-xs leading-normal text-gray-200 subpixel-antialiased shadow-lg"
>
<div className="top mb-2 flex px-5">
<div className="h-3 w-3 rounded-full bg-red-500" />
<div className="ml-2 h-3 w-3 rounded-full bg-yellow-300" />
<div className="ml-2 h-3 w-3 rounded-full bg-green-500" />
</div>
<div className="overflow-y-hidden px-5">
<motion.div initial={{ y: 0 }} animate={wrapper}>
<div className="mt-4 flex">
<span className="text-green-nx-base mr-2">/workspace </span>
<motion.p
initial={{ opacity: 0 }}
animate={npxCreateNxWorkspace}
className="typing flex-1 items-center"
>
{typing('npx create-nx-workspace ludicrous-narwhals').map(
(x) => x
)}
</motion.p>
</div>
<div className="mt-2 flex flex-col">
<AnimateSharedLayout>
{/*LOADING*/}
<motion.div
className="bg-green-nx-base inline-block items-center"
initial={{ width: '0%', height: '12px' }}
animate={firstLoading}
/>
{/*FRAMEWORK SELECTION*/}
<motion.div
className="mt-2 flex-1 items-center"
initial={{ opacity: 0 }}
animate={frameworkSelectionTitle}
>
What to create in the new workspace{' '}
<motion.span
className="text-green-nx-base"
initial={{ opacity: 0 }}
animate={frameworkSelectionAnswerValidation}
>
react [a workspace with a single React application]
</motion.span>
</motion.div>
<motion.div
className="relative mt-2"
initial={{ opacity: 0 }}
animate={frameworkSelectionAnswerSection}
>
{/*SELECTION ARROW*/}
<motion.div
className="text-green-nx-base absolute -left-4 top-0"
initial={{ y: 0 }}
animate={frameworkSelectionAnswerSectionArrow}
>
</motion.div>
<motion.span
initial={{ color: '#34D399' }}
animate={frameworkSelectionAnswerSectionPreviousHighlight}
>
apps{' '}
<span className="text-[9px]">
[an empty workspace with no plugins with a layout that
works best for building apps]
</span>
</motion.span>
<br />
core{' '}
<span className="text-[9px]">
[an empty workspace with no plugins set up to publish npm
packages (similar to yarn workspaces)]
</span>
<br />
ts{' '}
<span className="text-[9px]">
[an empty workspace with the JS/TS plugin preinstalled]
</span>
<br />
<motion.span
initial={{ color: '#E5E7EB' }}
animate={frameworkSelectionAnswerSectionNextHighlight}
>
react{' '}
<span className="text-[9px]">
[a workspace with a single React application]
</span>
</motion.span>
<br />
angular{' '}
<span className="text-[9px]">
[a workspace with a single Angular application]
</span>
<br />
next.js{' '}
<span className="text-[9px]">
[a workspace with a single Next.js application]
</span>
<br />
gatsby{' '}
<span className="text-[9px]">
[a workspace with a single Gatsby application]
</span>
<br />
nest{' '}
<span className="text-[9px]">
[a workspace with a single Nest application]
</span>
<br />
express{' '}
<span className="text-[9px]">
[a workspace with a single Express application]
</span>
<br />
web components{' '}
<span className="text-[9px]">
[a workspace with a single app built using web components]
</span>
<br />
react-native{' '}
<span className="text-[9px]">
[a workspace with a single React Native application]
</span>
<br />
react-express{' '}
<span className="text-[9px]">
[a workspace with a full stack application (React +
Express)]
</span>
<br />
angular-nest{' '}
<span className="text-[9px]">
[a workspace with a full stack application (Angular + Nest)]
</span>
<br />
<span className="text-gray-500">(Use arrow keys)</span>
</motion.div>
{/*APPLICATION NAME*/}
<motion.div
className="flex-1 items-center"
initial={{ opacity: 0 }}
animate={applicationName}
>
Application name{' '}
<span className="text-green-nx-base">
{typing('tuxboard', 7).map((x) => x)}
</span>
</motion.div>
{/*STYLESHEET FORMAT*/}
<motion.div
className="flex-1 items-center"
initial={{ opacity: 0 }}
animate={stylesheetSelectionTitle}
>
Default stylesheet format{' '}
<motion.span
className="text-green-nx-base"
initial={{ opacity: 0 }}
animate={stylesheetSelectionAnswerValidation}
>
styled-components [
<a
href="https://styled-components.com"
target="_blank"
rel="nofollow"
className="cursor-pointer opacity-50 hover:underline hover:opacity-100"
>
https://styled-components.com
</a>
]
</motion.span>
</motion.div>
<motion.div
className="relative mt-2"
initial={{ opacity: 0 }}
animate={stylesheetSelectionAnswerSection}
>
{/*SELECTION ARROW*/}
<motion.div
className="text-green-nx-base absolute -left-4 top-0"
initial={{ y: 0 }}
animate={stylesheetSelectionAnswerSectionArrow}
>
</motion.div>
<motion.span
initial={{ color: '#34D399' }}
animate={stylesheetSelectionAnswerSectionPreviousHighlight}
>
CSS
</motion.span>
<br />
SASS(.scss) [
<a
href="https://sass-lang.com"
target="_blank"
rel="nofollow"
className="cursor-pointer opacity-50 hover:underline hover:opacity-100"
>
https://sass-lang.com
</a>
] <br />
Stylus(.styl)[
<a
href="https://stylus-lang.com"
target="_blank"
rel="nofollow"
className="cursor-pointer opacity-50 hover:underline hover:opacity-100"
>
https://stylus-lang.com
</a>
] <br />
LESS [
<a
href="https://lesscss.org"
target="_blank"
rel="nofollow"
className="cursor-pointer opacity-50 hover:underline hover:opacity-100"
>
https://lesscss.org
</a>
] <br />
<motion.span
initial={{ color: '#E5E7EB' }}
animate={stylesheetSelectionAnswerSectionNextHighlight}
>
styled-components [
<a
href="https://styled-components.com"
target="_blank"
rel="nofollow"
className="cursor-pointer opacity-50 hover:underline hover:opacity-100"
>
https://styled-components.com
</a>
]
</motion.span>
<br />
emotion [
<a
href="https://emotion.sh"
target="_blank"
rel="nofollow"
className="cursor-pointer opacity-50 hover:underline hover:opacity-100"
>
https://emotion.sh
</a>
] <br />
styled-jsx [
<a
href="https://www.npmjs.com/package/styled-jsx"
target="_blank"
rel="nofollow"
className="cursor-pointer opacity-50 hover:underline hover:opacity-100"
>
https://www.npmjs.com/package/styled-jsx
</a>
] <br />
<span className="text-gray-500">(Use arrow keys)</span>
</motion.div>
{/*NX CLOUD*/}
<motion.div
layout
className="flex-1 items-center"
initial={{ opacity: 0 }}
animate={nxCloudSelectionTitle}
>
Use Nx Cloud? (It's free and doesn't require registration.){' '}
<motion.span
className="text-green-nx-base"
initial={{ opacity: 0 }}
animate={nxCloudSelectionAnswerValidation}
>
Yes
</motion.span>
</motion.div>
<motion.div
className="relative mt-2"
initial={{ opacity: 0 }}
animate={nxCloudSelectionAnswerSection}
>
{/*SELECTION ARROW*/}
<motion.div
className="text-green-nx-base absolute -left-4 top-0"
initial={{ y: 18 }}
animate={nxCloudSelectionAnswerSectionArrow}
>
</motion.div>
<motion.span
initial={{ color: '#E5E7EB' }}
animate={nxCloudSelectionAnswerSectionNextHighlight}
>
Yes
</motion.span>
<br />
<motion.span
initial={{ color: '#34D399' }}
animate={nxCloudSelectionAnswerSectionPreviousHighlight}
>
No
</motion.span>
<br />
<span className="text-gray-500">(Use arrow keys)</span>
</motion.div>
{/*CREATING NX WORKSPACE*/}
<motion.div
layout
className="mt-2"
initial={{ opacity: 0 }}
animate={creatingNxWorkspace}
>
<span className="bg-green-nx-base px-1 py-0.5">NX</span> Nx is
creating your workspace. To make sure the command works
reliably in all environments, and that the preset is applied
correctly, Nx will run "yarn install" several times. Please
wait.
</motion.div>
<motion.div
layout
className="mt-2"
initial={{ opacity: 0 }}
animate={creatingNxWorkspace2}
>
Creating your workspace
</motion.div>
{/*LOADING*/}
<motion.div
layout
className="bg-green-nx-base mt-2 items-center"
initial={{ width: '0%', height: '12px' }}
animate={secondLoading}
/>
{/*NX WORKSPACE CREATED*/}
<motion.div
layout
className="mt-2"
initial={{ opacity: 0 }}
animate={workpaceReady}
>
<div>
<span className="bg-green-nx-base px-1 py-0.5">
NX SUCCESS
</span>{' '}
Nx has successfully created the workspace.
</div>
<div className="my-3 h-px w-full bg-gray-100" />
<div>
<span className="bg-green-nx-base px-1 py-0.5">NX</span>
<span className="ml-1 bg-yellow-500 px-1 py-0.5">
NOTE
</span>{' '}
First time using Nx? Check out this interactive Nx tutorial.
<br />
<a
href="https://nx.dev/react/tutorial/01-create-application"
target="_blank"
rel="nofollow"
className="cursor-pointer opacity-50 hover:underline hover:opacity-100"
>
https://nx.dev/react/tutorial/01-create-application
</a>
<br />
Prefer watching videos? Check out this free Nx course on
Egghead.io.
<br />
<a
href="https://egghead.io/playlists/scale-react-development-with-nx-4038"
target="_blank"
rel="nofollow"
className="cursor-pointer opacity-50 hover:underline hover:opacity-100"
>
https://egghead.io/playlists/scale-react-development-with-nx-4038
</a>
</div>
</motion.div>
</AnimateSharedLayout>
</div>
</motion.div>
</div>
<motion.div
className="absolute top-2 right-4"
initial={{ y: -100 }}
animate={restartButton}
>
<button
type="button"
onClick={() => restartFunction() && sequence()}
className="text-green-nx-base w-full flex-none rounded-md border border-gray-700 bg-gray-800 py-1 px-3 text-xs font-normal transition hover:bg-gray-700 sm:w-auto"
>
<svg
className="r-2 inline-flex h-5 w-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>{' '}
Play again
</button>
</motion.div>
</div>
</>
);
}
export function NpxCreateNxWorkspace() {
const [isDisplayed, setIsDisplayed] = useState(true);
const restart = () => {
setIsDisplayed(false);
setTimeout(() => {
setIsDisplayed(true);
});
};
return (
<>
{isDisplayed ? (
<NpxCreateNxWorkspaceAnimation restartFunction={restart} />
) : (
<div
key={'npx-create-nx-workspace-animation'}
className="relative h-96 w-full overflow-hidden rounded-lg bg-gray-800
pt-4 pb-6 pt-4 font-mono text-xs leading-normal text-gray-200 subpixel-antialiased shadow-lg"
>
<div className="top mb-2 flex px-5">
<div className="h-3 w-3 rounded-full bg-red-500" />
<div className="ml-2 h-3 w-3 rounded-full bg-yellow-300" />
<div className="ml-2 h-3 w-3 rounded-full bg-green-500" />
</div>
<div className="overflow-y-hidden px-5" />
</div>
)}
</>
);
}
export default NpxCreateNxWorkspace;