diff --git a/assets/js/react/components/FieldSet.tsx b/assets/js/react/components/FieldSet.tsx new file mode 100644 index 0000000..ef5dd11 --- /dev/null +++ b/assets/js/react/components/FieldSet.tsx @@ -0,0 +1,66 @@ +import * as React from "react" + +export const FieldContext = React.createContext<{ + required?: boolean + disabled?: boolean + error?: string | boolean +}>({}) + +function Wrapper(props: React.ComponentPropsWithoutRef<"div">) { + const fieldContext = React.useContext(FieldContext) + const { children, ...other } = props + + return ( + <> +
{children}
+ {typeof fieldContext?.error === "string" && ( +

{fieldContext?.error}

+ )} + + ) +} + +type WrapperProps = + React.ComponentPropsWithoutRef & { + slotProps?: { + root?: React.ComponentPropsWithoutRef<"div"> + } + } + +export const Field = React.forwardRef< + HTMLDivElement, + WrapperProps<"div"> & { + required?: boolean + disabled?: boolean + error?: string | boolean + } +>(function Field(props, ref) { + const { children, slotProps, required, disabled, error, ...other } = props + + return ( + +
+ {children} +
+
+ ) +}) + +export const FieldSet = React.forwardRef< + HTMLFieldSetElement, + WrapperProps<"fieldset"> & { + required?: boolean + disabled?: boolean + error?: string | boolean + } +>(function FieldSet(props, ref) { + const { children, slotProps, required, disabled, error, ...other } = props + + return ( + +
+ {children} +
+
+ ) +}) diff --git a/assets/js/react/components/FilterModal.tsx b/assets/js/react/components/FilterModal.tsx new file mode 100644 index 0000000..980f3b3 --- /dev/null +++ b/assets/js/react/components/FilterModal.tsx @@ -0,0 +1,138 @@ +import * as React from "react" +import { Controller, useForm } from "react-hook-form" + +import { Button } from "./Button" +import { Field } from "./FieldSet" +import { Input } from "./Input" +import { Label } from "./Label" +import { Modal } from "./Modal" +import { Slider } from "./Slider" + +import { + FIDE_RATING_MIN, + FIDE_RATING_MAX, + SearchParams, +} from "../types/SearchParams" + +const computeStepLabels = ( + min: number, + max: number, + // The number of labels (+ 1) that should be produced. + steps: number, + // To which value numbers should be rounded to. + round: number +) => { + let labels = [] + const delta = Math.floor((max - min) / steps) + for (let i = min; i <= max; i += delta) { + if (i % round <= round / 2) { + labels.push(i - (i % round)) + } else { + labels.push(i + round - (i % round)) + } + } + + labels[labels.length - 1] = max + + return labels +} + +interface FilterModalProps { + open: boolean + defaultValues: SearchParams + onClose: () => void + onSubmit: (p: SearchParams) => void +} + +export function FilterModal({ + open, + defaultValues, + onClose, + onSubmit, +}: FilterModalProps) { + const idPrefix = React.useId() + + const { watch, reset, control, register, setValue, handleSubmit } = + useForm({ defaultValues }) + + // Default values are processed immediately despite the modal not being open + // at the start. Furthermore, values are preserved after closing and + // re-opening the modal, but we want closing the modal to signify canceling. + // A simple workaround is to reset everytime we open the modal. + React.useEffect(() => reset(defaultValues), [open]) + + // Registration + + const controlFIDERating = register("fideRating") + + return ( + + Search coaches + + ), + onSubmit: handleSubmit(onSubmit), + }} + > +
+ + +

+ Find coaches that have a rating within the specified range. Keep in + mind, a higher rating does not necessarily mean a better coach{" "} + for you. If you are unsure of this or do not have any + preference, leave as is. +

+
+ ( + { + event && onChange(event) + setValue("fideRating.0", newValue[0]) + setValue("fideRating.1", newValue[1]) + }} + step={10} + min={FIDE_RATING_MIN} + max={FIDE_RATING_MAX} + marks={computeStepLabels( + FIDE_RATING_MIN, + FIDE_RATING_MAX, + 7, + 50 + ).map((s) => ({ value: s, label: `${s}` }))} + /> + )} + /> +
+
+ + +
+
+ + +
+
+
+
+
+
+ ) +} diff --git a/assets/js/react/components/Input.tsx b/assets/js/react/components/Input.tsx new file mode 100644 index 0000000..d8dbbc7 --- /dev/null +++ b/assets/js/react/components/Input.tsx @@ -0,0 +1,41 @@ +import * as React from "react" +import clsx from "clsx" +import { + Input as BaseInput, + InputProps, + InputOwnerState, +} from "@mui/base/Input" + +import { FieldContext } from "./FieldSet" +import { resolveSlotProps } from "../utils/props" + +export const Input = React.forwardRef( + function Input(props: InputProps, ref: React.ForwardedRef) { + const fieldContext = React.useContext(FieldContext) + const { disabled = fieldContext?.disabled, ...other } = props + + const inputSlotProps = (ownerState: InputOwnerState) => { + const resolved = resolveSlotProps(props.slotProps?.input, ownerState) + return { + ...resolved, + className: clsx( + "text-sm font-normal leading-5 px-3 py-2 rounded-lg shadow-md border border-solid shadow-slate-100 focus:shadow-lg bg-white text-slate-900", + fieldContext?.error + ? "border-amber-800 focus-visible:outline focus-visible:outline-1 focus-visible:outline-amber-800" + : "border-slate-300", + { "opacity-60": ownerState.disabled }, + resolved?.className + ), + } + } + + return ( + + ) + } +) diff --git a/assets/js/react/components/Label.tsx b/assets/js/react/components/Label.tsx new file mode 100644 index 0000000..59eb5b5 --- /dev/null +++ b/assets/js/react/components/Label.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import clsx from "clsx" + +import { FieldContext } from "./FieldSet" + +type LabelProps = { + children: React.ReactNode + sublabel?: boolean +} & React.ComponentPropsWithoutRef<"label"> + +export const Label = React.forwardRef( + function Label(props, ref) { + const fieldContext = React.useContext(FieldContext) + const { children, sublabel, className, ...other } = props + + return ( + + ) + } +) diff --git a/assets/js/react/components/Modal.tsx b/assets/js/react/components/Modal.tsx new file mode 100644 index 0000000..7486722 --- /dev/null +++ b/assets/js/react/components/Modal.tsx @@ -0,0 +1,93 @@ +import * as React from "react" +import clsx from "clsx" +import { + Modal as BaseModal, + ModalBackdropSlotProps, + ModalProps, +} from "@mui/base/Modal" + +import XIcon from "../icons/X" +import { FadeIn } from "./FadeIn" + +const Backdrop = React.forwardRef( + function Backdrop(props, ref) { + const { open, ownerState, onClick, ...other } = props + + return ( +
+
+
+ ) + } +) + +type FrameProps = + React.ComponentPropsWithoutRef & { + as?: T + title: string + footer: React.ReactNode + onClose?: ModalProps["onClose"] + } + +function Frame(props: FrameProps) { + const { as, title, footer, onClose, children, ...other } = props + let Component = as ?? "div" + + return ( + +
+ + {title} +
+
{children}
+
{footer}
+
+ ) +} + +export function Modal( + props: ModalProps & { frame?: FrameProps } +) { + const { className, children, frame, onClose, ...other } = props + + return ( + +
+ + {frame ? ( + + {children} + + ) : ( + children + )} + +
+
+ ) +} + +Modal.displayName = "Modal" diff --git a/assets/js/react/components/Slider.tsx b/assets/js/react/components/Slider.tsx new file mode 100644 index 0000000..cf680ba --- /dev/null +++ b/assets/js/react/components/Slider.tsx @@ -0,0 +1,101 @@ +import * as React from "react" +import clsx from "clsx" +import { + Slider as BaseSlider, + SliderProps as BaseSliderProps, + SliderOwnerState, +} from "@mui/base/Slider" + +import { resolveSlotProps } from "../utils/props" + +export type SliderProps = BaseSliderProps + +export const Slider = React.forwardRef( + function Slider( + props: SliderProps, + ref: React.ForwardedRef + ) { + const rootSlotProps = (ownerState: SliderOwnerState) => { + const resolved = resolveSlotProps(props.slotProps?.root, ownerState) + return { + ...resolved, + className: clsx("hover:opacity-100", resolved?.className), + } + } + + const railSlotProps = (ownerState: SliderOwnerState) => { + const resolved = resolveSlotProps(props.slotProps?.rail, ownerState) + return { + ...resolved, + className: clsx( + "block absolute w-full h-1 rounded-sm bg-slate-300", + resolved?.className + ), + } + } + + const trackSlotProps = (ownerState: SliderOwnerState) => { + const resolved = resolveSlotProps(props.slotProps?.track, ownerState) + return { + ...resolved, + className: clsx( + "block absolute w-full h-1 rounded-sm bg-current", + resolved?.className + ), + } + } + + const thumbSlotProps = (ownerState: SliderOwnerState) => { + const resolved = resolveSlotProps(props.slotProps?.thumb, ownerState) + return { + ...resolved, + className: clsx( + "absolute w-6 h-6 -ml-2 -mt-2.5 box-border rounded-full bg-current hover:shadow hover:shadow-slate-300", + resolved?.className + ), + } + } + + const markSlotProps = (ownerState: SliderOwnerState) => { + const resolved = resolveSlotProps(props.slotProps?.mark, ownerState) + return { + ...resolved, + className: clsx( + "absolute w-1 h-1 opacity-70 bg-current rounded-sm -translate-x-2/4 top-1/2", + resolved?.className + ), + } + } + + const markLabelSlotProps = (ownerState: SliderOwnerState) => { + const resolved = resolveSlotProps(props.slotProps?.markLabel, ownerState) + return { + ...resolved, + className: clsx( + "absolute text-sm top-5 -translate-x-1/2", + resolved?.className + ), + } + } + + return ( + + ) + } +) diff --git a/assets/js/react/pages/Search.tsx b/assets/js/react/pages/Search.tsx index 01b7ffc..a71c646 100644 --- a/assets/js/react/pages/Search.tsx +++ b/assets/js/react/pages/Search.tsx @@ -3,14 +3,15 @@ import axios from "axios" import { useQuery } from "@tanstack/react-query" import type { Coach } from "../types/Coach" -import { type SearchParams, defaultSearchParams } from "../types/SearchParams" import { Container } from "../components/Container" import { FadeIn, FadeInStagger } from "../components/FadeIn" import { FallbackMessage } from "../components/FallbackMessage" +import { FilterModal } from "../components/FilterModal" import { FilterScroll } from "../components/FilterScroll" import { Loading } from "../components/Loading" import { SearchResult } from "../components/SearchResult" +import { defaultSearchParams } from "../types/SearchParams" function SearchResults() { const { isLoading, isError, data } = useQuery({ @@ -54,13 +55,23 @@ function SearchResults() { export function Search() { const [searchParams, setSearchParams] = React.useState(defaultSearchParams) + const [modalOpen, setModalOpen] = React.useState(false) return ( {}} + onModal={() => setModalOpen(true)} + /> + setModalOpen(false)} + onSubmit={(q) => { + setSearchParams(q) + setModalOpen(false) + }} /> diff --git a/assets/js/react/types/SearchParams.ts b/assets/js/react/types/SearchParams.ts index 77204c1..847d99d 100644 --- a/assets/js/react/types/SearchParams.ts +++ b/assets/js/react/types/SearchParams.ts @@ -2,8 +2,8 @@ export type SearchParams = { fideRating: [number, number] } -const FIDE_RATING_MIN = 1500 -const FIDE_RATING_MAX = 3200 +export const FIDE_RATING_MIN = 1500 +export const FIDE_RATING_MAX = 3200 export const defaultSearchParams: SearchParams = { fideRating: [FIDE_RATING_MIN, FIDE_RATING_MAX], diff --git a/assets/js/react/utils/props.ts b/assets/js/react/utils/props.ts new file mode 100644 index 0000000..d6b7afc --- /dev/null +++ b/assets/js/react/utils/props.ts @@ -0,0 +1,11 @@ +// Used when overriding slot props. `SlotComponentProps` (the generic type being +// overridden) is one of the following: +// +// 1. `Partial> & TOverrides` +// 2. `(ownerState: TOwnerState) => +// Partial> & TOverrides` +// +// Refer to `mui/base/utils/types.d.ts`. The following checks which of the two +// we're working with and returns the `Partial` type. +export const resolveSlotProps = (fn: any, args: any) => + typeof fn === "function" ? fn(args) : fn diff --git a/assets/node-packages.nix b/assets/node-packages.nix index 94ee809..e1db8f7 100644 --- a/assets/node-packages.nix +++ b/assets/node-packages.nix @@ -4,6 +4,15 @@ let sources = { + "@babel/runtime-7.23.5" = { + name = "_at_babel_slash_runtime"; + packageName = "@babel/runtime"; + version = "7.23.5"; + src = fetchurl { + url = "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz"; + sha512 = "NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w=="; + }; + }; "@emotion/is-prop-valid-0.8.8" = { name = "_at_emotion_slash_is-prop-valid"; packageName = "@emotion/is-prop-valid"; @@ -22,6 +31,78 @@ let sha512 = "Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="; }; }; + "@floating-ui/core-1.5.1" = { + name = "_at_floating-ui_slash_core"; + packageName = "@floating-ui/core"; + version = "1.5.1"; + src = fetchurl { + url = "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.1.tgz"; + sha512 = "QgcKYwzcc8vvZ4n/5uklchy8KVdjJwcOeI+HnnTNclJjs2nYsy23DOCf+sSV1kBwD9yDAoVKCkv/gEPzgQU3Pw=="; + }; + }; + "@floating-ui/dom-1.5.3" = { + name = "_at_floating-ui_slash_dom"; + packageName = "@floating-ui/dom"; + version = "1.5.3"; + src = fetchurl { + url = "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz"; + sha512 = "ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA=="; + }; + }; + "@floating-ui/react-dom-2.0.4" = { + name = "_at_floating-ui_slash_react-dom"; + packageName = "@floating-ui/react-dom"; + version = "2.0.4"; + src = fetchurl { + url = "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.4.tgz"; + sha512 = "CF8k2rgKeh/49UrnIBs4BdxPUV6vize/Db1d/YbCLyp9GiVZ0BEwf5AiDSxJRCr6yOkGqTFHtmrULxkEfYZ7dQ=="; + }; + }; + "@floating-ui/utils-0.1.6" = { + name = "_at_floating-ui_slash_utils"; + packageName = "@floating-ui/utils"; + version = "0.1.6"; + src = fetchurl { + url = "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz"; + sha512 = "OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A=="; + }; + }; + "@mui/base-5.0.0-beta.25" = { + name = "_at_mui_slash_base"; + packageName = "@mui/base"; + version = "5.0.0-beta.25"; + src = fetchurl { + url = "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.25.tgz"; + sha512 = "Iiv+IcappRRv6IBlknIVmLkXxfp51NEX1+l9f+dIbBuPU4PaRULegr1lCeHKsC45KU5ruxM5xMg4R/de03aJQg=="; + }; + }; + "@mui/types-7.2.10" = { + name = "_at_mui_slash_types"; + packageName = "@mui/types"; + version = "7.2.10"; + src = fetchurl { + url = "https://registry.npmjs.org/@mui/types/-/types-7.2.10.tgz"; + sha512 = "wX1vbDC+lzF7FlhT6A3ffRZgEoKWPF8VqRoTu4lZwouFX2t90KyCMsgepMw5DxLak1BSp/KP86CmtZttikb/gQ=="; + }; + }; + "@mui/utils-5.14.19" = { + name = "_at_mui_slash_utils"; + packageName = "@mui/utils"; + version = "5.14.19"; + src = fetchurl { + url = "https://registry.npmjs.org/@mui/utils/-/utils-5.14.19.tgz"; + sha512 = "qAHvTXzk7basbyqPvhgWqN6JbmI2wLB/mf97GkSlz5c76MiKYV6Ffjvw9BjKZQ1YRb8rDX9kgdjRezOcoB91oQ=="; + }; + }; + "@popperjs/core-2.11.8" = { + name = "_at_popperjs_slash_core"; + packageName = "@popperjs/core"; + version = "2.11.8"; + src = fetchurl { + url = "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"; + sha512 = "P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="; + }; + }; "@remix-run/router-1.13.1" = { name = "_at_remix-run_slash_router"; packageName = "@remix-run/router"; @@ -31,6 +112,69 @@ let sha512 = "so+DHzZKsoOcoXrILB4rqDkMDy7NLMErRdOxvzvOKb507YINKUP4Di+shbTZDhSE/pBZ+vr7XGIpcOO0VLSA+Q=="; }; }; + "@tanstack/query-core-5.12.1" = { + name = "_at_tanstack_slash_query-core"; + packageName = "@tanstack/query-core"; + version = "5.12.1"; + src = fetchurl { + url = "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.12.1.tgz"; + sha512 = "WbZztNmKq0t6QjdNmHzezbi/uifYo9j6e2GLJkodsYaYUlzMbAp91RDyeHkIZrm7EfO4wa6Sm5sxJZm5SPlh6w=="; + }; + }; + "@tanstack/react-query-5.12.2" = { + name = "_at_tanstack_slash_react-query"; + packageName = "@tanstack/react-query"; + version = "5.12.2"; + src = fetchurl { + url = "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.12.2.tgz"; + sha512 = "BeWZu8zVFH20oRc+S/K9ADPgWjEzP/XQCGBNz5IbApUwPQAdwkQYbXODVL5AyAlWiSxhx+P2xlARPBApj2Yrog=="; + }; + }; + "@types/prop-types-15.7.11" = { + name = "_at_types_slash_prop-types"; + packageName = "@types/prop-types"; + version = "15.7.11"; + src = fetchurl { + url = "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz"; + sha512 = "ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="; + }; + }; + "@types/react-18.2.40" = { + name = "_at_types_slash_react"; + packageName = "@types/react"; + version = "18.2.40"; + src = fetchurl { + url = "https://registry.npmjs.org/@types/react/-/react-18.2.40.tgz"; + sha512 = "H+BUhb9C1zBtogDLAk+KCNRKiHDrqSwQT/0z0PVTwMFBxqg3011ByLomADtgkgMkfwj4AMOiXBReyLTUBg681g=="; + }; + }; + "@types/scheduler-0.16.8" = { + name = "_at_types_slash_scheduler"; + packageName = "@types/scheduler"; + version = "0.16.8"; + src = fetchurl { + url = "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz"; + sha512 = "WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A=="; + }; + }; + "asynckit-0.4.0" = { + name = "asynckit"; + packageName = "asynckit"; + version = "0.4.0"; + src = fetchurl { + url = "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz"; + sha512 = "Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="; + }; + }; + "axios-1.6.2" = { + name = "axios"; + packageName = "axios"; + version = "1.6.2"; + src = fetchurl { + url = "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz"; + sha512 = "7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A=="; + }; + }; "clsx-2.0.0" = { name = "clsx"; packageName = "clsx"; @@ -40,6 +184,51 @@ let sha512 = "rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q=="; }; }; + "combined-stream-1.0.8" = { + name = "combined-stream"; + packageName = "combined-stream"; + version = "1.0.8"; + src = fetchurl { + url = "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"; + sha512 = "FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="; + }; + }; + "csstype-3.1.2" = { + name = "csstype"; + packageName = "csstype"; + version = "3.1.2"; + src = fetchurl { + url = "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz"; + sha512 = "I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="; + }; + }; + "delayed-stream-1.0.0" = { + name = "delayed-stream"; + packageName = "delayed-stream"; + version = "1.0.0"; + src = fetchurl { + url = "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"; + sha512 = "ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="; + }; + }; + "follow-redirects-1.15.3" = { + name = "follow-redirects"; + packageName = "follow-redirects"; + version = "1.15.3"; + src = fetchurl { + url = "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz"; + sha512 = "1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q=="; + }; + }; + "form-data-4.0.0" = { + name = "form-data"; + packageName = "form-data"; + version = "4.0.0"; + src = fetchurl { + url = "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz"; + sha512 = "ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww=="; + }; + }; "framer-motion-10.16.12" = { name = "framer-motion"; packageName = "framer-motion"; @@ -67,6 +256,51 @@ let sha512 = "lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="; }; }; + "mime-db-1.52.0" = { + name = "mime-db"; + packageName = "mime-db"; + version = "1.52.0"; + src = fetchurl { + url = "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"; + sha512 = "sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="; + }; + }; + "mime-types-2.1.35" = { + name = "mime-types"; + packageName = "mime-types"; + version = "2.1.35"; + src = fetchurl { + url = "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"; + sha512 = "ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="; + }; + }; + "object-assign-4.1.1" = { + name = "object-assign"; + packageName = "object-assign"; + version = "4.1.1"; + src = fetchurl { + url = "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"; + sha512 = "rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="; + }; + }; + "prop-types-15.8.1" = { + name = "prop-types"; + packageName = "prop-types"; + version = "15.8.1"; + src = fetchurl { + url = "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"; + sha512 = "oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="; + }; + }; + "proxy-from-env-1.1.0" = { + name = "proxy-from-env"; + packageName = "proxy-from-env"; + version = "1.1.0"; + src = fetchurl { + url = "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz"; + sha512 = "D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="; + }; + }; "react-18.2.0" = { name = "react"; packageName = "react"; @@ -85,6 +319,33 @@ let sha512 = "6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="; }; }; + "react-hook-form-7.48.2" = { + name = "react-hook-form"; + packageName = "react-hook-form"; + version = "7.48.2"; + src = fetchurl { + url = "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.48.2.tgz"; + sha512 = "H0T2InFQb1hX7qKtDIZmvpU1Xfn/bdahWBN1fH19gSe4bBEqTfmlr7H3XWTaVtiK4/tpPaI1F3355GPMZYge+A=="; + }; + }; + "react-is-16.13.1" = { + name = "react-is"; + packageName = "react-is"; + version = "16.13.1"; + src = fetchurl { + url = "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"; + sha512 = "24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="; + }; + }; + "react-is-18.2.0" = { + name = "react-is"; + packageName = "react-is"; + version = "18.2.0"; + src = fetchurl { + url = "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz"; + sha512 = "xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="; + }; + }; "react-router-6.20.1" = { name = "react-router"; packageName = "react-router"; @@ -103,6 +364,15 @@ let sha512 = "npzfPWcxfQN35psS7rJgi/EW0Gx6EsNjfdJSAk73U/HqMEJZ2k/8puxfwHFgDQhBGmS3+sjnGbMdMSV45axPQw=="; }; }; + "regenerator-runtime-0.14.0" = { + name = "regenerator-runtime"; + packageName = "regenerator-runtime"; + version = "0.14.0"; + src = fetchurl { + url = "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz"; + sha512 = "srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="; + }; + }; "scheduler-0.23.0" = { name = "scheduler"; packageName = "scheduler"; @@ -128,17 +398,50 @@ let version = "0.1.0"; src = ./.; dependencies = [ + sources."@babel/runtime-7.23.5" sources."@emotion/is-prop-valid-0.8.8" sources."@emotion/memoize-0.7.4" + sources."@floating-ui/core-1.5.1" + sources."@floating-ui/dom-1.5.3" + sources."@floating-ui/react-dom-2.0.4" + sources."@floating-ui/utils-0.1.6" + sources."@mui/base-5.0.0-beta.25" + sources."@mui/types-7.2.10" + sources."@mui/utils-5.14.19" + sources."@popperjs/core-2.11.8" sources."@remix-run/router-1.13.1" + sources."@tanstack/query-core-5.12.1" + sources."@tanstack/react-query-5.12.2" + sources."@types/prop-types-15.7.11" + sources."@types/react-18.2.40" + sources."@types/scheduler-0.16.8" + sources."asynckit-0.4.0" + sources."axios-1.6.2" sources."clsx-2.0.0" + sources."combined-stream-1.0.8" + sources."csstype-3.1.2" + sources."delayed-stream-1.0.0" + sources."follow-redirects-1.15.3" + sources."form-data-4.0.0" sources."framer-motion-10.16.12" sources."js-tokens-4.0.0" sources."loose-envify-1.4.0" + sources."mime-db-1.52.0" + sources."mime-types-2.1.35" + sources."object-assign-4.1.1" + (sources."prop-types-15.8.1" // { + dependencies = [ + sources."react-is-16.13.1" + ]; + }) + sources."proxy-from-env-1.1.0" sources."react-18.2.0" sources."react-dom-18.2.0" + sources."react-hook-form-7.48.2" + sources."react-is-18.2.0" sources."react-router-6.20.1" sources."react-router-dom-6.20.1" + sources."regenerator-runtime-0.14.0" sources."scheduler-0.23.0" sources."tslib-2.6.2" ]; diff --git a/assets/package-lock.json b/assets/package-lock.json index f9128d6..f56f65a 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -15,6 +15,7 @@ "framer-motion": "^10.16.12", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-hook-form": "^7.48.2", "react-router-dom": "^6.20.1" }, "devDependencies": { @@ -465,6 +466,21 @@ "react": "^18.2.0" } }, + "node_modules/react-hook-form": { + "version": "7.48.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.48.2.tgz", + "integrity": "sha512-H0T2InFQb1hX7qKtDIZmvpU1Xfn/bdahWBN1fH19gSe4bBEqTfmlr7H3XWTaVtiK4/tpPaI1F3355GPMZYge+A==", + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", @@ -818,6 +834,12 @@ "scheduler": "^0.23.0" } }, + "react-hook-form": { + "version": "7.48.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.48.2.tgz", + "integrity": "sha512-H0T2InFQb1hX7qKtDIZmvpU1Xfn/bdahWBN1fH19gSe4bBEqTfmlr7H3XWTaVtiK4/tpPaI1F3355GPMZYge+A==", + "requires": {} + }, "react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", diff --git a/assets/package.json b/assets/package.json index f94ddb6..ca357ae 100644 --- a/assets/package.json +++ b/assets/package.json @@ -9,6 +9,7 @@ "framer-motion": "^10.16.12", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-hook-form": "^7.48.2", "react-router-dom": "^6.20.1" }, "devDependencies": { diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4ff32e6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "website", + "lockfileVersion": 3, + "requires": true, + "packages": {} +}