diff --git a/src/app/page.tsx b/src/app/page.tsx index e69de29..be88f73 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -0,0 +1,118 @@ +import Image from 'next/image' +import { Inter } from 'next/font/google' + +const inter = Inter({ subsets: ['latin'] }) + +export default function Home() { + return ( +
+
+

+ Get started by editing  + src/pages/index.tsx +

+
+ + By{' '} + Vercel Logo + +
+
+ +
+ Next.js Logo +
+ +
+ +

+ Docs{' '} + + -> + +

+

+ Find in-depth information about Next.js features and API. +

+
+ + +

+ Learn{' '} + + -> + +

+

+ Learn about Next.js in an interactive course with quizzes! +

+
+ + +

+ Templates{' '} + + -> + +

+

+ Discover and deploy boilerplate example Next.js projects. +

+
+ + +

+ Deploy{' '} + + -> + +

+

+ Instantly deploy your Next.js site to a shareable URL with Vercel. +

+
+
+
+ ) +} diff --git a/src/components/SwitchableComponent.tsx b/src/components/SwitchableComponent.tsx new file mode 100644 index 0000000..3a80cd6 --- /dev/null +++ b/src/components/SwitchableComponent.tsx @@ -0,0 +1,81 @@ +import { Variant, AnimatePresence, motion } from "framer-motion"; +import React from "react"; + +const SwitchableComponentContext = React.createContext(undefined); + +export const SwitchableComponentProvider = ({ children }: React.PropsWithChildren) => { + const [visibleComponent, setVisibleComponent] = React.useState(); + + return + {children} + +} + +export function useSwitchableComponent(initialValue?: SwitchableComponentType) { + const contextValue = React.useContext(SwitchableComponentContext); + + if (contextValue === undefined) { + throw new Error('useSwitchableComponent hook is being used outside of its context. Please ensure that it is wrapped within a .'); + } + React.useEffect(() => { + // Set the initial value if it's provided + if (initialValue && contextValue.visibleComponent) { + contextValue.setVisibleComponent(initialValue); + } + }, [initialValue]); + + return contextValue; +} + +const variants: Record = { + hidden: { y: 50, opacity: 0, position: 'absolute' }, + show: { + y: 0, + opacity: 1, + position: 'relative', + transition: { + type: "tween", + ease: 'easeInOut' + }, + }, + exit: { y: -50, opacity: 0, position: 'absolute' } +}; + +export const SwitchableComponent = ({ children, index }: React.PropsWithChildren<{ index: string }>) => { + return ( + + + {children} + + + ); +}; + +type SwitchableComponentType = { + index: string, + render: (props: T | any) => ReturnType +} + +type SwitchableComponentContextType = { + visibleComponent: SwitchableComponentType, + setVisibleComponent: React.Dispatch | undefined>> +} + +const DEFAULT_COMPONENT = { render: () => undefined, index: Symbol('DEFAULT_COMPONENT').toString() } + +// Factory function +export function makeSwitchable(Component: React.FC, index: string) { + return { + render(props: T) { return }, + index: index || Symbol(Component.name).toString() + }; +}; \ No newline at end of file diff --git a/src/components/lume/LumeIdentity.tsx b/src/components/lume/LumeIdentity.tsx deleted file mode 100644 index 71e3567..0000000 --- a/src/components/lume/LumeIdentity.tsx +++ /dev/null @@ -1,167 +0,0 @@ -// src/components/sign-in-with-lume.tsx -import React, { useCallback, useMemo } from 'react'; -import { AnimatePresence, Variant, motion } from 'framer-motion'; -import { useForm } from "react-hook-form"; - -import LumeLogoBg from '@/assets/lume-logo-bg.svg'; -import { Button } from '@/components/ui/button'; -import { Input } from '@/components/ui/input'; - -type Props = { - onSignIn: () => void; // TODO: Properly type this - onSignUp: () => void; // TODO: Properly type this -} - -const LumeIdentity: React.FC = ({ onSignIn, onSignUp }) => { - // FIXME: There has to be a better way to organize this component, for the time being this suffices - const SubmitButton = useMemo(() => { - return { - render() { - return - }, - index: Symbol('submit-button').toString() - } - }, []); - - const SeedPhraseInput = useMemo(() => { - return { - render() { - return - - - - - - }, - index: Symbol('seed-phrase-input').toString() - } - }, []); - - const SetupAccountKey = useMemo(() => { - return { - render() { - return - - - }, - index: Symbol('setup-account-key').toString() - } - }, []); - - const SeedPhraseForm = useMemo(() => { - return { - render({ phraseLength = 12 }: { phraseLength: number }) { - const { register, handleSubmit, formState: { errors } } = useForm(); - - const onSubmit = (data: any) => { - console.log(data); - }; - - return
- {Array(phraseLength).fill(null).map((_, index) => { - const fieldName = `phrase${index}`; - return ( -
- - {index + 1} -
) - })} - -
- }, - index: Symbol('seed-phrase-form').toString() - } - }, []); - - const [visibleComponent, setVisibleComponent] = React.useState(SubmitButton as { render: (props: Record) => React.ReactElement, index: string }); - - const isSubmitButtonInView = [SubmitButton.index].includes(visibleComponent.index) - const isCreatingAccount = [SetupAccountKey.index, SeedPhraseForm.index].includes(visibleComponent.index) - const shouldShowBackButton = isCreatingAccount - console.log({ isCreatingAccount, shouldShowBackButton, visibleComponent }) - const headingElement = !isCreatingAccount ? (

Sign-in with Lume

) : (

Set up your account key

) - - const coloredOrLine = isSubmitButtonInView ? 'text-primary' : 'text-border' - - return
-
- -
-
-
- {headingElement} -
-
- - - -
- - - - -
- -
-
-
- -}; - -const variants: Record = { - hidden: { y: 50, opacity: 0, position: 'absolute' }, - show: { - y: 0, - opacity: 1, - position: 'relative', - transition: { - type: "tween", - ease: 'easeInOut' - }, - }, - exit: { y: -50, opacity: 0, position: 'absolute' } -}; - -const SwitchableComponent = ({ children, index }: React.PropsWithChildren<{ index: string }>) => { - - return ( - - - {children} - - - ); -}; - -export default LumeIdentity; \ No newline at end of file diff --git a/src/components/lume/LumeIdentity.stories.tsx b/src/components/lume/LumeIdentity/LumeIdentity.stories.tsx similarity index 100% rename from src/components/lume/LumeIdentity.stories.tsx rename to src/components/lume/LumeIdentity/LumeIdentity.stories.tsx diff --git a/src/components/lume/LumeIdentity/LumeIdentity.tsx b/src/components/lume/LumeIdentity/LumeIdentity.tsx new file mode 100644 index 0000000..6f80213 --- /dev/null +++ b/src/components/lume/LumeIdentity/LumeIdentity.tsx @@ -0,0 +1,53 @@ +// src/components/sign-in-with-lume.tsx +import React from 'react'; + +import LumeLogoBg from '@/assets/lume-logo-bg.svg'; +import { Button } from '@/components/ui/button'; +import { SwitchableComponent, SwitchableComponentProvider, useSwitchableComponent } from '@/components/SwitchableComponent'; +import ComponentList from "./components"; + +type Props = {} + +const LumeIdentity: React.FC = ({ }) => { + const { visibleComponent, setVisibleComponent } = useSwitchableComponent(ComponentList.SubmitButton) + console.log({ visibleComponent }) + + const isSubmitButtonInView = [ComponentList.SubmitButton.index].includes(visibleComponent.index) + const isCreatingAccount = [ComponentList.SetupAccountKey.index, ComponentList.SeedPhraseForm.index].includes(visibleComponent.index) + const shouldShowBackButton = isCreatingAccount + + const headingElement = !isCreatingAccount ? (

