diff --git a/components/elements/CodeBlock.tsx b/components/elements/CodeBlock.tsx index c438befc..b957118e 100644 --- a/components/elements/CodeBlock.tsx +++ b/components/elements/CodeBlock.tsx @@ -24,18 +24,20 @@ function cargo(Prism: any) { SyntaxHighlighter.registerLanguage('cargo', cargo) interface Props { + readonly id?: string readonly language: string readonly code: string readonly showLineNumbers?: boolean readonly className?: string readonly copyBtn?: boolean + readonly style?: React.CSSProperties } -export default function CodeBlock({ code, language, showLineNumbers, className, copyBtn }: Props) { +export default function CodeBlock({ id, code, language, showLineNumbers, className, copyBtn, style }: Props) { useWindowSize() return ( -
+
{copyBtn && } diff --git a/components/sections/Home/LaunchSystem/LaunchSystemStep1.tsx b/components/sections/Home/LaunchSystem/LaunchSystemStep1.tsx index 9e6053bb..5a39a10b 100644 --- a/components/sections/Home/LaunchSystem/LaunchSystemStep1.tsx +++ b/components/sections/Home/LaunchSystem/LaunchSystemStep1.tsx @@ -2,7 +2,7 @@ import Xarrow from 'react-xarrows' import Step1Top from '../Step1Top' import Step1Left from '../Step1Left' import Step1Right from '../Step1Right' -import Step1Bottom from '../Step1Bottom' +import Step1Bottom from './Step1Bottom' import RocketColor1 from '../RocketColor1' export default function LaunchSystemStep1() { @@ -61,7 +61,7 @@ export default function LaunchSystemStep1() {
- +
diff --git a/components/sections/Home/LaunchSystem/LaunchSystemStep2.tsx b/components/sections/Home/LaunchSystem/LaunchSystemStep2.tsx index ac9c46d9..8ab10086 100644 --- a/components/sections/Home/LaunchSystem/LaunchSystemStep2.tsx +++ b/components/sections/Home/LaunchSystem/LaunchSystemStep2.tsx @@ -3,7 +3,7 @@ import RocketColor2 from '../RocketColor2' import Step2Top from '../Step2Top' import Step2Left from '../Step2Left' import Step2Right from '../Step2Right' -import Step2Bottom from '../Step2Bottom' +import Step2Bottom from './Step2Bottom' export default function LaunchSystemStep2() { return ( diff --git a/components/sections/Home/LaunchSystem/Step1Bottom.tsx b/components/sections/Home/LaunchSystem/Step1Bottom.tsx new file mode 100644 index 00000000..5c3ccbfa --- /dev/null +++ b/components/sections/Home/LaunchSystem/Step1Bottom.tsx @@ -0,0 +1,165 @@ +import { Splide, SplideSlide, SplideTrack } from '@splidejs/react-splide' +import clsx from 'clsx' +import { CodeBlock } from 'components/elements' +import { trackEvent } from 'lib/posthog' +import { FC, useState } from 'react' + +type SelectedItem = 'hello-world' | 'using-db' | 'using-secrets' + +interface Step2BottomProps { + id?: string + className?: string + style?: React.CSSProperties +} + +const Step2Bottom: FC = ({ id, className, style }) => { + const [selectedItem, setSelectedItem] = useState('hello-world') + + return ( +
+
+ + + + + + + + + + + + + +
+ +
+
+
+ ) +} + +export default Step2Bottom + +const HELLO_WORLD = ` +use rocket::{get, routes}; + +#[get("/")] +fn index() -> &'static str { + "Hello, world!" +} + +#[shuttle_runtime::main] +async fn main() -> shuttle_rocket::ShuttleRocket { + let rocket = rocket::build().mount("/", routes![index]); + + Ok(rocket.into()) +} +`.trim() + +const USING_DB = ` +use axum::{routing::get, Router}; + +async fn hello_world() -> &'static str { + "Hello, world!" +} + +#[shuttle_runtime::main] +async fn main() -> shuttle_axum::ShuttleAxum { + let router = Router::new().route("/", get(hello_world)); + + Ok(router.into()) +} + +`.trim() + +const USING_SECRETS = ` +use actix_web::{get, web::ServiceConfig}; +use shuttle_actix_web::ShuttleActixWeb; + +#[get("/")] +async fn hello_world() -> &'static str { + "Hello World!" +} + +#[shuttle_runtime::main] +async fn main() -> ShuttleActixWeb { + let config = move |cfg: &mut ServiceConfig| { + cfg.service(hello_world); + }; + + Ok(config.into()) +} +`.trim() diff --git a/components/sections/Home/LaunchSystem/Step2Bottom.tsx b/components/sections/Home/LaunchSystem/Step2Bottom.tsx new file mode 100644 index 00000000..c41fc943 --- /dev/null +++ b/components/sections/Home/LaunchSystem/Step2Bottom.tsx @@ -0,0 +1,179 @@ +import { Splide, SplideSlide, SplideTrack } from '@splidejs/react-splide' +import clsx from 'clsx' +import { CodeBlock } from 'components/elements' +import { trackEvent } from 'lib/posthog' +import { FC, useState } from 'react' + +type SelectedItem = 'hello-world' | 'using-db' | 'using-secrets' + +interface Step2BottomProps { + id?: string + className?: string + style?: React.CSSProperties +} + +const Step2Bottom: FC = ({ id, className, style }) => { + const [selectedItem, setSelectedItem] = useState('hello-world') + + return ( +
+
+ + + + + + + + + + + + + +
+ +
+
+
+ ) +} + +export default Step2Bottom + +const HELLO_WORLD = ` +use axum::{routing::get, Router}; + +async fn hello_world() -> &'static str { + "Hello, world!" +} + +#[shuttle_runtime::main] +async fn main() -> shuttle_axum::ShuttleAxum { + let router = Router::new().route("/", get(hello_world)); + + Ok(router.into()) +} +`.trim() + +const USING_DB = ` +use sqlx::PgPool; +mod router; +mod routes; + + +#[shuttle_runtime::main] +async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_axum::ShuttleAxum { + sqlx::migrate!() + .run(&pool) + .await + .expect("Failed to run migrations"); + + let router = router::init_router(pool); + + Ok(router.into()) +} +`.trim() + +const USING_SECRETS = ` +use axum::{extract::State, routing::get, Router}; +use qdrant_client::Qdrant; +use std::sync::Arc; + +struct AppState { + qdrant: Qdrant, +} + +async fn list_collections(State(state): State>) -> String { + format!("{:?}\n", state.qdrant.list_collections().await) +} + +#[shuttle_runtime::main] +async fn main( + #[shuttle_qdrant::Qdrant(cloud_url = "{secrets.CLOUD_URL}", api_key = "{secrets.API_KEY}")] + qdrant: Qdrant, +) -> shuttle_axum::ShuttleAxum { + let state = Arc::new(AppState { qdrant }); + + let router = Router::new() + .route("/", get(list_collections)) + .with_state(state); + + Ok(router.into()) +} +`.trim() diff --git a/components/sections/Home/LaunchSystem/index.tsx b/components/sections/Home/LaunchSystem/index.tsx index 0a9ebadc..5d4bae11 100644 --- a/components/sections/Home/LaunchSystem/index.tsx +++ b/components/sections/Home/LaunchSystem/index.tsx @@ -1,16 +1,16 @@ 'use client' -import { motion, useMotionValueEvent, useScroll } from 'framer-motion' +import { distance, motion, useMotionValueEvent, useScroll, useVelocity } from 'framer-motion' import LaunchSystemStep1 from './LaunchSystemStep1' import LaunchSystemStep2 from './LaunchSystemStep2' import LaunchSystemStep3 from './LaunchSystemStep3' import LaunchSystemStep4 from './LaunchSystemStep4' -import { useRef, useState } from 'react' +import { use, useRef, useState } from 'react' import Step1Top from '../Step1Top' import Step1Left from '../Step1Left' import Step1Right from '../Step1Right' -import Step1Bottom from '../Step1Bottom' +import Step1Bottom from './Step1Bottom' import RocketColor1 from '../RocketColor1' import RocketColor2 from '../RocketColor2' import RocketColor3 from '../RocketColor3' @@ -21,7 +21,7 @@ import Step2Left from '../Step2Left' import Step3Left from '../Step3Left' import Step2Right from '../Step2Right' import Step3Right from '../Step3Right' -import Step2Bottom from '../Step2Bottom' +import Step2Bottom from './Step2Bottom' export default function LaunchSystem() { const css = ` @@ -35,8 +35,88 @@ export default function LaunchSystem() { const ref = useRef(null) const { scrollYProgress } = useScroll({ target: ref }) const [scrollPosition, setScrollPosition] = useState(0) + const [scrollVelocity, setScrollVelocity] = useState(0) + const [scrollingToNext, setScrollingToNext] = useState(false) - useMotionValueEvent(scrollYProgress, 'change', setScrollPosition) + useMotionValueEvent(scrollYProgress, 'change', (position) => { + let distanceToNextCheckpoint = 0 + let distanceToPrevCheckpoint = 0 + + if (scrollPosition < 0.37) { + distanceToNextCheckpoint = 0.37 - scrollPosition + } else if (scrollPosition < 0.6) { + distanceToNextCheckpoint = 0.6 - scrollPosition + } else if (scrollPosition < 1) { + distanceToNextCheckpoint = 1 - scrollPosition + } + + if (scrollPosition >= 0.99) { + distanceToPrevCheckpoint = scrollPosition - 0.6 + } else if (scrollPosition >= 0.59) { + distanceToPrevCheckpoint = scrollPosition - 0.37 + } else if (scrollPosition >= 0.36) { + distanceToPrevCheckpoint = scrollPosition + } + const prevCheckpoint = scrollPosition - distanceToPrevCheckpoint + const nextCheckpoint = scrollPosition + distanceToNextCheckpoint + + if (scrollVelocity > 0.25 && position >= 0.01 && scrollPosition <= 1.01 && !scrollingToNext) { + if (scrollPosition >= 1) { + // Scroll to the very end of the section + + setScrollingToNext(false) + + // @ts-ignore + const endOfSection = ref.current.scrollHeight + window.scrollTo({ top: endOfSection, behavior: 'smooth' }) + return + } + + const interval = setInterval(() => { + setScrollingToNext(true) + setScrollPosition((prev) => { + if (prev > nextCheckpoint) { + clearInterval(interval) + setScrollingToNext(false) + return nextCheckpoint + } + return prev + 0.02 + }) + }, 50) + } + + // Same for opposite + else if (scrollVelocity < -0.25 && position >= 0.01 && scrollPosition <= 1.01 && !scrollingToNext) { + if (scrollPosition <= 0.02) { + // Scroll to the very end of the section + + setScrollingToNext(false) + + // @ts-ignore + const startOfSection = ref.current.getBoundingClientRect().top + window.scrollTo({ top: startOfSection, behavior: 'smooth' }) + return + } + + const interval = setInterval(() => { + setScrollingToNext(true) + setScrollPosition((prev) => { + if (prev < prevCheckpoint) { + clearInterval(interval) + setScrollingToNext(false) + return prevCheckpoint + } + + return prev - 0.02 + }) + }, 50) + } + }) + + const scrollYVelocity = useVelocity(scrollYProgress) + useMotionValueEvent(scrollYVelocity, 'change', setScrollVelocity) + + // console.log(scrollVelocity, scrollPosition) // Change opacity based on section const changeOpacity = ( @@ -245,17 +325,18 @@ export default function LaunchSystem() { > 2 ? changeOpacity(2, scrollPosition, 1, 0, 0.2) : changeOpacity(1, scrollPosition, 0, 1, 0.2), + visibility: scrollPosition * 4 > 1.2 ? 'visible' : 'collapse', }} /> @@ -300,11 +381,6 @@ export default function LaunchSystem() { - - {/* {currentSection === 1 && } - {currentSection === 2 && } - {currentSection === 3 && } - {currentSection === 4 && } */} ) diff --git a/components/sections/Home/Step1Bottom.tsx b/components/sections/Home/Step1Bottom.tsx deleted file mode 100644 index 0c1dba41..00000000 --- a/components/sections/Home/Step1Bottom.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import clsx from 'clsx' - -export default function Step1Bottom({ - className, - id, - style, -}: { - className?: string - id: string - style?: React.SVGAttributes['style'] -}) { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ) -} diff --git a/components/sections/Home/Step2Bottom.tsx b/components/sections/Home/Step2Bottom.tsx deleted file mode 100644 index 21023224..00000000 --- a/components/sections/Home/Step2Bottom.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import clsx from 'clsx' -import React from 'react' - -export default function Step2Bottom({ - className, - id, - style, -}: { - className?: string - id?: string - style?: React.SVGAttributes['style'] -}) { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ) -}