Sign-in with Lume

) : (

Set up your account key

) + const coloredOrLine = isSubmitButtonInView ? 'text-primary' : 'text-border' + + return
+
+ +
+
+
+ {headingElement} +
+
+ + + +
+ + + + +
+ +
+
+
+ +}; + +export default () => { + return + + +}; \ No newline at end of file diff --git a/src/components/lume/LumeIdentity/components.tsx b/src/components/lume/LumeIdentity/components.tsx new file mode 100644 index 0000000..50f2533 --- /dev/null +++ b/src/components/lume/LumeIdentity/components.tsx @@ -0,0 +1,77 @@ +import { makeSwitchable, useSwitchableComponent } from "@/components/SwitchableComponent"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { motion } from "framer-motion"; +import React from "react"; + +// Extracted components +const SubmitButtonComponent = ({ }) => { + const { setVisibleComponent } = useSwitchableComponent(); + return ( + + ) +}; + +const SeedPhraseInputComponent = ({ signIn }: { signIn: (value: string) => void }) => { + const [value, setValue] = React.useState(""); + return ( + + setValue(e.target?.value)} /> + + + + + ); +}; + +const SetupAccountKeyComponent = () => { + const { setVisibleComponent } = useSwitchableComponent(); + + return ( + + + + ) +}; + +const SeedPhraseFormComponent = ({ phraseLength = 12 }) => ( +
+ {Array(phraseLength).fill("a phrase").map((phrase, index) => ( +
+ {phrase} + {index + 1} +
+ ))} + +
+); + +// Usage +const components = { + SubmitButton: makeSwitchable(SubmitButtonComponent, 'submit-button'), + SeedPhraseInput: makeSwitchable(SeedPhraseInputComponent, 'seed-phrase-input'), + SetupAccountKey: makeSwitchable(SetupAccountKeyComponent, 'setup-account-key'), + SeedPhraseForm: makeSwitchable(SeedPhraseFormComponent, 'seed-phrase-form'), +}; + +export default components; diff --git a/src/pages/index.tsx b/src/pages/index.tsx deleted file mode 100644 index be88f73..0000000 --- a/src/pages/index.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import Image from 'next/image' -import { Inter } from 'next/font/google' - -const inter = Inter({ subsets: ['latin'] }) - -export default function Home() { - return ( -
-
-

- Get started by editing  - src/pages/index.tsx -

- -
- -
- Next.js Logo -
- - -
- ) -}